diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 25b2c393e6773de..5806216d46e7eb6 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -5127,6 +5127,16 @@ def f(): f" {executor} at offset {idx} rather" f" than expected _EXIT_TRACE") + def test_jit_shutdown_after_cold_executor_creation(self): + script_helper.assert_python_ok("-c", textwrap.dedent(f""" + def f(): + for x in range({TIER2_THRESHOLD + 3}): + for y in range({TIER2_THRESHOLD + 3}): + z = x + y + + f() + """), PYTHON_JIT="1") + def test_enter_executor_valid_op_arg(self): script_helper.assert_python_ok("-c", textwrap.dedent(""" import sys diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-07-19-16-18-25.gh-issue-154014.CJsjVL.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-07-19-16-18-25.gh-issue-154014.CJsjVL.rst new file mode 100644 index 000000000000000..6bdcf83725168a2 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-07-19-16-18-25.gh-issue-154014.CJsjVL.rst @@ -0,0 +1,2 @@ +Fix a JIT assertion during interpreter shutdown by initializing ``vm_data`` +fields for cold executors that bypass ``_Py_ExecutorInit()``. diff --git a/Python/optimizer.c b/Python/optimizer.c index c9f6ebdb62f07b2..e05adb344c8d06d 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -1797,6 +1797,11 @@ make_cold_executor(uint16_t opcode) Py_FatalError("Cannot allocate core JIT code"); } ((_PyUOpInstruction *)cold->trace)->opcode = opcode; + // Cold executors bypass _Py_ExecutorInit(). + cold->vm_data.valid = true; + cold->vm_data.pending_deletion = 0; + cold->vm_data.code = NULL; + // This is initialized to false so we can prevent the executor // from being immediately detected as cold and invalidated. cold->vm_data.cold = false; @@ -1804,7 +1809,7 @@ make_cold_executor(uint16_t opcode) cold->jit_code = NULL; cold->jit_size = 0; if (_PyJIT_Compile(cold, cold->trace, 1)) { - Py_DECREF(cold); + _PyExecutor_Free(cold); Py_FatalError("Cannot allocate core JIT code"); } #endif