Skip to content

Commit a233064

Browse files
Rewind stop tracing to previous target
1 parent 888d101 commit a233064

File tree

2 files changed

+48
-3
lines changed

2 files changed

+48
-3
lines changed

Lib/test/test_capi/test_opt.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3194,6 +3194,48 @@ class B: ...
31943194
for i in range(TIER2_THRESHOLD * 10):
31953195
f1()
31963196

3197+
def test_143183(self):
3198+
# https://github.com/python/cpython/issues/143183
3199+
3200+
result = script_helper.run_python_until_end('-c', textwrap.dedent(f"""
3201+
def f1():
3202+
class AsyncIter:
3203+
def __init__(self):
3204+
self.limit = 0
3205+
self.count = 0
3206+
3207+
def __aiter__(self):
3208+
return self
3209+
3210+
async def __anext__(self):
3211+
if self.count >= self.limit:
3212+
...
3213+
self.count += 1j
3214+
3215+
class AsyncCtx:
3216+
async def async_for_driver():
3217+
try:
3218+
for _ in range({TIER2_THRESHOLD}):
3219+
try:
3220+
async for _ in AsyncIter():
3221+
...
3222+
except TypeError:
3223+
...
3224+
except Exception:
3225+
...
3226+
3227+
c = async_for_driver()
3228+
while True:
3229+
try:
3230+
c.send(None)
3231+
except StopIteration:
3232+
break
3233+
3234+
for _ in range({TIER2_THRESHOLD // 40}):
3235+
f1()
3236+
"""), PYTHON_JIT="1")
3237+
self.assertEqual(result[0].rc, 0, result)
3238+
31973239
def global_identity(x):
31983240
return x
31993241

Python/optimizer.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,7 @@ _PyJit_translate_single_bytecode_to_trace(
625625
int trace_length = _tstate->jit_tracer_state.prev_state.code_curr_size;
626626
_PyUOpInstruction *trace = _tstate->jit_tracer_state.code_buffer;
627627
int max_length = _tstate->jit_tracer_state.prev_state.code_max_size;
628+
int exit_op = stop_tracing_opcode == 0 ? _EXIT_TRACE : stop_tracing_opcode;
628629

629630
_Py_CODEUNIT *this_instr = _tstate->jit_tracer_state.prev_state.instr;
630631
_Py_CODEUNIT *target_instr = this_instr;
@@ -691,8 +692,10 @@ _PyJit_translate_single_bytecode_to_trace(
691692
}
692693

693694
if (stop_tracing_opcode != 0) {
694-
ADD_TO_TRACE(stop_tracing_opcode, 0, 0, target);
695-
goto done;
695+
// gh-143183: It's important we rewind to the last known proper target.
696+
// The current target mgiht be garbage as stop tracing usually indicates
697+
// we are in something that we can't trace.
698+
goto unsupported;
696699
}
697700

698701
DPRINTF(2, "%p %d: %s(%d) %d %d\n", old_code, target, _PyOpcode_OpName[opcode], oparg, needs_guard_ip, old_stack_level);
@@ -738,7 +741,7 @@ _PyJit_translate_single_bytecode_to_trace(
738741
int32_t old_target = (int32_t)uop_get_target(curr);
739742
curr++;
740743
trace_length++;
741-
curr->opcode = _EXIT_TRACE;
744+
curr->opcode = exit_op;
742745
curr->format = UOP_FORMAT_TARGET;
743746
curr->target = old_target;
744747
}

0 commit comments

Comments
 (0)