bpo-43760: Streamline dispatch sequence for machines without computed… · python/cpython@28d28e0

@@ -1264,6 +1264,23 @@ eval_frame_handle_pending(PyThreadState *tstate)

12641264

-fno-crossjumping).

12651265

*/

126612661267+

/* 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

1283130012841301

#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

1316131813171319

#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;

160016021601-

/* 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

}

1621161516221616

PyTraceInfo trace_info;

1623-

/* Mark trace_info as initialized */

1617+

/* Mark trace_info as uninitialized */

16241618

trace_info.code = NULL;

1625161916261620

/* push frame */

@@ -1754,10 +1748,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)

1754174817551749

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

}

178417761785-

fast_next_opcode:

1777+

tracing_dispatch:

17861778

f->f_lasti = INSTR_OFFSET();

1779+

NEXTOPARG();

1787178017881781

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

}

181218071813-

/* 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

183918221823+

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) {

1841183318421834

/* 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() ! */

1845183718461838

case TARGET(NOP): {

18471839

DISPATCH();

@@ -5427,7 +5419,6 @@ unpack_iterable(PyThreadState *tstate, PyObject *v,

54275419

return 0;

54285420

}

542954215430-54315422

#ifdef LLTRACE

54325423

static int

54335424

prtrace(PyThreadState *tstate, PyObject *v, const char *str)