]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-44878: Remove loop from interpreter. All dispatching is done by gotos. (GH-27727)
authorMark Shannon <mark@hotpy.org>
Thu, 12 Aug 2021 10:47:38 +0000 (11:47 +0100)
committerGitHub <noreply@github.com>
Thu, 12 Aug 2021 10:47:38 +0000 (11:47 +0100)
Misc/NEWS.d/next/Core and Builtins/2021-08-11-14-12-41.bpo-44878.pAbBfc.rst [new file with mode: 0644]
Python/ceval.c

diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-08-11-14-12-41.bpo-44878.pAbBfc.rst b/Misc/NEWS.d/next/Core and Builtins/2021-08-11-14-12-41.bpo-44878.pAbBfc.rst
new file mode 100644 (file)
index 0000000..9e07fa8
--- /dev/null
@@ -0,0 +1,2 @@
+Remove the loop from the bytecode interpreter. All instructions end with a
+DISPATCH macro, so the loop is now redundant.
index e8c4e4c8c07eb6ccb29dde4aae4309b60b3144a0..f494e8477fac714aa733ffefa6a414969502823f 100644 (file)
@@ -1280,7 +1280,7 @@ eval_frame_handle_pending(PyThreadState *tstate)
 
 #define CHECK_EVAL_BREAKER() \
     if (_Py_atomic_load_relaxed(eval_breaker)) { \
-        continue; \
+        goto check_eval_breaker; \
     }
 
 
@@ -1584,7 +1584,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
     assert(!_PyErr_Occurred(tstate));
 #endif
 
-    for (;;) {
+check_eval_breaker:
+    {
         assert(STACK_LEVEL() >= 0); /* else underflow */
         assert(STACK_LEVEL() <= co->co_stacksize);  /* else overflow */
         assert(!_PyErr_Occurred(tstate));
@@ -4292,6 +4293,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
             CHECK_EVAL_BREAKER();
             DISPATCH();
         }
+
         TARGET(CALL_METHOD_KW): {
             /* Designed to work in tandem with LOAD_METHOD. Same as CALL_METHOD
             but pops TOS to get a tuple of keyword names. */
@@ -4315,6 +4317,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
             CHECK_EVAL_BREAKER();
             DISPATCH();
         }
+
         TARGET(CALL_FUNCTION): {
             PREDICTED(CALL_FUNCTION);
             PyObject **sp, *res;
@@ -4621,7 +4624,17 @@ exception_unwind:
         int level, handler, lasti;
         if (get_exception_handler(co, offset, &level, &handler, &lasti) == 0) {
             // No handlers, so exit.
-            break;
+            assert(retval == NULL);
+            assert(_PyErr_Occurred(tstate));
+
+            /* Pop remaining stack entries. */
+            while (!EMPTY()) {
+                PyObject *o = POP();
+                Py_XDECREF(o);
+            }
+            frame->stackdepth = 0;
+            frame->f_state = FRAME_RAISED;
+            goto exiting;
         }
 
         assert(STACK_LEVEL() >= level);
@@ -4661,18 +4674,8 @@ exception_unwind:
         NEXTOPARG();
         PRE_DISPATCH_GOTO();
         DISPATCH_GOTO();
-    } /* main loop */
-
-    assert(retval == NULL);
-    assert(_PyErr_Occurred(tstate));
-
-    /* Pop remaining stack entries. */
-    while (!EMPTY()) {
-        PyObject *o = POP();
-        Py_XDECREF(o);
     }
-    frame->stackdepth = 0;
-    frame->f_state = FRAME_RAISED;
+
 exiting:
     if (cframe.use_tracing) {
         if (tstate->c_tracefunc) {