mirror of
https://github.com/python/cpython.git
synced 2025-08-22 09:45:06 +00:00
gh-87729: specialize LOAD_SUPER_ATTR_METHOD (#103809)
This commit is contained in:
parent
cef542ca57
commit
ef25febcf2
14 changed files with 539 additions and 357 deletions
|
@ -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 */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue