Skip to content

Commit 2028a4f

Browse files
authored
gh-106290: Fix edge cases around uops (#106319)
- Tweak uops debugging output - Fix the bug from gh-106290 - Rename `SET_IP` to `SAVE_IP` (per faster-cpython/ideas#558) - Add a `SAVE_IP` uop at the start of the trace (ditto) - Allow `unbound_local_error`; this gives us uops for `LOAD_FAST_CHECK`, `LOAD_CLOSURE`, and `DELETE_FAST` - Longer traces - Support `STORE_FAST_LOAD_FAST`, `STORE_FAST_STORE_FAST` - Add deps on pycore_uops.h to Makefile(.pre.in)
1 parent 5890621 commit 2028a4f

File tree

7 files changed

+274
-234
lines changed

7 files changed

+274
-234
lines changed

Include/internal/pycore_uops.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ extern "C" {
88
# error "this header requires Py_BUILD_CORE define"
99
#endif
1010

11-
#define _Py_UOP_MAX_TRACE_LENGTH 16
11+
#define _Py_UOP_MAX_TRACE_LENGTH 32
1212

1313
typedef struct {
1414
int opcode;

Makefile.pre.in

+1
Original file line numberDiff line numberDiff line change
@@ -1800,6 +1800,7 @@ PYTHON_HEADERS= \
18001800
$(srcdir)/Include/internal/pycore_unionobject.h \
18011801
$(srcdir)/Include/internal/pycore_unicodeobject.h \
18021802
$(srcdir)/Include/internal/pycore_unicodeobject_generated.h \
1803+
$(srcdir)/Include/internal/pycore_uops.h \
18031804
$(srcdir)/Include/internal/pycore_warnings.h \
18041805
$(srcdir)/Include/internal/pycore_weakref.h \
18051806
$(DTRACE_HEADERS) \

Python/ceval.c

+31-31
Original file line numberDiff line numberDiff line change
@@ -2773,24 +2773,26 @@ void Py_LeaveRecursiveCall(void)
27732773
_PyInterpreterFrame *
27742774
_PyUopExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject **stack_pointer)
27752775
{
2776-
#ifdef LLTRACE
2776+
#ifdef Py_DEBUG
27772777
char *uop_debug = Py_GETENV("PYTHONUOPSDEBUG");
27782778
int lltrace = 0;
27792779
if (uop_debug != NULL && *uop_debug >= '0') {
27802780
lltrace = *uop_debug - '0'; // TODO: Parse an int and all that
27812781
}
2782-
if (lltrace >= 2) {
2783-
PyCodeObject *code = _PyFrame_GetCode(frame);
2784-
_Py_CODEUNIT *instr = frame->prev_instr + 1;
2785-
fprintf(stderr,
2786-
"Entering _PyUopExecute for %s (%s:%d) at offset %ld\n",
2787-
PyUnicode_AsUTF8(code->co_qualname),
2788-
PyUnicode_AsUTF8(code->co_filename),
2789-
code->co_firstlineno,
2790-
(long)(instr - (_Py_CODEUNIT *)code->co_code_adaptive));
2791-
}
2782+
#define DPRINTF(level, ...) \
2783+
if (lltrace >= (level)) { fprintf(stderr, __VA_ARGS__); }
2784+
#else
2785+
#define DPRINTF(level, ...)
27922786
#endif
27932787

2788+
DPRINTF(3,
2789+
"Entering _PyUopExecute for %s (%s:%d) at offset %ld\n",
2790+
PyUnicode_AsUTF8(_PyFrame_GetCode(frame)->co_qualname),
2791+
PyUnicode_AsUTF8(_PyFrame_GetCode(frame)->co_filename),
2792+
_PyFrame_GetCode(frame)->co_firstlineno,
2793+
(long)(frame->prev_instr + 1 -
2794+
(_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive));
2795+
27942796
PyThreadState *tstate = _PyThreadState_GET();
27952797
_PyUOpExecutorObject *self = (_PyUOpExecutorObject *)executor;
27962798

@@ -2803,7 +2805,7 @@ _PyUopExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject
28032805
}
28042806

28052807
OBJECT_STAT_INC(optimization_traces_executed);
2806-
_Py_CODEUNIT *ip_offset = (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive - 1;
2808+
_Py_CODEUNIT *ip_offset = (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive;
28072809
int pc = 0;
28082810
int opcode;
28092811
uint64_t operand;
@@ -2812,14 +2814,11 @@ _PyUopExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject
28122814
opcode = self->trace[pc].opcode;
28132815
operand = self->trace[pc].operand;
28142816
oparg = (int)operand;
2815-
#ifdef LLTRACE
2816-
if (lltrace >= 3) {
2817-
const char *opname = opcode < 256 ? _PyOpcode_OpName[opcode] : _PyOpcode_uop_name[opcode];
2818-
int stack_level = (int)(stack_pointer - _PyFrame_Stackbase(frame));
2819-
fprintf(stderr, " uop %s, operand %" PRIu64 ", stack_level %d\n",
2820-
opname, operand, stack_level);
2821-
}
2822-
#endif
2817+
DPRINTF(3,
2818+
" uop %s, operand %" PRIu64 ", stack_level %d\n",
2819+
opcode < 256 ? _PyOpcode_OpName[opcode] : _PyOpcode_uop_name[opcode],
2820+
operand,
2821+
(int)(stack_pointer - _PyFrame_Stackbase(frame)));
28232822
pc++;
28242823
OBJECT_STAT_INC(optimization_uops_executed);
28252824
switch (opcode) {
@@ -2828,14 +2827,15 @@ _PyUopExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject
28282827
#define ENABLE_SPECIALIZATION 0
28292828
#include "executor_cases.c.h"
28302829

2831-
case SET_IP:
2830+
case SAVE_IP:
28322831
{
28332832
frame->prev_instr = ip_offset + oparg;
28342833
break;
28352834
}
28362835

28372836
case EXIT_TRACE:
28382837
{
2838+
frame->prev_instr--; // Back up to just before destination
28392839
_PyFrame_SetStackPointer(frame, stack_pointer);
28402840
Py_DECREF(self);
28412841
return frame;
@@ -2850,6 +2850,13 @@ _PyUopExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject
28502850
}
28512851
}
28522852

2853+
unbound_local_error:
2854+
format_exc_check_arg(tstate, PyExc_UnboundLocalError,
2855+
UNBOUNDLOCAL_ERROR_MSG,
2856+
PyTuple_GetItem(_PyFrame_GetCode(frame)->co_localsplusnames, oparg)
2857+
);
2858+
goto error;
2859+
28532860
pop_4_error:
28542861
STACK_SHRINK(1);
28552862
pop_3_error:
@@ -2861,23 +2868,16 @@ _PyUopExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject
28612868
error:
28622869
// On ERROR_IF we return NULL as the frame.
28632870
// The caller recovers the frame from cframe.current_frame.
2864-
#ifdef LLTRACE
2865-
if (lltrace >= 2) {
2866-
fprintf(stderr, "Error: [Opcode %d, operand %" PRIu64 "]\n", opcode, operand);
2867-
}
2868-
#endif
2871+
DPRINTF(2, "Error: [Opcode %d, operand %" PRIu64 "]\n", opcode, operand);
28692872
_PyFrame_SetStackPointer(frame, stack_pointer);
28702873
Py_DECREF(self);
28712874
return NULL;
28722875

28732876
deoptimize:
28742877
// On DEOPT_IF we just repeat the last instruction.
28752878
// This presumes nothing was popped from the stack (nor pushed).
2876-
#ifdef LLTRACE
2877-
if (lltrace >= 2) {
2878-
fprintf(stderr, "DEOPT: [Opcode %d, operand %" PRIu64 "]\n", opcode, operand);
2879-
}
2880-
#endif
2879+
DPRINTF(2, "DEOPT: [Opcode %d, operand %" PRIu64 "]\n", opcode, operand);
2880+
frame->prev_instr--; // Back up to just before destination
28812881
_PyFrame_SetStackPointer(frame, stack_pointer);
28822882
Py_DECREF(self);
28832883
return frame;

0 commit comments

Comments
 (0)