gh-143421: Move JitOptContext from stack allocation to per-thread heap allocation (GH-143536)

* move JitOptContext to _PyThreadStateImpl
* make _PyUOpInstruction buffer a part of _PyThreadStateImpl

Co-authored-by: Kumar Aditya <kumaraditya@python.org>
This commit is contained in:
Hai Zhu 2026-01-09 03:38:21 +08:00 committed by GitHub
parent cea2d2475d
commit aeb3403563
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 150 additions and 147 deletions

View file

@ -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;
@ -1484,8 +1477,8 @@ uop_optimize(
OPT_STAT_INC(traces_created);
if (!is_noopt) {
length = _Py_uop_analyze_and_optimize(
_tstate->jit_tracer_state.initial_state.func,
buffer,length,
_tstate,
buffer, length,
curr_stackentries, dependencies);
if (length <= 0) {
return length;

View file

@ -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,7 +335,7 @@ _Py_opt_assert_within_stack_bounds(
/* >0 (length) for success, 0 for not ready, clears all possible errors. */
static int
optimize_uops(
PyFunctionObject *func,
_PyThreadStateImpl *tstate,
_PyUOpInstruction *trace,
int trace_len,
int curr_stacklen,
@ -342,9 +343,9 @@ optimize_uops(
)
{
assert(!PyErr_Occurred());
PyFunctionObject *func = tstate->jit_tracer_state.initial_state.func;
JitOptContext context;
JitOptContext *ctx = &context;
JitOptContext *ctx = &tstate->jit_tracer_state.opt_context;
uint32_t opcode = UINT16_MAX;
// Make sure that watchers are set up
@ -574,7 +575,7 @@ remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size)
// > 0 - length of optimized trace
int
_Py_uop_analyze_and_optimize(
PyFunctionObject *func,
_PyThreadStateImpl *tstate,
_PyUOpInstruction *buffer,
int length,
int curr_stacklen,
@ -584,7 +585,7 @@ _Py_uop_analyze_and_optimize(
OPT_STAT_INC(optimizer_attempts);
length = optimize_uops(
func, buffer,
tstate, buffer,
length, curr_stacklen, dependencies);
if (length == 0) {

View file

@ -1553,7 +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;
#endif
tstate->delete_later = NULL;
@ -1868,14 +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;
}
#endif
HEAD_UNLOCK(runtime);
// XXX Unbind in PyThreadState_Clear(), or earlier