]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Fix exception tracing
authorKen Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Sat, 20 Sep 2025 21:17:47 +0000 (22:17 +0100)
committerKen Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Sat, 20 Sep 2025 21:17:47 +0000 (22:17 +0100)
Include/internal/pycore_optimizer.h
Include/internal/pycore_uop_metadata.h
Python/bytecodes.c
Python/ceval.c
Python/executor_cases.c.h
Python/optimizer.c
Python/optimizer_analysis.c

index bea2838b8ba0922e22f3e6ddbd449ecf3319a0b4..2eea92c9b64d45a1115a1997e5266c2628a32da5 100644 (file)
@@ -345,7 +345,8 @@ static inline int is_terminator(const _PyUOpInstruction *uop)
     int opcode = uop->opcode;
     return (
         opcode == _EXIT_TRACE ||
-        opcode == _JUMP_TO_TOP
+        opcode == _JUMP_TO_TOP ||
+        opcode == _DYNAMIC_EXIT
     );
 }
 
index 2b33e63ac6cf94a8387d7c2ac3e0dd875279336f..f5d7e1fafe808613a0bc074f5cc3508c1549950a 100644 (file)
@@ -339,8 +339,8 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
     [_ERROR_POP_N] = HAS_ARG_FLAG,
     [_TIER2_RESUME_CHECK] = HAS_PERIODIC_FLAG,
     [_COLD_EXIT] = HAS_ESCAPES_FLAG,
-    [_GUARD_IP] = 0,
-    [_DYNAMIC_EXIT] = 0,
+    [_GUARD_IP] = HAS_ESCAPES_FLAG,
+    [_DYNAMIC_EXIT] = HAS_ESCAPES_FLAG,
 };
 
 const ReplicationRange _PyUop_Replication[MAX_UOP_ID+1] = {
index a0983a474af801d0f05007fb9fc945ee707a1a54..5cec4f1112e437629ae279faa5799027d194166c 100644 (file)
@@ -5446,11 +5446,31 @@ dummy_func(
 
         tier2 op(_GUARD_IP, (ip/4 --)) {
             if (frame->instr_ptr != (_Py_CODEUNIT *)ip) {
+#ifdef Py_DEBUG
+                _Py_CODEUNIT *target = frame->instr_ptr;
+                if (frame->lltrace >= 2) {
+                    printf("GUARD IP EXIT: [UOp ");
+                    _PyUOpPrint(&next_uop[-1]);
+                    printf(", target %d -> %s]\n",
+                        (int)(target - _PyFrame_GetBytecode(frame)),
+                        _PyOpcode_OpName[target->op.code]);
+                }
+#endif
                 GOTO_TIER_ONE(frame->instr_ptr, 1);
             }
         }
 
         tier2 op(_DYNAMIC_EXIT, (ip/4 --)) {
+#ifdef Py_DEBUG
+            _Py_CODEUNIT *target = frame->instr_ptr;
+            if (frame->lltrace >= 2) {
+                printf("GUARD IP EXIT: [UOp ");
+                _PyUOpPrint(&next_uop[-1]);
+                printf(", target %d -> %s]\n",
+                    (int)(target - _PyFrame_GetBytecode(frame)),
+                    _PyOpcode_OpName[target->op.code]);
+            }
+#endif
             GOTO_TIER_ONE(frame->instr_ptr, 1);
         }
 
index 3eed68821021f059eb2f79d67abec0715d04f389..afb69602a2574d57d2385f5d63e660c4f65ce22d 100644 (file)
@@ -1198,7 +1198,10 @@ tier2_dispatch:
         if (frame->lltrace >= 4 &&
             next_uop->opcode != _YIELD_VALUE &&
             next_uop->opcode != _FOR_ITER_GEN_FRAME &&
-            next_uop->opcode != _PUSH_FRAME) {
+            next_uop->opcode != _PUSH_FRAME &&
+            next_uop->opcode != _PY_FRAME_KW &&
+            next_uop->opcode != _SAVE_RETURN_OFFSET &&
+            next_uop->opcode != _SAVE_RETURN_OFFSET) {
             dump_stack(frame, stack_pointer);
             if (next_uop->opcode == _START_EXECUTOR) {
                 printf("%4d uop: ", 0);
index f6c729f533504c1e3496e814c4f017e05ad08120..013d7e7836169831c589f64971f20c4b17dd48ff 100644 (file)
         case _GUARD_IP: {
             PyObject *ip = (PyObject *)CURRENT_OPERAND0();
             if (frame->instr_ptr != (_Py_CODEUNIT *)ip) {
+                #ifdef Py_DEBUG
+                _Py_CODEUNIT *target = frame->instr_ptr;
+                if (frame->lltrace >= 2) {
+                    _PyFrame_SetStackPointer(frame, stack_pointer);
+                    printf("GUARD IP EXIT: [UOp ");
+                    _PyUOpPrint(&next_uop[-1]);
+                    printf(", target %d -> %s]\n",
+                           (int)(target - _PyFrame_GetBytecode(frame)),
+                           _PyOpcode_OpName[target->op.code]);
+                    stack_pointer = _PyFrame_GetStackPointer(frame);
+                }
+                #endif
                 GOTO_TIER_ONE(frame->instr_ptr, 1);
             }
             break;
 
         case _DYNAMIC_EXIT: {
             PyObject *ip = (PyObject *)CURRENT_OPERAND0();
+            #ifdef Py_DEBUG
+            _Py_CODEUNIT *target = frame->instr_ptr;
+            if (frame->lltrace >= 2) {
+                _PyFrame_SetStackPointer(frame, stack_pointer);
+                printf("GUARD IP EXIT: [UOp ");
+                _PyUOpPrint(&next_uop[-1]);
+                printf(", target %d -> %s]\n",
+                       (int)(target - _PyFrame_GetBytecode(frame)),
+                       _PyOpcode_OpName[target->op.code]);
+                stack_pointer = _PyFrame_GetStackPointer(frame);
+            }
+            #endif
             GOTO_TIER_ONE(frame->instr_ptr, 1);
             break;
         }
index 4de08899456baec532e98fce4d57ebee9ebb7736..fa6a9616b332ced225229e85ee0832975488be29 100644 (file)
@@ -587,16 +587,24 @@ _PyJIT_translate_single_bytecode_to_trace(
         goto full;
     }
 
-    // Unsupported opcodes
-    if (opcode == WITH_EXCEPT_START || opcode == RERAISE || opcode == CLEANUP_THROW) {
-        goto full;
-    }
-
     bool needs_guard_ip = _PyOpcode_NeedsGuardIp[opcode] &&
         !(opcode == FOR_ITER_RANGE || opcode == FOR_ITER_LIST || opcode == FOR_ITER_TUPLE) &&
         !(opcode == JUMP_BACKWARD_NO_INTERRUPT || opcode == JUMP_BACKWARD || opcode == JUMP_BACKWARD_JIT) &&
         !(opcode == POP_JUMP_IF_TRUE || opcode == POP_JUMP_IF_FALSE || opcode == POP_JUMP_IF_NONE || opcode == POP_JUMP_IF_NOT_NONE);
 
+
+    // Strange control-flow
+    if (opcode == WITH_EXCEPT_START || opcode == RERAISE || opcode == CLEANUP_THROW || opcode == PUSH_EXC_INFO) {
+        // Rewind to previous instruction and replace with _EXIT_TRACE.
+        _PyUOpInstruction *curr = &trace[trace_length-1];
+        while (curr->opcode != _SET_IP && trace_length > 0) {
+            trace_length--;
+            curr = &trace[trace_length-1];
+        }
+        curr->opcode = _EXIT_TRACE;
+        goto done;
+    }
+
     const struct opcode_macro_expansion *expansion = &_PyOpcode_macro_expansion[opcode];
     RESERVE_RAW(expansion->nuops + needs_guard_ip + 3, "uop and various checks");
 
@@ -618,6 +626,8 @@ _PyJIT_translate_single_bytecode_to_trace(
 
     // Loop back to the start
     if (tstate->interp->jit_tracer_initial_instr == this_instr && tstate->interp->jit_tracer_code_curr_size > 2) {
+        // Undo the last few instructions.
+        trace_length = tstate->interp->jit_tracer_code_curr_size;
         ADD_TO_TRACE(_JUMP_TO_TOP, 0, 0, 0);
         goto done;
     }
index 61a31adc6887dc99fd0ec001bf2b444eb6f682c0..1bb52188fba48e8bfcd1a305b81db4e98b165f12 100644 (file)
@@ -493,7 +493,7 @@ remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size)
                 }
                 /* _PUSH_FRAME doesn't escape or error, but it
                  * does need the IP for the return address */
-                bool needs_ip = (opcode == _PUSH_FRAME || opcode == _YIELD_VALUE);
+                bool needs_ip = (opcode == _PUSH_FRAME || opcode == _YIELD_VALUE || opcode == _DYNAMIC_EXIT);
                 if (_PyUop_Flags[opcode] & HAS_ESCAPES_FLAG) {
                     needs_ip = true;
                     may_have_escaped = true;
@@ -507,6 +507,7 @@ remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size)
             }
             case _JUMP_TO_TOP:
             case _EXIT_TRACE:
+            case _DYNAMIC_EXIT:
                 return pc + 1;
         }
     }