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

@ -96,6 +96,7 @@ _Py_GetSpecializationStats(void) {
return NULL;
}
int err = 0;
err += add_stat_dict(stats, LOAD_SUPER_ATTR, "load_super_attr");
err += add_stat_dict(stats, LOAD_ATTR, "load_attr");
err += add_stat_dict(stats, LOAD_GLOBAL, "load_global");
err += add_stat_dict(stats, BINARY_SUBSCR, "binary_subscr");
@ -320,6 +321,14 @@ _PyCode_Quicken(PyCodeObject *code)
#define SPEC_FAIL_LOAD_GLOBAL_NON_DICT 17
#define SPEC_FAIL_LOAD_GLOBAL_NON_STRING_OR_SPLIT 18
/* Super */
#define SPEC_FAIL_SUPER_NOT_LOAD_METHOD 9
#define SPEC_FAIL_SUPER_BAD_CLASS 10
#define SPEC_FAIL_SUPER_SHADOWED 11
#define SPEC_FAIL_SUPER_NOT_METHOD 12
#define SPEC_FAIL_SUPER_ERROR_OR_NOT_FOUND 13
/* Attributes */
#define SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR 9
@ -505,6 +514,52 @@ specialize_module_load_attr(
/* Attribute specialization */
void
_Py_Specialize_LoadSuperAttr(PyObject *global_super, PyObject *class, PyObject *self,
_Py_CODEUNIT *instr, PyObject *name, int load_method) {
assert(ENABLE_SPECIALIZATION);
assert(_PyOpcode_Caches[LOAD_SUPER_ATTR] == INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR);
_PySuperAttrCache *cache = (_PySuperAttrCache *)(instr + 1);
if (!load_method) {
SPECIALIZATION_FAIL(LOAD_SUPER_ATTR, SPEC_FAIL_SUPER_NOT_LOAD_METHOD);
goto fail;
}
if (global_super != (PyObject *)&PySuper_Type) {
SPECIALIZATION_FAIL(LOAD_SUPER_ATTR, SPEC_FAIL_SUPER_SHADOWED);
goto fail;
}
if (!PyType_Check(class)) {
SPECIALIZATION_FAIL(LOAD_SUPER_ATTR, SPEC_FAIL_SUPER_BAD_CLASS);
goto fail;
}
PyTypeObject *tp = (PyTypeObject *)class;
PyObject *res = _PySuper_LookupDescr(tp, self, name);
if (res == NULL) {
SPECIALIZATION_FAIL(LOAD_SUPER_ATTR, SPEC_FAIL_SUPER_ERROR_OR_NOT_FOUND);
PyErr_Clear();
goto fail;
}
if (_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)) {
write_u32(cache->class_version, tp->tp_version_tag);
write_u32(cache->self_type_version, Py_TYPE(self)->tp_version_tag);
write_obj(cache->method, res); // borrowed
instr->op.code = LOAD_SUPER_ATTR_METHOD;
goto success;
}
SPECIALIZATION_FAIL(LOAD_SUPER_ATTR, SPEC_FAIL_SUPER_NOT_METHOD);
fail:
STAT_INC(LOAD_SUPER_ATTR, failure);
assert(!PyErr_Occurred());
instr->op.code = LOAD_SUPER_ATTR;
cache->counter = adaptive_counter_backoff(cache->counter);
return;
success:
STAT_INC(LOAD_SUPER_ATTR, success);
assert(!PyErr_Occurred());
cache->counter = adaptive_counter_cooldown();
}
typedef enum {
OVERRIDING, /* Is an overriding descriptor, and will remain so. */
METHOD, /* Attribute has Py_TPFLAGS_METHOD_DESCRIPTOR set */