Skip to content

Commit bdd2123

Browse files
Stop recursive traces
1 parent 1f8c3df commit bdd2123

File tree

7 files changed

+66
-18
lines changed

7 files changed

+66
-18
lines changed

Include/internal/pycore_opcode_metadata.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_optimizer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,8 +361,8 @@ extern void _Py_ClearExecutorDeletionList(PyInterpreterState *interp);
361361

362362
int _PyJit_translate_single_bytecode_to_trace(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *next_instr);
363363

364-
void
365-
_PyJit_InitializeTracing(PyThreadState *tstate, _PyInterpreterFrame *frame,
364+
int
365+
_PyJit_TryInitializeTracing(PyThreadState *tstate, _PyInterpreterFrame *frame,
366366
_Py_CODEUNIT *curr_instr, _Py_CODEUNIT *insert_exec_instr,
367367
_Py_CODEUNIT *close_loop_instr, int curr_stackdepth, int chain_depth, _PyExitData *exit, int oparg);
368368

Python/bytecodes.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2972,8 +2972,10 @@ dummy_func(
29722972
oparg >>= 8;
29732973
insert_exec_at--;
29742974
}
2975-
_PyJit_InitializeTracing(tstate, frame, this_instr, insert_exec_at, next_instr, STACK_LEVEL(), 0, NULL, oparg);
2976-
ENTER_TRACING();
2975+
int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, next_instr, STACK_LEVEL(), 0, NULL, oparg);
2976+
if (succ) {
2977+
ENTER_TRACING();
2978+
}
29772979
}
29782980
}
29792981
else {
@@ -3019,6 +3021,15 @@ dummy_func(
30193021

30203022
tier1 inst(ENTER_EXECUTOR, (--)) {
30213023
#ifdef _Py_TIER2
3024+
// We want to end any current trace here, before we possibly need
3025+
// to start tracing new ones due to recursive traces in any inner C functions
3026+
// in tier2 code.
3027+
if (IS_JIT_TRACING()) {
3028+
_PyJit_translate_single_bytecode_to_trace(tstate, frame, next_instr);
3029+
LEAVE_TRACING();
3030+
int err = bail_tracing_and_jit(tstate, frame);
3031+
ERROR_IF(err < 0);
3032+
}
30223033
PyCodeObject *code = _PyFrame_GetCode(frame);
30233034
_PyExecutorObject *executor = code->co_executors->executors[oparg & 255];
30243035
assert(executor->vm_data.index == INSTR_OFFSET() - 1);
@@ -5428,9 +5439,12 @@ dummy_func(
54285439
// Note: it's safe to use target->op.arg here instead of the oparg given by EXTENDED_ARG.
54295440
// The invariant in the optimizer is the deopt target always points back to the first EXTENDED_ARG.
54305441
// So setting it to anything else is wrong.
5431-
_PyJit_InitializeTracing(tstate, frame, target, target, target, STACK_LEVEL(), chain_depth, exit, target->op.arg);
5442+
int succ = _PyJit_TryInitializeTracing(tstate, frame, target, target, target, STACK_LEVEL(), chain_depth, exit, target->op.arg);
54325443
exit->temperature = initial_temperature_backoff_counter();
5433-
GOTO_TIER_ONE_CONTINUE_TRACING(target);
5444+
if (succ) {
5445+
GOTO_TIER_ONE_CONTINUE_TRACING(target);
5446+
}
5447+
GOTO_TIER_ONE(target);
54345448
}
54355449
assert(tstate->jit_exit == exit);
54365450
exit->executor = executor;
@@ -5636,7 +5650,9 @@ dummy_func(
56365650
}
56375651
tstate->interp->jit_state.specialize_counter = 0;
56385652
PyCodeObject *prev_code = (PyCodeObject *)Py_NewRef(_PyFrame_GetCode(frame));
5639-
Py_SETREF(tstate->interp->jit_state.prev_instr_code, prev_code);
5653+
if (tstate->interp->jit_state.prev_instr_code != prev_code) {
5654+
Py_SETREF(tstate->interp->jit_state.prev_instr_code, prev_code);
5655+
}
56405656

56415657
tstate->interp->jit_state.prev_instr_frame = frame;
56425658
tstate->interp->jit_state.prev_instr_oparg = oparg;

Python/executor_cases.c.h

Lines changed: 5 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/generated_cases.c.h

Lines changed: 22 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/optimizer.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,11 @@ _PyJit_translate_single_bytecode_to_trace(
619619
}
620620

621621
if (opcode == ENTER_EXECUTOR) {
622+
int is_first_instr = tstate->interp->jit_state.close_loop_instr == next_instr || tstate->interp->jit_state.insert_exec_instr == next_instr;
623+
if (is_first_instr && tstate->interp->jit_state.code_curr_size > 5) {
624+
ADD_TO_TRACE(_JUMP_TO_TOP, 0, 0, 0);
625+
goto done;
626+
}
622627
goto full;
623628
}
624629

@@ -925,9 +930,15 @@ _PyJit_translate_single_bytecode_to_trace(
925930
return 0;
926931
}
927932

928-
void
929-
_PyJit_InitializeTracing(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *curr_instr, _Py_CODEUNIT *insert_exec_instr, _Py_CODEUNIT *close_loop_instr, int curr_stackdepth, int chain_depth, _PyExitData *exit, int oparg)
933+
// Returns 0 for do not enter tracing, 1 on enter tracing.
934+
int
935+
_PyJit_TryInitializeTracing(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *curr_instr, _Py_CODEUNIT *insert_exec_instr, _Py_CODEUNIT *close_loop_instr, int curr_stackdepth, int chain_depth, _PyExitData *exit, int oparg)
930936
{
937+
// A recursive trace.
938+
// Don't trace into the inner call because it will stomp on the previous trace, causing endless retraces.
939+
if (tstate->interp->jit_state.code_curr_size > 2) {
940+
return 0;
941+
}
931942
PyCodeObject *code = _PyFrame_GetCode(frame);
932943
#ifdef Py_DEBUG
933944
char *python_lltrace = Py_GETENV("PYTHON_LLTRACE");
@@ -965,6 +976,7 @@ _PyJit_InitializeTracing(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_
965976
tstate->interp->jit_state.dynamic_jump_taken = false;
966977
tstate->interp->jit_state.prev_instr_is_super = false;
967978
_Py_BloomFilter_Init(&tstate->interp->jit_state.dependencies);
979+
return 1;
968980
}
969981

970982
void

Tools/cases_generator/analyzer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ def has_error_without_pop(op: parser.CodeDef) -> bool:
699699
"PyStackRef_Unwrap",
700700
"_PyLong_CheckExactAndCompact",
701701
"_PyExecutor_FromExit",
702-
"_PyJit_InitializeTracing",
702+
"_PyJit_TryInitializeTracing",
703703
)
704704

705705

0 commit comments

Comments
 (0)