Browse Source
bpo-42266: Handle monkey-patching descriptors in LOAD_ATTR cache (GH-23157)
pull/23164/head
Pablo Galindo
5 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with
28 additions and
7 deletions
-
Lib/test/test_opcache.py
-
Misc/NEWS.d/next/Core and Builtins/2020-11-04-23-03-25.bpo-42266.G4hGDe.rst
-
PCbuild/lib.pyproj
-
Python/ceval.c
|
|
|
@ -0,0 +1,23 @@ |
|
|
|
import unittest |
|
|
|
|
|
|
|
class TestLoadAttrCache(unittest.TestCase): |
|
|
|
def test_descriptor_added_after_optimization(self): |
|
|
|
class Descriptor: |
|
|
|
pass |
|
|
|
|
|
|
|
class C: |
|
|
|
def __init__(self): |
|
|
|
self.x = 1 |
|
|
|
x = Descriptor() |
|
|
|
|
|
|
|
def f(o): |
|
|
|
return o.x |
|
|
|
|
|
|
|
o = C() |
|
|
|
for i in range(1025): |
|
|
|
assert f(o) == 1 |
|
|
|
|
|
|
|
Descriptor.__get__ = lambda self, instance, value: 2 |
|
|
|
Descriptor.__set__ = lambda *args: None |
|
|
|
|
|
|
|
self.assertEqual(f(o), 2) |
|
|
|
@ -0,0 +1,3 @@ |
|
|
|
Fixed a bug with the LOAD_ATTR opcode cache that was not respecting |
|
|
|
monkey-patching a class-level attribute to make it a descriptor. Patch by |
|
|
|
Pablo Galindo. |
|
|
|
@ -1196,6 +1196,7 @@ |
|
|
|
<Compile Include="test\test_nntplib.py" /> |
|
|
|
<Compile Include="test\test_ntpath.py" /> |
|
|
|
<Compile Include="test\test_numeric_tower.py" /> |
|
|
|
<Compile Include="test\test_opcache.py" /> |
|
|
|
<Compile Include="test\test_opcodes.py" /> |
|
|
|
<Compile Include="test\test_openpty.py" /> |
|
|
|
<Compile Include="test\test_operator.py" /> |
|
|
|
|
|
|
|
@ -3179,7 +3179,6 @@ main_loop: |
|
|
|
if (co_opcache != NULL && /* co_opcache can be NULL after a DEOPT() call. */ |
|
|
|
type->tp_getattro == PyObject_GenericGetAttr) |
|
|
|
{ |
|
|
|
PyObject *descr; |
|
|
|
Py_ssize_t ret; |
|
|
|
|
|
|
|
if (type->tp_dictoffset > 0) { |
|
|
|
@ -3190,12 +3189,7 @@ main_loop: |
|
|
|
goto error; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
descr = _PyType_Lookup(type, name); |
|
|
|
if (descr == NULL || |
|
|
|
Py_TYPE(descr)->tp_descr_get == NULL || |
|
|
|
!PyDescr_IsData(descr)) |
|
|
|
{ |
|
|
|
if (_PyType_Lookup(type, name) == NULL) { |
|
|
|
dictptr = (PyObject **) ((char *)owner + type->tp_dictoffset); |
|
|
|
dict = *dictptr; |
|
|
|
|
|
|
|
|