@@ -1264,6 +1264,23 @@ eval_frame_handle_pending(PyThreadState *tstate)
12641264 -fno-crossjumping).
12651265*/
12661266
1267+ /* Use macros rather than inline functions, to make it as clear as possible
1268+ * to the C compiler that the tracing check is a simple test then branch.
1269+ * We want to be sure that the compiler knows this before it generates
1270+ * the CFG.
1271+ */
1272+ #ifdef LLTRACE
1273+ #define OR_LLTRACE || lltrace
1274+ #else
1275+ #define OR_LLTRACE
1276+ #endif
1277+
1278+ #ifdef WITH_DTRACE
1279+ #define OR_DTRACE_LINE || PyDTrace_LINE_ENABLED()
1280+ #else
1281+ #define OR_DTRACE_LINE
1282+ #endif
1283+
12671284#ifdef DYNAMIC_EXECUTION_PROFILE
12681285#undef USE_COMPUTED_GOTOS
12691286#define USE_COMPUTED_GOTOS 0
@@ -1282,37 +1299,22 @@ eval_frame_handle_pending(PyThreadState *tstate)
12821299#endif
12831300
12841301#if USE_COMPUTED_GOTOS
1285- #define TARGET (op ) \
1286- op: \
1287- TARGET_##op
1288-
1289- #ifdef LLTRACE
1290- #define DISPATCH () \
1291- { \
1292- if (!lltrace && !_Py_TracingPossible(ceval2) && !PyDTrace_LINE_ENABLED()) { \
1293- f->f_lasti = INSTR_OFFSET(); \
1294- NEXTOPARG(); \
1295- goto *opcode_targets[opcode]; \
1296- } \
1297- goto fast_next_opcode; \
1298- }
1302+ #define TARGET (op ) op: TARGET_##op
1303+ #define DISPATCH_GOTO () goto *opcode_targets[opcode]
12991304#else
1305+ #define TARGET (op ) op
1306+ #define DISPATCH_GOTO () goto dispatch_opcode
1307+ #endif
1308+
13001309#define DISPATCH () \
13011310 { \
1302- if (!_Py_TracingPossible(ceval2) && !PyDTrace_LINE_ENABLED()) { \
1303- f->f_lasti = INSTR_OFFSET(); \
1304- NEXTOPARG(); \
1305- goto *opcode_targets[opcode]; \
1311+ if (_Py_TracingPossible(ceval2) OR_DTRACE_LINE OR_LLTRACE) { \
1312+ goto tracing_dispatch; \
13061313 } \
1307- goto fast_next_opcode; \
1314+ f->f_lasti = INSTR_OFFSET(); \
1315+ NEXTOPARG(); \
1316+ DISPATCH_GOTO(); \
13081317 }
1309- #endif
1310-
1311- #else
1312- #define TARGET (op ) op
1313- #define DISPATCH () goto fast_next_opcode
1314-
1315- #endif
13161318
13171319#define CHECK_EVAL_BREAKER () \
13181320 if (_Py_atomic_load_relaxed(eval_breaker)) { \
@@ -1598,14 +1600,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
15981600 _Py_atomic_int * const eval_breaker = & ceval2 -> eval_breaker ;
15991601 PyCodeObject * co ;
16001602
1601- /* when tracing we set things up so that
1602-
1603- not (instr_lb <= current_bytecode_offset < instr_ub)
1604-
1605- is true when the line being executed has changed. The
1606- initial values are such as to make this false the first
1607- time it is tested. */
1608-
16091603 const _Py_CODEUNIT * first_instr ;
16101604 PyObject * names ;
16111605 PyObject * consts ;
@@ -1620,7 +1614,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
16201614 }
16211615
16221616 PyTraceInfo trace_info ;
1623- /* Mark trace_info as initialized */
1617+ /* Mark trace_info as uninitialized */
16241618 trace_info .code = NULL ;
16251619
16261620 /* push frame */
@@ -1754,10 +1748,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
17541748
17551749 if (_Py_atomic_load_relaxed (eval_breaker )) {
17561750 opcode = _Py_OPCODE (* next_instr );
1757- if (opcode == SETUP_FINALLY ||
1758- opcode == SETUP_WITH ||
1759- opcode == BEFORE_ASYNC_WITH ||
1760- opcode = = YIELD_FROM ) {
1751+ if (opcode != SETUP_FINALLY &&
1752+ opcode != SETUP_WITH &&
1753+ opcode != BEFORE_ASYNC_WITH &&
1754+ opcode ! = YIELD_FROM ) {
17611755 /* Few cases where we skip running signal handlers and other
17621756 pending calls:
17631757 - If we're about to enter the 'with:'. It will prevent
@@ -1774,16 +1768,15 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
17741768 running the signal handler and raising KeyboardInterrupt
17751769 (see bpo-30039).
17761770 */
1777- goto fast_next_opcode ;
1778- }
1779-
1780- if (eval_frame_handle_pending (tstate ) != 0 ) {
1781- goto error ;
1782- }
1771+ if (eval_frame_handle_pending (tstate ) != 0 ) {
1772+ goto error ;
1773+ }
1774+ }
17831775 }
17841776
1785- fast_next_opcode :
1777+ tracing_dispatch :
17861778 f -> f_lasti = INSTR_OFFSET ();
1779+ NEXTOPARG ();
17871780
17881781 if (PyDTrace_LINE_ENABLED ())
17891782 maybe_dtrace_line (f , & trace_info );
@@ -1805,23 +1798,13 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
18051798 JUMPTO (f -> f_lasti );
18061799 stack_pointer = f -> f_valuestack + f -> f_stackdepth ;
18071800 f -> f_stackdepth = -1 ;
1808- if (err )
1801+ if (err ) {
18091802 /* trace function raised an exception */
18101803 goto error ;
1804+ }
1805+ NEXTOPARG ();
18111806 }
18121807
1813- /* Extract opcode and argument */
1814-
1815- NEXTOPARG ();
1816- dispatch_opcode :
1817- #ifdef DYNAMIC_EXECUTION_PROFILE
1818- #ifdef DXPAIRS
1819- dxpairs [lastopcode ][opcode ]++ ;
1820- lastopcode = opcode ;
1821- #endif
1822- dxp [opcode ]++ ;
1823- #endif
1824-
18251808#ifdef LLTRACE
18261809 /* Instruction tracing */
18271810
@@ -1837,11 +1820,20 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
18371820 }
18381821#endif
18391822
1823+ dispatch_opcode :
1824+ #ifdef DYNAMIC_EXECUTION_PROFILE
1825+ #ifdef DXPAIRS
1826+ dxpairs [lastopcode ][opcode ]++ ;
1827+ lastopcode = opcode ;
1828+ #endif
1829+ dxp [opcode ]++ ;
1830+ #endif
1831+
18401832 switch (opcode ) {
18411833
18421834 /* BEWARE!
18431835 It is essential that any operation that fails must goto error
1844- and that all operation that succeed call [FAST_] DISPATCH() ! */
1836+ and that all operation that succeed call DISPATCH() ! */
18451837
18461838 case TARGET (NOP ): {
18471839 DISPATCH ();
@@ -5427,7 +5419,6 @@ unpack_iterable(PyThreadState *tstate, PyObject *v,
54275419 return 0 ;
54285420}
54295421
5430-
54315422#ifdef LLTRACE
54325423static int
54335424prtrace (PyThreadState * tstate , PyObject * v , const char * str )
0 commit comments