gh-104909: Split more LOAD_ATTR specializations (GH-110317)

* Split LOAD_ATTR_MODULE

* Split LOAD_ATTR_WITH_HINT

* Split _GUARD_TYPE_VERSION out of the latter

* Split LOAD_ATTR_CLASS

* Split LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES

* Fix indent of DEOPT_IF in macros

* Split LOAD_ATTR_METHOD_LAZY_DICT

* Split LOAD_ATTR_NONDESCRIPTOR_NO_DICT

* Fix omission of _CHECK_ATTR_METHOD_LAZY_DICT
This commit is contained in:
Guido van Rossum 2023-10-04 08:08:02 -07:00 committed by GitHub
parent d8c00d2a60
commit 7c149a76b2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 598 additions and 219 deletions

View file

@ -1711,6 +1711,82 @@
break;
}
case _CHECK_ATTR_MODULE: {
PyObject *owner;
owner = stack_pointer[-1];
uint32_t type_version = (uint32_t)operand;
DEOPT_IF(!PyModule_CheckExact(owner), _CHECK_ATTR_MODULE);
PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict;
assert(dict != NULL);
DEOPT_IF(dict->ma_keys->dk_version != type_version, _CHECK_ATTR_MODULE);
break;
}
case _LOAD_ATTR_MODULE: {
PyObject *owner;
PyObject *attr;
PyObject *null = NULL;
owner = stack_pointer[-1];
uint16_t index = (uint16_t)operand;
PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict;
assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE);
assert(index < dict->ma_keys->dk_nentries);
PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + index;
attr = ep->me_value;
DEOPT_IF(attr == NULL, _LOAD_ATTR_MODULE);
STAT_INC(LOAD_ATTR, hit);
Py_INCREF(attr);
null = NULL;
Py_DECREF(owner);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = attr;
if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; }
break;
}
case _CHECK_ATTR_WITH_HINT: {
PyObject *owner;
owner = stack_pointer[-1];
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
DEOPT_IF(_PyDictOrValues_IsValues(dorv), _CHECK_ATTR_WITH_HINT);
PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
DEOPT_IF(dict == NULL, _CHECK_ATTR_WITH_HINT);
assert(PyDict_CheckExact((PyObject *)dict));
break;
}
case _LOAD_ATTR_WITH_HINT: {
PyObject *owner;
PyObject *attr;
PyObject *null = NULL;
owner = stack_pointer[-1];
uint16_t hint = (uint16_t)operand;
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, _LOAD_ATTR_WITH_HINT);
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
if (DK_IS_UNICODE(dict->ma_keys)) {
PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint;
DEOPT_IF(ep->me_key != name, _LOAD_ATTR_WITH_HINT);
attr = ep->me_value;
}
else {
PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + hint;
DEOPT_IF(ep->me_key != name, _LOAD_ATTR_WITH_HINT);
attr = ep->me_value;
}
DEOPT_IF(attr == NULL, _LOAD_ATTR_WITH_HINT);
STAT_INC(LOAD_ATTR, hit);
Py_INCREF(attr);
null = NULL;
Py_DECREF(owner);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = attr;
if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; }
break;
}
case _LOAD_ATTR_SLOT: {
PyObject *owner;
PyObject *attr;
@ -1730,6 +1806,33 @@
break;
}
case _CHECK_ATTR_CLASS: {
PyObject *owner;
owner = stack_pointer[-1];
uint32_t type_version = (uint32_t)operand;
DEOPT_IF(!PyType_Check(owner), _CHECK_ATTR_CLASS);
assert(type_version != 0);
DEOPT_IF(((PyTypeObject *)owner)->tp_version_tag != type_version, _CHECK_ATTR_CLASS);
break;
}
case _LOAD_ATTR_CLASS: {
PyObject *owner;
PyObject *attr;
PyObject *null = NULL;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)operand;
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
attr = Py_NewRef(descr);
null = NULL;
Py_DECREF(owner);
STACK_GROW(((oparg & 1) ? 1 : 0));
stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = attr;
if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; }
break;
}
case _GUARD_DORV_VALUES: {
PyObject *owner;
owner = stack_pointer[-1];
@ -2339,6 +2442,64 @@
break;
}
case _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES: {
PyObject *owner;
PyObject *attr;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)operand;
assert((oparg & 1) == 0);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
Py_DECREF(owner);
attr = Py_NewRef(descr);
stack_pointer[-1] = attr;
break;
}
case _LOAD_ATTR_NONDESCRIPTOR_NO_DICT: {
PyObject *owner;
PyObject *attr;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)operand;
assert((oparg & 1) == 0);
assert(Py_TYPE(owner)->tp_dictoffset == 0);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
Py_DECREF(owner);
attr = Py_NewRef(descr);
stack_pointer[-1] = attr;
break;
}
case _CHECK_ATTR_METHOD_LAZY_DICT: {
PyObject *owner;
owner = stack_pointer[-1];
Py_ssize_t dictoffset = Py_TYPE(owner)->tp_dictoffset;
assert(dictoffset > 0);
PyObject *dict = *(PyObject **)((char *)owner + dictoffset);
/* This object has a __dict__, just not yet created */
DEOPT_IF(dict != NULL, _CHECK_ATTR_METHOD_LAZY_DICT);
break;
}
case _LOAD_ATTR_METHOD_LAZY_DICT: {
PyObject *owner;
PyObject *attr;
PyObject *self;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)operand;
assert(oparg & 1);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
attr = Py_NewRef(descr);
self = owner;
STACK_GROW(1);
stack_pointer[-2] = attr;
stack_pointer[-1] = self;
break;
}
case _CHECK_CALL_BOUND_METHOD_EXACT_ARGS: {
PyObject *null;
PyObject *callable;