gh-87729: specialize LOAD_SUPER_ATTR_METHOD (#103809)

This commit is contained in:
Carl Meyer 2023-04-25 11:45:51 -06:00 committed by GitHub
parent cef542ca57
commit ef25febcf2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 539 additions and 357 deletions

View file

@ -1554,34 +1554,47 @@ dummy_func(
PREDICT(JUMP_BACKWARD);
}
inst(LOAD_SUPER_ATTR, (global_super, class, self -- res2 if (oparg & 1), res)) {
family(load_super_attr, INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR) = {
LOAD_SUPER_ATTR,
LOAD_SUPER_ATTR_METHOD,
};
inst(LOAD_SUPER_ATTR, (unused/9, global_super, class, self -- res2 if (oparg & 1), res)) {
PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 2);
if (global_super == (PyObject *)&PySuper_Type && PyType_Check(class)) {
int method = 0;
Py_DECREF(global_super);
res = _PySuper_Lookup((PyTypeObject *)class, self, name, oparg & 1 ? &method : NULL);
Py_DECREF(class);
if (res == NULL) {
Py_DECREF(self);
ERROR_IF(true, error);
}
// Works with CALL, pushes two values: either `meth | self` or `NULL | meth`.
if (method) {
res2 = res;
res = self; // transfer ownership
} else {
res2 = NULL;
Py_DECREF(self);
}
} else {
PyObject *stack[] = {class, self};
PyObject *super = PyObject_Vectorcall(global_super, stack, oparg & 2, NULL);
DECREF_INPUTS();
ERROR_IF(super == NULL, error);
res = PyObject_GetAttr(super, name);
Py_DECREF(super);
ERROR_IF(res == NULL, error);
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);
DISPATCH_SAME_OPARG();
}
STAT_INC(LOAD_SUPER_ATTR, deferred);
DECREMENT_ADAPTIVE_COUNTER(cache->counter);
#endif /* ENABLE_SPECIALIZATION */
// we make no attempt to optimize here; specializations should
// handle any case whose performance we care about
PyObject *stack[] = {class, self};
PyObject *super = PyObject_Vectorcall(global_super, stack, oparg & 2, NULL);
DECREF_INPUTS();
ERROR_IF(super == NULL, error);
res = PyObject_GetAttr(super, name);
Py_DECREF(super);
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)) {
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);
Py_DECREF(global_super);
Py_DECREF(class);
}
family(load_attr, INLINE_CACHE_ENTRIES_LOAD_ATTR) = {