1818#include "pycore_opcode_metadata.h"
1919#include "pycore_opcode_utils.h"
2020#include "pycore_pystate.h" // _PyInterpreterState_GET()
21+ #include "pycore_tstate.h" // _PyThreadStateImpl
2122#include "pycore_uop_metadata.h"
2223#include "pycore_long.h"
2324#include "pycore_interpframe.h" // _PyFrame_GetCode
@@ -334,6 +335,7 @@ _Py_opt_assert_within_stack_bounds(
334335/* >0 (length) for success, 0 for not ready, clears all possible errors. */
335336static int
336337optimize_uops (
338+ _PyThreadStateImpl * tstate ,
337339 PyFunctionObject * func ,
338340 _PyUOpInstruction * trace ,
339341 int trace_len ,
@@ -343,8 +345,15 @@ optimize_uops(
343345{
344346 assert (!PyErr_Occurred ());
345347
346- JitOptContext context ;
347- JitOptContext * ctx = & context ;
348+ // Use thread-local JitOptContext to avoid stack overflow
349+ JitOptContext * ctx = tstate -> jit_tracer_state .opt_context ;
350+ if (ctx == NULL ) {
351+ ctx = (JitOptContext * )PyMem_RawMalloc (sizeof (JitOptContext ));
352+ if (ctx == NULL ) {
353+ return 0 ;
354+ }
355+ tstate -> jit_tracer_state .opt_context = ctx ;
356+ }
348357 uint32_t opcode = UINT16_MAX ;
349358
350359 // Make sure that watchers are set up
@@ -574,6 +583,7 @@ remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size)
574583// > 0 - length of optimized trace
575584int
576585_Py_uop_analyze_and_optimize (
586+ _PyThreadStateImpl * tstate ,
577587 PyFunctionObject * func ,
578588 _PyUOpInstruction * buffer ,
579589 int length ,
@@ -584,7 +594,7 @@ _Py_uop_analyze_and_optimize(
584594 OPT_STAT_INC (optimizer_attempts );
585595
586596 length = optimize_uops (
587- func , buffer ,
597+ tstate , func , buffer ,
588598 length , curr_stacklen , dependencies );
589599
590600 if (length == 0 ) {
0 commit comments