Skip to content

Commit 021fc44

Browse files
Fix exception tracing
1 parent 07542dd commit 021fc44

File tree

7 files changed

+69
-10
lines changed

7 files changed

+69
-10
lines changed

Include/internal/pycore_optimizer.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,8 @@ static inline int is_terminator(const _PyUOpInstruction *uop)
345345
int opcode = uop->opcode;
346346
return (
347347
opcode == _EXIT_TRACE ||
348-
opcode == _JUMP_TO_TOP
348+
opcode == _JUMP_TO_TOP ||
349+
opcode == _DYNAMIC_EXIT
349350
);
350351
}
351352

Include/internal/pycore_uop_metadata.h

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

Python/bytecodes.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5446,11 +5446,31 @@ dummy_func(
54465446

54475447
tier2 op(_GUARD_IP, (ip/4 --)) {
54485448
if (frame->instr_ptr != (_Py_CODEUNIT *)ip) {
5449+
#ifdef Py_DEBUG
5450+
_Py_CODEUNIT *target = frame->instr_ptr;
5451+
if (frame->lltrace >= 2) {
5452+
printf("GUARD IP EXIT: [UOp ");
5453+
_PyUOpPrint(&next_uop[-1]);
5454+
printf(", target %d -> %s]\n",
5455+
(int)(target - _PyFrame_GetBytecode(frame)),
5456+
_PyOpcode_OpName[target->op.code]);
5457+
}
5458+
#endif
54495459
GOTO_TIER_ONE(frame->instr_ptr, 1);
54505460
}
54515461
}
54525462

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

Python/ceval.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1198,7 +1198,10 @@ _PyTier2Interpreter(
11981198
if (frame->lltrace >= 4 &&
11991199
next_uop->opcode != _YIELD_VALUE &&
12001200
next_uop->opcode != _FOR_ITER_GEN_FRAME &&
1201-
next_uop->opcode != _PUSH_FRAME) {
1201+
next_uop->opcode != _PUSH_FRAME &&
1202+
next_uop->opcode != _PY_FRAME_KW &&
1203+
next_uop->opcode != _SAVE_RETURN_OFFSET &&
1204+
next_uop->opcode != _SAVE_RETURN_OFFSET) {
12021205
dump_stack(frame, stack_pointer);
12031206
if (next_uop->opcode == _START_EXECUTOR) {
12041207
printf("%4d uop: ", 0);

Python/executor_cases.c.h

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

Python/optimizer.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -587,16 +587,24 @@ _PyJIT_translate_single_bytecode_to_trace(
587587
goto full;
588588
}
589589

590-
// Unsupported opcodes
591-
if (opcode == WITH_EXCEPT_START || opcode == RERAISE || opcode == CLEANUP_THROW) {
592-
goto full;
593-
}
594-
595590
bool needs_guard_ip = _PyOpcode_NeedsGuardIp[opcode] &&
596591
!(opcode == FOR_ITER_RANGE || opcode == FOR_ITER_LIST || opcode == FOR_ITER_TUPLE) &&
597592
!(opcode == JUMP_BACKWARD_NO_INTERRUPT || opcode == JUMP_BACKWARD || opcode == JUMP_BACKWARD_JIT) &&
598593
!(opcode == POP_JUMP_IF_TRUE || opcode == POP_JUMP_IF_FALSE || opcode == POP_JUMP_IF_NONE || opcode == POP_JUMP_IF_NOT_NONE);
599594

595+
596+
// Strange control-flow
597+
if (opcode == WITH_EXCEPT_START || opcode == RERAISE || opcode == CLEANUP_THROW || opcode == PUSH_EXC_INFO) {
598+
// Rewind to previous instruction and replace with _EXIT_TRACE.
599+
_PyUOpInstruction *curr = &trace[trace_length-1];
600+
while (curr->opcode != _SET_IP && trace_length > 0) {
601+
trace_length--;
602+
curr = &trace[trace_length-1];
603+
}
604+
curr->opcode = _EXIT_TRACE;
605+
goto done;
606+
}
607+
600608
const struct opcode_macro_expansion *expansion = &_PyOpcode_macro_expansion[opcode];
601609
RESERVE_RAW(expansion->nuops + needs_guard_ip + 3, "uop and various checks");
602610

@@ -618,6 +626,8 @@ _PyJIT_translate_single_bytecode_to_trace(
618626

619627
// Loop back to the start
620628
if (tstate->interp->jit_tracer_initial_instr == this_instr && tstate->interp->jit_tracer_code_curr_size > 2) {
629+
// Undo the last few instructions.
630+
trace_length = tstate->interp->jit_tracer_code_curr_size;
621631
ADD_TO_TRACE(_JUMP_TO_TOP, 0, 0, 0);
622632
goto done;
623633
}

Python/optimizer_analysis.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size)
493493
}
494494
/* _PUSH_FRAME doesn't escape or error, but it
495495
* does need the IP for the return address */
496-
bool needs_ip = (opcode == _PUSH_FRAME || opcode == _YIELD_VALUE);
496+
bool needs_ip = (opcode == _PUSH_FRAME || opcode == _YIELD_VALUE || opcode == _DYNAMIC_EXIT);
497497
if (_PyUop_Flags[opcode] & HAS_ESCAPES_FLAG) {
498498
needs_ip = true;
499499
may_have_escaped = true;
@@ -507,6 +507,7 @@ remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size)
507507
}
508508
case _JUMP_TO_TOP:
509509
case _EXIT_TRACE:
510+
case _DYNAMIC_EXIT:
510511
return pc + 1;
511512
}
512513
}

0 commit comments

Comments
 (0)