@@ -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
@@ -1282,37 +1299,22 @@ eval_frame_handle_pending(PyThreadState *tstate)
1282
1299
#endif
1283
1300
1284
1301
#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]
1299
1304
#else
1305
+ #define TARGET (op ) op
1306
+ #define DISPATCH_GOTO () goto dispatch_opcode
1307
+ #endif
1308
+
1300
1309
#define DISPATCH () \
1301
1310
{ \
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; \
1306
1313
} \
1307
- goto fast_next_opcode; \
1314
+ f->f_lasti = INSTR_OFFSET(); \
1315
+ NEXTOPARG(); \
1316
+ DISPATCH_GOTO(); \
1308
1317
}
1309
- #endif
1310
-
1311
- #else
1312
- #define TARGET (op ) op
1313
- #define DISPATCH () goto fast_next_opcode
1314
-
1315
- #endif
1316
1318
1317
1319
#define CHECK_EVAL_BREAKER () \
1318
1320
if (_Py_atomic_load_relaxed(eval_breaker)) { \
@@ -1598,14 +1600,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
1598
1600
_Py_atomic_int * const eval_breaker = & ceval2 -> eval_breaker ;
1599
1601
PyCodeObject * co ;
1600
1602
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
1603
const _Py_CODEUNIT * first_instr ;
1610
1604
PyObject * names ;
1611
1605
PyObject * consts ;
@@ -1620,7 +1614,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
1620
1614
}
1621
1615
1622
1616
PyTraceInfo trace_info ;
1623
- /* Mark trace_info as initialized */
1617
+ /* Mark trace_info as uninitialized */
1624
1618
trace_info .code = NULL ;
1625
1619
1626
1620
/* push frame */
@@ -1754,10 +1748,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
1754
1748
1755
1749
if (_Py_atomic_load_relaxed (eval_breaker )) {
1756
1750
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 ) {
1761
1755
/* Few cases where we skip running signal handlers and other
1762
1756
pending calls:
1763
1757
- If we're about to enter the 'with:'. It will prevent
@@ -1774,16 +1768,15 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
1774
1768
running the signal handler and raising KeyboardInterrupt
1775
1769
(see bpo-30039).
1776
1770
*/
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
+ }
1783
1775
}
1784
1776
1785
- fast_next_opcode :
1777
+ tracing_dispatch :
1786
1778
f -> f_lasti = INSTR_OFFSET ();
1779
+ NEXTOPARG ();
1787
1780
1788
1781
if (PyDTrace_LINE_ENABLED ())
1789
1782
maybe_dtrace_line (f , & trace_info );
@@ -1805,23 +1798,13 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
1805
1798
JUMPTO (f -> f_lasti );
1806
1799
stack_pointer = f -> f_valuestack + f -> f_stackdepth ;
1807
1800
f -> f_stackdepth = -1 ;
1808
- if (err )
1801
+ if (err ) {
1809
1802
/* trace function raised an exception */
1810
1803
goto error ;
1804
+ }
1805
+ NEXTOPARG ();
1811
1806
}
1812
1807
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
1808
#ifdef LLTRACE
1826
1809
/* Instruction tracing */
1827
1810
@@ -1837,11 +1820,20 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
1837
1820
}
1838
1821
#endif
1839
1822
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
+
1840
1832
switch (opcode ) {
1841
1833
1842
1834
/* BEWARE!
1843
1835
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() ! */
1845
1837
1846
1838
case TARGET (NOP ): {
1847
1839
DISPATCH ();
@@ -5427,7 +5419,6 @@ unpack_iterable(PyThreadState *tstate, PyObject *v,
5427
5419
return 0 ;
5428
5420
}
5429
5421
5430
-
5431
5422
#ifdef LLTRACE
5432
5423
static int
5433
5424
prtrace (PyThreadState * tstate , PyObject * v , const char * str )
0 commit comments