diff options
author | Mark Shannon <mark@hotpy.org> | 2023-07-10 10:40:35 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-10 10:40:35 (GMT) |
commit | 0c90e7561046a2deb358e6695148060a1c199b49 (patch) | |
tree | 981359878b814a308c6fe977dd0c552e99bdd653 /Python/bytecodes.c | |
parent | 34c14147a2c52930b8b471905074509639e82d5b (diff) | |
download | cpython-0c90e7561046a2deb358e6695148060a1c199b49.zip cpython-0c90e7561046a2deb358e6695148060a1c199b49.tar.gz cpython-0c90e7561046a2deb358e6695148060a1c199b49.tar.bz2 |
GH-100288: Specialize LOAD_ATTR for simple class attributes. (#105990)
* Add two more specializations of LOAD_ATTR.
Diffstat (limited to 'Python/bytecodes.c')
-rw-r--r-- | Python/bytecodes.c | 43 |
1 files changed, 37 insertions, 6 deletions
diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 89b077a..0848bbf 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1809,6 +1809,8 @@ dummy_func( LOAD_ATTR_METHOD_WITH_VALUES, LOAD_ATTR_METHOD_NO_DICT, LOAD_ATTR_METHOD_LAZY_DICT, + LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, + LOAD_ATTR_NONDESCRIPTOR_NO_DICT, }; inst(LOAD_ATTR, (unused/9, owner -- res2 if (oparg & 1), res)) { @@ -2657,7 +2659,8 @@ dummy_func( exc_info->exc_value = Py_NewRef(new_exc); } - inst(LOAD_ATTR_METHOD_WITH_VALUES, (unused/1, type_version/2, keys_version/2, descr/4, self -- res2 if (oparg & 1), res)) { + inst(LOAD_ATTR_METHOD_WITH_VALUES, (unused/1, type_version/2, keys_version/2, descr/4, self -- res2 if (1), res)) { + assert(oparg & 1); /* Cached method object */ PyTypeObject *self_cls = Py_TYPE(self); assert(type_version != 0); @@ -2673,10 +2676,10 @@ dummy_func( res2 = Py_NewRef(descr); assert(_PyType_HasFeature(Py_TYPE(res2), Py_TPFLAGS_METHOD_DESCRIPTOR)); res = self; - assert(oparg & 1); } - inst(LOAD_ATTR_METHOD_NO_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (oparg & 1), res)) { + inst(LOAD_ATTR_METHOD_NO_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (1), res)) { + assert(oparg & 1); PyTypeObject *self_cls = Py_TYPE(self); DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); assert(self_cls->tp_dictoffset == 0); @@ -2685,10 +2688,39 @@ dummy_func( assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); res2 = Py_NewRef(descr); res = self; - assert(oparg & 1); } - inst(LOAD_ATTR_METHOD_LAZY_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (oparg & 1), res)) { + inst(LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, (unused/1, type_version/2, keys_version/2, descr/4, self -- res2 if (0), res)) { + assert((oparg & 1) == 0); + PyTypeObject *self_cls = Py_TYPE(self); + assert(type_version != 0); + DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); + assert(self_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT); + PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(self); + DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR); + PyHeapTypeObject *self_heap_type = (PyHeapTypeObject *)self_cls; + DEOPT_IF(self_heap_type->ht_cached_keys->dk_version != + keys_version, LOAD_ATTR); + STAT_INC(LOAD_ATTR, hit); + assert(descr != NULL); + DECREF_INPUTS(); + res = Py_NewRef(descr); + } + + inst(LOAD_ATTR_NONDESCRIPTOR_NO_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (0), res)) { + assert((oparg & 1) == 0); + PyTypeObject *self_cls = Py_TYPE(self); + assert(type_version != 0); + DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); + assert(self_cls->tp_dictoffset == 0); + STAT_INC(LOAD_ATTR, hit); + assert(descr != NULL); + DECREF_INPUTS(); + res = Py_NewRef(descr); + } + + inst(LOAD_ATTR_METHOD_LAZY_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (1), res)) { + assert(oparg & 1); PyTypeObject *self_cls = Py_TYPE(self); DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); Py_ssize_t dictoffset = self_cls->tp_dictoffset; @@ -2701,7 +2733,6 @@ dummy_func( assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); res2 = Py_NewRef(descr); res = self; - assert(oparg & 1); } inst(KW_NAMES, (--)) { |