summaryrefslogtreecommitdiffstats
path: root/Python/bytecodes.c
diff options
context:
space:
mode:
authorCarl Meyer <carl@oddbird.net>2023-05-11 14:08:13 (GMT)
committerGitHub <noreply@github.com>2023-05-11 14:08:13 (GMT)
commit77262458fe3fe9f3f0266bbf578675a906b1e353 (patch)
treeb066d678cfdba47c64e82ed49ecb73a1d1d8a701 /Python/bytecodes.c
parentddc0e70a326180d90a45dfd8abeded9c9f911217 (diff)
downloadcpython-77262458fe3fe9f3f0266bbf578675a906b1e353.zip
cpython-77262458fe3fe9f3f0266bbf578675a906b1e353.tar.gz
cpython-77262458fe3fe9f3f0266bbf578675a906b1e353.tar.bz2
gh-87729: improve hit rate of LOAD_SUPER_ATTR specialization (#104270)
Diffstat (limited to 'Python/bytecodes.c')
-rw-r--r--Python/bytecodes.c40
1 files changed, 31 insertions, 9 deletions
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 1c09dc6..118a0b5 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -1562,17 +1562,18 @@ dummy_func(
family(load_super_attr, INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR) = {
LOAD_SUPER_ATTR,
+ LOAD_SUPER_ATTR_ATTR,
LOAD_SUPER_ATTR_METHOD,
};
- inst(LOAD_SUPER_ATTR, (unused/9, global_super, class, self -- res2 if (oparg & 1), res)) {
+ inst(LOAD_SUPER_ATTR, (unused/1, global_super, class, self -- res2 if (oparg & 1), res)) {
PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 2);
int load_method = oparg & 1;
#if ENABLE_SPECIALIZATION
_PySuperAttrCache *cache = (_PySuperAttrCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
next_instr--;
- _Py_Specialize_LoadSuperAttr(global_super, class, self, next_instr, name, load_method);
+ _Py_Specialize_LoadSuperAttr(global_super, class, next_instr, load_method);
DISPATCH_SAME_OPARG();
}
STAT_INC(LOAD_SUPER_ATTR, deferred);
@@ -1590,17 +1591,38 @@ dummy_func(
ERROR_IF(res == NULL, error);
}
- inst(LOAD_SUPER_ATTR_METHOD, (unused/1, class_version/2, self_type_version/2, method/4, global_super, class, self -- res2, res)) {
+ inst(LOAD_SUPER_ATTR_ATTR, (unused/1, global_super, class, self -- res2 if (oparg & 1), res)) {
+ assert(!(oparg & 1));
DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR);
DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR);
- DEOPT_IF(((PyTypeObject *)class)->tp_version_tag != class_version, LOAD_SUPER_ATTR);
- PyTypeObject *self_type = Py_TYPE(self);
- DEOPT_IF(self_type->tp_version_tag != self_type_version, LOAD_SUPER_ATTR);
- res2 = method;
- res = self; // transfer ownership
- Py_INCREF(res2);
+ STAT_INC(LOAD_SUPER_ATTR, hit);
+ PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 2);
+ res = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL);
+ ERROR_IF(res == NULL, error);
+ DECREF_INPUTS();
+ }
+
+ inst(LOAD_SUPER_ATTR_METHOD, (unused/1, global_super, class, self -- res2, res)) {
+ assert(oparg & 1);
+ DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR);
+ DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR);
+ STAT_INC(LOAD_SUPER_ATTR, hit);
+ PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 2);
+ int method_found = 0;
+ res2 = _PySuper_Lookup((PyTypeObject *)class, self, name, &method_found);
Py_DECREF(global_super);
Py_DECREF(class);
+ if (res2 == NULL) {
+ Py_DECREF(self);
+ ERROR_IF(true, error);
+ }
+ if (method_found) {
+ res = self; // transfer ownership
+ } else {
+ Py_DECREF(self);
+ res = res2;
+ res2 = NULL;
+ }
}
family(load_attr, INLINE_CACHE_ENTRIES_LOAD_ATTR) = {