gh-100288: Specialise LOAD_ATTR_METHOD for managed dictionaries (GH-1… · python/cpython@c3c7848 (original) (raw)
`@@ -335,7 +335,6 @@ _PyCode_Quicken(PyCodeObject *code)
`
335
335
`#define SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD 22
`
336
336
`#define SPEC_FAIL_ATTR_CLASS_METHOD_OBJ 23
`
337
337
`#define SPEC_FAIL_ATTR_OBJECT_SLOT 24
`
338
``
`-
#define SPEC_FAIL_ATTR_HAS_MANAGED_DICT 25
`
339
338
`#define SPEC_FAIL_ATTR_INSTANCE_ATTRIBUTE 26
`
340
339
`#define SPEC_FAIL_ATTR_METACLASS_ATTRIBUTE 27
`
341
340
`#define SPEC_FAIL_ATTR_PROPERTY_NOT_PY_FUNCTION 28
`
`@@ -1036,11 +1035,14 @@ PyObject *descr, DescriptorClassification kind)
`
1036
1035
`PyDictKeysObject *keys;
`
1037
1036
`if (owner_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT) {
`
1038
1037
`PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
`
1039
``
`-
keys = ((PyHeapTypeObject *)owner_cls)->ht_cached_keys;
`
1040
1038
`if (_PyDictOrValues_IsValues(dorv)) {
`
``
1039
`+
keys = ((PyHeapTypeObject *)owner_cls)->ht_cached_keys;
`
1041
1040
`dictkind = MANAGED_VALUES;
`
1042
1041
` }
`
1043
1042
`else {
`
``
1043
`+
PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
`
``
1044
`+
keys = dict != NULL ? dict->ma_keys : NULL;
`
``
1045
`+
// User has directly accessed dict.
`
1044
1046
`dictkind = MANAGED_DICT;
`
1045
1047
` }
`
1046
1048
` }
`
`@@ -1067,7 +1069,7 @@ PyObject *descr, DescriptorClassification kind)
`
1067
1069
` }
`
1068
1070
` }
`
1069
1071
` }
`
1070
``
`-
if (dictkind == MANAGED_VALUES || dictkind == OFFSET_DICT) {
`
``
1072
`+
if (dictkind == MANAGED_VALUES || dictkind == OFFSET_DICT || (dictkind == MANAGED_DICT && keys != NULL)) {
`
1071
1073
`Py_ssize_t index = _PyDictKeys_StringLookup(keys, name);
`
1072
1074
`if (index != DKIX_EMPTY) {
`
1073
1075
`SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_SHADOWED);
`
`@@ -1088,8 +1090,11 @@ PyObject *descr, DescriptorClassification kind)
`
1088
1090
`_py_set_opcode(instr, LOAD_ATTR_METHOD_WITH_VALUES);
`
1089
1091
`break;
`
1090
1092
`case MANAGED_DICT:
`
1091
``
`-
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_HAS_MANAGED_DICT);
`
1092
``
`-
goto fail;
`
``
1093
`+
if (keys == NULL) {
`
``
1094
`+
write_u32(cache->keys_version, 0);
`
``
1095
`+
}
`
``
1096
`+
_py_set_opcode(instr, LOAD_ATTR_METHOD_MANAGED_DICT);
`
``
1097
`+
break;
`
1093
1098
`case OFFSET_DICT:
`
1094
1099
`assert(owner_cls->tp_dictoffset > 0 && owner_cls->tp_dictoffset <= INT16_MAX);
`
1095
1100
`_py_set_opcode(instr, LOAD_ATTR_METHOD_WITH_DICT);
`