]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-143946: Show `JitOptSymbol` on abstract stack when set PYTHON_OPT_DEBUG > 4 (GH...
authorHai Zhu <35182391+cocolato@users.noreply.github.com>
Sat, 17 Jan 2026 15:20:35 +0000 (23:20 +0800)
committerGitHub <noreply@github.com>
Sat, 17 Jan 2026 15:20:35 +0000 (15:20 +0000)
Include/internal/pycore_optimizer.h
Python/optimizer_analysis.c
Python/optimizer_bytecodes.c
Python/optimizer_cases.c.h
Python/optimizer_symbols.c

index 5f92a86f813aae565989334f9d0ad3f70e1fe36b..0592221f15226e4ae819eb1494e0ce35d20ebe67 100644 (file)
@@ -115,8 +115,10 @@ static inline uint16_t uop_get_error_target(const _PyUOpInstruction *inst)
 
 
 #define REF_IS_BORROWED 1
+#define REF_IS_INVALID  2
+#define REF_TAG_BITS    3
 
-#define JIT_BITS_TO_PTR_MASKED(REF) ((JitOptSymbol *)(((REF).bits) & (~REF_IS_BORROWED)))
+#define JIT_BITS_TO_PTR_MASKED(REF) ((JitOptSymbol *)(((REF).bits) & (~REF_TAG_BITS)))
 
 static inline JitOptSymbol *
 PyJitRef_Unwrap(JitOptRef ref)
@@ -133,6 +135,18 @@ PyJitRef_Wrap(JitOptSymbol *sym)
     return (JitOptRef){.bits=(uintptr_t)sym};
 }
 
+static inline JitOptRef
+PyJitRef_WrapInvalid(void *ptr)
+{
+    return (JitOptRef){.bits=(uintptr_t)ptr | REF_IS_INVALID};
+}
+
+static inline bool
+PyJitRef_IsInvalid(JitOptRef ref)
+{
+    return (ref.bits & REF_IS_INVALID) == REF_IS_INVALID;
+}
+
 static inline JitOptRef
 PyJitRef_StripReferenceInfo(JitOptRef ref)
 {
index e855df4977acf829834ef0879e2b3fad99076c6d..cd3b79a2c131407830599d65149b1ee631796eb3 100644 (file)
@@ -39,6 +39,7 @@
 #ifdef Py_DEBUG
     extern const char *_PyUOpName(int index);
     extern void _PyUOpPrint(const _PyUOpInstruction *uop);
+    extern void _PyUOpSymPrint(JitOptRef ref);
     static const char *const DEBUG_ENV = "PYTHON_OPT_DEBUG";
     static inline int get_lltrace(void) {
         char *uop_debug = Py_GETENV(DEBUG_ENV);
     }
     #define DPRINTF(level, ...) \
     if (get_lltrace() >= (level)) { printf(__VA_ARGS__); }
+
+
+
+static void
+dump_abstract_stack(_Py_UOpsAbstractFrame *frame, JitOptRef *stack_pointer)
+{
+    JitOptRef *stack_base = frame->stack;
+    JitOptRef *locals_base = frame->locals;
+    printf("    locals=[");
+    for (JitOptRef *ptr = locals_base; ptr < stack_base; ptr++) {
+        if (ptr != locals_base) {
+            printf(", ");
+        }
+        _PyUOpSymPrint(*ptr);
+    }
+    printf("]\n");
+    if (stack_pointer < stack_base) {
+        printf("    stack=%d\n", (int)(stack_pointer - stack_base));
+    }
+    else {
+        printf("    stack=[");
+        for (JitOptRef *ptr = stack_base; ptr < stack_pointer; ptr++) {
+            if (ptr != stack_base) {
+                printf(", ");
+            }
+            _PyUOpSymPrint(*ptr);
+        }
+        printf("]\n");
+    }
+    fflush(stdout);
+}
+
 #else
     #define DPRINTF(level, ...)
 #endif
@@ -383,7 +416,10 @@ optimize_uops(
         if (get_lltrace() >= 3) {
             printf("%4d abs: ", (int)(this_instr - trace));
             _PyUOpPrint(this_instr);
-            printf(" ");
+            printf(" \n");
+            if (get_lltrace() >= 5 && !CURRENT_FRAME_IS_INIT_SHIM()) {
+                dump_abstract_stack(ctx->frame, stack_pointer);
+            }
         }
 #endif
 
index 1a64810b50a3a4a689a6de00eacd8ca57ec7e1eb..8fae031e11b4b0f6ed936c4810a7e8842da33b37 100644 (file)
@@ -340,7 +340,7 @@ dummy_func(void) {
         }
         f->locals[0] = container;
         f->locals[1] = sub;
-        new_frame = PyJitRef_Wrap((JitOptSymbol *)f);
+        new_frame = PyJitRef_WrapInvalid(f);
     }
 
     op(_BINARY_OP_SUBSCR_STR_INT, (str_st, sub_st -- res, s, i)) {
@@ -784,7 +784,7 @@ dummy_func(void) {
             break;
         }
         f->locals[0] = owner;
-        new_frame = PyJitRef_Wrap((JitOptSymbol *)f);
+        new_frame = PyJitRef_WrapInvalid(f);
     }
 
     op(_INIT_CALL_BOUND_METHOD_EXACT_ARGS, (callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
@@ -848,9 +848,9 @@ dummy_func(void) {
         }
 
         if (sym_is_null(self_or_null) || sym_is_not_null(self_or_null)) {
-            new_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, args, argcount));
+            new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, args, argcount));
         } else {
-            new_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, NULL, 0));
+            new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0));
         }
     }
 
@@ -868,7 +868,7 @@ dummy_func(void) {
             break;
         }
 
-        new_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, NULL, 0));
+        new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0));
     }
 
     op(_PY_FRAME_KW, (callable, self_or_null, args[oparg], kwnames -- new_frame)) {
@@ -879,7 +879,7 @@ dummy_func(void) {
             break;
         }
 
-        new_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, NULL, 0));
+        new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0));
     }
 
     op(_PY_FRAME_EX, (func_st, null, callargs_st, kwargs_st -- ex_frame)) {
@@ -890,7 +890,7 @@ dummy_func(void) {
             break;
         }
 
-        ex_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, NULL, 0));
+        ex_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0));
     }
 
     op(_CHECK_AND_ALLOCATE_OBJECT, (type_version/2, callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) {
@@ -914,7 +914,7 @@ dummy_func(void) {
         ctx->curr_frame_depth++;
         assert((this_instr + 1)->opcode == _PUSH_FRAME);
         PyCodeObject *co = get_code_with_logging((this_instr + 1));
-        init_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, args-1, oparg+1));
+        init_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, args-1, oparg+1));
     }
 
     op(_RETURN_VALUE, (retval -- res)) {
@@ -1007,7 +1007,7 @@ dummy_func(void) {
             break;
         }
         new_frame->stack[0] = sym_new_const(ctx, Py_None);
-        gen_frame = PyJitRef_Wrap((JitOptSymbol *)new_frame);
+        gen_frame = PyJitRef_WrapInvalid(new_frame);
     }
 
     op(_SEND_GEN_FRAME, (unused, v -- unused, gen_frame)) {
@@ -1023,7 +1023,7 @@ dummy_func(void) {
             break;
         }
         new_frame->stack[0] = PyJitRef_StripReferenceInfo(v);
-        gen_frame = PyJitRef_Wrap((JitOptSymbol *)new_frame);
+        gen_frame = PyJitRef_WrapInvalid(new_frame);
     }
 
     op(_CHECK_STACK_SPACE, (unused, unused, unused[oparg] -- unused, unused, unused[oparg])) {
index f3bc7213fcce3f71aa138b87bc52d4739ff96b28..e737a0b8800b2c304d3922393369f90737a5f275 100644 (file)
             }
             f->locals[0] = container;
             f->locals[1] = sub;
-            new_frame = PyJitRef_Wrap((JitOptSymbol *)f);
+            new_frame = PyJitRef_WrapInvalid(f);
             CHECK_STACK_BOUNDS(-2);
             stack_pointer[-3] = new_frame;
             stack_pointer += -2;
                 break;
             }
             new_frame->stack[0] = PyJitRef_StripReferenceInfo(v);
-            gen_frame = PyJitRef_Wrap((JitOptSymbol *)new_frame);
+            gen_frame = PyJitRef_WrapInvalid(new_frame);
             stack_pointer[-1] = gen_frame;
             break;
         }
                 break;
             }
             f->locals[0] = owner;
-            new_frame = PyJitRef_Wrap((JitOptSymbol *)f);
+            new_frame = PyJitRef_WrapInvalid(f);
             stack_pointer[-1] = new_frame;
             break;
         }
                 break;
             }
             new_frame->stack[0] = sym_new_const(ctx, Py_None);
-            gen_frame = PyJitRef_Wrap((JitOptSymbol *)new_frame);
+            gen_frame = PyJitRef_WrapInvalid(new_frame);
             CHECK_STACK_BOUNDS(1);
             stack_pointer[0] = gen_frame;
             stack_pointer += 1;
                 ctx->done = true;
                 break;
             }
-            new_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, NULL, 0));
+            new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0));
             CHECK_STACK_BOUNDS(-1 - oparg);
             stack_pointer[-2 - oparg] = new_frame;
             stack_pointer += -1 - oparg;
                 argcount++;
             }
             if (sym_is_null(self_or_null) || sym_is_not_null(self_or_null)) {
-                new_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, args, argcount));
+                new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, args, argcount));
             } else {
-                new_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, NULL, 0));
+                new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0));
             }
             CHECK_STACK_BOUNDS(-1 - oparg);
             stack_pointer[-2 - oparg] = new_frame;
             ctx->curr_frame_depth++;
             assert((this_instr + 1)->opcode == _PUSH_FRAME);
             PyCodeObject *co = get_code_with_logging((this_instr + 1));
-            init_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, args-1, oparg+1));
+            init_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, args-1, oparg+1));
             CHECK_STACK_BOUNDS(-1 - oparg);
             stack_pointer[-2 - oparg] = init_frame;
             stack_pointer += -1 - oparg;
                 ctx->done = true;
                 break;
             }
-            new_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, NULL, 0));
+            new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0));
             CHECK_STACK_BOUNDS(-2 - oparg);
             stack_pointer[-3 - oparg] = new_frame;
             stack_pointer += -2 - oparg;
                 ctx->done = true;
                 break;
             }
-            ex_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, NULL, 0));
+            ex_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0));
             CHECK_STACK_BOUNDS(-3);
             stack_pointer[-4] = ex_frame;
             stack_pointer += -3;
index c6b54b9b58b795461856e19a81a548abb9ca9196..5f5086d33b5c4c1ab824d6f2ae9e1a40ca097aae 100644 (file)
@@ -68,6 +68,57 @@ static inline int get_lltrace(void) {
 }
 #define DPRINTF(level, ...) \
     if (get_lltrace() >= (level)) { printf(__VA_ARGS__); }
+
+void
+_PyUOpSymPrint(JitOptRef ref)
+{
+    if (PyJitRef_IsNull(ref)) {
+        printf("<JitRef NULL>");
+        return;
+    }
+    if (PyJitRef_IsInvalid(ref)) {
+        printf("<INVALID frame at %p>", (void *)PyJitRef_Unwrap(ref));
+        return;
+    }
+    JitOptSymbol *sym = PyJitRef_Unwrap(ref);
+    switch (sym->tag) {
+        case JIT_SYM_UNKNOWN_TAG:
+            printf("<? at %p>", (void *)sym);
+            break;
+        case JIT_SYM_NULL_TAG:
+            printf("<NULL at %p>", (void *)sym);
+            break;
+        case JIT_SYM_NON_NULL_TAG:
+            printf("<!NULL at %p>", (void *)sym);
+            break;
+        case JIT_SYM_BOTTOM_TAG:
+            printf("<BOTTOM at %p>", (void *)sym);
+            break;
+        case JIT_SYM_TYPE_VERSION_TAG:
+            printf("<v%u at %p>", sym->version.version, (void *)sym);
+            break;
+        case JIT_SYM_KNOWN_CLASS_TAG:
+            printf("<%s at %p>", sym->cls.type->tp_name, (void *)sym);
+            break;
+        case JIT_SYM_KNOWN_VALUE_TAG:
+            printf("<%s val=%p at %p>", Py_TYPE(sym->value.value)->tp_name,
+                   (void *)sym->value.value, (void *)sym);
+            break;
+        case JIT_SYM_TUPLE_TAG:
+            printf("<tuple[%d] at %p>", sym->tuple.length, (void *)sym);
+            break;
+        case JIT_SYM_TRUTHINESS_TAG:
+            printf("<truthiness%s at %p>", sym->truthiness.invert ? "!" : "", (void *)sym);
+            break;
+        case JIT_SYM_COMPACT_INT:
+            printf("<compact_int at %p>", (void *)sym);
+            break;
+        default:
+            printf("<tag=%d at %p>", sym->tag, (void *)sym);
+            break;
+    }
+}
+
 #else
 #define DPRINTF(level, ...)
 #endif