diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-10-28-22-15-00.gh-issue-160852.st0pTr.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-28-22-15-00.gh-issue-160852.st0pTr.rst new file mode 100644 index 000000000000000..dcf86d6f06323e6 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-28-22-15-00.gh-issue-160852.st0pTr.rst @@ -0,0 +1,2 @@ +Fix a crash in the experimental JIT when a finalizer invalidates an +executor while ``stop_tracing`` leaves the tracer. diff --git a/Modules/_testinternalcapi/test_cases.c.h b/Modules/_testinternalcapi/test_cases.c.h index 8e7ba1f69553dda..10e1dfc91248b89 100644 --- a/Modules/_testinternalcapi/test_cases.c.h +++ b/Modules/_testinternalcapi/test_cases.c.h @@ -13836,6 +13836,8 @@ JUMP_TO_LABEL(error); if (err < 0) { JUMP_TO_LABEL(error); } + opcode = next_instr->op.code; + oparg = (oparg & ~255) | next_instr->op.arg; DISPATCH_GOTO_NON_TRACING(); #else Py_FatalError("JIT label executed in non-jit build."); diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 42ad83daa1ea461..d6b25d5ad1b29e5 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -6636,6 +6636,16 @@ dummy_func( LEAVE_TRACING(); int err = stop_tracing_and_jit(tstate, frame); ERROR_IF(err < 0); + /* stop_tracing_and_jit() can drop the last reference to a + temporary and run a finalizer. A ResourceWarning then writes + __warningregistry__ into a watched globals dict, and + executor_invalidate() restores this instruction and clears its + executor slot. Dispatching the ENTER_EXECUTOR opcode sampled + above calls _PyJIT_Entry(NULL). Keep any EXTENDED_ARG bits + already accumulated in oparg; only the low byte lives in the + code unit. */ + opcode = next_instr->op.code; + oparg = (oparg & ~255) | next_instr->op.arg; DISPATCH_GOTO_NON_TRACING(); #else Py_FatalError("JIT label executed in non-jit build."); diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index ee9b64107bb9f24..2775d918e024167 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -13833,6 +13833,8 @@ JUMP_TO_LABEL(error); if (err < 0) { JUMP_TO_LABEL(error); } + opcode = next_instr->op.code; + oparg = (oparg & ~255) | next_instr->op.arg; DISPATCH_GOTO_NON_TRACING(); #else Py_FatalError("JIT label executed in non-jit build.");