https://github.com/python/cpython/commit/daa9aa4c0a8490f09b01339b6928434d7fe02843 commit: daa9aa4c0a8490f09b01339b6928434d7fe02843 branch: main author: Ken Jin <[email protected]> committer: Fidget-Spinner <[email protected]> date: 2025-12-28T22:12:31Z summary:
gh-143183: Rewind stop tracing to previous target (GH-143187) Co-authored-by: Kumar Aditya <[email protected]> files: A Misc/NEWS.d/next/Core_and_Builtins/2025-12-26-11-00-44.gh-issue-143183.rhxzZr.rst M Lib/test/test_capi/test_opt.py M Python/optimizer.c diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index d090b22f3bb81d..ea1606fd5b5f05 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -3306,6 +3306,48 @@ class B: ... for i in range(TIER2_THRESHOLD * 10): f1() + def test_143183(self): + # https://github.com/python/cpython/issues/143183 + + result = script_helper.run_python_until_end('-c', textwrap.dedent(f""" + def f1(): + class AsyncIter: + def __init__(self): + self.limit = 0 + self.count = 0 + + def __aiter__(self): + return self + + async def __anext__(self): + if self.count >= self.limit: + ... + self.count += 1j + + class AsyncCtx: + async def async_for_driver(): + try: + for _ in range({TIER2_THRESHOLD}): + try: + async for _ in AsyncIter(): + ... + except TypeError: + ... + except Exception: + ... + + c = async_for_driver() + while True: + try: + c.send(None) + except StopIteration: + break + + for _ in range({TIER2_THRESHOLD // 40}): + f1() + """), PYTHON_JIT="1") + self.assertEqual(result[0].rc, 0, result) + def global_identity(x): return x diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-12-26-11-00-44.gh-issue-143183.rhxzZr.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-26-11-00-44.gh-issue-143183.rhxzZr.rst new file mode 100644 index 00000000000000..bee2eb672e8813 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-26-11-00-44.gh-issue-143183.rhxzZr.rst @@ -0,0 +1 @@ +Fix a bug in the JIT when dealing with unsupported control-flow or operations. diff --git a/Python/optimizer.c b/Python/optimizer.c index 5e97f20f869efd..b497ac629960ac 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -625,6 +625,7 @@ _PyJit_translate_single_bytecode_to_trace( int trace_length = _tstate->jit_tracer_state.prev_state.code_curr_size; _PyUOpInstruction *trace = _tstate->jit_tracer_state.code_buffer; int max_length = _tstate->jit_tracer_state.prev_state.code_max_size; + int exit_op = stop_tracing_opcode == 0 ? _EXIT_TRACE : stop_tracing_opcode; _Py_CODEUNIT *this_instr = _tstate->jit_tracer_state.prev_state.instr; _Py_CODEUNIT *target_instr = this_instr; @@ -691,8 +692,11 @@ _PyJit_translate_single_bytecode_to_trace( } if (stop_tracing_opcode != 0) { - ADD_TO_TRACE(stop_tracing_opcode, 0, 0, target); - goto done; + // gh-143183: It's important we rewind to the last known proper target. + // The current target might be garbage as stop tracing usually indicates + // we are in something that we can't trace. + DPRINTF(2, "Told to stop tracing\n"); + goto unsupported; } DPRINTF(2, "%p %d: %s(%d) %d %d\n", old_code, target, _PyOpcode_OpName[opcode], oparg, needs_guard_ip, old_stack_level); @@ -703,10 +707,6 @@ _PyJit_translate_single_bytecode_to_trace( } #endif - if (opcode == ENTER_EXECUTOR) { - goto full; - } - if (!_tstate->jit_tracer_state.prev_state.dependencies_still_valid) { goto full; } @@ -720,11 +720,6 @@ _PyJit_translate_single_bytecode_to_trace( if (oparg > 0xFFFF) { DPRINTF(2, "Unsupported: oparg too large\n"); - goto unsupported; - } - - // TODO (gh-140277): The constituent use one extra stack slot. So we need to check for headroom. - if (opcode == BINARY_OP_SUBSCR_GETITEM && old_stack_level + 1 > old_code->co_stacksize) { unsupported: { // Rewind to previous instruction and replace with _EXIT_TRACE. @@ -738,7 +733,7 @@ _PyJit_translate_single_bytecode_to_trace( int32_t old_target = (int32_t)uop_get_target(curr); curr++; trace_length++; - curr->opcode = _EXIT_TRACE; + curr->opcode = exit_op; curr->format = UOP_FORMAT_TARGET; curr->target = old_target; } @@ -746,6 +741,7 @@ _PyJit_translate_single_bytecode_to_trace( } } + if (opcode == NOP) { return 1; } _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]
