[Python-checkins] gh-104584: Fix error handling from backedge optimization (#106484)

gvanrossum webhook-mailer at python.org
Thu Jul 6 14:39:57 EDT 2023


https://github.com/python/cpython/commit/003ba71dcbe94f0d5cb1d0c56d7f1d5a6dae56f7
commit: 003ba71dcbe94f0d5cb1d0c56d7f1d5a6dae56f7
branch: main
author: Guido van Rossum <guido at python.org>
committer: gvanrossum <gvanrossum at gmail.com>
date: 2023-07-06T18:39:53Z
summary:

gh-104584: Fix error handling from backedge optimization (#106484)

When `_PyOptimizer_BackEdge` returns `NULL`, we should restore `next_instr` (and `stack_pointer`). To accomplish this we should jump to `resume_with_error` instead of just `error`.

The problem this causes is subtle -- the only repro I have is in PR gh-106393, at commit d7df54b139bcc47f5ea094bfaa9824f79bc45adc. But the fix is real (as shown later in that PR).

While we're at it, also improve the debug output: the offsets at which traces are identified are now measured in bytes, and always show the start offset. This makes it easier to correlate executor calls with optimizer calls, and either with `dis` output.

<!-- gh-issue-number: gh-104584 -->
* Issue: gh-104584
<!-- /gh-issue-number -->

files:
M Python/bytecodes.c
M Python/ceval.c
M Python/generated_cases.c.h
M Python/optimizer.c

diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index f69ac2beef4c2..70b52391e6bda 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -2234,7 +2234,7 @@ dummy_func(
                 frame = _PyOptimizer_BackEdge(frame, here, next_instr, stack_pointer);
                 if (frame == NULL) {
                     frame = cframe.current_frame;
-                    goto error;
+                    goto resume_with_error;
                 }
                 assert(frame == cframe.current_frame);
                 here[1].cache &= ((1 << OPTIMIZER_BITS_IN_COUNTER) -1);
diff --git a/Python/ceval.c b/Python/ceval.c
index 6714229fd0784..0ee95bc3a3a4b 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -2737,11 +2737,11 @@ _PyUopExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject
 #endif
 
     DPRINTF(3,
-            "Entering _PyUopExecute for %s (%s:%d) at offset %ld\n",
+            "Entering _PyUopExecute for %s (%s:%d) at byte offset %ld\n",
             PyUnicode_AsUTF8(_PyFrame_GetCode(frame)->co_qualname),
             PyUnicode_AsUTF8(_PyFrame_GetCode(frame)->co_filename),
             _PyFrame_GetCode(frame)->co_firstlineno,
-            (long)(frame->prev_instr + 1 -
+            2 * (long)(frame->prev_instr + 1 -
                    (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive));
 
     PyThreadState *tstate = _PyThreadState_GET();
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index eb2422943984b..6000ab2da1133 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -3193,7 +3193,7 @@
                 frame = _PyOptimizer_BackEdge(frame, here, next_instr, stack_pointer);
                 if (frame == NULL) {
                     frame = cframe.current_frame;
-                    goto error;
+                    goto resume_with_error;
                 }
                 assert(frame == cframe.current_frame);
                 here[1].cache &= ((1 << OPTIMIZER_BITS_IN_COUNTER) -1);
diff --git a/Python/optimizer.c b/Python/optimizer.c
index c3ab649b51b0e..2c1be61f8d614 100644
--- a/Python/optimizer.c
+++ b/Python/optimizer.c
@@ -181,6 +181,7 @@ _PyOptimizer_BackEdge(_PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNI
     }
     insert_executor(code, src, index, executor);
     assert(frame->prev_instr == src);
+    frame->prev_instr = dest - 1;
     return executor->execute(executor, frame, stack_pointer);
 jump_to_destination:
     frame->prev_instr = dest - 1;
@@ -201,7 +202,7 @@ PyUnstable_GetExecutor(PyCodeObject *code, int offset)
         }
         i += _PyInstruction_GetLength(code, i);
     }
-    PyErr_SetString(PyExc_ValueError, "no executor at given offset");
+    PyErr_SetString(PyExc_ValueError, "no executor at given byte offset");
     return NULL;
 }
 
@@ -373,6 +374,9 @@ translate_bytecode_to_trace(
     _PyUOpInstruction *trace,
     int max_length)
 {
+#ifdef Py_DEBUG
+    _Py_CODEUNIT *initial_instr = instr;
+#endif
     int trace_length = 0;
 
 #ifdef Py_DEBUG
@@ -398,11 +402,11 @@ translate_bytecode_to_trace(
     trace_length++;
 
     DPRINTF(4,
-            "Optimizing %s (%s:%d) at offset %ld\n",
+            "Optimizing %s (%s:%d) at byte offset %ld\n",
             PyUnicode_AsUTF8(code->co_qualname),
             PyUnicode_AsUTF8(code->co_filename),
             code->co_firstlineno,
-            (long)(instr - (_Py_CODEUNIT *)code->co_code_adaptive));
+            2 * (long)(initial_instr - (_Py_CODEUNIT *)code->co_code_adaptive));
 
     for (;;) {
         ADD_TO_TRACE(SAVE_IP, (int)(instr - (_Py_CODEUNIT *)code->co_code_adaptive));
@@ -492,21 +496,21 @@ translate_bytecode_to_trace(
     if (trace_length > 3) {
         ADD_TO_TRACE(EXIT_TRACE, 0);
         DPRINTF(1,
-                "Created a trace for %s (%s:%d) at offset %ld -- length %d\n",
+                "Created a trace for %s (%s:%d) at byte offset %ld -- length %d\n",
                 PyUnicode_AsUTF8(code->co_qualname),
                 PyUnicode_AsUTF8(code->co_filename),
                 code->co_firstlineno,
-                (long)(instr - (_Py_CODEUNIT *)code->co_code_adaptive),
+                2 * (long)(initial_instr - (_Py_CODEUNIT *)code->co_code_adaptive),
                 trace_length);
         return trace_length;
     }
     else {
         DPRINTF(4,
-                "No trace for %s (%s:%d) at offset %ld\n",
+                "No trace for %s (%s:%d) at byte offset %ld\n",
                 PyUnicode_AsUTF8(code->co_qualname),
                 PyUnicode_AsUTF8(code->co_filename),
                 code->co_firstlineno,
-                (long)(instr - (_Py_CODEUNIT *)code->co_code_adaptive));
+                2 * (long)(initial_instr - (_Py_CODEUNIT *)code->co_code_adaptive));
     }
     return 0;
 



More information about the Python-checkins mailing list