@@ -965,6 +965,64 @@ analyze_descriptor(PyTypeObject *type, PyObject *name, PyObject **descr, unsigne
965965 return classify_descriptor (descriptor , has_getattr );
966966}
967967
968+ static int
969+ specialize_inline_values_access (
970+ PyObject * owner , _Py_CODEUNIT * instr , PyTypeObject * type ,
971+ PyObject * name , int base_op , int values_op )
972+ {
973+ PyDictKeysObject * keys = ((PyHeapTypeObject * )type )-> ht_cached_keys ;
974+ _PyAttrCache * cache = (_PyAttrCache * )(instr + 1 );
975+ assert (PyUnicode_CheckExact (name ));
976+ Py_ssize_t index = _PyDictKeys_StringLookup (keys , name );
977+ assert (index != DKIX_ERROR );
978+ if (index == DKIX_EMPTY ) {
979+ SPECIALIZATION_FAIL (base_op , SPEC_FAIL_ATTR_NOT_IN_KEYS );
980+ return 0 ;
981+ }
982+ assert (index >= 0 );
983+ char * value_addr = (char * )& _PyObject_InlineValues (owner )-> values [index ];
984+ Py_ssize_t offset = value_addr - (char * )owner ;
985+ if (offset != (uint16_t )offset ) {
986+ SPECIALIZATION_FAIL (base_op , SPEC_FAIL_OUT_OF_RANGE );
987+ return 0 ;
988+ }
989+ write_u32 (cache -> version , type -> tp_version_tag );
990+ cache -> index = (uint16_t )offset ;
991+ specialize (instr , values_op );
992+ return 1 ;
993+ }
994+
995+ static int
996+ specialize_managed_dict_access (
997+ PyObject * owner , _Py_CODEUNIT * instr , PyTypeObject * type ,
998+ PyObject * name , int base_op , int hint_op )
999+ {
1000+ PyDictObject * dict = _PyObject_GetManagedDict (owner );
1001+ _PyAttrCache * cache = (_PyAttrCache * )(instr + 1 );
1002+ if (dict == NULL || !PyDict_CheckExact (dict )) {
1003+ SPECIALIZATION_FAIL (base_op , SPEC_FAIL_NO_DICT );
1004+ return 0 ;
1005+ }
1006+ // We found an instance with a __dict__.
1007+ if (dict -> ma_values ) {
1008+ SPECIALIZATION_FAIL (base_op , SPEC_FAIL_ATTR_SPLIT_DICT );
1009+ return 0 ;
1010+ }
1011+ Py_ssize_t index =
1012+ _PyDict_LookupIndex (dict , name );
1013+ if (index != (uint16_t )index ) {
1014+ SPECIALIZATION_FAIL (base_op ,
1015+ index == DKIX_EMPTY ?
1016+ SPEC_FAIL_ATTR_NOT_IN_DICT :
1017+ SPEC_FAIL_OUT_OF_RANGE );
1018+ return 0 ;
1019+ }
1020+ cache -> index = (uint16_t )index ;
1021+ write_u32 (cache -> version , type -> tp_version_tag );
1022+ specialize (instr , hint_op );
1023+ return 1 ;
1024+ }
1025+
9681026static int
9691027specialize_dict_access (
9701028 PyObject * owner , _Py_CODEUNIT * instr , PyTypeObject * type ,
@@ -979,55 +1037,17 @@ specialize_dict_access(
9791037 SPECIALIZATION_FAIL (base_op , SPEC_FAIL_ATTR_NOT_MANAGED_DICT );
9801038 return 0 ;
9811039 }
982- _PyAttrCache * cache = (_PyAttrCache * )(instr + 1 );
9831040 if (type -> tp_flags & Py_TPFLAGS_INLINE_VALUES &&
9841041 _PyObject_InlineValues (owner )-> valid &&
9851042 !(base_op == STORE_ATTR && _PyObject_GetManagedDict (owner ) != NULL ))
9861043 {
987- PyDictKeysObject * keys = ((PyHeapTypeObject * )type )-> ht_cached_keys ;
988- assert (PyUnicode_CheckExact (name ));
989- Py_ssize_t index = _PyDictKeys_StringLookup (keys , name );
990- assert (index != DKIX_ERROR );
991- if (index == DKIX_EMPTY ) {
992- SPECIALIZATION_FAIL (base_op , SPEC_FAIL_ATTR_NOT_IN_KEYS );
993- return 0 ;
994- }
995- assert (index >= 0 );
996- char * value_addr = (char * )& _PyObject_InlineValues (owner )-> values [index ];
997- Py_ssize_t offset = value_addr - (char * )owner ;
998- if (offset != (uint16_t )offset ) {
999- SPECIALIZATION_FAIL (base_op , SPEC_FAIL_OUT_OF_RANGE );
1000- return 0 ;
1001- }
1002- write_u32 (cache -> version , type -> tp_version_tag );
1003- cache -> index = (uint16_t )offset ;
1004- specialize (instr , values_op );
1044+ return specialize_inline_values_access (
1045+ owner , instr , type , name , base_op , values_op );
10051046 }
10061047 else {
1007- PyDictObject * dict = _PyObject_GetManagedDict (owner );
1008- if (dict == NULL || !PyDict_CheckExact (dict )) {
1009- SPECIALIZATION_FAIL (base_op , SPEC_FAIL_NO_DICT );
1010- return 0 ;
1011- }
1012- // We found an instance with a __dict__.
1013- if (dict -> ma_values ) {
1014- SPECIALIZATION_FAIL (base_op , SPEC_FAIL_ATTR_SPLIT_DICT );
1015- return 0 ;
1016- }
1017- Py_ssize_t index =
1018- _PyDict_LookupIndex (dict , name );
1019- if (index != (uint16_t )index ) {
1020- SPECIALIZATION_FAIL (base_op ,
1021- index == DKIX_EMPTY ?
1022- SPEC_FAIL_ATTR_NOT_IN_DICT :
1023- SPEC_FAIL_OUT_OF_RANGE );
1024- return 0 ;
1025- }
1026- cache -> index = (uint16_t )index ;
1027- write_u32 (cache -> version , type -> tp_version_tag );
1028- specialize (instr , hint_op );
1048+ return specialize_managed_dict_access (
1049+ owner , instr , type , name , base_op , hint_op );
10291050 }
1030- return 1 ;
10311051}
10321052
10331053static int
0 commit comments