From 8b380392f94ff4df46f29df9843c6b1f4bac06e0 Mon Sep 17 00:00:00 2001 From: LloydZ <35182391+cocolato@users.noreply.github.com> Date: Thu, 8 Jan 2026 03:17:33 +0000 Subject: [PATCH 1/5] move JitOptContext to _PyThreadStateImpl --- Include/internal/pycore_optimizer.h | 1 + Include/internal/pycore_tstate.h | 1 + Python/optimizer.c | 1 + Python/optimizer_analysis.c | 16 +++++++++++++--- Python/pystate.c | 7 +++++++ 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h index 6a0fc1a59e7965..254d0a6711710c 100644 --- a/Include/internal/pycore_optimizer.h +++ b/Include/internal/pycore_optimizer.h @@ -84,6 +84,7 @@ PyAPI_FUNC(void) _Py_Executors_InvalidateCold(PyInterpreterState *interp); #define JIT_CLEANUP_THRESHOLD 1000 int _Py_uop_analyze_and_optimize( + struct _PyThreadStateImpl *tstate, PyFunctionObject *func, _PyUOpInstruction *trace, int trace_len, int curr_stackentries, _PyBloomFilter *dependencies); diff --git a/Include/internal/pycore_tstate.h b/Include/internal/pycore_tstate.h index d8f4bfef98af7e..12f9d15c398a5b 100644 --- a/Include/internal/pycore_tstate.h +++ b/Include/internal/pycore_tstate.h @@ -53,6 +53,7 @@ typedef struct _PyJitTracerTranslatorState { typedef struct _PyJitTracerState { _PyUOpInstruction *code_buffer; + struct _JitOptContext *opt_context; _PyJitTracerInitialState initial_state; _PyJitTracerPreviousState prev_state; _PyJitTracerTranslatorState translator_state; diff --git a/Python/optimizer.c b/Python/optimizer.c index d32fae2e489af4..4070b2f940bb74 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -1484,6 +1484,7 @@ uop_optimize( OPT_STAT_INC(traces_created); if (!is_noopt) { length = _Py_uop_analyze_and_optimize( + _tstate, _tstate->jit_tracer_state.initial_state.func, buffer,length, curr_stackentries, dependencies); diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 29a088e43c2a0f..f3fc5137afdd75 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -18,6 +18,7 @@ #include "pycore_opcode_metadata.h" #include "pycore_opcode_utils.h" #include "pycore_pystate.h" // _PyInterpreterState_GET() +#include "pycore_tstate.h" // _PyThreadStateImpl #include "pycore_uop_metadata.h" #include "pycore_long.h" #include "pycore_interpframe.h" // _PyFrame_GetCode @@ -334,6 +335,7 @@ _Py_opt_assert_within_stack_bounds( /* >0 (length) for success, 0 for not ready, clears all possible errors. */ static int optimize_uops( + _PyThreadStateImpl *tstate, PyFunctionObject *func, _PyUOpInstruction *trace, int trace_len, @@ -343,8 +345,15 @@ optimize_uops( { assert(!PyErr_Occurred()); - JitOptContext context; - JitOptContext *ctx = &context; + // Use thread-local JitOptContext to avoid stack overflow + JitOptContext *ctx = tstate->jit_tracer_state.opt_context; + if (ctx == NULL) { + ctx = (JitOptContext *)PyMem_RawMalloc(sizeof(JitOptContext)); + if (ctx == NULL) { + return 0; + } + tstate->jit_tracer_state.opt_context = ctx; + } uint32_t opcode = UINT16_MAX; // Make sure that watchers are set up @@ -574,6 +583,7 @@ remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size) // > 0 - length of optimized trace int _Py_uop_analyze_and_optimize( + _PyThreadStateImpl *tstate, PyFunctionObject *func, _PyUOpInstruction *buffer, int length, @@ -584,7 +594,7 @@ _Py_uop_analyze_and_optimize( OPT_STAT_INC(optimizer_attempts); length = optimize_uops( - func, buffer, + tstate, func, buffer, length, curr_stacklen, dependencies); if (length == 0) { diff --git a/Python/pystate.c b/Python/pystate.c index 23853f69792450..970c46a0e611c3 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1554,6 +1554,7 @@ init_threadstate(_PyThreadStateImpl *_tstate, "PYTHON_JIT_SIDE_EXIT_INITIAL_BACKOFF", SIDE_EXIT_INITIAL_BACKOFF, 0, MAX_BACKOFF); _tstate->jit_tracer_state.code_buffer = NULL; + _tstate->jit_tracer_state.opt_context = NULL; #endif tstate->delete_later = NULL; @@ -1874,6 +1875,12 @@ tstate_delete_common(PyThreadState *tstate, int release_gil) _PyObject_VirtualFree(_tstate->jit_tracer_state.code_buffer, UOP_BUFFER_SIZE); _tstate->jit_tracer_state.code_buffer = NULL; } + if (_tstate->jit_tracer_state.opt_context != NULL) { + // Ensure any resources in opt_context are cleaned up + _Py_uop_abstractcontext_fini(_tstate->jit_tracer_state.opt_context); + PyMem_RawFree(_tstate->jit_tracer_state.opt_context); + _tstate->jit_tracer_state.opt_context = NULL; + } #endif HEAD_UNLOCK(runtime); From 97176293ca761abbe408999031aec10577313448 Mon Sep 17 00:00:00 2001 From: LloydZ <35182391+cocolato@users.noreply.github.com> Date: Thu, 8 Jan 2026 06:38:32 +0000 Subject: [PATCH 2/5] remove redundant func parameter --- Include/internal/pycore_optimizer.h | 1 - Python/optimizer.c | 3 +-- Python/optimizer_analysis.c | 5 ++--- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h index 254d0a6711710c..564544aff42a9e 100644 --- a/Include/internal/pycore_optimizer.h +++ b/Include/internal/pycore_optimizer.h @@ -85,7 +85,6 @@ PyAPI_FUNC(void) _Py_Executors_InvalidateCold(PyInterpreterState *interp); int _Py_uop_analyze_and_optimize( struct _PyThreadStateImpl *tstate, - PyFunctionObject *func, _PyUOpInstruction *trace, int trace_len, int curr_stackentries, _PyBloomFilter *dependencies); diff --git a/Python/optimizer.c b/Python/optimizer.c index 4070b2f940bb74..a0d72454aa3ea5 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -1485,8 +1485,7 @@ uop_optimize( if (!is_noopt) { length = _Py_uop_analyze_and_optimize( _tstate, - _tstate->jit_tracer_state.initial_state.func, - buffer,length, + buffer, length, curr_stackentries, dependencies); if (length <= 0) { return length; diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index f3fc5137afdd75..155612104638a7 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -336,7 +336,6 @@ _Py_opt_assert_within_stack_bounds( static int optimize_uops( _PyThreadStateImpl *tstate, - PyFunctionObject *func, _PyUOpInstruction *trace, int trace_len, int curr_stacklen, @@ -344,6 +343,7 @@ optimize_uops( ) { assert(!PyErr_Occurred()); + PyFunctionObject *func = tstate->jit_tracer_state.initial_state.func; // Use thread-local JitOptContext to avoid stack overflow JitOptContext *ctx = tstate->jit_tracer_state.opt_context; @@ -584,7 +584,6 @@ remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size) int _Py_uop_analyze_and_optimize( _PyThreadStateImpl *tstate, - PyFunctionObject *func, _PyUOpInstruction *buffer, int length, int curr_stacklen, @@ -594,7 +593,7 @@ _Py_uop_analyze_and_optimize( OPT_STAT_INC(optimizer_attempts); length = optimize_uops( - tstate, func, buffer, + tstate, buffer, length, curr_stacklen, dependencies); if (length == 0) { From 4e7a918ae394708d19f360a62ec0c057ea26e3f1 Mon Sep 17 00:00:00 2001 From: LloydZ <35182391+cocolato@users.noreply.github.com> Date: Thu, 8 Jan 2026 11:13:51 +0000 Subject: [PATCH 3/5] add _PyJitOptState --- Include/internal/pycore_tstate.h | 6 +++++- Python/optimizer_analysis.c | 5 ++--- Python/pystate.c | 10 ++++------ 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Include/internal/pycore_tstate.h b/Include/internal/pycore_tstate.h index 12f9d15c398a5b..b3fbb4edadec9d 100644 --- a/Include/internal/pycore_tstate.h +++ b/Include/internal/pycore_tstate.h @@ -51,9 +51,13 @@ typedef struct _PyJitTracerTranslatorState { int jump_backward_seen; } _PyJitTracerTranslatorState; +typedef struct _PyJitOptState { + struct _JitOptContext *opt_context; +} _PyJitOptState; + typedef struct _PyJitTracerState { _PyUOpInstruction *code_buffer; - struct _JitOptContext *opt_context; + _PyJitOptState opt_state; _PyJitTracerInitialState initial_state; _PyJitTracerPreviousState prev_state; _PyJitTracerTranslatorState translator_state; diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 155612104638a7..30a76798a0dcc7 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -345,14 +345,13 @@ optimize_uops( assert(!PyErr_Occurred()); PyFunctionObject *func = tstate->jit_tracer_state.initial_state.func; - // Use thread-local JitOptContext to avoid stack overflow - JitOptContext *ctx = tstate->jit_tracer_state.opt_context; + JitOptContext *ctx = tstate->jit_tracer_state.opt_state.opt_context; if (ctx == NULL) { ctx = (JitOptContext *)PyMem_RawMalloc(sizeof(JitOptContext)); if (ctx == NULL) { return 0; } - tstate->jit_tracer_state.opt_context = ctx; + tstate->jit_tracer_state.opt_state.opt_context = ctx; } uint32_t opcode = UINT16_MAX; diff --git a/Python/pystate.c b/Python/pystate.c index 970c46a0e611c3..8064abce86fe2b 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1554,7 +1554,7 @@ init_threadstate(_PyThreadStateImpl *_tstate, "PYTHON_JIT_SIDE_EXIT_INITIAL_BACKOFF", SIDE_EXIT_INITIAL_BACKOFF, 0, MAX_BACKOFF); _tstate->jit_tracer_state.code_buffer = NULL; - _tstate->jit_tracer_state.opt_context = NULL; + _tstate->jit_tracer_state.opt_state.opt_context = NULL; #endif tstate->delete_later = NULL; @@ -1875,11 +1875,9 @@ tstate_delete_common(PyThreadState *tstate, int release_gil) _PyObject_VirtualFree(_tstate->jit_tracer_state.code_buffer, UOP_BUFFER_SIZE); _tstate->jit_tracer_state.code_buffer = NULL; } - if (_tstate->jit_tracer_state.opt_context != NULL) { - // Ensure any resources in opt_context are cleaned up - _Py_uop_abstractcontext_fini(_tstate->jit_tracer_state.opt_context); - PyMem_RawFree(_tstate->jit_tracer_state.opt_context); - _tstate->jit_tracer_state.opt_context = NULL; + if (_tstate->jit_tracer_state.opt_state.opt_context != NULL) { + PyMem_RawFree(_tstate->jit_tracer_state.opt_state.opt_context); + _tstate->jit_tracer_state.opt_state.opt_context = NULL; } #endif From f25f6c8cc71ba54e5a29759d561373f5dd8d1bd5 Mon Sep 17 00:00:00 2001 From: Hai Zhu <35182391+cocolato@users.noreply.github.com> Date: Thu, 8 Jan 2026 20:07:44 +0800 Subject: [PATCH 4/5] Update Include/internal/pycore_optimizer.h Co-authored-by: Kumar Aditya --- Include/internal/pycore_optimizer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h index 564544aff42a9e..f346001892d990 100644 --- a/Include/internal/pycore_optimizer.h +++ b/Include/internal/pycore_optimizer.h @@ -84,7 +84,7 @@ PyAPI_FUNC(void) _Py_Executors_InvalidateCold(PyInterpreterState *interp); #define JIT_CLEANUP_THRESHOLD 1000 int _Py_uop_analyze_and_optimize( - struct _PyThreadStateImpl *tstate, + _PyThreadStateImpl *tstate, _PyUOpInstruction *trace, int trace_len, int curr_stackentries, _PyBloomFilter *dependencies); From 32dc7fb90a05830e2753104eedc8797780da64ab Mon Sep 17 00:00:00 2001 From: LloydZ <35182391+cocolato@users.noreply.github.com> Date: Thu, 8 Jan 2026 16:06:19 +0000 Subject: [PATCH 5/5] Embed JitOptContext and code_buffer in _PyThreadStateImpl --- Include/internal/pycore_optimizer.h | 123 +------------------ Include/internal/pycore_optimizer_types.h | 137 ++++++++++++++++++++++ Include/internal/pycore_tstate.h | 9 +- Python/optimizer.c | 7 -- Python/optimizer_analysis.c | 9 +- Python/pystate.c | 14 --- 6 files changed, 142 insertions(+), 157 deletions(-) create mode 100644 Include/internal/pycore_optimizer_types.h diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h index f346001892d990..d1d22c77507c6c 100644 --- a/Include/internal/pycore_optimizer.h +++ b/Include/internal/pycore_optimizer.h @@ -12,6 +12,7 @@ extern "C" { #include "pycore_uop.h" // _PyUOpInstruction #include "pycore_uop_ids.h" #include "pycore_stackref.h" // _PyStackRef +#include "pycore_optimizer_types.h" #include @@ -112,86 +113,6 @@ static inline uint16_t uop_get_error_target(const _PyUOpInstruction *inst) return inst->error_target; } -// Holds locals, stack, locals, stack ... co_consts (in that order) -#define MAX_ABSTRACT_INTERP_SIZE 4096 - -#define TY_ARENA_SIZE (UOP_MAX_TRACE_LENGTH * 5) - -// Need extras for root frame and for overflow frame (see TRACE_STACK_PUSH()) -#define MAX_ABSTRACT_FRAME_DEPTH (16) - -// The maximum number of side exits that we can take before requiring forward -// progress (and inserting a new ENTER_EXECUTOR instruction). In practice, this -// is the "maximum amount of polymorphism" that an isolated trace tree can -// handle before rejoining the rest of the program. -#define MAX_CHAIN_DEPTH 4 - -/* Symbols */ -/* See explanation in optimizer_symbols.c */ - - -typedef enum _JitSymType { - JIT_SYM_UNKNOWN_TAG = 1, - JIT_SYM_NULL_TAG = 2, - JIT_SYM_NON_NULL_TAG = 3, - JIT_SYM_BOTTOM_TAG = 4, - JIT_SYM_TYPE_VERSION_TAG = 5, - JIT_SYM_KNOWN_CLASS_TAG = 6, - JIT_SYM_KNOWN_VALUE_TAG = 7, - JIT_SYM_TUPLE_TAG = 8, - JIT_SYM_TRUTHINESS_TAG = 9, - JIT_SYM_COMPACT_INT = 10, -} JitSymType; - -typedef struct _jit_opt_known_class { - uint8_t tag; - uint32_t version; - PyTypeObject *type; -} JitOptKnownClass; - -typedef struct _jit_opt_known_version { - uint8_t tag; - uint32_t version; -} JitOptKnownVersion; - -typedef struct _jit_opt_known_value { - uint8_t tag; - PyObject *value; -} JitOptKnownValue; - -#define MAX_SYMBOLIC_TUPLE_SIZE 7 - -typedef struct _jit_opt_tuple { - uint8_t tag; - uint8_t length; - uint16_t items[MAX_SYMBOLIC_TUPLE_SIZE]; -} JitOptTuple; - -typedef struct { - uint8_t tag; - bool invert; - uint16_t value; -} JitOptTruthiness; - -typedef struct { - uint8_t tag; -} JitOptCompactInt; - -typedef union _jit_opt_symbol { - uint8_t tag; - JitOptKnownClass cls; - JitOptKnownValue value; - JitOptKnownVersion version; - JitOptTuple tuple; - JitOptTruthiness truthiness; - JitOptCompactInt compact; -} JitOptSymbol; - - -// This mimics the _PyStackRef API -typedef union { - uintptr_t bits; -} JitOptRef; #define REF_IS_BORROWED 1 @@ -238,48 +159,6 @@ PyJitRef_IsBorrowed(JitOptRef ref) return (ref.bits & REF_IS_BORROWED) == REF_IS_BORROWED; } -struct _Py_UOpsAbstractFrame { - bool globals_watched; - // The version number of the globals dicts, once checked. 0 if unchecked. - uint32_t globals_checked_version; - // Max stacklen - int stack_len; - int locals_len; - PyFunctionObject *func; - PyCodeObject *code; - - JitOptRef *stack_pointer; - JitOptRef *stack; - JitOptRef *locals; -}; - -typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame; - -typedef struct ty_arena { - int ty_curr_number; - int ty_max_number; - JitOptSymbol arena[TY_ARENA_SIZE]; -} ty_arena; - -typedef struct _JitOptContext { - char done; - char out_of_space; - bool contradiction; - // Has the builtins dict been watched? - bool builtins_watched; - // The current "executing" frame. - _Py_UOpsAbstractFrame *frame; - _Py_UOpsAbstractFrame frames[MAX_ABSTRACT_FRAME_DEPTH]; - int curr_frame_depth; - - // Arena for the symbolic types. - ty_arena t_arena; - - JitOptRef *n_consumed; - JitOptRef *limit; - JitOptRef locals_and_stack[MAX_ABSTRACT_INTERP_SIZE]; -} JitOptContext; - extern bool _Py_uop_sym_is_null(JitOptRef sym); extern bool _Py_uop_sym_is_not_null(JitOptRef sym); extern bool _Py_uop_sym_is_const(JitOptContext *ctx, JitOptRef sym); diff --git a/Include/internal/pycore_optimizer_types.h b/Include/internal/pycore_optimizer_types.h new file mode 100644 index 00000000000000..de8e50921e3311 --- /dev/null +++ b/Include/internal/pycore_optimizer_types.h @@ -0,0 +1,137 @@ +#ifndef Py_INTERNAL_OPTIMIZER_TYPES_H +#define Py_INTERNAL_OPTIMIZER_TYPES_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#include "pycore_uop.h" // UOP_MAX_TRACE_LENGTH + +// Holds locals, stack, locals, stack ... co_consts (in that order) +#define MAX_ABSTRACT_INTERP_SIZE 4096 + +#define TY_ARENA_SIZE (UOP_MAX_TRACE_LENGTH * 5) + +// Need extras for root frame and for overflow frame (see TRACE_STACK_PUSH()) +#define MAX_ABSTRACT_FRAME_DEPTH (16) + +// The maximum number of side exits that we can take before requiring forward +// progress (and inserting a new ENTER_EXECUTOR instruction). In practice, this +// is the "maximum amount of polymorphism" that an isolated trace tree can +// handle before rejoining the rest of the program. +#define MAX_CHAIN_DEPTH 4 + +/* Symbols */ +/* See explanation in optimizer_symbols.c */ + + +typedef enum _JitSymType { + JIT_SYM_UNKNOWN_TAG = 1, + JIT_SYM_NULL_TAG = 2, + JIT_SYM_NON_NULL_TAG = 3, + JIT_SYM_BOTTOM_TAG = 4, + JIT_SYM_TYPE_VERSION_TAG = 5, + JIT_SYM_KNOWN_CLASS_TAG = 6, + JIT_SYM_KNOWN_VALUE_TAG = 7, + JIT_SYM_TUPLE_TAG = 8, + JIT_SYM_TRUTHINESS_TAG = 9, + JIT_SYM_COMPACT_INT = 10, +} JitSymType; + +typedef struct _jit_opt_known_class { + uint8_t tag; + uint32_t version; + PyTypeObject *type; +} JitOptKnownClass; + +typedef struct _jit_opt_known_version { + uint8_t tag; + uint32_t version; +} JitOptKnownVersion; + +typedef struct _jit_opt_known_value { + uint8_t tag; + PyObject *value; +} JitOptKnownValue; + +#define MAX_SYMBOLIC_TUPLE_SIZE 7 + +typedef struct _jit_opt_tuple { + uint8_t tag; + uint8_t length; + uint16_t items[MAX_SYMBOLIC_TUPLE_SIZE]; +} JitOptTuple; + +typedef struct { + uint8_t tag; + bool invert; + uint16_t value; +} JitOptTruthiness; + +typedef struct { + uint8_t tag; +} JitOptCompactInt; + +typedef union _jit_opt_symbol { + uint8_t tag; + JitOptKnownClass cls; + JitOptKnownValue value; + JitOptKnownVersion version; + JitOptTuple tuple; + JitOptTruthiness truthiness; + JitOptCompactInt compact; +} JitOptSymbol; + +// This mimics the _PyStackRef API +typedef union { + uintptr_t bits; +} JitOptRef; + +typedef struct _Py_UOpsAbstractFrame { + bool globals_watched; + // The version number of the globals dicts, once checked. 0 if unchecked. + uint32_t globals_checked_version; + // Max stacklen + int stack_len; + int locals_len; + PyFunctionObject *func; + PyCodeObject *code; + + JitOptRef *stack_pointer; + JitOptRef *stack; + JitOptRef *locals; +} _Py_UOpsAbstractFrame; + +typedef struct ty_arena { + int ty_curr_number; + int ty_max_number; + JitOptSymbol arena[TY_ARENA_SIZE]; +} ty_arena; + +typedef struct _JitOptContext { + char done; + char out_of_space; + bool contradiction; + // Has the builtins dict been watched? + bool builtins_watched; + // The current "executing" frame. + _Py_UOpsAbstractFrame *frame; + _Py_UOpsAbstractFrame frames[MAX_ABSTRACT_FRAME_DEPTH]; + int curr_frame_depth; + + // Arena for the symbolic types. + ty_arena t_arena; + + JitOptRef *n_consumed; + JitOptRef *limit; + JitOptRef locals_and_stack[MAX_ABSTRACT_INTERP_SIZE]; +} JitOptContext; + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_OPTIMIZER_TYPES_H */ diff --git a/Include/internal/pycore_tstate.h b/Include/internal/pycore_tstate.h index b3fbb4edadec9d..81cabb4dca47e4 100644 --- a/Include/internal/pycore_tstate.h +++ b/Include/internal/pycore_tstate.h @@ -12,6 +12,7 @@ extern "C" { #include "pycore_freelist_state.h" // struct _Py_freelists #include "pycore_interpframe_structs.h" // _PyInterpreterFrame #include "pycore_mimalloc.h" // struct _mimalloc_thread_state +#include "pycore_optimizer_types.h" // JitOptContext #include "pycore_qsbr.h" // struct qsbr #include "pycore_uop.h" // struct _PyUOpInstruction #include "pycore_structs.h" @@ -51,16 +52,12 @@ typedef struct _PyJitTracerTranslatorState { int jump_backward_seen; } _PyJitTracerTranslatorState; -typedef struct _PyJitOptState { - struct _JitOptContext *opt_context; -} _PyJitOptState; - typedef struct _PyJitTracerState { - _PyUOpInstruction *code_buffer; - _PyJitOptState opt_state; _PyJitTracerInitialState initial_state; _PyJitTracerPreviousState prev_state; _PyJitTracerTranslatorState translator_state; + JitOptContext opt_context; + _PyUOpInstruction code_buffer[UOP_MAX_TRACE_LENGTH]; } _PyJitTracerState; #endif diff --git a/Python/optimizer.c b/Python/optimizer.c index a0d72454aa3ea5..73617f6ca26425 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -1025,13 +1025,6 @@ _PyJit_TryInitializeTracing( if (oparg > 0xFFFF) { return 0; } - if (_tstate->jit_tracer_state.code_buffer == NULL) { - _tstate->jit_tracer_state.code_buffer = (_PyUOpInstruction *)_PyObject_VirtualAlloc(UOP_BUFFER_SIZE); - if (_tstate->jit_tracer_state.code_buffer == NULL) { - // Don't error, just go to next instruction. - return 0; - } - } PyObject *func = PyStackRef_AsPyObjectBorrow(frame->f_funcobj); if (func == NULL) { return 0; diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 30a76798a0dcc7..56d4f9945d6908 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -345,14 +345,7 @@ optimize_uops( assert(!PyErr_Occurred()); PyFunctionObject *func = tstate->jit_tracer_state.initial_state.func; - JitOptContext *ctx = tstate->jit_tracer_state.opt_state.opt_context; - if (ctx == NULL) { - ctx = (JitOptContext *)PyMem_RawMalloc(sizeof(JitOptContext)); - if (ctx == NULL) { - return 0; - } - tstate->jit_tracer_state.opt_state.opt_context = ctx; - } + JitOptContext *ctx = &tstate->jit_tracer_state.opt_context; uint32_t opcode = UINT16_MAX; // Make sure that watchers are set up diff --git a/Python/pystate.c b/Python/pystate.c index 8064abce86fe2b..74507efa5b4cf3 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1553,8 +1553,6 @@ init_threadstate(_PyThreadStateImpl *_tstate, init_policy(&_tstate->policy.jit.side_exit_initial_backoff, "PYTHON_JIT_SIDE_EXIT_INITIAL_BACKOFF", SIDE_EXIT_INITIAL_BACKOFF, 0, MAX_BACKOFF); - _tstate->jit_tracer_state.code_buffer = NULL; - _tstate->jit_tracer_state.opt_state.opt_context = NULL; #endif tstate->delete_later = NULL; @@ -1869,18 +1867,6 @@ tstate_delete_common(PyThreadState *tstate, int release_gil) assert(tstate_impl->refcounts.values == NULL); #endif -#if _Py_TIER2 - _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate; - if (_tstate->jit_tracer_state.code_buffer != NULL) { - _PyObject_VirtualFree(_tstate->jit_tracer_state.code_buffer, UOP_BUFFER_SIZE); - _tstate->jit_tracer_state.code_buffer = NULL; - } - if (_tstate->jit_tracer_state.opt_state.opt_context != NULL) { - PyMem_RawFree(_tstate->jit_tracer_state.opt_state.opt_context); - _tstate->jit_tracer_state.opt_state.opt_context = NULL; - } -#endif - HEAD_UNLOCK(runtime); // XXX Unbind in PyThreadState_Clear(), or earlier