gh-148438: implement _RECORD_BOUND_METHOD in JIT (GH-148457)

This commit is contained in:
Neko Asakura 2026-04-12 14:57:55 -04:00 committed by GitHub
parent 18d7d90ef9
commit 63492628be
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 128 additions and 8 deletions

View file

@ -996,8 +996,18 @@ dummy_func(void) {
}
op(_INIT_CALL_BOUND_METHOD_EXACT_ARGS, (callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
callable = sym_new_not_null(ctx);
self_or_null = sym_new_not_null(ctx);
PyObject *bound_method = sym_get_probable_value(callable);
if (bound_method != NULL && Py_TYPE(bound_method) == &PyMethod_Type) {
PyMethodObject *method = (PyMethodObject *)bound_method;
callable = sym_new_not_null(ctx);
sym_set_recorded_value(callable, method->im_func);
self_or_null = sym_new_not_null(ctx);
sym_set_recorded_value(self_or_null, method->im_self);
}
else {
callable = sym_new_not_null(ctx);
self_or_null = sym_new_not_null(ctx);
}
}
op(_CHECK_FUNCTION_VERSION, (func_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
@ -1019,6 +1029,19 @@ dummy_func(void) {
ADD_OP(_CHECK_FUNCTION_VERSION_INLINE, 0, func_version);
uop_buffer_last(&ctx->out_buffer)->operand1 = (uintptr_t)method->im_func;
}
else {
// Guarding on the bound method, safe to promote.
PyObject *bound_method = sym_get_probable_value(callable);
if (bound_method != NULL && Py_TYPE(bound_method) == &PyMethod_Type) {
PyMethodObject *method = (PyMethodObject *)bound_method;
PyObject *func = method->im_func;
if (PyFunction_Check(func) &&
((PyFunctionObject *)func)->func_version == func_version) {
_Py_BloomFilter_Add(dependencies, func);
sym_set_const(callable, bound_method);
}
}
}
sym_set_type(callable, &PyMethod_Type);
}
@ -1057,6 +1080,18 @@ dummy_func(void) {
}
}
op(_EXPAND_METHOD, (callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
if (sym_is_const(ctx, callable) && sym_matches_type(callable, &PyMethod_Type)) {
PyMethodObject *method = (PyMethodObject *)sym_get_const(ctx, callable);
callable = sym_new_const(ctx, method->im_func);
self_or_null = sym_new_const(ctx, method->im_self);
}
else {
callable = sym_new_not_null(ctx);
self_or_null = sym_new_not_null(ctx);
}
}
op(_MAYBE_EXPAND_METHOD, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) {
(void)args;
callable = sym_new_not_null(ctx);
@ -2226,6 +2261,10 @@ dummy_func(void) {
sym_set_recorded_value(func, (PyObject *)this_instr->operand0);
}
op(_RECORD_BOUND_METHOD, (callable, self, args[oparg] -- callable, self, args[oparg])) {
sym_set_recorded_value(callable, (PyObject *)this_instr->operand0);
}
op(_RECORD_NOS_GEN_FUNC, (nos, tos -- nos, tos)) {
PyFunctionObject *func = (PyFunctionObject *)this_instr->operand0;
assert(func == NULL || PyFunction_Check(func));