Skip to content

Commit

Permalink
GH-100288: Specialize LOAD_ATTR for simple class attributes. (#105990)
Browse files Browse the repository at this point in the history
* Add two more specializations of LOAD_ATTR.
  • Loading branch information
markshannon authored Jul 10, 2023
1 parent 34c1414 commit 0c90e75
Show file tree
Hide file tree
Showing 10 changed files with 405 additions and 290 deletions.
40 changes: 20 additions & 20 deletions Include/internal/pycore_opcode.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

52 changes: 27 additions & 25 deletions Include/opcode.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Lib/_opcode_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@
"LOAD_ATTR_METHOD_WITH_VALUES",
"LOAD_ATTR_METHOD_NO_DICT",
"LOAD_ATTR_METHOD_LAZY_DICT",
"LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES",
"LOAD_ATTR_NONDESCRIPTOR_NO_DICT",
],
"COMPARE_OP": [
"COMPARE_OP_FLOAT",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Specialize :opcode:`LOAD_ATTR` for non-descriptors on the class. Adds
:opcode:`LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES` and :opcode
`LOAD_ATTR_NONDESCRIPTOR_NO_DICT`.
43 changes: 37 additions & 6 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1809,6 +1809,8 @@ dummy_func(
LOAD_ATTR_METHOD_WITH_VALUES,
LOAD_ATTR_METHOD_NO_DICT,
LOAD_ATTR_METHOD_LAZY_DICT,
LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES,
LOAD_ATTR_NONDESCRIPTOR_NO_DICT,
};

inst(LOAD_ATTR, (unused/9, owner -- res2 if (oparg & 1), res)) {
Expand Down Expand Up @@ -2657,7 +2659,8 @@ dummy_func(
exc_info->exc_value = Py_NewRef(new_exc);
}

inst(LOAD_ATTR_METHOD_WITH_VALUES, (unused/1, type_version/2, keys_version/2, descr/4, self -- res2 if (oparg & 1), res)) {
inst(LOAD_ATTR_METHOD_WITH_VALUES, (unused/1, type_version/2, keys_version/2, descr/4, self -- res2 if (1), res)) {
assert(oparg & 1);
/* Cached method object */
PyTypeObject *self_cls = Py_TYPE(self);
assert(type_version != 0);
Expand All @@ -2673,10 +2676,10 @@ dummy_func(
res2 = Py_NewRef(descr);
assert(_PyType_HasFeature(Py_TYPE(res2), Py_TPFLAGS_METHOD_DESCRIPTOR));
res = self;
assert(oparg & 1);
}

inst(LOAD_ATTR_METHOD_NO_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (oparg & 1), res)) {
inst(LOAD_ATTR_METHOD_NO_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (1), res)) {
assert(oparg & 1);
PyTypeObject *self_cls = Py_TYPE(self);
DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);
assert(self_cls->tp_dictoffset == 0);
Expand All @@ -2685,10 +2688,39 @@ dummy_func(
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
res2 = Py_NewRef(descr);
res = self;
assert(oparg & 1);
}

inst(LOAD_ATTR_METHOD_LAZY_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (oparg & 1), res)) {
inst(LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, (unused/1, type_version/2, keys_version/2, descr/4, self -- res2 if (0), res)) {
assert((oparg & 1) == 0);
PyTypeObject *self_cls = Py_TYPE(self);
assert(type_version != 0);
DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);
assert(self_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT);
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(self);
DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR);
PyHeapTypeObject *self_heap_type = (PyHeapTypeObject *)self_cls;
DEOPT_IF(self_heap_type->ht_cached_keys->dk_version !=
keys_version, LOAD_ATTR);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
DECREF_INPUTS();
res = Py_NewRef(descr);
}

inst(LOAD_ATTR_NONDESCRIPTOR_NO_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (0), res)) {
assert((oparg & 1) == 0);
PyTypeObject *self_cls = Py_TYPE(self);
assert(type_version != 0);
DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);
assert(self_cls->tp_dictoffset == 0);
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
DECREF_INPUTS();
res = Py_NewRef(descr);
}

inst(LOAD_ATTR_METHOD_LAZY_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (1), res)) {
assert(oparg & 1);
PyTypeObject *self_cls = Py_TYPE(self);
DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);
Py_ssize_t dictoffset = self_cls->tp_dictoffset;
Expand All @@ -2701,7 +2733,6 @@ dummy_func(
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
res2 = Py_NewRef(descr);
res = self;
assert(oparg & 1);
}

inst(KW_NAMES, (--)) {
Expand Down
Loading

0 comments on commit 0c90e75

Please sign in to comment.