Skip to content

Commit 1d3aed1

Browse files
properly restore exponential backoffs
1 parent 01c2d73 commit 1d3aed1

File tree

7 files changed

+36
-10
lines changed

7 files changed

+36
-10
lines changed

Include/internal/pycore_interp_structs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,8 @@ typedef struct _PyJitTracerState {
775775
_Py_CODEUNIT *prev_instr;
776776
PyCodeObject *prev_instr_code; // Strong
777777
struct _PyExitData *prev_exit;
778+
struct _PyExecutorObject *prev_executor; // Strong
779+
_Py_CODEUNIT *jump_backward_instr;
778780
_PyInterpreterFrame *prev_instr_frame;
779781
_PyBloomFilter dependencies;
780782
} _PyJitTracerState;

Include/internal/pycore_optimizer.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,8 @@ int _PyJit_translate_single_bytecode_to_trace(PyThreadState *tstate, _PyInterpre
365365
int
366366
_PyJit_TryInitializeTracing(PyThreadState *tstate, _PyInterpreterFrame *frame,
367367
_Py_CODEUNIT *curr_instr, _Py_CODEUNIT *insert_exec_instr,
368-
_Py_CODEUNIT *close_loop_instr, int curr_stackdepth, int chain_depth, _PyExitData *exit, int oparg);
368+
_Py_CODEUNIT *close_loop_instr, int curr_stackdepth, int chain_depth, _PyExitData *exit,
369+
_PyExecutorObject *prev_exec, int oparg);
369370

370371
void _PyJit_FinalizeTracing(PyThreadState *tstate);
371372

Python/bytecodes.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2956,7 +2956,6 @@ dummy_func(
29562956
if (!IS_JIT_TRACING() && backoff_counter_triggers(counter) &&
29572957
this_instr->op.code == JUMP_BACKWARD_JIT &&
29582958
next_instr->op.code != ENTER_EXECUTOR) {
2959-
this_instr[1].counter = restart_backoff_counter(counter);
29602959
if (tstate->interp->jit_state.code_buffer == NULL) {
29612960
tstate->interp->jit_state.code_buffer = (_PyUOpInstruction *)_PyObject_VirtualAlloc(UOP_BUFFER_SIZE);
29622961
if (tstate->interp->jit_state.code_buffer == NULL) {
@@ -2972,7 +2971,7 @@ dummy_func(
29722971
oparg >>= 8;
29732972
insert_exec_at--;
29742973
}
2975-
int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, next_instr, STACK_LEVEL(), 0, NULL, oparg);
2974+
int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, next_instr, STACK_LEVEL(), 0, NULL, NULL, oparg);
29762975
if (succ) {
29772976
ENTER_TRACING();
29782977
}
@@ -5432,8 +5431,7 @@ dummy_func(
54325431
// Note: it's safe to use target->op.arg here instead of the oparg given by EXTENDED_ARG.
54335432
// The invariant in the optimizer is the deopt target always points back to the first EXTENDED_ARG.
54345433
// So setting it to anything else is wrong.
5435-
int succ = _PyJit_TryInitializeTracing(tstate, frame, target, target, target, STACK_LEVEL(), chain_depth, exit, target->op.arg);
5436-
exit->temperature = initial_temperature_backoff_counter();
5434+
int succ = _PyJit_TryInitializeTracing(tstate, frame, target, target, target, STACK_LEVEL(), chain_depth, exit, previous_executor, target->op.arg);
54375435
if (succ) {
54385436
GOTO_TIER_ONE_CONTINUE_TRACING(target);
54395437
}

Python/ceval.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,29 @@ bail_tracing_and_jit(PyThreadState *tstate, _PyInterpreterFrame *frame)
998998
if (!_PyErr_Occurred(tstate) && !_is_sys_tracing) {
999999
err = _PyOptimizer_Optimize(frame, tstate);
10001000
}
1001+
// Deal with backoffs
1002+
_PyExitData *exit = tstate->interp->jit_state.prev_exit;
1003+
if (exit == NULL) {
1004+
// We hold a strong reference to the code object, so the instruction won't be freed.
1005+
if (err <= 0) {
1006+
assert(tstate->interp->jit_state.jump_backward_instr->op.code == JUMP_BACKWARD_JIT);
1007+
_Py_BackoffCounter counter = tstate->interp->jit_state.jump_backward_instr[1].counter;
1008+
tstate->interp->jit_state.jump_backward_instr[1].counter = restart_backoff_counter(counter);
1009+
}
1010+
else {
1011+
tstate->interp->jit_state.jump_backward_instr[1].counter = initial_jump_backoff_counter();
1012+
}
1013+
}
1014+
else {
1015+
// Likewise, we hold a strong reference to the executor containing this exit, so the exit is guaranteed
1016+
// to be valid to access.
1017+
if (err <= 0) {
1018+
exit->temperature = restart_backoff_counter(exit->temperature);
1019+
}
1020+
else {
1021+
exit->temperature = initial_temperature_backoff_counter();
1022+
}
1023+
}
10011024
_PyJit_FinalizeTracing(tstate);
10021025
return err;
10031026
}

Python/executor_cases.c.h

Lines changed: 1 addition & 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: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/optimizer.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -949,7 +949,7 @@ _PyJit_translate_single_bytecode_to_trace(
949949

950950
// Returns 0 for do not enter tracing, 1 on enter tracing.
951951
int
952-
_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)
952+
_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, _PyExecutorObject *prev_exec, int oparg)
953953
{
954954
// A recursive trace.
955955
// Don't trace into the inner call because it will stomp on the previous trace, causing endless retraces.
@@ -991,6 +991,9 @@ _PyJit_TryInitializeTracing(PyThreadState *tstate, _PyInterpreterFrame *frame, _
991991
tstate->interp->jit_state.prev_instr_oparg = oparg;
992992
tstate->interp->jit_state.prev_instr_stacklevel = curr_stackdepth;
993993
tstate->interp->jit_state.prev_instr_is_super = false;
994+
assert(curr_instr->op.code == JUMP_BACKWARD_JIT || (prev_exec != NULL && exit != NULL));
995+
tstate->interp->jit_state.jump_backward_instr = curr_instr;
996+
tstate->interp->jit_state.prev_executor = (_PyExecutorObject *)Py_XNewRef(prev_exec);
994997
_Py_BloomFilter_Init(&tstate->interp->jit_state.dependencies);
995998
return 1;
996999
}
@@ -1001,6 +1004,7 @@ _PyJit_FinalizeTracing(PyThreadState *tstate)
10011004
Py_CLEAR(tstate->interp->jit_state.initial_code);
10021005
Py_CLEAR(tstate->interp->jit_state.initial_func);
10031006
Py_CLEAR(tstate->interp->jit_state.prev_instr_code);
1007+
Py_CLEAR(tstate->interp->jit_state.prev_executor);
10041008
tstate->interp->jit_state.code_curr_size = 2;
10051009
tstate->interp->jit_state.code_max_size = UOP_MAX_TRACE_LENGTH - 1;
10061010
}

0 commit comments

Comments
 (0)