Skip to content

Commit 36554a5

Browse files
Fix over-tracing bug
1 parent 20b283b commit 36554a5

File tree

6 files changed

+74
-44
lines changed

6 files changed

+74
-44
lines changed

Include/internal/pycore_uop_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.

Python/bytecodes.c

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2961,7 +2961,9 @@ dummy_func(
29612961
tier1 op(_JIT, (--)) {
29622962
#ifdef _Py_TIER2
29632963
_Py_BackoffCounter counter = this_instr[1].counter;
2964-
if (!IS_JIT_TRACING() && backoff_counter_triggers(counter) && this_instr->op.code == JUMP_BACKWARD_JIT) {
2964+
if (!IS_JIT_TRACING() && backoff_counter_triggers(counter) &&
2965+
this_instr->op.code == JUMP_BACKWARD_JIT &&
2966+
next_instr->op.code != ENTER_EXECUTOR) {
29652967
_Py_CODEUNIT *start = this_instr;
29662968
/* Back up over EXTENDED_ARGs so optimizer sees the whole instruction */
29672969
int curr_oparg = oparg;
@@ -3053,7 +3055,7 @@ dummy_func(
30533055
next_instr = this_instr;
30543056
DISPATCH_GOTO();
30553057
}
3056-
TIER1_TO_TIER2(executor, 1);
3058+
TIER1_TO_TIER2(executor);
30573059
#else
30583060
Py_FatalError("ENTER_EXECUTOR is not supported in this build");
30593061
#endif /* _Py_TIER2 */
@@ -5458,24 +5460,12 @@ dummy_func(
54585460
}
54595461

54605462
tier2 op(_GUARD_IP, (ip/4 --)) {
5461-
if (frame->instr_ptr != (_Py_CODEUNIT *)ip) {
5462-
#ifdef Py_DEBUG
5463-
_Py_CODEUNIT *target = frame->instr_ptr;
5464-
if (frame->lltrace >= 2) {
5465-
printf("GUARD IP EXIT: [UOp ");
5466-
_PyUOpPrint(&next_uop[-1]);
5467-
printf(", target %d -> %s]\n",
5468-
(int)(target - _PyFrame_GetBytecode(frame)),
5469-
_PyOpcode_OpName[target->op.code]);
5470-
}
5471-
#endif
5472-
GOTO_TIER_ONE(frame->instr_ptr, 1);
5473-
}
5463+
EXIT_IF(frame->instr_ptr != (_Py_CODEUNIT *)ip);
54745464
}
54755465

5476-
tier2 op(_DYNAMIC_EXIT, (ip/4 --)) {
5477-
#ifdef Py_DEBUG
5466+
tier2 op(_DYNAMIC_EXIT, (exit_p/4 --)) {
54785467
_Py_CODEUNIT *target = frame->instr_ptr;
5468+
#ifdef Py_DEBUG
54795469
if (frame->lltrace >= 2) {
54805470
printf("GUARD IP EXIT: [UOp ");
54815471
_PyUOpPrint(&next_uop[-1]);
@@ -5484,7 +5474,28 @@ dummy_func(
54845474
_PyOpcode_OpName[target->op.code]);
54855475
}
54865476
#endif
5487-
GOTO_TIER_ONE(frame->instr_ptr, 1);
5477+
_PyExitData *exit = (_PyExitData *)exit_p;
5478+
tstate->jit_exit = exit_p;
5479+
_Py_BackoffCounter temperature = exit->temperature;
5480+
_PyExecutorObject *executor;
5481+
if (target->op.code == ENTER_EXECUTOR) {
5482+
PyCodeObject *code = _PyFrame_GetCode(frame);
5483+
executor = code->co_executors->executors[target->op.arg];
5484+
Py_INCREF(executor);
5485+
}
5486+
else {
5487+
if (!backoff_counter_triggers(temperature)) {
5488+
exit->temperature = advance_backoff_counter(temperature);
5489+
GOTO_TIER_ONE(frame->instr_ptr, 0);
5490+
}
5491+
_PyExecutorObject *previous_executor = _PyExecutor_FromExit(exit);
5492+
assert(tstate->current_executor == (PyObject *)previous_executor);
5493+
int chain_depth = previous_executor->vm_data.chain_depth + 1;
5494+
_PyJIT_InitializeTracing(tstate, frame, target, STACK_LEVEL(), chain_depth);
5495+
GOTO_TIER_ONE(target, 1);
5496+
}
5497+
exit->executor = executor;
5498+
TIER2_TO_TIER2(exit->executor);
54885499
}
54895500

54905501
label(pop_2_error) {

Python/ceval_macros.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ _PyFrame_SetStackPointer(frame, stack_pointer)
402402

403403
/* Tier-switching macros. */
404404

405-
#define TIER1_TO_TIER2(EXECUTOR, IN_ENTER_EXECUTOR) \
405+
#define TIER1_TO_TIER2(EXECUTOR) \
406406
do { \
407407
OPT_STAT_INC(traces_executed); \
408408
next_instr = _Py_jit_entry((EXECUTOR), frame, stack_pointer, tstate); \
@@ -414,7 +414,8 @@ do { \
414414
next_instr = frame->instr_ptr; \
415415
JUMP_TO_LABEL(error); \
416416
} \
417-
if (!IN_ENTER_EXECUTOR && keep_tracing_bit) { \
417+
if (keep_tracing_bit) { \
418+
assert(next_instr->op.code != ENTER_EXECUTOR); \
418419
ENTER_TRACING(); \
419420
_PyJIT_InitializeTracing(tstate, frame, next_instr, STACK_LEVEL(), 0); \
420421
} \

Python/executor_cases.c.h

Lines changed: 30 additions & 16 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: 8 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/optimizer.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,7 @@ count_exits(_PyUOpInstruction *buffer, int length)
842842
int exit_count = 0;
843843
for (int i = 0; i < length; i++) {
844844
int opcode = buffer[i].opcode;
845-
if (opcode == _EXIT_TRACE) {
845+
if (opcode == _EXIT_TRACE || opcode == _DYNAMIC_EXIT) {
846846
exit_count++;
847847
}
848848
}
@@ -898,7 +898,7 @@ prepare_for_execution(_PyUOpInstruction *buffer, int length)
898898
else if (exit_flags & HAS_PERIODIC_FLAG) {
899899
exit_op = _HANDLE_PENDING_AND_DEOPT;
900900
}
901-
if (opcode == _FOR_ITER_TIER_TWO) {
901+
if (opcode == _FOR_ITER_TIER_TWO || opcode == _GUARD_IP) {
902902
exit_op = _DYNAMIC_EXIT;
903903
}
904904
int32_t jump_target = target;
@@ -1053,7 +1053,7 @@ make_executor_from_uops(_PyUOpInstruction *buffer, int length, const _PyBloomFil
10531053
int opcode = buffer[i].opcode;
10541054
dest--;
10551055
*dest = buffer[i];
1056-
if (opcode == _EXIT_TRACE) {
1056+
if (opcode == _EXIT_TRACE || opcode == _DYNAMIC_EXIT) {
10571057
_PyExitData *exit = &executor->exits[next_exit];
10581058
exit->target = buffer[i].target;
10591059
dest->operand0 = (uint64_t)exit;

0 commit comments

Comments
 (0)