https://github.com/python/cpython/commit/61ec66acd5c73430c37877d2e2707905785c2ceb
commit: 61ec66acd5c73430c37877d2e2707905785c2ceb
branch: main
author: Hai Zhu <[email protected]>
committer: Fidget-Spinner <[email protected]>
date: 2026-01-17T15:20:35Z
summary:
gh-143946: Show `JitOptSymbol` on abstract stack when set PYTHON_OPT_DEBUG > 4
(GH-143957)
files:
M Include/internal/pycore_optimizer.h
M Python/optimizer_analysis.c
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h
M Python/optimizer_symbols.c
diff --git a/Include/internal/pycore_optimizer.h
b/Include/internal/pycore_optimizer.h
index 5f92a86f813aae..0592221f15226e 100644
--- a/Include/internal/pycore_optimizer.h
+++ b/Include/internal/pycore_optimizer.h
@@ -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)
{
diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c
index e855df4977acf8..cd3b79a2c13140 100644
--- a/Python/optimizer_analysis.c
+++ b/Python/optimizer_analysis.c
@@ -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);
@@ -50,6 +51,38 @@
}
#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
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index 1a64810b50a3a4..8fae031e11b4b0 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -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])) {
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index f3bc7213fcce3f..e737a0b8800b2c 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -1131,7 +1131,7 @@
}
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;
@@ -1295,7 +1295,7 @@
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;
}
@@ -1977,7 +1977,7 @@
break;
}
f->locals[0] = owner;
- new_frame = PyJitRef_Wrap((JitOptSymbol *)f);
+ new_frame = PyJitRef_WrapInvalid(f);
stack_pointer[-1] = new_frame;
break;
}
@@ -2662,7 +2662,7 @@
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;
@@ -2846,7 +2846,7 @@
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;
@@ -2978,9 +2978,9 @@
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;
@@ -3175,7 +3175,7 @@
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;
@@ -3441,7 +3441,7 @@
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;
@@ -3493,7 +3493,7 @@
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;
diff --git a/Python/optimizer_symbols.c b/Python/optimizer_symbols.c
index c6b54b9b58b795..5f5086d33b5c4c 100644
--- a/Python/optimizer_symbols.c
+++ b/Python/optimizer_symbols.c
@@ -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
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]