mirror of
https://github.com/python/cpython.git
synced 2026-04-20 02:40:59 +00:00
gh-148438: implement _RECORD_BOUND_METHOD in JIT (GH-148457)
This commit is contained in:
parent
18d7d90ef9
commit
63492628be
5 changed files with 128 additions and 8 deletions
|
|
@ -6160,8 +6160,7 @@ dummy_func(
|
|||
tier2 op(_RECORD_BOUND_METHOD, (callable, self, args[oparg] -- callable, self, args[oparg])) {
|
||||
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
|
||||
if (Py_TYPE(callable_o) == &PyMethod_Type) {
|
||||
PyObject *func = ((PyMethodObject *)callable_o)->im_func;
|
||||
RECORD_VALUE(func);
|
||||
RECORD_VALUE(callable_o);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
44
Python/optimizer_cases.c.h
generated
44
Python/optimizer_cases.c.h
generated
|
|
@ -3644,11 +3644,38 @@
|
|||
ADD_OP(_CHECK_FUNCTION_VERSION_INLINE, 0, func_version);
|
||||
uop_buffer_last(&ctx->out_buffer)->operand1 = (uintptr_t)method->im_func;
|
||||
}
|
||||
else {
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
||||
case _EXPAND_METHOD: {
|
||||
JitOptRef self_or_null;
|
||||
JitOptRef callable;
|
||||
self_or_null = stack_pointer[-1 - oparg];
|
||||
callable = stack_pointer[-2 - 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);
|
||||
}
|
||||
stack_pointer[-2 - oparg] = callable;
|
||||
stack_pointer[-1 - oparg] = self_or_null;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -3687,8 +3714,18 @@
|
|||
JitOptRef callable;
|
||||
self_or_null = stack_pointer[-1 - oparg];
|
||||
callable = stack_pointer[-2 - 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);
|
||||
}
|
||||
stack_pointer[-2 - oparg] = callable;
|
||||
stack_pointer[-1 - oparg] = self_or_null;
|
||||
break;
|
||||
|
|
@ -5212,6 +5249,9 @@
|
|||
}
|
||||
|
||||
case _RECORD_BOUND_METHOD: {
|
||||
JitOptRef callable;
|
||||
callable = stack_pointer[-2 - oparg];
|
||||
sym_set_recorded_value(callable, (PyObject *)this_instr->operand0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
3
Python/record_functions.c.h
generated
3
Python/record_functions.c.h
generated
|
|
@ -74,8 +74,7 @@ void _PyOpcode_RecordFunction_BOUND_METHOD(_PyInterpreterFrame *frame, _PyStackR
|
|||
callable = stack_pointer[-2 - oparg];
|
||||
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
|
||||
if (Py_TYPE(callable_o) == &PyMethod_Type) {
|
||||
PyObject *func = ((PyMethodObject *)callable_o)->im_func;
|
||||
*recorded_value = (PyObject *)func;
|
||||
*recorded_value = (PyObject *)callable_o;
|
||||
Py_INCREF(*recorded_value);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue