mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
gh-98831: Modernize the LOAD_ATTR family (#101488)
This commit is contained in:
parent
95fb0e0258
commit
7840ff3cdb
3 changed files with 205 additions and 230 deletions
198
Python/generated_cases.c.h
generated
198
Python/generated_cases.c.h
generated
|
@ -596,6 +596,7 @@
|
|||
|
||||
TARGET(STORE_SUBSCR) {
|
||||
PREDICTED(STORE_SUBSCR);
|
||||
static_assert(INLINE_CACHE_ENTRIES_STORE_SUBSCR == 1, "incorrect cache size");
|
||||
PyObject *sub = PEEK(1);
|
||||
PyObject *container = PEEK(2);
|
||||
PyObject *v = PEEK(3);
|
||||
|
@ -1180,6 +1181,7 @@
|
|||
|
||||
TARGET(STORE_ATTR) {
|
||||
PREDICTED(STORE_ATTR);
|
||||
static_assert(INLINE_CACHE_ENTRIES_STORE_ATTR == 4, "incorrect cache size");
|
||||
PyObject *owner = PEEK(1);
|
||||
PyObject *v = PEEK(2);
|
||||
uint16_t counter = read_u16(&next_instr[0].cache);
|
||||
|
@ -1748,6 +1750,7 @@
|
|||
|
||||
TARGET(LOAD_ATTR) {
|
||||
PREDICTED(LOAD_ATTR);
|
||||
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
|
||||
PyObject *owner = PEEK(1);
|
||||
PyObject *res2 = NULL;
|
||||
PyObject *res;
|
||||
|
@ -1805,62 +1808,67 @@
|
|||
}
|
||||
|
||||
TARGET(LOAD_ATTR_INSTANCE_VALUE) {
|
||||
assert(cframe.use_tracing == 0);
|
||||
PyObject *owner = TOP();
|
||||
PyObject *owner = PEEK(1);
|
||||
PyObject *res2 = NULL;
|
||||
PyObject *res;
|
||||
uint32_t type_version = read_u32(&next_instr[1].cache);
|
||||
uint16_t index = read_u16(&next_instr[3].cache);
|
||||
assert(cframe.use_tracing == 0);
|
||||
PyTypeObject *tp = Py_TYPE(owner);
|
||||
_PyAttrCache *cache = (_PyAttrCache *)next_instr;
|
||||
uint32_t type_version = read_u32(cache->version);
|
||||
assert(type_version != 0);
|
||||
DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
|
||||
assert(tp->tp_dictoffset < 0);
|
||||
assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR);
|
||||
res = _PyDictOrValues_GetValues(dorv)->values[cache->index];
|
||||
res = _PyDictOrValues_GetValues(dorv)->values[index];
|
||||
DEOPT_IF(res == NULL, LOAD_ATTR);
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
Py_INCREF(res);
|
||||
SET_TOP(NULL);
|
||||
STACK_GROW((oparg & 1));
|
||||
SET_TOP(res);
|
||||
res2 = NULL;
|
||||
Py_DECREF(owner);
|
||||
JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);
|
||||
STACK_GROW(((oparg & 1) ? 1 : 0));
|
||||
POKE(1, res);
|
||||
if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); }
|
||||
JUMPBY(9);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(LOAD_ATTR_MODULE) {
|
||||
assert(cframe.use_tracing == 0);
|
||||
PyObject *owner = TOP();
|
||||
PyObject *owner = PEEK(1);
|
||||
PyObject *res2 = NULL;
|
||||
PyObject *res;
|
||||
_PyAttrCache *cache = (_PyAttrCache *)next_instr;
|
||||
uint32_t type_version = read_u32(&next_instr[1].cache);
|
||||
uint16_t index = read_u16(&next_instr[3].cache);
|
||||
assert(cframe.use_tracing == 0);
|
||||
DEOPT_IF(!PyModule_CheckExact(owner), LOAD_ATTR);
|
||||
PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict;
|
||||
assert(dict != NULL);
|
||||
DEOPT_IF(dict->ma_keys->dk_version != read_u32(cache->version),
|
||||
LOAD_ATTR);
|
||||
DEOPT_IF(dict->ma_keys->dk_version != type_version, LOAD_ATTR);
|
||||
assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE);
|
||||
assert(cache->index < dict->ma_keys->dk_nentries);
|
||||
PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + cache->index;
|
||||
assert(index < dict->ma_keys->dk_nentries);
|
||||
PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + index;
|
||||
res = ep->me_value;
|
||||
DEOPT_IF(res == NULL, LOAD_ATTR);
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
Py_INCREF(res);
|
||||
SET_TOP(NULL);
|
||||
STACK_GROW((oparg & 1));
|
||||
SET_TOP(res);
|
||||
res2 = NULL;
|
||||
Py_DECREF(owner);
|
||||
JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);
|
||||
STACK_GROW(((oparg & 1) ? 1 : 0));
|
||||
POKE(1, res);
|
||||
if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); }
|
||||
JUMPBY(9);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(LOAD_ATTR_WITH_HINT) {
|
||||
assert(cframe.use_tracing == 0);
|
||||
PyObject *owner = TOP();
|
||||
PyObject *owner = PEEK(1);
|
||||
PyObject *res2 = NULL;
|
||||
PyObject *res;
|
||||
uint32_t type_version = read_u32(&next_instr[1].cache);
|
||||
uint16_t index = read_u16(&next_instr[3].cache);
|
||||
assert(cframe.use_tracing == 0);
|
||||
PyTypeObject *tp = Py_TYPE(owner);
|
||||
_PyAttrCache *cache = (_PyAttrCache *)next_instr;
|
||||
uint32_t type_version = read_u32(cache->version);
|
||||
assert(type_version != 0);
|
||||
DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
|
||||
assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
|
@ -1870,7 +1878,7 @@
|
|||
DEOPT_IF(dict == NULL, LOAD_ATTR);
|
||||
assert(PyDict_CheckExact((PyObject *)dict));
|
||||
PyObject *name = GETITEM(names, oparg>>1);
|
||||
uint16_t hint = cache->index;
|
||||
uint16_t hint = index;
|
||||
DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, LOAD_ATTR);
|
||||
if (DK_IS_UNICODE(dict->ma_keys)) {
|
||||
PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint;
|
||||
|
@ -1885,73 +1893,78 @@
|
|||
DEOPT_IF(res == NULL, LOAD_ATTR);
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
Py_INCREF(res);
|
||||
SET_TOP(NULL);
|
||||
STACK_GROW((oparg & 1));
|
||||
SET_TOP(res);
|
||||
res2 = NULL;
|
||||
Py_DECREF(owner);
|
||||
JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);
|
||||
STACK_GROW(((oparg & 1) ? 1 : 0));
|
||||
POKE(1, res);
|
||||
if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); }
|
||||
JUMPBY(9);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(LOAD_ATTR_SLOT) {
|
||||
assert(cframe.use_tracing == 0);
|
||||
PyObject *owner = TOP();
|
||||
PyObject *owner = PEEK(1);
|
||||
PyObject *res2 = NULL;
|
||||
PyObject *res;
|
||||
uint32_t type_version = read_u32(&next_instr[1].cache);
|
||||
uint16_t index = read_u16(&next_instr[3].cache);
|
||||
assert(cframe.use_tracing == 0);
|
||||
PyTypeObject *tp = Py_TYPE(owner);
|
||||
_PyAttrCache *cache = (_PyAttrCache *)next_instr;
|
||||
uint32_t type_version = read_u32(cache->version);
|
||||
assert(type_version != 0);
|
||||
DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
|
||||
char *addr = (char *)owner + cache->index;
|
||||
char *addr = (char *)owner + index;
|
||||
res = *(PyObject **)addr;
|
||||
DEOPT_IF(res == NULL, LOAD_ATTR);
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
Py_INCREF(res);
|
||||
SET_TOP(NULL);
|
||||
STACK_GROW((oparg & 1));
|
||||
SET_TOP(res);
|
||||
res2 = NULL;
|
||||
Py_DECREF(owner);
|
||||
JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);
|
||||
STACK_GROW(((oparg & 1) ? 1 : 0));
|
||||
POKE(1, res);
|
||||
if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); }
|
||||
JUMPBY(9);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(LOAD_ATTR_CLASS) {
|
||||
PyObject *cls = PEEK(1);
|
||||
PyObject *res2 = NULL;
|
||||
PyObject *res;
|
||||
uint32_t type_version = read_u32(&next_instr[1].cache);
|
||||
PyObject *descr = read_obj(&next_instr[5].cache);
|
||||
assert(cframe.use_tracing == 0);
|
||||
_PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr;
|
||||
|
||||
PyObject *cls = TOP();
|
||||
DEOPT_IF(!PyType_Check(cls), LOAD_ATTR);
|
||||
uint32_t type_version = read_u32(cache->type_version);
|
||||
DEOPT_IF(((PyTypeObject *)cls)->tp_version_tag != type_version,
|
||||
LOAD_ATTR);
|
||||
assert(type_version != 0);
|
||||
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
PyObject *res = read_obj(cache->descr);
|
||||
res2 = NULL;
|
||||
res = descr;
|
||||
assert(res != NULL);
|
||||
Py_INCREF(res);
|
||||
SET_TOP(NULL);
|
||||
STACK_GROW((oparg & 1));
|
||||
SET_TOP(res);
|
||||
Py_DECREF(cls);
|
||||
JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);
|
||||
STACK_GROW(((oparg & 1) ? 1 : 0));
|
||||
POKE(1, res);
|
||||
if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); }
|
||||
JUMPBY(9);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(LOAD_ATTR_PROPERTY) {
|
||||
PyObject *owner = PEEK(1);
|
||||
uint32_t type_version = read_u32(&next_instr[1].cache);
|
||||
uint32_t func_version = read_u32(&next_instr[3].cache);
|
||||
PyObject *fget = read_obj(&next_instr[5].cache);
|
||||
assert(cframe.use_tracing == 0);
|
||||
DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR);
|
||||
_PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr;
|
||||
|
||||
PyObject *owner = TOP();
|
||||
PyTypeObject *cls = Py_TYPE(owner);
|
||||
uint32_t type_version = read_u32(cache->type_version);
|
||||
DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR);
|
||||
assert(type_version != 0);
|
||||
PyObject *fget = read_obj(cache->descr);
|
||||
assert(Py_IS_TYPE(fget, &PyFunction_Type));
|
||||
PyFunctionObject *f = (PyFunctionObject *)fget;
|
||||
uint32_t func_version = read_u32(cache->keys_version);
|
||||
assert(func_version != 0);
|
||||
DEOPT_IF(f->func_version != func_version, LOAD_ATTR);
|
||||
PyCodeObject *code = (PyCodeObject *)f->func_code;
|
||||
|
@ -1960,6 +1973,7 @@
|
|||
STAT_INC(LOAD_ATTR, hit);
|
||||
Py_INCREF(fget);
|
||||
_PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 1);
|
||||
// Manipulate stack directly because we exit with DISPATCH_INLINED().
|
||||
SET_TOP(NULL);
|
||||
int shrink_stack = !(oparg & 1);
|
||||
STACK_SHRINK(shrink_stack);
|
||||
|
@ -1969,18 +1983,17 @@
|
|||
}
|
||||
|
||||
TARGET(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN) {
|
||||
PyObject *owner = PEEK(1);
|
||||
uint32_t type_version = read_u32(&next_instr[1].cache);
|
||||
uint32_t func_version = read_u32(&next_instr[3].cache);
|
||||
PyObject *getattribute = read_obj(&next_instr[5].cache);
|
||||
assert(cframe.use_tracing == 0);
|
||||
DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR);
|
||||
_PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr;
|
||||
PyObject *owner = TOP();
|
||||
PyTypeObject *cls = Py_TYPE(owner);
|
||||
uint32_t type_version = read_u32(cache->type_version);
|
||||
DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR);
|
||||
assert(type_version != 0);
|
||||
PyObject *getattribute = read_obj(cache->descr);
|
||||
assert(Py_IS_TYPE(getattribute, &PyFunction_Type));
|
||||
PyFunctionObject *f = (PyFunctionObject *)getattribute;
|
||||
uint32_t func_version = read_u32(cache->keys_version);
|
||||
assert(func_version != 0);
|
||||
DEOPT_IF(f->func_version != func_version, LOAD_ATTR);
|
||||
PyCodeObject *code = (PyCodeObject *)f->func_code;
|
||||
|
@ -1991,6 +2004,7 @@
|
|||
PyObject *name = GETITEM(names, oparg >> 1);
|
||||
Py_INCREF(f);
|
||||
_PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 2);
|
||||
// Manipulate stack directly because we exit with DISPATCH_INLINED().
|
||||
SET_TOP(NULL);
|
||||
int shrink_stack = !(oparg & 1);
|
||||
STACK_SHRINK(shrink_stack);
|
||||
|
@ -2831,12 +2845,15 @@
|
|||
}
|
||||
|
||||
TARGET(LOAD_ATTR_METHOD_WITH_VALUES) {
|
||||
PyObject *self = PEEK(1);
|
||||
PyObject *res2 = NULL;
|
||||
PyObject *res;
|
||||
uint32_t type_version = read_u32(&next_instr[1].cache);
|
||||
uint32_t keys_version = read_u32(&next_instr[3].cache);
|
||||
PyObject *descr = read_obj(&next_instr[5].cache);
|
||||
/* Cached method object */
|
||||
assert(cframe.use_tracing == 0);
|
||||
PyObject *self = TOP();
|
||||
PyTypeObject *self_cls = Py_TYPE(self);
|
||||
_PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr;
|
||||
uint32_t type_version = read_u32(cache->type_version);
|
||||
assert(type_version != 0);
|
||||
DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);
|
||||
assert(self_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
|
@ -2844,41 +2861,51 @@
|
|||
DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR);
|
||||
PyHeapTypeObject *self_heap_type = (PyHeapTypeObject *)self_cls;
|
||||
DEOPT_IF(self_heap_type->ht_cached_keys->dk_version !=
|
||||
read_u32(cache->keys_version), LOAD_ATTR);
|
||||
keys_version, LOAD_ATTR);
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
PyObject *res = read_obj(cache->descr);
|
||||
assert(res != NULL);
|
||||
assert(_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR));
|
||||
SET_TOP(Py_NewRef(res));
|
||||
PUSH(self);
|
||||
JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);
|
||||
assert(descr != NULL);
|
||||
res2 = Py_NewRef(descr);
|
||||
assert(_PyType_HasFeature(Py_TYPE(res2), Py_TPFLAGS_METHOD_DESCRIPTOR));
|
||||
res = self;
|
||||
assert(oparg & 1);
|
||||
STACK_GROW(((oparg & 1) ? 1 : 0));
|
||||
POKE(1, res);
|
||||
if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); }
|
||||
JUMPBY(9);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(LOAD_ATTR_METHOD_NO_DICT) {
|
||||
PyObject *self = PEEK(1);
|
||||
PyObject *res2 = NULL;
|
||||
PyObject *res;
|
||||
uint32_t type_version = read_u32(&next_instr[1].cache);
|
||||
PyObject *descr = read_obj(&next_instr[5].cache);
|
||||
assert(cframe.use_tracing == 0);
|
||||
PyObject *self = TOP();
|
||||
PyTypeObject *self_cls = Py_TYPE(self);
|
||||
_PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr;
|
||||
uint32_t type_version = read_u32(cache->type_version);
|
||||
DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);
|
||||
assert(self_cls->tp_dictoffset == 0);
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
PyObject *res = read_obj(cache->descr);
|
||||
assert(res != NULL);
|
||||
assert(_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR));
|
||||
SET_TOP(Py_NewRef(res));
|
||||
PUSH(self);
|
||||
JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);
|
||||
assert(descr != NULL);
|
||||
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
|
||||
res2 = Py_NewRef(descr);
|
||||
res = self;
|
||||
assert(oparg & 1);
|
||||
STACK_GROW(((oparg & 1) ? 1 : 0));
|
||||
POKE(1, res);
|
||||
if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); }
|
||||
JUMPBY(9);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(LOAD_ATTR_METHOD_LAZY_DICT) {
|
||||
PyObject *self = PEEK(1);
|
||||
PyObject *res2 = NULL;
|
||||
PyObject *res;
|
||||
uint32_t type_version = read_u32(&next_instr[1].cache);
|
||||
PyObject *descr = read_obj(&next_instr[5].cache);
|
||||
assert(cframe.use_tracing == 0);
|
||||
PyObject *self = TOP();
|
||||
PyTypeObject *self_cls = Py_TYPE(self);
|
||||
_PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr;
|
||||
uint32_t type_version = read_u32(cache->type_version);
|
||||
DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);
|
||||
Py_ssize_t dictoffset = self_cls->tp_dictoffset;
|
||||
assert(dictoffset > 0);
|
||||
|
@ -2886,12 +2913,15 @@
|
|||
/* This object has a __dict__, just not yet created */
|
||||
DEOPT_IF(dict != NULL, LOAD_ATTR);
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
PyObject *res = read_obj(cache->descr);
|
||||
assert(res != NULL);
|
||||
assert(_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR));
|
||||
SET_TOP(Py_NewRef(res));
|
||||
PUSH(self);
|
||||
JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);
|
||||
assert(descr != NULL);
|
||||
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
|
||||
res2 = Py_NewRef(descr);
|
||||
res = self;
|
||||
assert(oparg & 1);
|
||||
STACK_GROW(((oparg & 1) ? 1 : 0));
|
||||
POKE(1, res);
|
||||
if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); }
|
||||
JUMPBY(9);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue