diff --git a/Python/ceval.c b/Python/ceval.c index 46bf644106a..a43cc60a9e4 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1408,7 +1408,9 @@ stop_tracing_and_jit(PyThreadState *tstate, _PyInterpreterFrame *frame) // 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) { - exit->temperature = restart_backoff_counter(exit->temperature); + if (exit->executor->vm_data.linked || exit->executor->vm_data.valid) { + exit->temperature = restart_backoff_counter(exit->temperature); + } } else { exit->temperature = initial_temperature_backoff_counter(); diff --git a/Python/optimizer.c b/Python/optimizer.c index 9db894f0bf0..1cbb1ffd16d 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -140,6 +140,14 @@ _PyOptimizer_Optimize( } assert(!interp->compiling); assert(_tstate->jit_tracer_state.initial_state.stack_depth >= 0); + _PyExitData *exit = _tstate->jit_tracer_state.initial_state.exit; + _PyExecutorObject *cold_executor = _PyExecutor_GetColdExecutor(); + if (exit != NULL && + (!exit->executor->vm_data.linked || !exit->executor->vm_data.valid) && + exit->executor != cold_executor) { + // gh-141786 Parent executor is either unlinked or invalid - cannot optimize. + return 0; + } #ifndef Py_GIL_DISABLED assert(_tstate->jit_tracer_state.initial_state.func != NULL); interp->compiling = true; @@ -185,7 +193,6 @@ _PyOptimizer_Optimize( else { executor->vm_data.code = NULL; } - _PyExitData *exit = _tstate->jit_tracer_state.initial_state.exit; if (exit != NULL) { exit->executor = executor; }