bpo-44878: Remove loop from interpreter. All dispatching is done by gotos. (GH-27727)

This commit is contained in:
Mark Shannon 2021-08-12 11:47:38 +01:00 committed by GitHub
parent f08e6d1bb3
commit a530a9538f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 19 additions and 14 deletions

View file

@ -0,0 +1,2 @@
Remove the loop from the bytecode interpreter. All instructions end with a
DISPATCH macro, so the loop is now redundant.

View file

@ -1280,7 +1280,7 @@ eval_frame_handle_pending(PyThreadState *tstate)
#define CHECK_EVAL_BREAKER() \ #define CHECK_EVAL_BREAKER() \
if (_Py_atomic_load_relaxed(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)); assert(!_PyErr_Occurred(tstate));
#endif #endif
for (;;) { check_eval_breaker:
{
assert(STACK_LEVEL() >= 0); /* else underflow */ assert(STACK_LEVEL() >= 0); /* else underflow */
assert(STACK_LEVEL() <= co->co_stacksize); /* else overflow */ assert(STACK_LEVEL() <= co->co_stacksize); /* else overflow */
assert(!_PyErr_Occurred(tstate)); assert(!_PyErr_Occurred(tstate));
@ -4292,6 +4293,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
CHECK_EVAL_BREAKER(); CHECK_EVAL_BREAKER();
DISPATCH(); DISPATCH();
} }
TARGET(CALL_METHOD_KW): { TARGET(CALL_METHOD_KW): {
/* Designed to work in tandem with LOAD_METHOD. Same as CALL_METHOD /* Designed to work in tandem with LOAD_METHOD. Same as CALL_METHOD
but pops TOS to get a tuple of keyword names. */ 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(); CHECK_EVAL_BREAKER();
DISPATCH(); DISPATCH();
} }
TARGET(CALL_FUNCTION): { TARGET(CALL_FUNCTION): {
PREDICTED(CALL_FUNCTION); PREDICTED(CALL_FUNCTION);
PyObject **sp, *res; PyObject **sp, *res;
@ -4621,7 +4624,17 @@ exception_unwind:
int level, handler, lasti; int level, handler, lasti;
if (get_exception_handler(co, offset, &level, &handler, &lasti) == 0) { if (get_exception_handler(co, offset, &level, &handler, &lasti) == 0) {
// No handlers, so exit. // 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); assert(STACK_LEVEL() >= level);
@ -4661,18 +4674,8 @@ exception_unwind:
NEXTOPARG(); NEXTOPARG();
PRE_DISPATCH_GOTO(); PRE_DISPATCH_GOTO();
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: exiting:
if (cframe.use_tracing) { if (cframe.use_tracing) {
if (tstate->c_tracefunc) { if (tstate->c_tracefunc) {