bpo-42266: Handle monkey-patching descriptors in LOAD_ATTR cache (GH-23157)
This commit is contained in:
parent
178695b7ae
commit
80449f243b
|
@ -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_nntplib.py" />
|
||||||
<Compile Include="test\test_ntpath.py" />
|
<Compile Include="test\test_ntpath.py" />
|
||||||
<Compile Include="test\test_numeric_tower.py" />
|
<Compile Include="test\test_numeric_tower.py" />
|
||||||
|
<Compile Include="test\test_opcache.py" />
|
||||||
<Compile Include="test\test_opcodes.py" />
|
<Compile Include="test\test_opcodes.py" />
|
||||||
<Compile Include="test\test_openpty.py" />
|
<Compile Include="test\test_openpty.py" />
|
||||||
<Compile Include="test\test_operator.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. */
|
if (co_opcache != NULL && /* co_opcache can be NULL after a DEOPT() call. */
|
||||||
type->tp_getattro == PyObject_GenericGetAttr)
|
type->tp_getattro == PyObject_GenericGetAttr)
|
||||||
{
|
{
|
||||||
PyObject *descr;
|
|
||||||
Py_ssize_t ret;
|
Py_ssize_t ret;
|
||||||
|
|
||||||
if (type->tp_dictoffset > 0) {
|
if (type->tp_dictoffset > 0) {
|
||||||
|
@ -3190,12 +3189,7 @@ main_loop:
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (_PyType_Lookup(type, name) == NULL) {
|
||||||
descr = _PyType_Lookup(type, name);
|
|
||||||
if (descr == NULL ||
|
|
||||||
Py_TYPE(descr)->tp_descr_get == NULL ||
|
|
||||||
!PyDescr_IsData(descr))
|
|
||||||
{
|
|
||||||
dictptr = (PyObject **) ((char *)owner + type->tp_dictoffset);
|
dictptr = (PyObject **) ((char *)owner + type->tp_dictoffset);
|
||||||
dict = *dictptr;
|
dict = *dictptr;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue