gh-142982: Specialize CALL_FUNCTION_EX (GH-143391)

This commit is contained in:
Ken Jin 2026-01-07 04:34:08 +08:00 committed by GitHub
parent ff7d1cec41
commit df355348f0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 2074 additions and 1188 deletions

View file

@ -4794,6 +4794,11 @@ dummy_func(
_CALL_KW_NON_PY +
_CHECK_PERIODIC_AT_END;
family(CALL_FUNCTION_EX, INLINE_CACHE_ENTRIES_CALL_FUNCTION_EX) = {
CALL_EX_PY,
CALL_EX_NON_PY_GENERAL,
};
op(_MAKE_CALLARGS_A_TUPLE, (func, unused, callargs, kwargs -- func, unused, callargs, kwargs)) {
PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs);
if (!PyTuple_CheckExact(callargs_o)) {
@ -4872,8 +4877,8 @@ dummy_func(
if (new_frame == NULL) {
ERROR_NO_POP();
}
assert(INSTRUCTION_SIZE == 1);
frame->return_offset = 1;
assert(INSTRUCTION_SIZE == 1 + INLINE_CACHE_ENTRIES_CALL_FUNCTION_EX);
frame->return_offset = INSTRUCTION_SIZE;
DISPATCH_INLINED(new_frame);
}
PyObject *callargs = PyStackRef_AsPyObjectBorrow(callargs_st);
@ -4890,12 +4895,92 @@ dummy_func(
result = PyStackRef_FromPyObjectSteal(result_o);
}
specializing op(_SPECIALIZE_CALL_FUNCTION_EX, (counter/1, func, unused, unused, unused -- func, unused, unused, unused)) {
#if ENABLE_SPECIALIZATION_FT
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
next_instr = this_instr;
_Py_Specialize_CallFunctionEx(func, next_instr);
DISPATCH_SAME_OPARG();
}
OPCODE_DEFERRED_INC(CALL_FUNCTION_EX);
ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter);
#endif /* ENABLE_SPECIALIZATION_FT */
}
macro(CALL_FUNCTION_EX) =
_SPECIALIZE_CALL_FUNCTION_EX +
_MAKE_CALLARGS_A_TUPLE +
_DO_CALL_FUNCTION_EX +
_CHECK_PERIODIC_AT_END;
op(_CHECK_IS_PY_CALLABLE_EX, (func_st, unused, unused, unused -- func_st, unused, unused, unused)) {
PyObject *func = PyStackRef_AsPyObjectBorrow(func_st);
EXIT_IF(Py_TYPE(func) != &PyFunction_Type);
EXIT_IF(((PyFunctionObject *)func)->vectorcall != _PyFunction_Vectorcall);
}
op(_PY_FRAME_EX, (func_st, null, callargs_st, kwargs_st -- ex_frame)) {
PyObject *func = PyStackRef_AsPyObjectBorrow(func_st);
PyObject *callargs = PyStackRef_AsPyObjectSteal(callargs_st);
assert(PyTuple_CheckExact(callargs));
assert(Py_TYPE(func) == &PyFunction_Type);
assert(((PyFunctionObject *)func)->vectorcall == _PyFunction_Vectorcall);
PyObject *kwargs = PyStackRef_IsNull(kwargs_st) ? NULL : PyStackRef_AsPyObjectSteal(kwargs_st);
assert(kwargs == NULL || PyDict_CheckExact(kwargs));
Py_ssize_t nargs = PyTuple_GET_SIZE(callargs);
int code_flags = ((PyCodeObject *)PyFunction_GET_CODE(func))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(func));
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_Ex(
tstate, func_st, locals,
nargs, callargs, kwargs, frame);
INPUTS_DEAD();
SYNC_SP();
if (new_frame == NULL) {
ERROR_NO_POP();
}
ex_frame = PyStackRef_Wrap(new_frame);
}
macro(CALL_EX_PY) =
unused/1 +
_CHECK_PEP_523 +
_MAKE_CALLARGS_A_TUPLE +
_CHECK_IS_PY_CALLABLE_EX +
_PY_FRAME_EX +
_SAVE_RETURN_OFFSET +
_PUSH_FRAME;
op(_CHECK_IS_NOT_PY_CALLABLE_EX, (func_st, unused, unused, unused -- func_st, unused, unused, unused)) {
PyObject *func = PyStackRef_AsPyObjectBorrow(func_st);
EXIT_IF(Py_TYPE(func) == &PyFunction_Type && ((PyFunctionObject *)func)->vectorcall == _PyFunction_Vectorcall);
}
op(_CALL_FUNCTION_EX_NON_PY_GENERAL, (func_st, null, callargs_st, kwargs_st -- result)) {
PyObject *func = PyStackRef_AsPyObjectBorrow(func_st);
PyObject *callargs = PyStackRef_AsPyObjectBorrow(callargs_st);
(void)null;
assert(PyTuple_CheckExact(callargs));
PyObject *kwargs = PyStackRef_AsPyObjectBorrow(kwargs_st);
assert(kwargs == NULL || PyDict_CheckExact(kwargs));
PyObject *result_o = PyObject_Call(func, callargs, kwargs);
PyStackRef_XCLOSE(kwargs_st);
PyStackRef_CLOSE(callargs_st);
DEAD(null);
PyStackRef_CLOSE(func_st);
ERROR_IF(result_o == NULL);
result = PyStackRef_FromPyObjectSteal(result_o);
}
macro(CALL_EX_NON_PY_GENERAL) =
unused/1 +
_CHECK_IS_NOT_PY_CALLABLE_EX +
_MAKE_CALLARGS_A_TUPLE +
_CALL_FUNCTION_EX_NON_PY_GENERAL +
_CHECK_PERIODIC_AT_END;
macro(INSTRUMENTED_CALL_FUNCTION_EX) =
unused/1 +
_MAKE_CALLARGS_A_TUPLE +
_DO_CALL_FUNCTION_EX +
_CHECK_PERIODIC_AT_END;