gh-131798: constant fold special method lookups in JIT (#148432)

This commit is contained in:
Kumar Aditya 2026-04-14 21:32:23 +05:30 committed by GitHub
parent 11da7d4e21
commit 3cb7eaec85
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 71 additions and 6 deletions

View file

@ -3883,6 +3883,7 @@ dummy_func(
}
macro(LOAD_SPECIAL) =
_RECORD_TOS_TYPE +
_INSERT_NULL +
_LOAD_SPECIAL;

View file

@ -1845,8 +1845,30 @@ dummy_func(void) {
}
op(_LOAD_SPECIAL, (method_and_self[2] -- method_and_self[2])) {
method_and_self[0] = sym_new_not_null(ctx);
method_and_self[1] = sym_new_unknown(ctx);
bool optimized = false;
PyTypeObject *type = sym_get_probable_type(method_and_self[1]);
if (type != NULL) {
PyObject *name = _Py_SpecialMethods[oparg].name;
PyObject *descr = _PyType_Lookup(type, name);
if (descr != NULL && (Py_TYPE(descr)->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR)) {
ADD_OP(_GUARD_TYPE_VERSION, 0, type->tp_version_tag);
bool immortal = _Py_IsImmortal(descr) || (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE);
ADD_OP(immortal ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE,
0, (uintptr_t)descr);
ADD_OP(_SWAP, 3, 0);
ADD_OP(_POP_TOP, 0, 0);
if ((type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) {
PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type);
_Py_BloomFilter_Add(dependencies, type);
}
method_and_self[0] = sym_new_const(ctx, descr);
optimized = true;
}
}
if (!optimized) {
method_and_self[0] = sym_new_not_null(ctx);
method_and_self[1] = sym_new_unknown(ctx);
}
}
op(_JUMP_TO_TOP, (--)) {

View file

@ -3555,8 +3555,30 @@
case _LOAD_SPECIAL: {
JitOptRef *method_and_self;
method_and_self = &stack_pointer[-2];
method_and_self[0] = sym_new_not_null(ctx);
method_and_self[1] = sym_new_unknown(ctx);
bool optimized = false;
PyTypeObject *type = sym_get_probable_type(method_and_self[1]);
if (type != NULL) {
PyObject *name = _Py_SpecialMethods[oparg].name;
PyObject *descr = _PyType_Lookup(type, name);
if (descr != NULL && (Py_TYPE(descr)->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR)) {
ADD_OP(_GUARD_TYPE_VERSION, 0, type->tp_version_tag);
bool immortal = _Py_IsImmortal(descr) || (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE);
ADD_OP(immortal ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE,
0, (uintptr_t)descr);
ADD_OP(_SWAP, 3, 0);
ADD_OP(_POP_TOP, 0, 0);
if ((type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) {
PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type);
_Py_BloomFilter_Add(dependencies, type);
}
method_and_self[0] = sym_new_const(ctx, descr);
optimized = true;
}
}
if (!optimized) {
method_and_self[0] = sym_new_not_null(ctx);
method_and_self[1] = sym_new_unknown(ctx);
}
break;
}

View file

@ -115,6 +115,7 @@ const _PyOpcodeRecordEntry _PyOpcode_RecordEntries[256] = {
[STORE_ATTR_WITH_HINT] = {1, {_RECORD_TOS_TYPE_INDEX}},
[STORE_ATTR_SLOT] = {1, {_RECORD_TOS_TYPE_INDEX}},
[FOR_ITER_GEN] = {1, {_RECORD_NOS_GEN_FUNC_INDEX}},
[LOAD_SPECIAL] = {1, {_RECORD_TOS_TYPE_INDEX}},
[LOAD_ATTR_METHOD_WITH_VALUES] = {1, {_RECORD_TOS_TYPE_INDEX}},
[LOAD_ATTR_METHOD_NO_DICT] = {1, {_RECORD_TOS_TYPE_INDEX}},
[LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = {1, {_RECORD_TOS_TYPE_INDEX}},