GH-100288: Specialize LOAD_ATTR for simple class attributes. (#105990)

* Add two more specializations of LOAD_ATTR.
This commit is contained in:
Mark Shannon 2023-07-10 11:40:35 +01:00 committed by GitHub
parent 34c14147a2
commit 0c90e75610
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 405 additions and 290 deletions

View file

@ -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)) {
@ -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);
@ -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);
@ -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;
@ -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, (--)) {