]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-109094: remove unnecessary updates of frame->prev_instr in instrumentation functio...
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>
Thu, 7 Sep 2023 17:23:11 +0000 (18:23 +0100)
committerGitHub <noreply@github.com>
Thu, 7 Sep 2023 17:23:11 +0000 (18:23 +0100)
Lib/test/test_sys_settrace.py
Python/instrumentation.c

index 232900876392ff29676f7ab7d901e048bd6c78ac..369a276ac33a1290d8c48b3c9cb732dab803e804 100644 (file)
@@ -317,6 +317,13 @@ generator_example.events = ([(0, 'call'),
                             [(5, 'line'), (5, 'return')])
 
 
+def lineno_matches_lasti(frame):
+    last_line = None
+    for start, end, line in frame.f_code.co_lines():
+        if start <= frame.f_lasti < end:
+            last_line = line
+    return last_line == frame.f_lineno
+
 class Tracer:
     def __init__(self, trace_line_events=None, trace_opcode_events=None):
         self.trace_line_events = trace_line_events
@@ -330,6 +337,7 @@ class Tracer:
             frame.f_trace_opcodes = self.trace_opcode_events
 
     def trace(self, frame, event, arg):
+        assert lineno_matches_lasti(frame)
         self._reconfigure_frame(frame)
         self.events.append((frame.f_lineno, event))
         return self.trace
@@ -1890,6 +1898,7 @@ class JumpTracer:
     def trace(self, frame, event, arg):
         if self.done:
             return
+        assert lineno_matches_lasti(frame)
         # frame.f_code.co_firstlineno is the first line of the decorator when
         # 'function' is decorated and the decorator may be written using
         # multiple physical lines when it is too long. Use the first line
index acc3278d50a60a3740d579ca48aec8ceb4581b45..74c3adf0c1f475220d03cb73a7ad6a5f29ce630d 100644 (file)
@@ -1057,8 +1057,6 @@ _Py_call_instrumentation_jump(
     assert(event == PY_MONITORING_EVENT_JUMP ||
            event == PY_MONITORING_EVENT_BRANCH);
     assert(frame->prev_instr == instr);
-    /* Event should occur after the jump */
-    frame->prev_instr = target;
     PyCodeObject *code = _PyFrame_GetCode(frame);
     int to = (int)(target - _PyCode_CODE(code));
     PyObject *to_obj = PyLong_FromLong(to * (int)sizeof(_Py_CODEUNIT));
@@ -1071,12 +1069,10 @@ _Py_call_instrumentation_jump(
     if (err) {
         return NULL;
     }
-    if (frame->prev_instr != target) {
+    if (frame->prev_instr != instr) {
         /* The callback has caused a jump (by setting the line number) */
         return frame->prev_instr;
     }
-    /* Reset prev_instr for INSTRUMENTED_LINE */
-    frame->prev_instr = instr;
     return target;
 }
 
@@ -1125,7 +1121,7 @@ _Py_Instrumentation_GetLine(PyCodeObject *code, int index)
 int
 _Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr, _Py_CODEUNIT *prev)
 {
-    frame->prev_instr = instr;
+    assert(frame->prev_instr == instr);
     PyCodeObject *code = _PyFrame_GetCode(frame);
     assert(is_version_up_to_date(code, tstate->interp));
     assert(instrumentation_cross_checks(tstate->interp, code));