summaryrefslogtreecommitdiffstats
path: root/Python/bytecodes.c
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2023-07-10 10:40:35 (GMT)
committerGitHub <noreply@github.com>2023-07-10 10:40:35 (GMT)
commit0c90e7561046a2deb358e6695148060a1c199b49 (patch)
tree981359878b814a308c6fe977dd0c552e99bdd653 /Python/bytecodes.c
parent34c14147a2c52930b8b471905074509639e82d5b (diff)
downloadcpython-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.c43
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, (--)) {