mirror of
https://github.com/python/cpython.git
synced 2025-08-22 17:55:18 +00:00
bpo-43760: Streamline dispatch sequence for machines without computed gotos. (GH-25244)
* Do fetch and decode at end of opcode then jump directly to switch. Should allow compilers that don't support computed-gotos, specifically MSVC, to generate better code.
This commit is contained in:
parent
b98eba5bc2
commit
28d28e053d
1 changed files with 54 additions and 63 deletions
117
Python/ceval.c
117
Python/ceval.c
|
@ -1264,6 +1264,23 @@ eval_frame_handle_pending(PyThreadState *tstate)
|
|||
-fno-crossjumping).
|
||||
*/
|
||||
|
||||
/* Use macros rather than inline functions, to make it as clear as possible
|
||||
* to the C compiler that the tracing check is a simple test then branch.
|
||||
* We want to be sure that the compiler knows this before it generates
|
||||
* the CFG.
|
||||
*/
|
||||
#ifdef LLTRACE
|
||||
#define OR_LLTRACE || lltrace
|
||||
#else
|
||||
#define OR_LLTRACE
|
||||
#endif
|
||||
|
||||
#ifdef WITH_DTRACE
|
||||
#define OR_DTRACE_LINE || PyDTrace_LINE_ENABLED()
|
||||
#else
|
||||
#define OR_DTRACE_LINE
|
||||
#endif
|
||||
|
||||
#ifdef DYNAMIC_EXECUTION_PROFILE
|
||||
#undef USE_COMPUTED_GOTOS
|
||||
#define USE_COMPUTED_GOTOS 0
|
||||
|
@ -1282,38 +1299,23 @@ eval_frame_handle_pending(PyThreadState *tstate)
|
|||
#endif
|
||||
|
||||
#if USE_COMPUTED_GOTOS
|
||||
#define TARGET(op) \
|
||||
op: \
|
||||
TARGET_##op
|
||||
|
||||
#ifdef LLTRACE
|
||||
#define DISPATCH() \
|
||||
{ \
|
||||
if (!lltrace && !_Py_TracingPossible(ceval2) && !PyDTrace_LINE_ENABLED()) { \
|
||||
f->f_lasti = INSTR_OFFSET(); \
|
||||
NEXTOPARG(); \
|
||||
goto *opcode_targets[opcode]; \
|
||||
} \
|
||||
goto fast_next_opcode; \
|
||||
}
|
||||
#else
|
||||
#define DISPATCH() \
|
||||
{ \
|
||||
if (!_Py_TracingPossible(ceval2) && !PyDTrace_LINE_ENABLED()) { \
|
||||
f->f_lasti = INSTR_OFFSET(); \
|
||||
NEXTOPARG(); \
|
||||
goto *opcode_targets[opcode]; \
|
||||
} \
|
||||
goto fast_next_opcode; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define TARGET(op) op: TARGET_##op
|
||||
#define DISPATCH_GOTO() goto *opcode_targets[opcode]
|
||||
#else
|
||||
#define TARGET(op) op
|
||||
#define DISPATCH() goto fast_next_opcode
|
||||
|
||||
#define DISPATCH_GOTO() goto dispatch_opcode
|
||||
#endif
|
||||
|
||||
#define DISPATCH() \
|
||||
{ \
|
||||
if (_Py_TracingPossible(ceval2) OR_DTRACE_LINE OR_LLTRACE) { \
|
||||
goto tracing_dispatch; \
|
||||
} \
|
||||
f->f_lasti = INSTR_OFFSET(); \
|
||||
NEXTOPARG(); \
|
||||
DISPATCH_GOTO(); \
|
||||
}
|
||||
|
||||
#define CHECK_EVAL_BREAKER() \
|
||||
if (_Py_atomic_load_relaxed(eval_breaker)) { \
|
||||
continue; \
|
||||
|
@ -1598,14 +1600,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
|
|||
_Py_atomic_int * const eval_breaker = &ceval2->eval_breaker;
|
||||
PyCodeObject *co;
|
||||
|
||||
/* when tracing we set things up so that
|
||||
|
||||
not (instr_lb <= current_bytecode_offset < instr_ub)
|
||||
|
||||
is true when the line being executed has changed. The
|
||||
initial values are such as to make this false the first
|
||||
time it is tested. */
|
||||
|
||||
const _Py_CODEUNIT *first_instr;
|
||||
PyObject *names;
|
||||
PyObject *consts;
|
||||
|
@ -1620,7 +1614,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
|
|||
}
|
||||
|
||||
PyTraceInfo trace_info;
|
||||
/* Mark trace_info as initialized */
|
||||
/* Mark trace_info as uninitialized */
|
||||
trace_info.code = NULL;
|
||||
|
||||
/* push frame */
|
||||
|
@ -1754,10 +1748,10 @@ main_loop:
|
|||
|
||||
if (_Py_atomic_load_relaxed(eval_breaker)) {
|
||||
opcode = _Py_OPCODE(*next_instr);
|
||||
if (opcode == SETUP_FINALLY ||
|
||||
opcode == SETUP_WITH ||
|
||||
opcode == BEFORE_ASYNC_WITH ||
|
||||
opcode == YIELD_FROM) {
|
||||
if (opcode != SETUP_FINALLY &&
|
||||
opcode != SETUP_WITH &&
|
||||
opcode != BEFORE_ASYNC_WITH &&
|
||||
opcode != YIELD_FROM) {
|
||||
/* Few cases where we skip running signal handlers and other
|
||||
pending calls:
|
||||
- If we're about to enter the 'with:'. It will prevent
|
||||
|
@ -1774,16 +1768,15 @@ main_loop:
|
|||
running the signal handler and raising KeyboardInterrupt
|
||||
(see bpo-30039).
|
||||
*/
|
||||
goto fast_next_opcode;
|
||||
}
|
||||
|
||||
if (eval_frame_handle_pending(tstate) != 0) {
|
||||
goto error;
|
||||
}
|
||||
if (eval_frame_handle_pending(tstate) != 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fast_next_opcode:
|
||||
tracing_dispatch:
|
||||
f->f_lasti = INSTR_OFFSET();
|
||||
NEXTOPARG();
|
||||
|
||||
if (PyDTrace_LINE_ENABLED())
|
||||
maybe_dtrace_line(f, &trace_info);
|
||||
|
@ -1805,23 +1798,13 @@ main_loop:
|
|||
JUMPTO(f->f_lasti);
|
||||
stack_pointer = f->f_valuestack+f->f_stackdepth;
|
||||
f->f_stackdepth = -1;
|
||||
if (err)
|
||||
if (err) {
|
||||
/* trace function raised an exception */
|
||||
goto error;
|
||||
}
|
||||
NEXTOPARG();
|
||||
}
|
||||
|
||||
/* Extract opcode and argument */
|
||||
|
||||
NEXTOPARG();
|
||||
dispatch_opcode:
|
||||
#ifdef DYNAMIC_EXECUTION_PROFILE
|
||||
#ifdef DXPAIRS
|
||||
dxpairs[lastopcode][opcode]++;
|
||||
lastopcode = opcode;
|
||||
#endif
|
||||
dxp[opcode]++;
|
||||
#endif
|
||||
|
||||
#ifdef LLTRACE
|
||||
/* Instruction tracing */
|
||||
|
||||
|
@ -1837,11 +1820,20 @@ main_loop:
|
|||
}
|
||||
#endif
|
||||
|
||||
dispatch_opcode:
|
||||
#ifdef DYNAMIC_EXECUTION_PROFILE
|
||||
#ifdef DXPAIRS
|
||||
dxpairs[lastopcode][opcode]++;
|
||||
lastopcode = opcode;
|
||||
#endif
|
||||
dxp[opcode]++;
|
||||
#endif
|
||||
|
||||
switch (opcode) {
|
||||
|
||||
/* BEWARE!
|
||||
It is essential that any operation that fails must goto error
|
||||
and that all operation that succeed call [FAST_]DISPATCH() ! */
|
||||
and that all operation that succeed call DISPATCH() ! */
|
||||
|
||||
case TARGET(NOP): {
|
||||
DISPATCH();
|
||||
|
@ -5427,7 +5419,6 @@ Error:
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef LLTRACE
|
||||
static int
|
||||
prtrace(PyThreadState *tstate, PyObject *v, const char *str)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue