Skip to content

Commit 9a66605

Browse files
Fix chain depth bug
1 parent 3e9f782 commit 9a66605

File tree

3 files changed

+31
-22
lines changed

3 files changed

+31
-22
lines changed

Python/bytecodes.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5289,6 +5289,7 @@ dummy_func(
52895289
}
52905290
#endif
52915291
tstate->jit_exit = exit;
5292+
assert(!exit->is_dynamic);
52925293
TIER2_TO_TIER2(exit->executor);
52935294
}
52945295

@@ -5454,7 +5455,7 @@ dummy_func(
54545455
}
54555456
_PyExecutorObject *previous_executor = _PyExecutor_FromExit(exit);
54565457
assert(tstate->current_executor == (PyObject *)previous_executor);
5457-
int chain_depth = 0;
5458+
int chain_depth = is_dynamic ? 0 : current_executor->vm_data.chain_depth + 1;
54585459
_PyJIT_InitializeTracing(tstate, frame, target, STACK_LEVEL(), chain_depth);
54595460
GOTO_TIER_ONE(target, 1);
54605461
}

Python/executor_cases.c.h

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

Python/optimizer.c

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ insert_executor(PyCodeObject *code, _Py_CODEUNIT *instr, int index, _PyExecutorO
102102
}
103103

104104
static _PyExecutorObject *
105-
make_executor_from_uops(_PyUOpInstruction *buffer, int length, const _PyBloomFilter *dependencies);
105+
make_executor_from_uops(_PyUOpInstruction *buffer, int length, const _PyBloomFilter *dependencies, int chain_depth);
106106

107107
static int
108108
uop_optimize(_PyInterpreterFrame *frame, PyThreadState *tstate,
@@ -128,8 +128,7 @@ _PyOptimizer_Optimize(
128128
// make progress in order to avoid infinite loops or excessively-long
129129
// side-exit chains. We can only insert the executor into the bytecode if
130130
// this is true, since a deopt won't infinitely re-enter the executor:
131-
chain_depth %= MAX_CHAIN_DEPTH;
132-
bool progress_needed = chain_depth == 0;
131+
bool progress_needed = (chain_depth % MAX_CHAIN_DEPTH) == 0;
133132
PyCodeObject *code = (PyCodeObject *)tstate->interp->jit_tracer_initial_func->func_code;
134133
assert(PyCode_Check(code));
135134
_Py_CODEUNIT *start = tstate->interp->jit_tracer_initial_instr;
@@ -144,19 +143,24 @@ _PyOptimizer_Optimize(
144143
return err;
145144
}
146145
assert(executor != NULL);
147-
int index = get_index_for_executor(code, start);
148-
if (index < 0) {
149-
/* Out of memory. Don't raise and assume that the
150-
* error will show up elsewhere.
151-
*
152-
* If an optimizer has already produced an executor,
153-
* it might get confused by the executor disappearing,
154-
* but there is not much we can do about that here. */
155-
Py_DECREF(executor);
156-
interp->compiling = false;
157-
return 0;
146+
if (progress_needed) {
147+
int index = get_index_for_executor(code, start);
148+
if (index < 0) {
149+
/* Out of memory. Don't raise and assume that the
150+
* error will show up elsewhere.
151+
*
152+
* If an optimizer has already produced an executor,
153+
* it might get confused by the executor disappearing,
154+
* but there is not much we can do about that here. */
155+
Py_DECREF(executor);
156+
interp->compiling = false;
157+
return 0;
158+
}
159+
insert_executor(code, start, index, executor);
160+
}
161+
else {
162+
executor->vm_data.code = NULL;
158163
}
159-
insert_executor(code, start, index, executor);
160164
executor->vm_data.chain_depth = chain_depth;
161165
assert(executor->vm_data.valid);
162166
interp->compiling = false;
@@ -544,7 +548,8 @@ _PyJIT_translate_single_bytecode_to_trace(
544548
if (Py_IsNone((PyObject *)func)) {
545549
func = NULL;
546550
}
547-
bool progress_needed = (tstate->interp->jit_tracer_initial_chain_depth % MAX_CHAIN_DEPTH) == 0;;
551+
int is_first_instr = tstate->interp->jit_tracer_initial_instr == this_instr ;
552+
bool progress_needed = (tstate->interp->jit_tracer_initial_chain_depth % MAX_CHAIN_DEPTH) == 0 && is_first_instr;;
548553
_PyBloomFilter *dependencies = &tstate->interp->jit_tracer_dependencies;
549554
_Py_BloomFilter_Add(dependencies, old_code);
550555
_Py_CODEUNIT *target_instr = this_instr;
@@ -629,7 +634,7 @@ _PyJIT_translate_single_bytecode_to_trace(
629634

630635
/* Special case the first instruction,
631636
* so that we can guarantee forward progress */
632-
if (progress_needed && tstate->interp->jit_tracer_initial_instr == this_instr && tstate->interp->jit_tracer_code_curr_size == 0) {
637+
if (progress_needed && is_first_instr && tstate->interp->jit_tracer_code_curr_size == 0) {
633638
if (OPCODE_HAS_EXIT(opcode) || OPCODE_HAS_DEOPT(opcode)) {
634639
opcode = _PyOpcode_Deopt[opcode];
635640
}
@@ -638,7 +643,7 @@ _PyJIT_translate_single_bytecode_to_trace(
638643
}
639644

640645
// Loop back to the start
641-
if (tstate->interp->jit_tracer_initial_instr == this_instr && tstate->interp->jit_tracer_code_curr_size > 2) {
646+
if (is_first_instr && tstate->interp->jit_tracer_code_curr_size > 2) {
642647
// Undo the last few instructions.
643648
trace_length = tstate->interp->jit_tracer_code_curr_size;
644649
ADD_TO_TRACE(_JUMP_TO_TOP, 0, 0, 0);
@@ -1047,7 +1052,7 @@ sanity_check(_PyExecutorObject *executor)
10471052
* and not a NOP.
10481053
*/
10491054
static _PyExecutorObject *
1050-
make_executor_from_uops(_PyUOpInstruction *buffer, int length, const _PyBloomFilter *dependencies)
1055+
make_executor_from_uops(_PyUOpInstruction *buffer, int length, const _PyBloomFilter *dependencies, int chain_depth)
10511056
{
10521057
int exit_count = count_exits(buffer, length);
10531058
_PyExecutorObject *executor = allocate_executor(exit_count, length);
@@ -1057,6 +1062,8 @@ make_executor_from_uops(_PyUOpInstruction *buffer, int length, const _PyBloomFil
10571062

10581063
/* Initialize exits */
10591064
_PyExecutorObject *cold = _PyExecutor_GetColdExecutor();
1065+
fprintf(stdout, "CHAIN DEPTH %d;\n", chain_depth);
1066+
cold->vm_data.chain_depth = chain_depth;
10601067
for (int i = 0; i < exit_count; i++) {
10611068
executor->exits[i].index = i;
10621069
executor->exits[i].temperature = initial_temperature_backoff_counter();
@@ -1191,7 +1198,7 @@ uop_optimize(
11911198
OPT_HIST(effective_trace_length(buffer, length), optimized_trace_length_hist);
11921199
length = prepare_for_execution(buffer, length);
11931200
assert(length <= UOP_MAX_TRACE_LENGTH);
1194-
_PyExecutorObject *executor = make_executor_from_uops(buffer, length, &dependencies);
1201+
_PyExecutorObject *executor = make_executor_from_uops(buffer, length, &dependencies, tstate->interp->jit_tracer_initial_chain_depth);
11951202
if (executor == NULL) {
11961203
return -1;
11971204
}

0 commit comments

Comments
 (0)