mirror of
https://github.com/python/cpython.git
synced 2026-04-14 07:41:00 +00:00
gh-143604: Hold strong reference to executor during JIT tracing (GH-143646)
Co-authored-by: Ken Jin <kenjin4096@gmail.com>
This commit is contained in:
parent
e7f5ffa0de
commit
e2f0160026
10 changed files with 41 additions and 8 deletions
|
|
@ -2990,7 +2990,7 @@ dummy_func(
|
|||
oparg >>= 8;
|
||||
insert_exec_at--;
|
||||
}
|
||||
int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, next_instr, STACK_LEVEL(), 0, NULL, oparg);
|
||||
int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, next_instr, STACK_LEVEL(), 0, NULL, oparg, NULL);
|
||||
if (succ) {
|
||||
ENTER_TRACING();
|
||||
}
|
||||
|
|
@ -5525,7 +5525,7 @@ dummy_func(
|
|||
// Note: it's safe to use target->op.arg here instead of the oparg given by EXTENDED_ARG.
|
||||
// The invariant in the optimizer is the deopt target always points back to the first EXTENDED_ARG.
|
||||
// So setting it to anything else is wrong.
|
||||
int succ = _PyJit_TryInitializeTracing(tstate, frame, target, target, target, STACK_LEVEL(), chain_depth, exit, target->op.arg);
|
||||
int succ = _PyJit_TryInitializeTracing(tstate, frame, target, target, target, STACK_LEVEL(), chain_depth, exit, target->op.arg, previous_executor);
|
||||
exit->temperature = restart_backoff_counter(exit->temperature);
|
||||
if (succ) {
|
||||
GOTO_TIER_ONE_CONTINUE_TRACING(target);
|
||||
|
|
|
|||
|
|
@ -1475,7 +1475,7 @@ stop_tracing_and_jit(PyThreadState *tstate, _PyInterpreterFrame *frame)
|
|||
tracer->initial_state.jump_backward_instr[1].counter = initial_jump_backoff_counter(&_tstate->policy);
|
||||
}
|
||||
}
|
||||
else {
|
||||
else if (tracer->initial_state.executor->vm_data.valid) {
|
||||
// Likewise, we hold a strong reference to the executor containing this exit, so the exit is guaranteed
|
||||
// to be valid to access.
|
||||
if (err <= 0) {
|
||||
|
|
|
|||
2
Python/executor_cases.c.h
generated
2
Python/executor_cases.c.h
generated
|
|
@ -18996,7 +18996,7 @@
|
|||
_PyExecutorObject *previous_executor = _PyExecutor_FromExit(exit);
|
||||
assert(tstate->current_executor == (PyObject *)previous_executor);
|
||||
int chain_depth = previous_executor->vm_data.chain_depth + !exit->is_control_flow;
|
||||
int succ = _PyJit_TryInitializeTracing(tstate, frame, target, target, target, STACK_LEVEL(), chain_depth, exit, target->op.arg);
|
||||
int succ = _PyJit_TryInitializeTracing(tstate, frame, target, target, target, STACK_LEVEL(), chain_depth, exit, target->op.arg, previous_executor);
|
||||
exit->temperature = restart_backoff_counter(exit->temperature);
|
||||
if (succ) {
|
||||
GOTO_TIER_ONE_CONTINUE_TRACING(target);
|
||||
|
|
|
|||
2
Python/generated_cases.c.h
generated
2
Python/generated_cases.c.h
generated
|
|
@ -7662,7 +7662,7 @@
|
|||
oparg >>= 8;
|
||||
insert_exec_at--;
|
||||
}
|
||||
int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, next_instr, STACK_LEVEL(), 0, NULL, oparg);
|
||||
int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, next_instr, STACK_LEVEL(), 0, NULL, oparg, NULL);
|
||||
if (succ) {
|
||||
ENTER_TRACING();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,6 +138,12 @@ _PyOptimizer_Optimize(
|
|||
// return immediately without optimization.
|
||||
return 0;
|
||||
}
|
||||
_PyExecutorObject *prev_executor = _tstate->jit_tracer_state->initial_state.executor;
|
||||
if (prev_executor != NULL && !prev_executor->vm_data.valid) {
|
||||
// gh-143604: If we are a side exit executor and the original executor is no
|
||||
// longer valid, don't compile to prevent a reference leak.
|
||||
return 0;
|
||||
}
|
||||
assert(!interp->compiling);
|
||||
assert(_tstate->jit_tracer_state->initial_state.stack_depth >= 0);
|
||||
#ifndef Py_GIL_DISABLED
|
||||
|
|
@ -1015,7 +1021,7 @@ Py_NO_INLINE int
|
|||
_PyJit_TryInitializeTracing(
|
||||
PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *curr_instr,
|
||||
_Py_CODEUNIT *start_instr, _Py_CODEUNIT *close_loop_instr, int curr_stackdepth, int chain_depth,
|
||||
_PyExitData *exit, int oparg)
|
||||
_PyExitData *exit, int oparg, _PyExecutorObject *current_executor)
|
||||
{
|
||||
_PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
|
||||
if (_tstate->jit_tracer_state == NULL) {
|
||||
|
|
@ -1062,6 +1068,7 @@ _PyJit_TryInitializeTracing(
|
|||
tracer->initial_state.close_loop_instr = close_loop_instr;
|
||||
tracer->initial_state.code = (PyCodeObject *)Py_NewRef(code);
|
||||
tracer->initial_state.func = (PyFunctionObject *)Py_NewRef(func);
|
||||
tracer->initial_state.executor = (_PyExecutorObject *)Py_XNewRef(current_executor);
|
||||
tracer->initial_state.exit = exit;
|
||||
tracer->initial_state.stack_depth = curr_stackdepth;
|
||||
tracer->initial_state.chain_depth = chain_depth;
|
||||
|
|
@ -1089,6 +1096,7 @@ _PyJit_FinalizeTracing(PyThreadState *tstate)
|
|||
_PyJitTracerState *tracer = _tstate->jit_tracer_state;
|
||||
Py_CLEAR(tracer->initial_state.code);
|
||||
Py_CLEAR(tracer->initial_state.func);
|
||||
Py_CLEAR(tracer->initial_state.executor);
|
||||
Py_CLEAR(tracer->prev_state.instr_code);
|
||||
tracer->prev_state.code_curr_size = CODE_SIZE_EMPTY;
|
||||
tracer->prev_state.code_max_size = UOP_MAX_TRACE_LENGTH/2 - 1;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue