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(""); + return; + } + if (PyJitRef_IsInvalid(ref)) { + printf("", (void *)PyJitRef_Unwrap(ref)); + return; + } + JitOptSymbol *sym = PyJitRef_Unwrap(ref); + switch (sym->tag) { + case JIT_SYM_UNKNOWN_TAG: + printf("", (void *)sym); + break; + case JIT_SYM_NULL_TAG: + printf("", (void *)sym); + break; + case JIT_SYM_NON_NULL_TAG: + printf("", (void *)sym); + break; + case JIT_SYM_BOTTOM_TAG: + printf("", (void *)sym); + break; + case JIT_SYM_TYPE_VERSION_TAG: + printf("", 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("", sym->tuple.length, (void *)sym); + break; + case JIT_SYM_TRUTHINESS_TAG: + printf("", sym->truthiness.invert ? "!" : "", (void *)sym); + break; + case JIT_SYM_COMPACT_INT: + printf("", (void *)sym); + break; + default: + printf("", sym->tag, (void *)sym); + break; + } +} + #else #define DPRINTF(level, ...) #endif