Skip to content

Commit 9639696

Browse files
authored
gh-109094: remove unnecessary updates of frame->prev_instr in instrumentation functions (#109076)
1 parent 403ab13 commit 9639696

File tree

2 files changed

+11
-6
lines changed

2 files changed

+11
-6
lines changed

Lib/test/test_sys_settrace.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,13 @@ def generator_example():
317317
[(5, 'line'), (5, 'return')])
318318

319319

320+
def lineno_matches_lasti(frame):
321+
last_line = None
322+
for start, end, line in frame.f_code.co_lines():
323+
if start <= frame.f_lasti < end:
324+
last_line = line
325+
return last_line == frame.f_lineno
326+
320327
class Tracer:
321328
def __init__(self, trace_line_events=None, trace_opcode_events=None):
322329
self.trace_line_events = trace_line_events
@@ -330,6 +337,7 @@ def _reconfigure_frame(self, frame):
330337
frame.f_trace_opcodes = self.trace_opcode_events
331338

332339
def trace(self, frame, event, arg):
340+
assert lineno_matches_lasti(frame)
333341
self._reconfigure_frame(frame)
334342
self.events.append((frame.f_lineno, event))
335343
return self.trace
@@ -1890,6 +1898,7 @@ def __init__(self, function, jumpFrom, jumpTo, event='line',
18901898
def trace(self, frame, event, arg):
18911899
if self.done:
18921900
return
1901+
assert lineno_matches_lasti(frame)
18931902
# frame.f_code.co_firstlineno is the first line of the decorator when
18941903
# 'function' is decorated and the decorator may be written using
18951904
# multiple physical lines when it is too long. Use the first line

Python/instrumentation.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,8 +1057,6 @@ _Py_call_instrumentation_jump(
10571057
assert(event == PY_MONITORING_EVENT_JUMP ||
10581058
event == PY_MONITORING_EVENT_BRANCH);
10591059
assert(frame->prev_instr == instr);
1060-
/* Event should occur after the jump */
1061-
frame->prev_instr = target;
10621060
PyCodeObject *code = _PyFrame_GetCode(frame);
10631061
int to = (int)(target - _PyCode_CODE(code));
10641062
PyObject *to_obj = PyLong_FromLong(to * (int)sizeof(_Py_CODEUNIT));
@@ -1071,12 +1069,10 @@ _Py_call_instrumentation_jump(
10711069
if (err) {
10721070
return NULL;
10731071
}
1074-
if (frame->prev_instr != target) {
1072+
if (frame->prev_instr != instr) {
10751073
/* The callback has caused a jump (by setting the line number) */
10761074
return frame->prev_instr;
10771075
}
1078-
/* Reset prev_instr for INSTRUMENTED_LINE */
1079-
frame->prev_instr = instr;
10801076
return target;
10811077
}
10821078

@@ -1125,7 +1121,7 @@ _Py_Instrumentation_GetLine(PyCodeObject *code, int index)
11251121
int
11261122
_Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr, _Py_CODEUNIT *prev)
11271123
{
1128-
frame->prev_instr = instr;
1124+
assert(frame->prev_instr == instr);
11291125
PyCodeObject *code = _PyFrame_GetCode(frame);
11301126
assert(is_version_up_to_date(code, tstate->interp));
11311127
assert(instrumentation_cross_checks(tstate->interp, code));

0 commit comments

Comments
 (0)