cpython: 17d3bbde60d2 (original) (raw)

--- a/Include/opcode.h +++ b/Include/opcode.h @@ -37,12 +37,21 @@ extern "C" { #define SLICE 30 /* Also uses 31-33 / +#define SLICE_1 31 +#define SLICE_2 32 +#define SLICE_3 33 #define STORE_SLICE 40 / Also uses 41-43 / +#define STORE_SLICE_1 41 +#define STORE_SLICE_2 42 +#define STORE_SLICE_3 43 #define DELETE_SLICE 50 / Also uses 51-53 */ +#define DELETE_SLICE_1 51 +#define DELETE_SLICE_2 52 +#define DELETE_SLICE_3 53 #define STORE_MAP 54 #define INPLACE_ADD 55

--- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -300,6 +300,16 @@ ASDLGEN= $(srcdir)/Parser/asdl_c.py ##########################################################################

Python

+ +OPCODETARGETS_H= [](#l2.8) + $(srcdir)/Python/opcode_targets.h + +OPCODETARGETGEN= [](#l2.11) + $(srcdir)/Python/makeopcodetargets.py + +OPCODETARGETGEN_FILES= [](#l2.14) + (OPCODETARGETGEN)(OPCODETARGETGEN) (OPCODETARGETGEN)(srcdir)/Lib/opcode.py + PYTHON_OBJS= [](#l2.17) Python/_warnings.o [](#l2.18) Python/Python-ast.o [](#l2.19) @@ -671,6 +681,11 @@ Objects/bytearrayobject.o: $(srcdir)/Obj Objects/stringobject.o: $(srcdir)/Objects/stringobject.c [](#l2.21) $(STRINGLIB_HEADERS) +$(OPCODETARGETS_H): $(OPCODETARGETGEN_FILES)

--- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ What's New in Python 2.7.11? Core and Builtins ----------------- +- Issue #4753: On compilers where it is supported, use "computed gotos" for

--- a/Python/ceval.c +++ b/Python/ceval.c @@ -688,6 +688,100 @@ PyEval_EvalFrame(PyFrameObject *f) { PyObject * PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) { +#ifdef DYNAMIC_EXECUTION_PROFILE

+#endif +#ifdef HAVE_COMPUTED_GOTOS

+#else

+#endif +#if USE_COMPUTED_GOTOS +/* Import the static jump table */ +#include "opcode_targets.h" +

+ +#define TARGET_WITH_IMPL_NOARG(op, impl) [](#l4.34) + TARGET_##op: [](#l4.35) + opcode = op; [](#l4.36) + case op: [](#l4.37) + goto impl; [](#l4.38) + +#define TARGET_NOARG(op) [](#l4.40) + TARGET_##op: [](#l4.41) + opcode = op; [](#l4.42) + case op:[](#l4.43) + +#define TARGET(op) [](#l4.45) + TARGET_##op: [](#l4.46) + opcode = op; [](#l4.47) + oparg = NEXTARG(); [](#l4.48) + case op:[](#l4.49) + + +#define DISPATCH() [](#l4.52) + { [](#l4.53) + int tick = Py_Ticker - 1; [](#l4.54) + Py_Ticker = tick; [](#l4.55) + if (tick >= 0) { [](#l4.56) + FAST_DISPATCH(); [](#l4.57) + } [](#l4.58) + continue; [](#l4.59) + } + +#ifdef LLTRACE +#define FAST_DISPATCH() [](#l4.63) + { [](#l4.64) + if (!lltrace && !Py_TracingPossible) { [](#l4.65) + f->f_lasti = INSTR_OFFSET(); [](#l4.66) + goto *opcode_targets[*next_instr++]; [](#l4.67) + } [](#l4.68) + goto fast_next_opcode; [](#l4.69) + } +#else +#define FAST_DISPATCH() { [](#l4.72) + if (!Py_TracingPossible) { [](#l4.73) + f->f_lasti = INSTR_OFFSET(); [](#l4.74) + goto *opcode_targets[next_instr++]; [](#l4.75) + } [](#l4.76) + goto fast_next_opcode;[](#l4.77) +} +#endif + +#else +#define TARGET(op) [](#l4.82) + case op: +#define TARGET_WITH_IMPL(op, impl) [](#l4.84) + / silence compiler warnings about impl unused */ [](#l4.85) + if (0) goto impl; [](#l4.86) + case op:[](#l4.87) + +#define TARGET_NOARG(op) [](#l4.89) + case op:[](#l4.90) + +#define TARGET_WITH_IMPL_NOARG(op, impl) [](#l4.92) + if (0) goto impl; [](#l4.93) + case op:[](#l4.94) + +#define DISPATCH() continue +#define FAST_DISPATCH() goto fast_next_opcode +#endif + + #ifdef DXPAIRS int lastopcode = 0; #endif @@ -805,14 +899,23 @@ PyEval_EvalFrameEx(PyFrameObject *f, int counter updates for both opcodes. */ + +// Next opcode prediction is also enabled for Computed Gotos as well. #ifdef DYNAMIC_EXECUTION_PROFILE -#define PREDICT(op) if (0) goto PRED##op +#define PREDICT(op) //if (0) goto PRED##op +#define PREDICTED(op) +#define PREDICTED_WITH_ARG(op) #else #define PREDICT(op) if (*next_instr == op) goto PRED##op +#define PREDICTED(op) PRED##op: next_instr++ +#ifdef USE_COMPUTED_GOTOS +#define PREDICTED_WITH_ARG(op) PRED##op: next_instr++ +#else +#define PREDICTED_WITH_ARG(op) PRED##op: oparg = PEEKARG(); next_instr += 3 #endif - -#define PREDICTED(op) PRED##op: next_instr++ -#define PREDICTED_WITH_ARG(op) PRED_##op: oparg = PEEKARG(); next_instr += 3 +#endif + + /* Stack manipulation macros */ @@ -1108,55 +1211,70 @@ PyEval_EvalFrameEx(PyFrameObject f, int / case STOP_CODE: this is an error! */

-

+

-

+

PREDICTED_WITH_ARG(STORE_FAST);

-

+

-

+

-

+

-

+

@@ -1165,15 +1283,21 @@ PyEval_EvalFrameEx(PyFrameObject *f, int SET_SECOND(w); SET_THIRD(x); SET_FOURTH(u);

-

+

-

+ +

@@ -1182,7 +1306,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int STACKADJ(2); SET_TOP(x); SET_SECOND(w);

@@ -1194,84 +1318,100 @@ PyEval_EvalFrameEx(PyFrameObject *f, int SET_TOP(x); SET_SECOND(w); SET_THIRD(v);

-

+

-

+

-

+

-

+

-

+

-

+

-

+

-

+

@@ -1279,32 +1419,37 @@ PyEval_EvalFrameEx(PyFrameObject *f, int Py_DECREF(v); Py_DECREF(w); SET_TOP(x);

-

+

-

+

@@ -1314,10 +1459,12 @@ PyEval_EvalFrameEx(PyFrameObject *f, int Py_DECREF(v); Py_DECREF(w); SET_TOP(x);

-

+

@@ -1346,10 +1493,12 @@ PyEval_EvalFrameEx(PyFrameObject *f, int skip_decref_vx: Py_DECREF(w); SET_TOP(x);

-

+

@@ -1371,10 +1520,12 @@ PyEval_EvalFrameEx(PyFrameObject *f, int Py_DECREF(v); Py_DECREF(w); SET_TOP(x);

-

+

@@ -1395,102 +1546,122 @@ PyEval_EvalFrameEx(PyFrameObject *f, int Py_DECREF(v); Py_DECREF(w); SET_TOP(x);

-

+

-

+

-

+

-

+

-

+

-

+

-

+

-

+

-

+

-

+

@@ -1498,42 +1669,50 @@ PyEval_EvalFrameEx(PyFrameObject *f, int Py_DECREF(v); Py_DECREF(w); SET_TOP(x);

-

+

-

+

-

+

@@ -1560,10 +1739,12 @@ PyEval_EvalFrameEx(PyFrameObject *f, int skip_decref_v: Py_DECREF(w); SET_TOP(x);

-

+

@@ -1583,63 +1764,78 @@ PyEval_EvalFrameEx(PyFrameObject *f, int Py_DECREF(v); Py_DECREF(w); SET_TOP(x);

-

+

-

+

-

+

-

+

-

+

-

+ +

@@ -1654,13 +1850,17 @@ PyEval_EvalFrameEx(PyFrameObject *f, int Py_XDECREF(v); Py_XDECREF(w); SET_TOP(x);

-

+

@@ -1676,13 +1876,17 @@ PyEval_EvalFrameEx(PyFrameObject *f, int Py_DECREF(u); Py_XDECREF(v); Py_XDECREF(w);

-

+ +

@@ -1697,10 +1901,12 @@ PyEval_EvalFrameEx(PyFrameObject *f, int Py_DECREF(u); Py_XDECREF(v); Py_XDECREF(w);

-

+

@@ -1710,10 +1916,12 @@ PyEval_EvalFrameEx(PyFrameObject *f, int Py_DECREF(u); Py_DECREF(v); Py_DECREF(w);

-

+

@@ -1721,10 +1929,12 @@ PyEval_EvalFrameEx(PyFrameObject *f, int err = PyObject_DelItem(v, w); Py_DECREF(v); Py_DECREF(w);

-

+

@@ -1747,12 +1957,16 @@ PyEval_EvalFrameEx(PyFrameObject *f, int Py_DECREF(v); Py_XDECREF(x); break; -

+

-

+

@@ -1798,16 +2012,20 @@ PyEval_EvalFrameEx(PyFrameObject *f, int Py_DECREF(v); Py_XDECREF(stream); stream = NULL;

-

+

-

+

@@ -1827,12 +2045,14 @@ PyEval_EvalFrameEx(PyFrameObject *f, int Py_XDECREF(stream); stream = NULL; break; -

#ifdef CASE_TOO_BIG default: switch (opcode) { #endif

+

@@ -1853,28 +2073,37 @@ PyEval_EvalFrameEx(PyFrameObject *f, int break; } break; -

+

-

+

-

+

-

+

@@ -1886,8 +2115,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int Py_DECREF(v); Py_DECREF(w); break; -

+

@@ -1895,10 +2126,12 @@ PyEval_EvalFrameEx(PyFrameObject *f, int Py_DECREF(v); } }

PREDICTED(END_FINALLY);

@@ -1922,8 +2155,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int } Py_DECREF(v); break; -

+

@@ -1934,8 +2169,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int Py_DECREF(v); Py_DECREF(w); break; -

+

@@ -1944,7 +2181,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int else err = PyObject_SetItem(x, w, v); Py_DECREF(v);

@@ -1955,8 +2192,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int PyString_AS_STRING(t)); Py_DECREF(t); break; -

+

@@ -1973,9 +2212,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int PyString_AS_STRING(w)); Py_DECREF(t); break;

PREDICTED_WITH_ARG(UNPACK_SEQUENCE);

@@ -1987,7 +2228,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int PUSH(w); } Py_DECREF(v);

@@ -2006,8 +2247,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int } Py_DECREF(v); break; -

+ +

@@ -2015,33 +2259,42 @@ PyEval_EvalFrameEx(PyFrameObject f, int err = PyObject_SetAttr(v, w, u); / v.w = u */ Py_DECREF(v); Py_DECREF(u);

-

+

-

+ +

-

+

-

+

@@ -2081,9 +2334,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int Py_INCREF(x); } PUSH(x);

-

+

@@ -2103,7 +2358,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int if (x != NULL) { Py_INCREF(x); PUSH(x);

@@ -2115,7 +2370,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int if (x != NULL) { Py_INCREF(x); PUSH(x);

@@ -2134,13 +2389,15 @@ PyEval_EvalFrameEx(PyFrameObject *f, int } Py_INCREF(x); PUSH(x);

-

+

@@ -2148,20 +2405,24 @@ PyEval_EvalFrameEx(PyFrameObject *f, int PyTuple_GetItem(co->co_varnames, oparg) ); break; -

+

-

+

@@ -2181,15 +2442,19 @@ PyEval_EvalFrameEx(PyFrameObject *f, int UNBOUNDFREE_ERROR_MSG, v); } break; -

+

-

+

@@ -2197,11 +2462,13 @@ PyEval_EvalFrameEx(PyFrameObject *f, int PyTuple_SET_ITEM(x, oparg, w); } PUSH(x);

-

+

@@ -2209,11 +2476,13 @@ PyEval_EvalFrameEx(PyFrameObject *f, int PyList_SET_ITEM(x, oparg, w); } PUSH(x);

-

+

@@ -2227,18 +2496,21 @@ PyEval_EvalFrameEx(PyFrameObject *f, int break; } PUSH(x);

- -

+

-

+

@@ -2247,10 +2519,12 @@ PyEval_EvalFrameEx(PyFrameObject f, int err = PyDict_SetItem(v, w, u); / v[w] = u */ Py_DECREF(u); Py_DECREF(w);

-

+

@@ -2261,20 +2535,24 @@ PyEval_EvalFrameEx(PyFrameObject *f, int Py_DECREF(w); if (err == 0) { PREDICT(JUMP_ABSOLUTE);

-

+

-

+

@@ -2307,9 +2585,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int if (x == NULL) break; PREDICT(POP_JUMP_IF_FALSE); PREDICT(POP_JUMP_IF_TRUE);

-

+

@@ -2350,10 +2630,12 @@ PyEval_EvalFrameEx(PyFrameObject *f, int READ_TIMESTAMP(intr1); Py_DECREF(w); SET_TOP(x);

-

+

@@ -2366,34 +2648,40 @@ PyEval_EvalFrameEx(PyFrameObject *f, int READ_TIMESTAMP(intr1); PyFrame_LocalsToFast(f, 0); Py_DECREF(v);

-

+

-

+

PREDICTED_WITH_ARG(POP_JUMP_IF_FALSE);

@@ -2403,19 +2691,21 @@ PyEval_EvalFrameEx(PyFrameObject *f, int JUMPTO(oparg); else break;

PREDICTED_WITH_ARG(POP_JUMP_IF_TRUE);

@@ -2427,18 +2717,20 @@ PyEval_EvalFrameEx(PyFrameObject *f, int ; else break;

-

+

@@ -2450,18 +2742,20 @@ PyEval_EvalFrameEx(PyFrameObject *f, int JUMPTO(oparg); else break;

-

+

@@ -2474,10 +2768,12 @@ PyEval_EvalFrameEx(PyFrameObject *f, int } else break;

PREDICTED_WITH_ARG(JUMP_ABSOLUTE);

#if FAST_LOOPS /* Enabling this path speeds-up all while and for-loops by bypassing @@ -2489,10 +2785,12 @@ PyEval_EvalFrameEx(PyFrameObject *f, int */ goto fast_next_opcode; #else

#endif -

+

@@ -2500,13 +2798,15 @@ PyEval_EvalFrameEx(PyFrameObject *f, int if (x != NULL) { SET_TOP(x); PREDICT(FOR_ITER);

PREDICTED_WITH_ARG(FOR_ITER);

@@ -2514,7 +2814,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int PUSH(x); PREDICT(STORE_FAST); PREDICT(UNPACK_SEQUENCE);

@@ -2526,13 +2826,17 @@ PyEval_EvalFrameEx(PyFrameObject *f, int x = v = POP(); Py_DECREF(v); JUMPBY(oparg);

-

+

-

+

@@ -2540,10 +2844,13 @@ PyEval_EvalFrameEx(PyFrameObject *f, int } why = WHY_CONTINUE; goto fast_block_end; -

+

@@ -2551,9 +2858,13 @@ PyEval_EvalFrameEx(PyFrameObject *f, int PyFrame_BlockSetup(f, opcode, INSTR_OFFSET() + oparg, STACK_LEVEL());

-

+ + +

@@ -2579,10 +2890,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int STACK_LEVEL()); PUSH(x);

@@ -2670,7 +2982,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int break; }

@@ -2682,14 +2994,14 @@ PyEval_EvalFrameEx(PyFrameObject *f, int #endif stack_pointer = sp; PUSH(x);

@@ -2727,12 +3039,13 @@ PyEval_EvalFrameEx(PyFrameObject *f, int Py_DECREF(w); } PUSH(x);

+

@@ -2753,8 +3066,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int } PUSH(x); break; -

+

@@ -2789,7 +3103,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int break; }

@@ -2801,14 +3116,20 @@ PyEval_EvalFrameEx(PyFrameObject *f, int Py_DECREF(v); Py_XDECREF(w); SET_TOP(x);

-

+

-

+ +#if USE_COMPUTED_GOTOS

+#endif default: fprintf(stderr, "XXX lineno: %d, opcode: %d\n",

new file mode 100755 --- /dev/null +++ b/Python/makeopcodetargets.py @@ -0,0 +1,45 @@ +#! /usr/bin/env python +"""Generate C code for the jump table of the threaded code interpreter +(for compilers supporting computed gotos or "labels-as-values", such as gcc). +""" + +# This code should stay compatible with Python 2.3, at least while +# some of the buildbots have Python 2.3 as their system Python. + +import imp +import os + + +def find_module(modname):

+ +def write_contents(f):

+ + +if name == "main":

new file mode 100644 --- /dev/null +++ b/Python/opcode_targets.h @@ -0,0 +1,258 @@ +static void *opcode_targets[256] = {

+};

--- a/configure +++ b/configure @@ -811,6 +811,7 @@ with_libm with_libc enable_big_digits enable_unicode +with_computed_gotos with_ensurepip ' ac_precious_vars='build_alias @@ -1494,6 +1495,9 @@ Optional Packages: --with-fpectl enable SIGFPE catching --with-libm=STRING math library --with-libc=STRING C library

@@ -14685,6 +14689,85 @@ for dir in $SRCDIRS; do mkdir $dir fi done + +# BEGIN_COMPUTED_GOTO +# Check for --with-computed-gotos +{ asecho"as_echo "asecho"as_me:${as_lineno-$LINENO}: checking for --with-computed-gotos" >&5 +$as_echo_n "checking for --with-computed-gotos... " >&6; } + +# Check whether --with-computed-gotos was given. +if test "${with_computed_gotos+set}" = set; then :

+LABEL1:

+LABEL2:

+} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then :

--- a/configure.ac +++ b/configure.ac @@ -4557,6 +4557,57 @@ for dir in $SRCDIRS; do mkdir $dir fi done + +# BEGIN_COMPUTED_GOTO +# Check for --with-computed-gotos +AC_MSG_CHECKING(for --with-computed-gotos) +AC_ARG_WITH(computed-gotos,

+[ +if test "$withval" = yes +then

+LABEL1:

+LABEL2:

+} +]]])], +[ac_cv_computed_gotos=yes], +[ac_cv_computed_gotos=no], +[if test "${with_computed_gotos+set}" = set; then

ensurepip option

--- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -118,6 +118,9 @@ /* Define to 1 if you have the clock' function. */[](#l9.4) #undef HAVE_CLOCK[](#l9.5) [](#l9.6) +/* Define if the C compiler supports computed gotos. */[](#l9.7) +#undef HAVE_COMPUTED_GOTOS[](#l9.8) +[](#l9.9) /* Define to 1 if you have the confstr' function. / #undef HAVE_CONFSTR @@ -1069,6 +1072,9 @@ / Define to 1 if your <sys/time.h> declares `struct tm'. / #undef TM_IN_SYS_TIME +/ Define if you want to use computed gotos in ceval.c. / +#undef USE_COMPUTED_GOTOS + / Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE

undef _ALL_SOURCE