GH-139922: Tail calling for MSVC (VS 2026) (GH-143068)

Co-authored-by: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Co-authored-by: Brandt Bucher <brandt@python.org>
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
This commit is contained in:
Chris Eibl 2025-12-23 00:01:34 +01:00 committed by GitHub
parent 665d2807a0
commit be3c131640
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 528 additions and 683 deletions

View file

@ -1071,6 +1071,65 @@ _Py_VectorCall_StackRefSteal(
return res;
}
PyObject*
_Py_VectorCallInstrumentation_StackRefSteal(
_PyStackRef callable,
_PyStackRef* arguments,
int total_args,
_PyStackRef kwnames,
bool call_instrumentation,
_PyInterpreterFrame* frame,
_Py_CODEUNIT* this_instr,
PyThreadState* tstate)
{
PyObject* res;
STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o);
if (CONVERSION_FAILED(args_o)) {
res = NULL;
goto cleanup;
}
PyObject* callable_o = PyStackRef_AsPyObjectBorrow(callable);
PyObject* kwnames_o = PyStackRef_AsPyObjectBorrow(kwnames);
int positional_args = total_args;
if (kwnames_o != NULL) {
positional_args -= (int)PyTuple_GET_SIZE(kwnames_o);
}
res = PyObject_Vectorcall(
callable_o, args_o,
positional_args | PY_VECTORCALL_ARGUMENTS_OFFSET,
kwnames_o);
STACKREFS_TO_PYOBJECTS_CLEANUP(args_o);
if (call_instrumentation) {
PyObject* arg = total_args == 0 ?
&_PyInstrumentation_MISSING : PyStackRef_AsPyObjectBorrow(arguments[0]);
if (res == NULL) {
_Py_call_instrumentation_exc2(
tstate, PY_MONITORING_EVENT_C_RAISE,
frame, this_instr, callable_o, arg);
}
else {
int err = _Py_call_instrumentation_2args(
tstate, PY_MONITORING_EVENT_C_RETURN,
frame, this_instr, callable_o, arg);
if (err < 0) {
Py_CLEAR(res);
}
}
}
assert((res != NULL) ^ (PyErr_Occurred() != NULL));
cleanup:
PyStackRef_XCLOSE(kwnames);
// arguments is a pointer into the GC visible stack,
// so we must NULL out values as we clear them.
for (int i = total_args - 1; i >= 0; i--) {
_PyStackRef tmp = arguments[i];
arguments[i] = PyStackRef_NULL;
PyStackRef_CLOSE(tmp);
}
PyStackRef_CLOSE(callable);
return res;
}
PyObject *
_Py_BuiltinCallFast_StackRefSteal(
_PyStackRef callable,