Skip to content

Commit 61ec66a

Browse files
authored
gh-143946: Show JitOptSymbol on abstract stack when set PYTHON_OPT_DEBUG > 4 (GH-143957)
1 parent 7e28ae5 commit 61ec66a

File tree

5 files changed

+123
-22
lines changed

5 files changed

+123
-22
lines changed

Include/internal/pycore_optimizer.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,10 @@ static inline uint16_t uop_get_error_target(const _PyUOpInstruction *inst)
115115

116116

117117
#define REF_IS_BORROWED 1
118+
#define REF_IS_INVALID 2
119+
#define REF_TAG_BITS 3
118120

119-
#define JIT_BITS_TO_PTR_MASKED(REF) ((JitOptSymbol *)(((REF).bits) & (~REF_IS_BORROWED)))
121+
#define JIT_BITS_TO_PTR_MASKED(REF) ((JitOptSymbol *)(((REF).bits) & (~REF_TAG_BITS)))
120122

121123
static inline JitOptSymbol *
122124
PyJitRef_Unwrap(JitOptRef ref)
@@ -133,6 +135,18 @@ PyJitRef_Wrap(JitOptSymbol *sym)
133135
return (JitOptRef){.bits=(uintptr_t)sym};
134136
}
135137

138+
static inline JitOptRef
139+
PyJitRef_WrapInvalid(void *ptr)
140+
{
141+
return (JitOptRef){.bits=(uintptr_t)ptr | REF_IS_INVALID};
142+
}
143+
144+
static inline bool
145+
PyJitRef_IsInvalid(JitOptRef ref)
146+
{
147+
return (ref.bits & REF_IS_INVALID) == REF_IS_INVALID;
148+
}
149+
136150
static inline JitOptRef
137151
PyJitRef_StripReferenceInfo(JitOptRef ref)
138152
{

Python/optimizer_analysis.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#ifdef Py_DEBUG
4040
extern const char *_PyUOpName(int index);
4141
extern void _PyUOpPrint(const _PyUOpInstruction *uop);
42+
extern void _PyUOpSymPrint(JitOptRef ref);
4243
static const char *const DEBUG_ENV = "PYTHON_OPT_DEBUG";
4344
static inline int get_lltrace(void) {
4445
char *uop_debug = Py_GETENV(DEBUG_ENV);
@@ -50,6 +51,38 @@
5051
}
5152
#define DPRINTF(level, ...) \
5253
if (get_lltrace() >= (level)) { printf(__VA_ARGS__); }
54+
55+
56+
57+
static void
58+
dump_abstract_stack(_Py_UOpsAbstractFrame *frame, JitOptRef *stack_pointer)
59+
{
60+
JitOptRef *stack_base = frame->stack;
61+
JitOptRef *locals_base = frame->locals;
62+
printf(" locals=[");
63+
for (JitOptRef *ptr = locals_base; ptr < stack_base; ptr++) {
64+
if (ptr != locals_base) {
65+
printf(", ");
66+
}
67+
_PyUOpSymPrint(*ptr);
68+
}
69+
printf("]\n");
70+
if (stack_pointer < stack_base) {
71+
printf(" stack=%d\n", (int)(stack_pointer - stack_base));
72+
}
73+
else {
74+
printf(" stack=[");
75+
for (JitOptRef *ptr = stack_base; ptr < stack_pointer; ptr++) {
76+
if (ptr != stack_base) {
77+
printf(", ");
78+
}
79+
_PyUOpSymPrint(*ptr);
80+
}
81+
printf("]\n");
82+
}
83+
fflush(stdout);
84+
}
85+
5386
#else
5487
#define DPRINTF(level, ...)
5588
#endif
@@ -383,7 +416,10 @@ optimize_uops(
383416
if (get_lltrace() >= 3) {
384417
printf("%4d abs: ", (int)(this_instr - trace));
385418
_PyUOpPrint(this_instr);
386-
printf(" ");
419+
printf(" \n");
420+
if (get_lltrace() >= 5 && !CURRENT_FRAME_IS_INIT_SHIM()) {
421+
dump_abstract_stack(ctx->frame, stack_pointer);
422+
}
387423
}
388424
#endif
389425

Python/optimizer_bytecodes.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ dummy_func(void) {
340340
}
341341
f->locals[0] = container;
342342
f->locals[1] = sub;
343-
new_frame = PyJitRef_Wrap((JitOptSymbol *)f);
343+
new_frame = PyJitRef_WrapInvalid(f);
344344
}
345345

346346
op(_BINARY_OP_SUBSCR_STR_INT, (str_st, sub_st -- res, s, i)) {
@@ -784,7 +784,7 @@ dummy_func(void) {
784784
break;
785785
}
786786
f->locals[0] = owner;
787-
new_frame = PyJitRef_Wrap((JitOptSymbol *)f);
787+
new_frame = PyJitRef_WrapInvalid(f);
788788
}
789789

790790
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) {
848848
}
849849

850850
if (sym_is_null(self_or_null) || sym_is_not_null(self_or_null)) {
851-
new_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, args, argcount));
851+
new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, args, argcount));
852852
} else {
853-
new_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, NULL, 0));
853+
new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0));
854854
}
855855
}
856856

@@ -868,7 +868,7 @@ dummy_func(void) {
868868
break;
869869
}
870870

871-
new_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, NULL, 0));
871+
new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0));
872872
}
873873

874874
op(_PY_FRAME_KW, (callable, self_or_null, args[oparg], kwnames -- new_frame)) {
@@ -879,7 +879,7 @@ dummy_func(void) {
879879
break;
880880
}
881881

882-
new_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, NULL, 0));
882+
new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0));
883883
}
884884

885885
op(_PY_FRAME_EX, (func_st, null, callargs_st, kwargs_st -- ex_frame)) {
@@ -890,7 +890,7 @@ dummy_func(void) {
890890
break;
891891
}
892892

893-
ex_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, NULL, 0));
893+
ex_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0));
894894
}
895895

896896
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) {
914914
ctx->curr_frame_depth++;
915915
assert((this_instr + 1)->opcode == _PUSH_FRAME);
916916
PyCodeObject *co = get_code_with_logging((this_instr + 1));
917-
init_frame = PyJitRef_Wrap((JitOptSymbol *)frame_new(ctx, co, 0, args-1, oparg+1));
917+
init_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, args-1, oparg+1));
918918
}
919919

920920
op(_RETURN_VALUE, (retval -- res)) {
@@ -1007,7 +1007,7 @@ dummy_func(void) {
10071007
break;
10081008
}
10091009
new_frame->stack[0] = sym_new_const(ctx, Py_None);
1010-
gen_frame = PyJitRef_Wrap((JitOptSymbol *)new_frame);
1010+
gen_frame = PyJitRef_WrapInvalid(new_frame);
10111011
}
10121012

10131013
op(_SEND_GEN_FRAME, (unused, v -- unused, gen_frame)) {
@@ -1023,7 +1023,7 @@ dummy_func(void) {
10231023
break;
10241024
}
10251025
new_frame->stack[0] = PyJitRef_StripReferenceInfo(v);
1026-
gen_frame = PyJitRef_Wrap((JitOptSymbol *)new_frame);
1026+
gen_frame = PyJitRef_WrapInvalid(new_frame);
10271027
}
10281028

10291029
op(_CHECK_STACK_SPACE, (unused, unused, unused[oparg] -- unused, unused, unused[oparg])) {

Python/optimizer_cases.c.h

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

Python/optimizer_symbols.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,57 @@ static inline int get_lltrace(void) {
6868
}
6969
#define DPRINTF(level, ...) \
7070
if (get_lltrace() >= (level)) { printf(__VA_ARGS__); }
71+
72+
void
73+
_PyUOpSymPrint(JitOptRef ref)
74+
{
75+
if (PyJitRef_IsNull(ref)) {
76+
printf("<JitRef NULL>");
77+
return;
78+
}
79+
if (PyJitRef_IsInvalid(ref)) {
80+
printf("<INVALID frame at %p>", (void *)PyJitRef_Unwrap(ref));
81+
return;
82+
}
83+
JitOptSymbol *sym = PyJitRef_Unwrap(ref);
84+
switch (sym->tag) {
85+
case JIT_SYM_UNKNOWN_TAG:
86+
printf("<? at %p>", (void *)sym);
87+
break;
88+
case JIT_SYM_NULL_TAG:
89+
printf("<NULL at %p>", (void *)sym);
90+
break;
91+
case JIT_SYM_NON_NULL_TAG:
92+
printf("<!NULL at %p>", (void *)sym);
93+
break;
94+
case JIT_SYM_BOTTOM_TAG:
95+
printf("<BOTTOM at %p>", (void *)sym);
96+
break;
97+
case JIT_SYM_TYPE_VERSION_TAG:
98+
printf("<v%u at %p>", sym->version.version, (void *)sym);
99+
break;
100+
case JIT_SYM_KNOWN_CLASS_TAG:
101+
printf("<%s at %p>", sym->cls.type->tp_name, (void *)sym);
102+
break;
103+
case JIT_SYM_KNOWN_VALUE_TAG:
104+
printf("<%s val=%p at %p>", Py_TYPE(sym->value.value)->tp_name,
105+
(void *)sym->value.value, (void *)sym);
106+
break;
107+
case JIT_SYM_TUPLE_TAG:
108+
printf("<tuple[%d] at %p>", sym->tuple.length, (void *)sym);
109+
break;
110+
case JIT_SYM_TRUTHINESS_TAG:
111+
printf("<truthiness%s at %p>", sym->truthiness.invert ? "!" : "", (void *)sym);
112+
break;
113+
case JIT_SYM_COMPACT_INT:
114+
printf("<compact_int at %p>", (void *)sym);
115+
break;
116+
default:
117+
printf("<tag=%d at %p>", sym->tag, (void *)sym);
118+
break;
119+
}
120+
}
121+
71122
#else
72123
#define DPRINTF(level, ...)
73124
#endif

0 commit comments

Comments
 (0)