summaryrefslogtreecommitdiffstats
path: root/Python/executor_cases.c.h
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2023-10-04 15:08:02 (GMT)
committerGitHub <noreply@github.com>2023-10-04 15:08:02 (GMT)
commit7c149a76b2bf4c66bb7c8650ffb71acce12f5ea2 (patch)
tree2dde159c7c323f1ce5e4535f3ca011992541d73d /Python/executor_cases.c.h
parentd8c00d2a607242932359b995e4637c222fcb2284 (diff)
downloadcpython-7c149a76b2bf4c66bb7c8650ffb71acce12f5ea2.zip
cpython-7c149a76b2bf4c66bb7c8650ffb71acce12f5ea2.tar.gz
cpython-7c149a76b2bf4c66bb7c8650ffb71acce12f5ea2.tar.bz2
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
Diffstat (limited to 'Python/executor_cases.c.h')
-rw-r--r--Python/executor_cases.c.h161
1 files changed, 161 insertions, 0 deletions
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index bbdc508..b3ccf8d 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -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;