diff options
author | Carl Meyer <carl@oddbird.net> | 2023-05-11 14:08:13 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-11 14:08:13 (GMT) |
commit | 77262458fe3fe9f3f0266bbf578675a906b1e353 (patch) | |
tree | b066d678cfdba47c64e82ed49ecb73a1d1d8a701 /Python/bytecodes.c | |
parent | ddc0e70a326180d90a45dfd8abeded9c9f911217 (diff) | |
download | cpython-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.c | 40 |
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) = { |