diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h index c8fad1562d8443..2a968a10097f4e 100644 --- a/Include/internal/pycore_frame.h +++ b/Include/internal/pycore_frame.h @@ -72,6 +72,8 @@ typedef struct _PyInterpreterFrame { * If there is no callee, then it is meaningless. */ uint16_t return_offset; char owner; + /* Used by INSTRUMENTED_LINE */ + int last_traced_index; /* Locals and stack */ PyObject *localsplus[1]; } _PyInterpreterFrame; @@ -137,6 +139,7 @@ _PyFrame_Initialize( frame->prev_instr = _PyCode_CODE(code) - 1; frame->return_offset = 0; frame->owner = FRAME_OWNED_BY_THREAD; + frame->last_traced_index = 0; for (int i = null_locals_from; i < code->co_nlocalsplus; i++) { frame->localsplus[i] = NULL; @@ -300,6 +303,7 @@ _PyFrame_PushTrampolineUnchecked(PyThreadState *tstate, PyCodeObject *code, int frame->prev_instr = _PyCode_CODE(code) + prev_instr; frame->owner = FRAME_OWNED_BY_THREAD; frame->return_offset = 0; + frame->last_traced_index = 0; return frame; } diff --git a/Include/internal/pycore_instruments.h b/Include/internal/pycore_instruments.h index 97dcfb9f8672f7..e83c2cc76dd580 100644 --- a/Include/internal/pycore_instruments.h +++ b/Include/internal/pycore_instruments.h @@ -70,7 +70,7 @@ _Py_call_instrumentation(PyThreadState *tstate, int event, extern int _Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, - _Py_CODEUNIT *instr, _Py_CODEUNIT *prev); + _Py_CODEUNIT *instr); extern int _Py_call_instrumentation_instruction( diff --git a/Python/ceval.c b/Python/ceval.c index b02bf60315b7e1..7128fe87a40d81 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -776,11 +776,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int case INSTRUMENTED_LINE: #endif { - _Py_CODEUNIT *prev = frame->prev_instr; _Py_CODEUNIT *here = frame->prev_instr = next_instr; _PyFrame_SetStackPointer(frame, stack_pointer); int original_opcode = _Py_call_instrumentation_line( - tstate, frame, here, prev); + tstate, frame, here); stack_pointer = _PyFrame_GetStackPointer(frame); if (original_opcode < 0) { next_instr = here+1; diff --git a/Python/instrumentation.c b/Python/instrumentation.c index fee6eae1734394..ca297542b49486 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -1113,7 +1113,7 @@ _Py_Instrumentation_GetLine(PyCodeObject *code, int index) } int -_Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr, _Py_CODEUNIT *prev) +_Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr) { assert(frame->prev_instr == instr); PyCodeObject *code = _PyFrame_GetCode(frame); @@ -1130,10 +1130,10 @@ _Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, int8_t line_delta = line_data->line_delta; int line = compute_line(code, i, line_delta); assert(line >= 0); - int prev_index = (int)(prev - _PyCode_CODE(code)); - int prev_line = _Py_Instrumentation_GetLine(code, prev_index); + int prev_line = frame->last_traced_index == 0 ? -1 : + _Py_Instrumentation_GetLine(code, frame->last_traced_index); if (prev_line == line) { - int prev_opcode = _PyCode_CODE(code)[prev_index].op.code; + int prev_opcode = _PyCode_CODE(code)[frame->last_traced_index].op.code; /* RESUME and INSTRUMENTED_RESUME are needed for the operation of * instrumentation, so must never be hidden by an INSTRUMENTED_LINE. */ @@ -1141,6 +1141,7 @@ _Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, goto done; } } + frame->last_traced_index = i; uint8_t tools = code->_co_monitoring->line_tools != NULL ? code->_co_monitoring->line_tools[i] : (interp->monitors.tools[PY_MONITORING_EVENT_LINE] |