diff --git a/Include/internal/pycore_tstate.h b/Include/internal/pycore_tstate.h index bad968428c73a1..0f51cf1d2574dc 100644 --- a/Include/internal/pycore_tstate.h +++ b/Include/internal/pycore_tstate.h @@ -21,6 +21,10 @@ struct _gc_thread_state { }; #endif +/* How much scratch space to give stackref to PyObject* conversion. */ +#define MAX_STACKREF_SCRATCH 10 + + // Every PyThreadState is actually allocated as a _PyThreadStateImpl. The // PyThreadState fields are exposed as part of the C API, although most fields // are intended to be private. The _PyThreadStateImpl fields not exposed. @@ -47,6 +51,9 @@ typedef struct _PyThreadStateImpl { struct _qsbr_thread_state *qsbr; // only used by free-threaded build struct llist_node mem_free_queue; // delayed free queue + // Scratch space to convert _PyStackRef to PyObject * + // +1 to account for possible vectorcalls. + PyObject *stackref_scratch[MAX_STACKREF_SCRATCH + 1]; #ifdef Py_GIL_DISABLED // Stack references for the current thread that exist on the C stack struct _PyCStackRef *c_stack_refs; diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h index 64ca7716fdbdee..6efa1c58ec6e8d 100644 --- a/Python/ceval_macros.h +++ b/Python/ceval_macros.h @@ -390,12 +390,10 @@ do { \ /* Stackref macros */ -/* How much scratch space to give stackref to PyObject* conversion. */ -#define MAX_STACKREF_SCRATCH 10 - #define STACKREFS_TO_PYOBJECTS(ARGS, ARG_COUNT, NAME) \ /* +1 because vectorcall might use -1 to write self */ \ - PyObject *NAME##_temp[MAX_STACKREF_SCRATCH+1]; \ + _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate; \ + PyObject **NAME##_temp = _tstate->stackref_scratch; \ PyObject **NAME = _PyObjectArray_FromStackRefArray(ARGS, ARG_COUNT, NAME##_temp + 1); #define STACKREFS_TO_PYOBJECTS_CLEANUP(NAME) \