mirror of
https://github.com/python/cpython.git
synced 2026-05-04 09:31:02 +00:00
Merge 49aa0101ab into d254d6ee49
This commit is contained in:
commit
3638f52bde
8 changed files with 89 additions and 1 deletions
0
.jit-stamp
Normal file
0
.jit-stamp
Normal file
2
Include/internal/pycore_uop_metadata.h
generated
2
Include/internal/pycore_uop_metadata.h
generated
|
|
@ -227,7 +227,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = {
|
|||
[_LOAD_ATTR_WITH_HINT] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_EXIT_FLAG,
|
||||
[_LOAD_ATTR_SLOT] = HAS_EXIT_FLAG,
|
||||
[_CHECK_ATTR_CLASS] = HAS_EXIT_FLAG,
|
||||
[_LOAD_ATTR_CLASS] = HAS_ESCAPES_FLAG,
|
||||
[_LOAD_ATTR_CLASS] = HAS_EXIT_FLAG | HAS_ESCAPES_FLAG,
|
||||
[_LOAD_ATTR_PROPERTY_FRAME] = HAS_ARG_FLAG | HAS_EXIT_FLAG,
|
||||
[_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_EXIT_FLAG,
|
||||
[_GUARD_DORV_NO_DICT] = HAS_EXIT_FLAG,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import enum
|
||||
import copy
|
||||
import pickle
|
||||
import dis
|
||||
|
|
@ -2114,6 +2115,45 @@ def load_enum_member():
|
|||
self.assert_specialized(load_enum_member,
|
||||
"LOAD_ATTR_CLASS_WITH_METACLASS_CHECK")
|
||||
|
||||
@cpython_only
|
||||
@requires_specialization
|
||||
def test_load_attr_class_with_metaclass_check_149239(self):
|
||||
# LOAD_ATTR_CLASS_WITH_METACLASS_CHECK must check
|
||||
# for `__class__` writes, see gh-149239
|
||||
class ColorMeta(enum.EnumType):
|
||||
pass
|
||||
|
||||
class Color(enum.IntEnum, metaclass=ColorMeta):
|
||||
RED = 1
|
||||
|
||||
red = Color.RED
|
||||
|
||||
def f1():
|
||||
for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
|
||||
assert Color.RED == 1
|
||||
|
||||
f1()
|
||||
self.assert_specialized(f1,
|
||||
"LOAD_ATTR_CLASS_WITH_METACLASS_CHECK")
|
||||
|
||||
# Reassign the `__class__` attr to deopt:
|
||||
class Descriptor(enum.IntEnum):
|
||||
RED = 1
|
||||
|
||||
def __get__(self, obj, owner):
|
||||
return "descr"
|
||||
|
||||
red.__class__ = Descriptor
|
||||
|
||||
def f2():
|
||||
for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
|
||||
assert Color.RED == 'descr'
|
||||
|
||||
f2()
|
||||
self.assert_no_opcode(f2,
|
||||
"LOAD_ATTR_CLASS_WITH_METACLASS_CHECK")
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
Deopt ``LOAD_ATTR_CLASS_WITH_METACLASS_CHECK`` opcode on ``__class__``
|
||||
reassigning.
|
||||
16
Modules/_testinternalcapi/test_cases.c.h
generated
16
Modules/_testinternalcapi/test_cases.c.h
generated
|
|
@ -8360,6 +8360,14 @@
|
|||
// _LOAD_ATTR_CLASS
|
||||
{
|
||||
PyObject *descr = read_obj(&this_instr[6].cache);
|
||||
PyTypeObject *descr_type = Py_TYPE(descr);
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
|
||||
if ((descr_type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0
|
||||
&& descr_type != (PyTypeObject *)owner_o) {
|
||||
UPDATE_MISS_STATS(LOAD_ATTR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR));
|
||||
JUMP_TO_PREDICTED(LOAD_ATTR);
|
||||
}
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
assert(descr != NULL);
|
||||
attr = PyStackRef_FromPyObjectNew(descr);
|
||||
|
|
@ -8428,6 +8436,14 @@
|
|||
// _LOAD_ATTR_CLASS
|
||||
{
|
||||
PyObject *descr = read_obj(&this_instr[6].cache);
|
||||
PyTypeObject *descr_type = Py_TYPE(descr);
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
|
||||
if ((descr_type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0
|
||||
&& descr_type != (PyTypeObject *)owner_o) {
|
||||
UPDATE_MISS_STATS(LOAD_ATTR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR));
|
||||
JUMP_TO_PREDICTED(LOAD_ATTR);
|
||||
}
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
assert(descr != NULL);
|
||||
attr = PyStackRef_FromPyObjectNew(descr);
|
||||
|
|
|
|||
|
|
@ -2976,6 +2976,11 @@ dummy_func(
|
|||
}
|
||||
|
||||
op(_LOAD_ATTR_CLASS, (descr/4, owner -- attr)) {
|
||||
PyTypeObject *descr_type = Py_TYPE(descr);
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
|
||||
EXIT_IF((descr_type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0
|
||||
&& descr_type != (PyTypeObject *)owner_o);
|
||||
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
assert(descr != NULL);
|
||||
attr = PyStackRef_FromPyObjectNew(descr);
|
||||
|
|
|
|||
9
Python/executor_cases.c.h
generated
9
Python/executor_cases.c.h
generated
|
|
@ -11967,6 +11967,15 @@
|
|||
_PyStackRef _stack_item_0 = _tos_cache0;
|
||||
owner = _stack_item_0;
|
||||
PyObject *descr = (PyObject *)CURRENT_OPERAND0_64();
|
||||
PyTypeObject *descr_type = Py_TYPE(descr);
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
|
||||
if ((descr_type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0
|
||||
&& descr_type != (PyTypeObject *)owner_o) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache0 = owner;
|
||||
SET_CURRENT_CACHED_VALUES(1);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
assert(descr != NULL);
|
||||
attr = PyStackRef_FromPyObjectNew(descr);
|
||||
|
|
|
|||
16
Python/generated_cases.c.h
generated
16
Python/generated_cases.c.h
generated
|
|
@ -8359,6 +8359,14 @@
|
|||
// _LOAD_ATTR_CLASS
|
||||
{
|
||||
PyObject *descr = read_obj(&this_instr[6].cache);
|
||||
PyTypeObject *descr_type = Py_TYPE(descr);
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
|
||||
if ((descr_type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0
|
||||
&& descr_type != (PyTypeObject *)owner_o) {
|
||||
UPDATE_MISS_STATS(LOAD_ATTR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR));
|
||||
JUMP_TO_PREDICTED(LOAD_ATTR);
|
||||
}
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
assert(descr != NULL);
|
||||
attr = PyStackRef_FromPyObjectNew(descr);
|
||||
|
|
@ -8427,6 +8435,14 @@
|
|||
// _LOAD_ATTR_CLASS
|
||||
{
|
||||
PyObject *descr = read_obj(&this_instr[6].cache);
|
||||
PyTypeObject *descr_type = Py_TYPE(descr);
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
|
||||
if ((descr_type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0
|
||||
&& descr_type != (PyTypeObject *)owner_o) {
|
||||
UPDATE_MISS_STATS(LOAD_ATTR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR));
|
||||
JUMP_TO_PREDICTED(LOAD_ATTR);
|
||||
}
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
assert(descr != NULL);
|
||||
attr = PyStackRef_FromPyObjectNew(descr);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue