@@ -1264,6 +1264,23 @@ eval_frame_handle_pending(PyThreadState *tstate)
1264
1264
-fno-crossjumping).
1265
1265
*/
1266
1266
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
+
1267
1284
#ifdef DYNAMIC_EXECUTION_PROFILE
1268
1285
#undef USE_COMPUTED_GOTOS
1269
1286
#define USE_COMPUTED_GOTOS 0
@@ -1285,34 +1302,21 @@ eval_frame_handle_pending(PyThreadState *tstate)
1285
1302
#define TARGET (op ) \
1286
1303
op: \
1287
1304
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
- }
1305
+ #define DISPATCH_GOTO goto *opcode_targets[opcode];
1299
1306
#else
1307
+ #define TARGET (op ) op
1308
+ #define DISPATCH_GOTO goto dispatch_opcode;
1309
+ #endif
1310
+
1300
1311
#define DISPATCH () \
1301
1312
{ \
1302
- if (!_Py_TracingPossible(ceval2) && !PyDTrace_LINE_ENABLED()) { \
1303
- f->f_lasti = INSTR_OFFSET(); \
1304
- NEXTOPARG(); \
1305
- goto *opcode_targets[opcode]; \
1313
+ if (_Py_TracingPossible(ceval2) OR_DTRACE_LINE OR_LLTRACE) { \
1314
+ goto tracing_dispatch; \
1306
1315
} \
1307
- goto fast_next_opcode; \
1316
+ f->f_lasti = INSTR_OFFSET(); \
1317
+ NEXTOPARG(); \
1318
+ DISPATCH_GOTO \
1308
1319
}
1309
- #endif
1310
-
1311
- #else
1312
- #define TARGET (op ) op
1313
- #define DISPATCH () goto fast_next_opcode
1314
-
1315
- #endif
1316
1320
1317
1321
#define CHECK_EVAL_BREAKER () \
1318
1322
if (_Py_atomic_load_relaxed(eval_breaker)) { \
@@ -1590,22 +1594,14 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
1590
1594
#endif
1591
1595
PyObject * * stack_pointer ; /* Next free slot in value stack */
1592
1596
const _Py_CODEUNIT * next_instr ;
1593
- int opcode ; /* Current opcode */
1597
+ uint8_t opcode ; /* Current opcode */
1594
1598
int oparg ; /* Current opcode argument, if any */
1595
1599
PyObject * * fastlocals , * * freevars ;
1596
1600
PyObject * retval = NULL ; /* Return value */
1597
1601
struct _ceval_state * const ceval2 = & tstate -> interp -> ceval ;
1598
1602
_Py_atomic_int * const eval_breaker = & ceval2 -> eval_breaker ;
1599
1603
PyCodeObject * co ;
1600
1604
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
-
1609
1605
const _Py_CODEUNIT * first_instr ;
1610
1606
PyObject * names ;
1611
1607
PyObject * consts ;
@@ -1620,7 +1616,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
1620
1616
}
1621
1617
1622
1618
PyTraceInfo trace_info ;
1623
- /* Mark trace_info as initialized */
1619
+ /* Mark trace_info as uninitialized */
1624
1620
trace_info .code = NULL ;
1625
1621
1626
1622
/* push frame */
@@ -1754,10 +1750,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
1754
1750
1755
1751
if (_Py_atomic_load_relaxed (eval_breaker )) {
1756
1752
opcode = _Py_OPCODE (* next_instr );
1757
- if (opcode == SETUP_FINALLY ||
1758
- opcode == SETUP_WITH ||
1759
- opcode == BEFORE_ASYNC_WITH ||
1760
- opcode = = YIELD_FROM ) {
1753
+ if (opcode != SETUP_FINALLY &&
1754
+ opcode != SETUP_WITH &&
1755
+ opcode != BEFORE_ASYNC_WITH &&
1756
+ opcode ! = YIELD_FROM ) {
1761
1757
/* Few cases where we skip running signal handlers and other
1762
1758
pending calls:
1763
1759
- If we're about to enter the 'with:'. It will prevent
@@ -1774,16 +1770,15 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
1774
1770
running the signal handler and raising KeyboardInterrupt
1775
1771
(see bpo-30039).
1776
1772
*/
1777
- goto fast_next_opcode ;
1778
- }
1779
-
1780
- if (eval_frame_handle_pending (tstate ) != 0 ) {
1781
- goto error ;
1782
- }
1773
+ if (eval_frame_handle_pending (tstate ) != 0 ) {
1774
+ goto error ;
1775
+ }
1776
+ }
1783
1777
}
1784
1778
1785
- fast_next_opcode :
1779
+ tracing_dispatch :
1786
1780
f -> f_lasti = INSTR_OFFSET ();
1781
+ NEXTOPARG ();
1787
1782
1788
1783
if (PyDTrace_LINE_ENABLED ())
1789
1784
maybe_dtrace_line (f , & trace_info );
@@ -1801,27 +1796,17 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
1801
1796
tstate -> c_traceobj ,
1802
1797
tstate , f ,
1803
1798
& trace_info );
1799
+ if (err ) {
1800
+ /* trace function raised an exception */
1801
+ goto error ;
1802
+ }
1804
1803
/* Reload possibly changed frame fields */
1805
1804
JUMPTO (f -> f_lasti );
1806
1805
stack_pointer = f -> f_valuestack + f -> f_stackdepth ;
1807
1806
f -> f_stackdepth = -1 ;
1808
- if (err )
1809
- /* trace function raised an exception */
1810
- goto error ;
1807
+ NEXTOPARG ();
1811
1808
}
1812
1809
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
-
1825
1810
#ifdef LLTRACE
1826
1811
/* Instruction tracing */
1827
1812
@@ -1837,11 +1822,20 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
1837
1822
}
1838
1823
#endif
1839
1824
1825
+ dispatch_opcode :
1826
+ #ifdef DYNAMIC_EXECUTION_PROFILE
1827
+ #ifdef DXPAIRS
1828
+ dxpairs [lastopcode ][opcode ]++ ;
1829
+ lastopcode = opcode ;
1830
+ #endif
1831
+ dxp [opcode ]++ ;
1832
+ #endif
1833
+
1840
1834
switch (opcode ) {
1841
1835
1842
1836
/* BEWARE!
1843
1837
It is essential that any operation that fails must goto error
1844
- and that all operation that succeed call [FAST_] DISPATCH() ! */
1838
+ and that all operation that succeed call DISPATCH() ! */
1845
1839
1846
1840
case TARGET (NOP ): {
1847
1841
DISPATCH ();
@@ -5427,7 +5421,6 @@ unpack_iterable(PyThreadState *tstate, PyObject *v,
5427
5421
return 0 ;
5428
5422
}
5429
5423
5430
-
5431
5424
#ifdef LLTRACE
5432
5425
static int
5433
5426
prtrace (PyThreadState * tstate , PyObject * v , const char * str )
0 commit comments