[Python-checkins] cpython (2.7): backport computed gotos (#4753)

benjamin.peterson python-checkins at python.org
Thu May 28 19:45:37 CEST 2015


https://hg.python.org/cpython/rev/17d3bbde60d2
changeset:   96336:17d3bbde60d2
branch:      2.7
parent:      96322:581776726b61
user:        Benjamin Peterson <benjamin at python.org>
date:        Thu May 28 12:45:31 2015 -0500
summary:
  backport computed gotos (#4753)

files:
  Include/opcode.h            |    9 +
  Makefile.pre.in             |   15 +
  Misc/NEWS                   |    4 +
  Python/ceval.c              |  961 ++++++++++++++++-------
  Python/makeopcodetargets.py |   45 +
  Python/opcode_targets.h     |  258 ++++++
  configure                   |   83 ++
  configure.ac                |   51 +
  pyconfig.h.in               |    6 +
  9 files changed, 1112 insertions(+), 320 deletions(-)


diff --git a/Include/opcode.h b/Include/opcode.h
--- a/Include/opcode.h
+++ b/Include/opcode.h
@@ -37,12 +37,21 @@
 
 #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
diff --git a/Makefile.pre.in b/Makefile.pre.in
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -300,6 +300,16 @@
 
 ##########################################################################
 # Python
+
+OPCODETARGETS_H= \
+		$(srcdir)/Python/opcode_targets.h
+		
+OPCODETARGETGEN= \
+		$(srcdir)/Python/makeopcodetargets.py
+
+OPCODETARGETGEN_FILES= \
+		$(OPCODETARGETGEN) $(srcdir)/Lib/opcode.py
+
 PYTHON_OBJS=	\
 		Python/_warnings.o \
 		Python/Python-ast.o \
@@ -671,6 +681,11 @@
 Objects/stringobject.o: $(srcdir)/Objects/stringobject.c \
 				$(STRINGLIB_HEADERS)
 
+$(OPCODETARGETS_H): $(OPCODETARGETGEN_FILES)
+	$(OPCODETARGETGEN) $(OPCODETARGETS_H)
+
+Python/ceval.o: $(OPCODETARGETS_H)
+
 Python/formatter_unicode.o: $(srcdir)/Python/formatter_unicode.c \
 				$(STRINGLIB_HEADERS)
 
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,10 @@
 Core and Builtins
 -----------------
 
+- Issue #4753: On compilers where it is supported, use "computed gotos" for
+  bytecode dispatch in the interpreter. This improves interpretation
+  performance.
+
 - Issue #22939: Fixed integer overflow in iterator object.  Original patch by
   Clement Rouault.
 
diff --git a/Python/ceval.c b/Python/ceval.c
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -688,6 +688,100 @@
 PyObject *
 PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
 {
+#ifdef DYNAMIC_EXECUTION_PROFILE
+  #undef USE_COMPUTED_GOTOS
+#endif
+#ifdef HAVE_COMPUTED_GOTOS
+    #ifndef USE_COMPUTED_GOTOS
+    #define USE_COMPUTED_GOTOS 1
+    #endif
+#else
+    #if defined(USE_COMPUTED_GOTOS) && USE_COMPUTED_GOTOS
+    #error "Computed gotos are not supported on this compiler."
+    #endif
+    #undef USE_COMPUTED_GOTOS
+    #define USE_COMPUTED_GOTOS 0
+#endif
+#if USE_COMPUTED_GOTOS
+/* Import the static jump table */
+#include "opcode_targets.h"
+
+  /* This macro is used when several opcodes defer to the same implementation
+   (e.g. SETUP_LOOP, SETUP_FINALLY) */
+#define TARGET_WITH_IMPL(op, impl) \
+		TARGET_##op: \
+		opcode = op; \
+		oparg = NEXTARG(); \
+		case op: \
+		goto impl; \
+
+#define TARGET_WITH_IMPL_NOARG(op, impl) \
+		TARGET_##op: \
+		opcode = op; \
+		case op: \
+		goto impl; \
+
+#define TARGET_NOARG(op) \
+		TARGET_##op: \
+		opcode = op; \
+		case op:\
+
+#define TARGET(op) \
+		TARGET_##op: \
+		opcode = op; \
+		oparg = NEXTARG(); \
+		case op:\
+
+
+#define DISPATCH() \
+		{ \
+	int _tick = _Py_Ticker - 1; \
+	_Py_Ticker = _tick; \
+	if (_tick >= 0) { \
+		FAST_DISPATCH(); \
+	} \
+	continue; \
+		}
+
+#ifdef LLTRACE
+#define FAST_DISPATCH() \
+		{ \
+	if (!lltrace && !_Py_TracingPossible) { \
+		f->f_lasti = INSTR_OFFSET(); \
+		goto *opcode_targets[*next_instr++]; \
+	} \
+	goto fast_next_opcode; \
+		}
+#else
+#define FAST_DISPATCH() { \
+		if (!_Py_TracingPossible) { \
+			f->f_lasti = INSTR_OFFSET(); \
+			goto *opcode_targets[*next_instr++]; \
+		} \
+		goto fast_next_opcode;\
+}
+#endif
+
+#else
+#define TARGET(op) \
+		case op:
+#define TARGET_WITH_IMPL(op, impl) \
+		/* silence compiler warnings about `impl` unused */ \
+		if (0) goto impl; \
+		case op:\
+
+#define TARGET_NOARG(op) \
+		case op:\
+
+#define TARGET_WITH_IMPL_NOARG(op, impl) \
+		if (0) goto impl; \
+		case op:\
+
+#define DISPATCH() continue
+#define FAST_DISPATCH() goto fast_next_opcode
+#endif
+
+
 #ifdef DXPAIRS
     int lastopcode = 0;
 #endif
@@ -805,14 +899,23 @@
     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 @@
 
         /* case STOP_CODE: this is an error! */
 
-        case NOP:
-            goto fast_next_opcode;
-
-        case LOAD_FAST:
+        TARGET_NOARG(NOP)
+    	{
+        	FAST_DISPATCH();
+    	}
+
+        TARGET(LOAD_FAST)
+        {
             x = GETLOCAL(oparg);
             if (x != NULL) {
                 Py_INCREF(x);
                 PUSH(x);
-                goto fast_next_opcode;
+        		FAST_DISPATCH();
             }
             format_exc_check_arg(PyExc_UnboundLocalError,
                 UNBOUNDLOCAL_ERROR_MSG,
                 PyTuple_GetItem(co->co_varnames, oparg));
             break;
-
-        case LOAD_CONST:
+        }
+
+        TARGET(LOAD_CONST)
+        {
             x = GETITEM(consts, oparg);
             Py_INCREF(x);
             PUSH(x);
-            goto fast_next_opcode;
+        	FAST_DISPATCH();
+        }
 
         PREDICTED_WITH_ARG(STORE_FAST);
-        case STORE_FAST:
+        TARGET(STORE_FAST)
+        {
             v = POP();
             SETLOCAL(oparg, v);
-            goto fast_next_opcode;
-
-        case POP_TOP:
+        	FAST_DISPATCH();
+        }
+
+        TARGET_NOARG(POP_TOP)
+        {
             v = POP();
             Py_DECREF(v);
-            goto fast_next_opcode;
-
-        case ROT_TWO:
+        	FAST_DISPATCH();
+        }
+
+        TARGET_NOARG(ROT_TWO)
+        {
             v = TOP();
             w = SECOND();
             SET_TOP(w);
             SET_SECOND(v);
-            goto fast_next_opcode;
-
-        case ROT_THREE:
+        	FAST_DISPATCH();
+        }
+
+        TARGET_NOARG(ROT_THREE)
+        {
             v = TOP();
             w = SECOND();
             x = THIRD();
             SET_TOP(w);
             SET_SECOND(x);
             SET_THIRD(v);
-            goto fast_next_opcode;
-
-        case ROT_FOUR:
+        	FAST_DISPATCH();
+        }
+
+        TARGET_NOARG(ROT_FOUR)
+     	{
             u = TOP();
             v = SECOND();
             w = THIRD();
@@ -1165,15 +1283,21 @@
             SET_SECOND(w);
             SET_THIRD(x);
             SET_FOURTH(u);
-            goto fast_next_opcode;
-
-        case DUP_TOP:
+            FAST_DISPATCH();
+		}
+
+       
+        TARGET_NOARG(DUP_TOP)
+        {
             v = TOP();
             Py_INCREF(v);
             PUSH(v);
-            goto fast_next_opcode;
-
-        case DUP_TOPX:
+        	FAST_DISPATCH();
+        }
+
+
+        TARGET(DUP_TOPX)
+        {
             if (oparg == 2) {
                 x = TOP();
                 Py_INCREF(x);
@@ -1182,7 +1306,7 @@
                 STACKADJ(2);
                 SET_TOP(x);
                 SET_SECOND(w);
-                goto fast_next_opcode;
+        		FAST_DISPATCH();
             } else if (oparg == 3) {
                 x = TOP();
                 Py_INCREF(x);
@@ -1194,84 +1318,100 @@
                 SET_TOP(x);
                 SET_SECOND(w);
                 SET_THIRD(v);
-                goto fast_next_opcode;
+        		FAST_DISPATCH();
             }
             Py_FatalError("invalid argument to DUP_TOPX"
                           " (bytecode corruption?)");
             /* Never returns, so don't bother to set why. */
             break;
-
-        case UNARY_POSITIVE:
+        }
+
+        TARGET_NOARG(UNARY_POSITIVE)
+        {
             v = TOP();
             x = PyNumber_Positive(v);
             Py_DECREF(v);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case UNARY_NEGATIVE:
+        }
+
+        TARGET_NOARG( UNARY_NEGATIVE)
+        {
             v = TOP();
             x = PyNumber_Negative(v);
             Py_DECREF(v);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case UNARY_NOT:
+        }
+
+        TARGET_NOARG(UNARY_NOT)
+        {
             v = TOP();
             err = PyObject_IsTrue(v);
             Py_DECREF(v);
             if (err == 0) {
                 Py_INCREF(Py_True);
                 SET_TOP(Py_True);
-                continue;
+        		DISPATCH();
             }
             else if (err > 0) {
                 Py_INCREF(Py_False);
                 SET_TOP(Py_False);
                 err = 0;
-                continue;
+        		DISPATCH();
             }
             STACKADJ(-1);
             break;
-
-        case UNARY_CONVERT:
+        }
+
+        TARGET_NOARG(UNARY_CONVERT)
+        {
             v = TOP();
             x = PyObject_Repr(v);
             Py_DECREF(v);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case UNARY_INVERT:
+        }
+
+        TARGET_NOARG(UNARY_INVERT)
+        {
             v = TOP();
             x = PyNumber_Invert(v);
             Py_DECREF(v);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case BINARY_POWER:
+        }
+
+        TARGET_NOARG(BINARY_POWER)
+        {
             w = POP();
             v = TOP();
             x = PyNumber_Power(v, w, Py_None);
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case BINARY_MULTIPLY:
+        }
+
+        TARGET_NOARG(BINARY_MULTIPLY)
+        {
             w = POP();
             v = TOP();
             x = PyNumber_Multiply(v, w);
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if(x!=NULL) DISPATCH();
             break;
-
-        case BINARY_DIVIDE:
+        }
+
+        TARGET_NOARG(BINARY_DIVIDE)
+        {
             if (!_Py_QnewFlag) {
                 w = POP();
                 v = TOP();
@@ -1279,32 +1419,37 @@
                 Py_DECREF(v);
                 Py_DECREF(w);
                 SET_TOP(x);
-                if (x != NULL) continue;
+        		if (x != NULL) DISPATCH();
                 break;
             }
-            /* -Qnew is in effect:  fall through to
-               BINARY_TRUE_DIVIDE */
-        case BINARY_TRUE_DIVIDE:
+        }
+        /* -Qnew is in effect:  fall through to BINARY_TRUE_DIVIDE */
+        TARGET_NOARG(BINARY_TRUE_DIVIDE)
+        {
             w = POP();
             v = TOP();
             x = PyNumber_TrueDivide(v, w);
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case BINARY_FLOOR_DIVIDE:
+        }
+
+        TARGET_NOARG(BINARY_FLOOR_DIVIDE)
+        {
             w = POP();
             v = TOP();
             x = PyNumber_FloorDivide(v, w);
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case BINARY_MODULO:
+        }
+
+        TARGET_NOARG(BINARY_MODULO)
+        {
             w = POP();
             v = TOP();
             if (PyString_CheckExact(v))
@@ -1314,10 +1459,12 @@
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case BINARY_ADD:
+        }
+
+        TARGET_NOARG(BINARY_ADD)
+        {
             w = POP();
             v = TOP();
             if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) {
@@ -1346,10 +1493,12 @@
           skip_decref_vx:
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+			if (x != NULL) DISPATCH();
             break;
-
-        case BINARY_SUBTRACT:
+        }
+
+        TARGET_NOARG(BINARY_SUBTRACT)
+        {
             w = POP();
             v = TOP();
             if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) {
@@ -1371,10 +1520,12 @@
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case BINARY_SUBSCR:
+        }
+
+        TARGET_NOARG(BINARY_SUBSCR)
+        {
             w = POP();
             v = TOP();
             if (PyList_CheckExact(v) && PyInt_CheckExact(w)) {
@@ -1395,102 +1546,122 @@
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case BINARY_LSHIFT:
+        }
+
+        TARGET_NOARG(BINARY_LSHIFT)
+        {
             w = POP();
             v = TOP();
             x = PyNumber_Lshift(v, w);
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case BINARY_RSHIFT:
+        }
+
+        TARGET_NOARG(BINARY_RSHIFT)
+        {
             w = POP();
             v = TOP();
             x = PyNumber_Rshift(v, w);
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case BINARY_AND:
+        }
+
+        TARGET_NOARG(BINARY_AND)
+        {
             w = POP();
             v = TOP();
             x = PyNumber_And(v, w);
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case BINARY_XOR:
+        }
+
+        TARGET_NOARG(BINARY_XOR)
+        {
             w = POP();
             v = TOP();
             x = PyNumber_Xor(v, w);
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case BINARY_OR:
+        }
+
+        TARGET_NOARG(BINARY_OR)
+        {
             w = POP();
             v = TOP();
             x = PyNumber_Or(v, w);
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case LIST_APPEND:
+        }
+
+        TARGET(LIST_APPEND)
+        {
             w = POP();
             v = PEEK(oparg);
             err = PyList_Append(v, w);
             Py_DECREF(w);
             if (err == 0) {
                 PREDICT(JUMP_ABSOLUTE);
-                continue;
+        		DISPATCH();
             }
             break;
-
-        case SET_ADD:
+        }
+
+        TARGET(SET_ADD)
+        {
             w = POP();
             v = stack_pointer[-oparg];
             err = PySet_Add(v, w);
             Py_DECREF(w);
             if (err == 0) {
                 PREDICT(JUMP_ABSOLUTE);
-                continue;
+        		DISPATCH();
             }
             break;
-
-        case INPLACE_POWER:
+        }
+
+        TARGET_NOARG(INPLACE_POWER)
+        {
             w = POP();
             v = TOP();
             x = PyNumber_InPlacePower(v, w, Py_None);
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case INPLACE_MULTIPLY:
+        }
+
+        TARGET_NOARG(INPLACE_MULTIPLY)
+        {
             w = POP();
             v = TOP();
             x = PyNumber_InPlaceMultiply(v, w);
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case INPLACE_DIVIDE:
+        }
+
+        TARGET_NOARG(INPLACE_DIVIDE)
+        {
             if (!_Py_QnewFlag) {
                 w = POP();
                 v = TOP();
@@ -1498,42 +1669,50 @@
                 Py_DECREF(v);
                 Py_DECREF(w);
                 SET_TOP(x);
-                if (x != NULL) continue;
+        		if (x != NULL) DISPATCH();
                 break;
             }
+        }
             /* -Qnew is in effect:  fall through to
                INPLACE_TRUE_DIVIDE */
-        case INPLACE_TRUE_DIVIDE:
+        TARGET_NOARG(INPLACE_TRUE_DIVIDE)
+        {
             w = POP();
             v = TOP();
             x = PyNumber_InPlaceTrueDivide(v, w);
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case INPLACE_FLOOR_DIVIDE:
+        }
+
+        TARGET_NOARG(INPLACE_FLOOR_DIVIDE)
+        {
             w = POP();
             v = TOP();
             x = PyNumber_InPlaceFloorDivide(v, w);
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case INPLACE_MODULO:
+        }
+
+        TARGET_NOARG(INPLACE_MODULO)
+        {
             w = POP();
             v = TOP();
             x = PyNumber_InPlaceRemainder(v, w);
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case INPLACE_ADD:
+        }
+
+        TARGET_NOARG(INPLACE_ADD)
+        {
             w = POP();
             v = TOP();
             if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) {
@@ -1560,10 +1739,12 @@
           skip_decref_v:
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+			if (x != NULL) DISPATCH();
             break;
-
-        case INPLACE_SUBTRACT:
+        }
+
+        TARGET_NOARG(INPLACE_SUBTRACT)
+        {
             w = POP();
             v = TOP();
             if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) {
@@ -1583,63 +1764,78 @@
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case INPLACE_LSHIFT:
+        }
+
+        TARGET_NOARG(INPLACE_LSHIFT)
+        {
             w = POP();
             v = TOP();
             x = PyNumber_InPlaceLshift(v, w);
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case INPLACE_RSHIFT:
+        }
+
+        TARGET_NOARG(INPLACE_RSHIFT)
+        {
             w = POP();
             v = TOP();
             x = PyNumber_InPlaceRshift(v, w);
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case INPLACE_AND:
+        }
+
+        TARGET_NOARG(INPLACE_AND)
+        {
             w = POP();
             v = TOP();
             x = PyNumber_InPlaceAnd(v, w);
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case INPLACE_XOR:
+        }
+
+        TARGET_NOARG(INPLACE_XOR)
+        {
             w = POP();
             v = TOP();
             x = PyNumber_InPlaceXor(v, w);
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case INPLACE_OR:
+        }
+
+        TARGET_NOARG(INPLACE_OR)
+        {
             w = POP();
             v = TOP();
             x = PyNumber_InPlaceOr(v, w);
             Py_DECREF(v);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case SLICE+0:
-        case SLICE+1:
-        case SLICE+2:
-        case SLICE+3:
+        }
+
+
+     
+        TARGET_WITH_IMPL_NOARG(SLICE, _slice)
+        TARGET_WITH_IMPL_NOARG(SLICE_1, _slice)
+		TARGET_WITH_IMPL_NOARG(SLICE_2, _slice)
+		TARGET_WITH_IMPL_NOARG(SLICE_3, _slice)
+		_slice:
+		{
             if ((opcode-SLICE) & 2)
                 w = POP();
             else
@@ -1654,13 +1850,17 @@
             Py_XDECREF(v);
             Py_XDECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case STORE_SLICE+0:
-        case STORE_SLICE+1:
-        case STORE_SLICE+2:
-        case STORE_SLICE+3:
+		}
+
+     
+        TARGET_WITH_IMPL_NOARG(STORE_SLICE, _store_slice)
+        TARGET_WITH_IMPL_NOARG(STORE_SLICE_1, _store_slice)
+		TARGET_WITH_IMPL_NOARG(STORE_SLICE_2, _store_slice)
+		TARGET_WITH_IMPL_NOARG(STORE_SLICE_3, _store_slice)
+		_store_slice:
+		{
             if ((opcode-STORE_SLICE) & 2)
                 w = POP();
             else
@@ -1676,13 +1876,17 @@
             Py_DECREF(u);
             Py_XDECREF(v);
             Py_XDECREF(w);
-            if (err == 0) continue;
+        	if (err == 0) DISPATCH();
             break;
-
-        case DELETE_SLICE+0:
-        case DELETE_SLICE+1:
-        case DELETE_SLICE+2:
-        case DELETE_SLICE+3:
+		}
+
+
+        TARGET_WITH_IMPL_NOARG(DELETE_SLICE, _delete_slice)
+        TARGET_WITH_IMPL_NOARG(DELETE_SLICE_1, _delete_slice)
+		TARGET_WITH_IMPL_NOARG(DELETE_SLICE_2, _delete_slice)
+		TARGET_WITH_IMPL_NOARG(DELETE_SLICE_3, _delete_slice)
+		_delete_slice:
+		{
             if ((opcode-DELETE_SLICE) & 2)
                 w = POP();
             else
@@ -1697,10 +1901,12 @@
             Py_DECREF(u);
             Py_XDECREF(v);
             Py_XDECREF(w);
-            if (err == 0) continue;
+        	if (err == 0) DISPATCH();
             break;
-
-        case STORE_SUBSCR:
+		}
+
+        TARGET_NOARG(STORE_SUBSCR)
+        {
             w = TOP();
             v = SECOND();
             u = THIRD();
@@ -1710,10 +1916,12 @@
             Py_DECREF(u);
             Py_DECREF(v);
             Py_DECREF(w);
-            if (err == 0) continue;
+        	if (err == 0) DISPATCH();
             break;
-
-        case DELETE_SUBSCR:
+        }
+
+        TARGET_NOARG(DELETE_SUBSCR)
+        {
             w = TOP();
             v = SECOND();
             STACKADJ(-2);
@@ -1721,10 +1929,12 @@
             err = PyObject_DelItem(v, w);
             Py_DECREF(v);
             Py_DECREF(w);
-            if (err == 0) continue;
+        	if (err == 0) DISPATCH();
             break;
-
-        case PRINT_EXPR:
+        }
+
+        TARGET_NOARG(PRINT_EXPR)
+        {
             v = POP();
             w = PySys_GetObject("displayhook");
             if (w == NULL) {
@@ -1747,12 +1957,16 @@
             Py_DECREF(v);
             Py_XDECREF(x);
             break;
-
-        case PRINT_ITEM_TO:
+        }
+
+        TARGET_NOARG(PRINT_ITEM_TO)
+        {
             w = stream = POP();
             /* fall through to PRINT_ITEM */
-
-        case PRINT_ITEM:
+        }
+
+        TARGET_NOARG(PRINT_ITEM)
+        {
             v = POP();
             if (stream == NULL || stream == Py_None) {
                 w = PySys_GetObject("stdout");
@@ -1798,16 +2012,20 @@
             Py_DECREF(v);
             Py_XDECREF(stream);
             stream = NULL;
-            if (err == 0)
-                continue;
+        	if (err == 0) DISPATCH();
             break;
-
-        case PRINT_NEWLINE_TO:
+        }
+
+        TARGET_NOARG(PRINT_NEWLINE_TO)
+        {
             w = stream = POP();
             /* fall through to PRINT_NEWLINE */
-
-        case PRINT_NEWLINE:
-            if (stream == NULL || stream == Py_None) {
+        }
+
+        TARGET_NOARG(PRINT_NEWLINE)
+        {
+        	if (stream == NULL || stream == Py_None)
+        	{
                 w = PySys_GetObject("stdout");
                 if (w == NULL) {
                     PyErr_SetString(PyExc_RuntimeError,
@@ -1827,12 +2045,14 @@
             Py_XDECREF(stream);
             stream = NULL;
             break;
-
+        }
 
 #ifdef CASE_TOO_BIG
         default: switch (opcode) {
 #endif
-        case RAISE_VARARGS:
+
+        TARGET(RAISE_VARARGS)
+    		{
             u = v = w = NULL;
             switch (oparg) {
             case 3:
@@ -1853,28 +2073,37 @@
                 break;
             }
             break;
-
-        case LOAD_LOCALS:
-            if ((x = f->f_locals) != NULL) {
+    		}
+
+        TARGET_NOARG(LOAD_LOCALS)
+        {
+        	if ((x = f->f_locals) != NULL)
+        	{
                 Py_INCREF(x);
                 PUSH(x);
-                continue;
+        		DISPATCH();
             }
             PyErr_SetString(PyExc_SystemError, "no locals");
             break;
-
-        case RETURN_VALUE:
+        }
+
+        TARGET_NOARG(RETURN_VALUE)
+        {
             retval = POP();
             why = WHY_RETURN;
             goto fast_block_end;
-
-        case YIELD_VALUE:
+        }
+
+        TARGET_NOARG(YIELD_VALUE)
+        {
             retval = POP();
             f->f_stacktop = stack_pointer;
             why = WHY_YIELD;
             goto fast_yield;
-
-        case EXEC_STMT:
+        }
+
+        TARGET_NOARG(EXEC_STMT)
+        {
             w = TOP();
             v = SECOND();
             u = THIRD();
@@ -1886,8 +2115,10 @@
             Py_DECREF(v);
             Py_DECREF(w);
             break;
-
-        case POP_BLOCK:
+        }
+
+        TARGET_NOARG(POP_BLOCK)
+        {
             {
                 PyTryBlock *b = PyFrame_BlockPop(f);
                 while (STACK_LEVEL() > b->b_level) {
@@ -1895,10 +2126,12 @@
                     Py_DECREF(v);
                 }
             }
-            continue;
+        	DISPATCH();
+        }
 
         PREDICTED(END_FINALLY);
-        case END_FINALLY:
+        TARGET_NOARG(END_FINALLY)
+        {
             v = POP();
             if (PyInt_Check(v)) {
                 why = (enum why_code) PyInt_AS_LONG(v);
@@ -1922,8 +2155,10 @@
             }
             Py_DECREF(v);
             break;
-
-        case BUILD_CLASS:
+        }
+
+        TARGET_NOARG(BUILD_CLASS)
+        {
             u = TOP();
             v = SECOND();
             w = THIRD();
@@ -1934,8 +2169,10 @@
             Py_DECREF(v);
             Py_DECREF(w);
             break;
-
-        case STORE_NAME:
+        }
+
+        TARGET(STORE_NAME)
+        {
             w = GETITEM(names, oparg);
             v = POP();
             if ((x = f->f_locals) != NULL) {
@@ -1944,7 +2181,7 @@
                 else
                     err = PyObject_SetItem(x, w, v);
                 Py_DECREF(v);
-                if (err == 0) continue;
+        		if (err == 0) DISPATCH();
                 break;
             }
             t = PyObject_Repr(w);
@@ -1955,8 +2192,10 @@
                          PyString_AS_STRING(t));
             Py_DECREF(t);
             break;
-
-        case DELETE_NAME:
+        }
+
+        TARGET(DELETE_NAME)
+        {
             w = GETITEM(names, oparg);
             if ((x = f->f_locals) != NULL) {
                 if ((err = PyObject_DelItem(x, w)) != 0)
@@ -1973,9 +2212,11 @@
                          PyString_AS_STRING(w));
             Py_DECREF(t);
             break;
+        }
 
         PREDICTED_WITH_ARG(UNPACK_SEQUENCE);
-        case UNPACK_SEQUENCE:
+        TARGET(UNPACK_SEQUENCE)
+        {
             v = POP();
             if (PyTuple_CheckExact(v) &&
                 PyTuple_GET_SIZE(v) == oparg) {
@@ -1987,7 +2228,7 @@
                     PUSH(w);
                 }
                 Py_DECREF(v);
-                continue;
+        		DISPATCH();
             } else if (PyList_CheckExact(v) &&
                        PyList_GET_SIZE(v) == oparg) {
                 PyObject **items = \
@@ -2006,8 +2247,11 @@
             }
             Py_DECREF(v);
             break;
-
-        case STORE_ATTR:
+        }
+
+
+        TARGET(STORE_ATTR)
+        {
             w = GETITEM(names, oparg);
             v = TOP();
             u = SECOND();
@@ -2015,33 +2259,42 @@
             err = PyObject_SetAttr(v, w, u); /* v.w = u */
             Py_DECREF(v);
             Py_DECREF(u);
-            if (err == 0) continue;
+        	if (err == 0) DISPATCH();
             break;
-
-        case DELETE_ATTR:
+        }
+
+        TARGET(DELETE_ATTR)
+        {
             w = GETITEM(names, oparg);
             v = POP();
             err = PyObject_SetAttr(v, w, (PyObject *)NULL);
                                             /* del v.w */
             Py_DECREF(v);
             break;
-
-        case STORE_GLOBAL:
+        }
+
+
+        TARGET(STORE_GLOBAL)
+        {
             w = GETITEM(names, oparg);
             v = POP();
             err = PyDict_SetItem(f->f_globals, w, v);
             Py_DECREF(v);
-            if (err == 0) continue;
+        	if (err == 0) DISPATCH();
             break;
-
-        case DELETE_GLOBAL:
+        }
+
+        TARGET(DELETE_GLOBAL)
+        {
             w = GETITEM(names, oparg);
             if ((err = PyDict_DelItem(f->f_globals, w)) != 0)
                 format_exc_check_arg(
                     PyExc_NameError, GLOBAL_NAME_ERROR_MSG, w);
             break;
-
-        case LOAD_NAME:
+        }
+
+        TARGET(LOAD_NAME)
+        {
             w = GETITEM(names, oparg);
             if ((v = f->f_locals) == NULL) {
                 why = WHY_EXCEPTION;
@@ -2081,9 +2334,11 @@
                 Py_INCREF(x);
             }
             PUSH(x);
-            continue;
-
-        case LOAD_GLOBAL:
+        	DISPATCH();
+        }
+
+        TARGET(LOAD_GLOBAL)
+        {
             w = GETITEM(names, oparg);
             if (PyString_CheckExact(w)) {
                 /* Inline the PyDict_GetItem() calls.
@@ -2103,7 +2358,7 @@
                     if (x != NULL) {
                         Py_INCREF(x);
                         PUSH(x);
-                        continue;
+        				DISPATCH();
                     }
                     d = (PyDictObject *)(f->f_builtins);
                     e = d->ma_lookup(d, w, hash);
@@ -2115,7 +2370,7 @@
                     if (x != NULL) {
                         Py_INCREF(x);
                         PUSH(x);
-                        continue;
+        				DISPATCH();
                     }
                     goto load_global_error;
                 }
@@ -2134,13 +2389,15 @@
             }
             Py_INCREF(x);
             PUSH(x);
-            continue;
-
-        case DELETE_FAST:
+        	DISPATCH();
+        }
+
+        TARGET(DELETE_FAST)
+        {
             x = GETLOCAL(oparg);
             if (x != NULL) {
                 SETLOCAL(oparg, NULL);
-                continue;
+        		DISPATCH();
             }
             format_exc_check_arg(
                 PyExc_UnboundLocalError,
@@ -2148,20 +2405,24 @@
                 PyTuple_GetItem(co->co_varnames, oparg)
                 );
             break;
-
-        case LOAD_CLOSURE:
+        }
+
+        TARGET(LOAD_CLOSURE)
+        {
             x = freevars[oparg];
             Py_INCREF(x);
             PUSH(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case LOAD_DEREF:
+        }
+
+        TARGET(LOAD_DEREF)
+        {
             x = freevars[oparg];
             w = PyCell_Get(x);
             if (w != NULL) {
                 PUSH(w);
-                continue;
+        		DISPATCH();
             }
             err = -1;
             /* Don't stomp existing exception */
@@ -2181,15 +2442,19 @@
                                      UNBOUNDFREE_ERROR_MSG, v);
             }
             break;
-
-        case STORE_DEREF:
+        }
+
+        TARGET(STORE_DEREF)
+        {
             w = POP();
             x = freevars[oparg];
             PyCell_Set(x, w);
             Py_DECREF(w);
-            continue;
-
-        case BUILD_TUPLE:
+        	DISPATCH();
+        }
+
+        TARGET(BUILD_TUPLE)
+        {
             x = PyTuple_New(oparg);
             if (x != NULL) {
                 for (; --oparg >= 0;) {
@@ -2197,11 +2462,13 @@
                     PyTuple_SET_ITEM(x, oparg, w);
                 }
                 PUSH(x);
-                continue;
+        		DISPATCH();
             }
             break;
-
-        case BUILD_LIST:
+        }
+
+        TARGET(BUILD_LIST)
+        {
             x =  PyList_New(oparg);
             if (x != NULL) {
                 for (; --oparg >= 0;) {
@@ -2209,11 +2476,13 @@
                     PyList_SET_ITEM(x, oparg, w);
                 }
                 PUSH(x);
-                continue;
+        		DISPATCH();
             }
             break;
-
-        case BUILD_SET:
+        }
+
+        TARGET(BUILD_SET)
+        {
             x = PySet_New(NULL);
             if (x != NULL) {
                 for (; --oparg >= 0;) {
@@ -2227,18 +2496,21 @@
                     break;
                 }
                 PUSH(x);
-                continue;
+        		DISPATCH();
             }
             break;
-
-
-        case BUILD_MAP:
+        }
+
+        TARGET(BUILD_MAP)
+        {
             x = _PyDict_NewPresized((Py_ssize_t)oparg);
             PUSH(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case STORE_MAP:
+        }
+
+        TARGET_NOARG(STORE_MAP)
+        {
             w = TOP();     /* key */
             u = SECOND();  /* value */
             v = THIRD();   /* dict */
@@ -2247,10 +2519,12 @@
             err = PyDict_SetItem(v, w, u);  /* v[w] = u */
             Py_DECREF(u);
             Py_DECREF(w);
-            if (err == 0) continue;
+        	if (err == 0) DISPATCH();
             break;
-
-        case MAP_ADD:
+        }
+
+        TARGET(MAP_ADD)
+        {
             w = TOP();     /* key */
             u = SECOND();  /* value */
             STACKADJ(-2);
@@ -2261,20 +2535,24 @@
             Py_DECREF(w);
             if (err == 0) {
                 PREDICT(JUMP_ABSOLUTE);
-                continue;
+        		DISPATCH();
             }
             break;
-
-        case LOAD_ATTR:
+        }
+
+        TARGET(LOAD_ATTR)
+        {
             w = GETITEM(names, oparg);
             v = TOP();
             x = PyObject_GetAttr(v, w);
             Py_DECREF(v);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case COMPARE_OP:
+        }
+
+        TARGET(COMPARE_OP)
+        {
             w = POP();
             v = TOP();
             if (PyInt_CheckExact(w) && PyInt_CheckExact(v)) {
@@ -2307,9 +2585,11 @@
             if (x == NULL) break;
             PREDICT(POP_JUMP_IF_FALSE);
             PREDICT(POP_JUMP_IF_TRUE);
-            continue;
-
-        case IMPORT_NAME:
+        	DISPATCH();
+        }
+
+        TARGET(IMPORT_NAME)
+        {
             w = GETITEM(names, oparg);
             x = PyDict_GetItemString(f->f_builtins, "__import__");
             if (x == NULL) {
@@ -2350,10 +2630,12 @@
             READ_TIMESTAMP(intr1);
             Py_DECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case IMPORT_STAR:
+        }
+
+        TARGET_NOARG(IMPORT_STAR)
+        {
             v = POP();
             PyFrame_FastToLocals(f);
             if ((x = f->f_locals) == NULL) {
@@ -2366,34 +2648,40 @@
             READ_TIMESTAMP(intr1);
             PyFrame_LocalsToFast(f, 0);
             Py_DECREF(v);
-            if (err == 0) continue;
+        	if (err == 0) DISPATCH();
             break;
-
-        case IMPORT_FROM:
+        }
+
+        TARGET(IMPORT_FROM)
+        {
             w = GETITEM(names, oparg);
             v = TOP();
             READ_TIMESTAMP(intr0);
             x = import_from(v, w);
             READ_TIMESTAMP(intr1);
             PUSH(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case JUMP_FORWARD:
+        }
+
+        TARGET(JUMP_FORWARD)
+        {
             JUMPBY(oparg);
-            goto fast_next_opcode;
+        	FAST_DISPATCH();
+        }
 
         PREDICTED_WITH_ARG(POP_JUMP_IF_FALSE);
-        case POP_JUMP_IF_FALSE:
+        TARGET(POP_JUMP_IF_FALSE)
+        {
             w = POP();
             if (w == Py_True) {
                 Py_DECREF(w);
-                goto fast_next_opcode;
+        		FAST_DISPATCH();
             }
             if (w == Py_False) {
                 Py_DECREF(w);
                 JUMPTO(oparg);
-                goto fast_next_opcode;
+        		FAST_DISPATCH();
             }
             err = PyObject_IsTrue(w);
             Py_DECREF(w);
@@ -2403,19 +2691,21 @@
                 JUMPTO(oparg);
             else
                 break;
-            continue;
+        	DISPATCH();
+        }
 
         PREDICTED_WITH_ARG(POP_JUMP_IF_TRUE);
-        case POP_JUMP_IF_TRUE:
+        TARGET(POP_JUMP_IF_TRUE)
+        {
             w = POP();
             if (w == Py_False) {
                 Py_DECREF(w);
-                goto fast_next_opcode;
+        		FAST_DISPATCH();
             }
             if (w == Py_True) {
                 Py_DECREF(w);
                 JUMPTO(oparg);
-                goto fast_next_opcode;
+        		FAST_DISPATCH();
             }
             err = PyObject_IsTrue(w);
             Py_DECREF(w);
@@ -2427,18 +2717,20 @@
                 ;
             else
                 break;
-            continue;
-
-        case JUMP_IF_FALSE_OR_POP:
+        	DISPATCH();
+        }
+
+        TARGET(JUMP_IF_FALSE_OR_POP)
+        {
             w = TOP();
             if (w == Py_True) {
                 STACKADJ(-1);
                 Py_DECREF(w);
-                goto fast_next_opcode;
+        		FAST_DISPATCH();
             }
             if (w == Py_False) {
                 JUMPTO(oparg);
-                goto fast_next_opcode;
+        		FAST_DISPATCH();
             }
             err = PyObject_IsTrue(w);
             if (err > 0) {
@@ -2450,18 +2742,20 @@
                 JUMPTO(oparg);
             else
                 break;
-            continue;
-
-        case JUMP_IF_TRUE_OR_POP:
+        	DISPATCH();
+        }
+
+        TARGET(JUMP_IF_TRUE_OR_POP)
+        {
             w = TOP();
             if (w == Py_False) {
                 STACKADJ(-1);
                 Py_DECREF(w);
-                goto fast_next_opcode;
+        		FAST_DISPATCH();
             }
             if (w == Py_True) {
                 JUMPTO(oparg);
-                goto fast_next_opcode;
+        		FAST_DISPATCH();
             }
             err = PyObject_IsTrue(w);
             if (err > 0) {
@@ -2474,10 +2768,12 @@
             }
             else
                 break;
-            continue;
+        	DISPATCH();
+        }
 
         PREDICTED_WITH_ARG(JUMP_ABSOLUTE);
-        case JUMP_ABSOLUTE:
+        TARGET(JUMP_ABSOLUTE)
+        {
             JUMPTO(oparg);
 #if FAST_LOOPS
             /* Enabling this path speeds-up all while and for-loops by bypassing
@@ -2489,10 +2785,12 @@
             */
             goto fast_next_opcode;
 #else
-            continue;
+        	DISPATCH();
 #endif
-
-        case GET_ITER:
+        }
+
+        TARGET_NOARG(GET_ITER)
+        {
             /* before: [obj]; after [getiter(obj)] */
             v = TOP();
             x = PyObject_GetIter(v);
@@ -2500,13 +2798,15 @@
             if (x != NULL) {
                 SET_TOP(x);
                 PREDICT(FOR_ITER);
-                continue;
+        		DISPATCH();
             }
             STACKADJ(-1);
             break;
+        }
 
         PREDICTED_WITH_ARG(FOR_ITER);
-        case FOR_ITER:
+        TARGET(FOR_ITER)
+        {
             /* before: [iter]; after: [iter, iter()] *or* [] */
             v = TOP();
             x = (*v->ob_type->tp_iternext)(v);
@@ -2514,7 +2814,7 @@
                 PUSH(x);
                 PREDICT(STORE_FAST);
                 PREDICT(UNPACK_SEQUENCE);
-                continue;
+        		DISPATCH();
             }
             if (PyErr_Occurred()) {
                 if (!PyErr_ExceptionMatches(
@@ -2526,13 +2826,17 @@
             x = v = POP();
             Py_DECREF(v);
             JUMPBY(oparg);
-            continue;
-
-        case BREAK_LOOP:
+        	DISPATCH();
+        }
+
+        TARGET_NOARG(BREAK_LOOP)
+        {
             why = WHY_BREAK;
             goto fast_block_end;
-
-        case CONTINUE_LOOP:
+        }
+
+        TARGET(CONTINUE_LOOP)
+        {
             retval = PyInt_FromLong(oparg);
             if (!retval) {
                 x = NULL;
@@ -2540,10 +2844,13 @@
             }
             why = WHY_CONTINUE;
             goto fast_block_end;
-
-        case SETUP_LOOP:
-        case SETUP_EXCEPT:
-        case SETUP_FINALLY:
+        }
+
+        TARGET_WITH_IMPL(SETUP_LOOP, _setup_finally)
+        TARGET_WITH_IMPL(SETUP_EXCEPT, _setup_finally)
+		TARGET(SETUP_FINALLY)
+		_setup_finally:
+		{
             /* NOTE: If you add any new block-setup opcodes that
                are not try/except/finally handlers, you may need
                to update the PyGen_NeedsFinalizing() function.
@@ -2551,9 +2858,13 @@
 
             PyFrame_BlockSetup(f, opcode, INSTR_OFFSET() + oparg,
                                STACK_LEVEL());
-            continue;
-
-        case SETUP_WITH:
+        	DISPATCH();
+		}
+
+
+
+        TARGET(SETUP_WITH)
+        {
         {
             static PyObject *exit, *enter;
             w = TOP();
@@ -2579,10 +2890,11 @@
                                STACK_LEVEL());
 
             PUSH(x);
-            continue;
+        		DISPATCH();
+        	}
         }
 
-        case WITH_CLEANUP:
+        TARGET_NOARG(WITH_CLEANUP)
         {
             /* At the top of the stack are 1-3 values indicating
                how/why we entered the finally clause:
@@ -2670,7 +2982,7 @@
             break;
         }
 
-        case CALL_FUNCTION:
+        TARGET(CALL_FUNCTION)
         {
             PyObject **sp;
             PCALL(PCALL_ALL);
@@ -2682,14 +2994,14 @@
 #endif
             stack_pointer = sp;
             PUSH(x);
-            if (x != NULL)
-                continue;
+        	if (x != NULL) DISPATCH();
             break;
         }
 
-        case CALL_FUNCTION_VAR:
-        case CALL_FUNCTION_KW:
-        case CALL_FUNCTION_VAR_KW:
+        TARGET_WITH_IMPL(CALL_FUNCTION_VAR, _call_function_var_kw)
+        TARGET_WITH_IMPL(CALL_FUNCTION_KW, _call_function_var_kw)
+		TARGET(CALL_FUNCTION_VAR_KW)
+		_call_function_var_kw:
         {
             int na = oparg & 0xff;
             int nk = (oparg>>8) & 0xff;
@@ -2727,12 +3039,13 @@
                 Py_DECREF(w);
             }
             PUSH(x);
-            if (x != NULL)
-                continue;
+        	if (x != NULL) DISPATCH();
             break;
         }
 
-        case MAKE_FUNCTION:
+
+        TARGET(MAKE_FUNCTION)
+        {
             v = POP(); /* code object */
             x = PyFunction_New(v, f->f_globals);
             Py_DECREF(v);
@@ -2753,8 +3066,9 @@
             }
             PUSH(x);
             break;
-
-        case MAKE_CLOSURE:
+        }
+
+        TARGET(MAKE_CLOSURE)
         {
             v = POP(); /* code object */
             x = PyFunction_New(v, f->f_globals);
@@ -2789,7 +3103,8 @@
             break;
         }
 
-        case BUILD_SLICE:
+        TARGET(BUILD_SLICE)
+        {
             if (oparg == 3)
                 w = POP();
             else
@@ -2801,14 +3116,20 @@
             Py_DECREF(v);
             Py_XDECREF(w);
             SET_TOP(x);
-            if (x != NULL) continue;
+        	if (x != NULL) DISPATCH();
             break;
-
-        case EXTENDED_ARG:
+        }
+
+        TARGET(EXTENDED_ARG)
+        {
             opcode = NEXTOP();
             oparg = oparg<<16 | NEXTARG();
             goto dispatch_opcode;
-
+        }
+
+#if USE_COMPUTED_GOTOS
+        _unknown_opcode:
+#endif
         default:
             fprintf(stderr,
                 "XXX lineno: %d, opcode: %d\n",
diff --git a/Python/makeopcodetargets.py b/Python/makeopcodetargets.py
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):
+    """Finds and returns a module in the local dist/checkout.
+    """
+    modpath = os.path.join(
+        os.path.dirname(os.path.dirname(__file__)), "Lib")
+    return imp.load_module(modname, *imp.find_module(modname, [modpath]))
+
+def write_contents(f):
+    """Write C code contents to the target file object.
+    """
+    opcode = find_module("opcode")
+    targets = ['_unknown_opcode'] * 256
+    for opname, op in opcode.opmap.items():
+        if opname == "STOP_CODE":
+            continue
+        targets[op] = "TARGET_%s" % opname.replace("+0", " ").replace("+", "_")
+    f.write("static void *opcode_targets[256] = {\n")
+    f.write(",\n".join(["    &&%s" % s for s in targets]))
+    f.write("\n};\n")
+
+
+if __name__ == "__main__":
+    import sys
+    assert len(sys.argv) < 3, "Too many arguments"
+    if len(sys.argv) == 2:
+        target = sys.argv[1]
+    else:
+        target = "Python/opcode_targets.h"
+    f = open(target, "w")
+    try:
+        write_contents(f)
+    finally:
+        f.close()
diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h
new file mode 100644
--- /dev/null
+++ b/Python/opcode_targets.h
@@ -0,0 +1,258 @@
+static void *opcode_targets[256] = {
+    &&_unknown_opcode,
+    &&TARGET_POP_TOP,
+    &&TARGET_ROT_TWO,
+    &&TARGET_ROT_THREE,
+    &&TARGET_DUP_TOP,
+    &&TARGET_ROT_FOUR,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&TARGET_NOP,
+    &&TARGET_UNARY_POSITIVE,
+    &&TARGET_UNARY_NEGATIVE,
+    &&TARGET_UNARY_NOT,
+    &&TARGET_UNARY_CONVERT,
+    &&_unknown_opcode,
+    &&TARGET_UNARY_INVERT,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&TARGET_BINARY_POWER,
+    &&TARGET_BINARY_MULTIPLY,
+    &&TARGET_BINARY_DIVIDE,
+    &&TARGET_BINARY_MODULO,
+    &&TARGET_BINARY_ADD,
+    &&TARGET_BINARY_SUBTRACT,
+    &&TARGET_BINARY_SUBSCR,
+    &&TARGET_BINARY_FLOOR_DIVIDE,
+    &&TARGET_BINARY_TRUE_DIVIDE,
+    &&TARGET_INPLACE_FLOOR_DIVIDE,
+    &&TARGET_INPLACE_TRUE_DIVIDE,
+    &&TARGET_SLICE ,
+    &&TARGET_SLICE_1,
+    &&TARGET_SLICE_2,
+    &&TARGET_SLICE_3,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&TARGET_STORE_SLICE ,
+    &&TARGET_STORE_SLICE_1,
+    &&TARGET_STORE_SLICE_2,
+    &&TARGET_STORE_SLICE_3,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&TARGET_DELETE_SLICE ,
+    &&TARGET_DELETE_SLICE_1,
+    &&TARGET_DELETE_SLICE_2,
+    &&TARGET_DELETE_SLICE_3,
+    &&TARGET_STORE_MAP,
+    &&TARGET_INPLACE_ADD,
+    &&TARGET_INPLACE_SUBTRACT,
+    &&TARGET_INPLACE_MULTIPLY,
+    &&TARGET_INPLACE_DIVIDE,
+    &&TARGET_INPLACE_MODULO,
+    &&TARGET_STORE_SUBSCR,
+    &&TARGET_DELETE_SUBSCR,
+    &&TARGET_BINARY_LSHIFT,
+    &&TARGET_BINARY_RSHIFT,
+    &&TARGET_BINARY_AND,
+    &&TARGET_BINARY_XOR,
+    &&TARGET_BINARY_OR,
+    &&TARGET_INPLACE_POWER,
+    &&TARGET_GET_ITER,
+    &&_unknown_opcode,
+    &&TARGET_PRINT_EXPR,
+    &&TARGET_PRINT_ITEM,
+    &&TARGET_PRINT_NEWLINE,
+    &&TARGET_PRINT_ITEM_TO,
+    &&TARGET_PRINT_NEWLINE_TO,
+    &&TARGET_INPLACE_LSHIFT,
+    &&TARGET_INPLACE_RSHIFT,
+    &&TARGET_INPLACE_AND,
+    &&TARGET_INPLACE_XOR,
+    &&TARGET_INPLACE_OR,
+    &&TARGET_BREAK_LOOP,
+    &&TARGET_WITH_CLEANUP,
+    &&TARGET_LOAD_LOCALS,
+    &&TARGET_RETURN_VALUE,
+    &&TARGET_IMPORT_STAR,
+    &&TARGET_EXEC_STMT,
+    &&TARGET_YIELD_VALUE,
+    &&TARGET_POP_BLOCK,
+    &&TARGET_END_FINALLY,
+    &&TARGET_BUILD_CLASS,
+    &&TARGET_STORE_NAME,
+    &&TARGET_DELETE_NAME,
+    &&TARGET_UNPACK_SEQUENCE,
+    &&TARGET_FOR_ITER,
+    &&TARGET_LIST_APPEND,
+    &&TARGET_STORE_ATTR,
+    &&TARGET_DELETE_ATTR,
+    &&TARGET_STORE_GLOBAL,
+    &&TARGET_DELETE_GLOBAL,
+    &&TARGET_DUP_TOPX,
+    &&TARGET_LOAD_CONST,
+    &&TARGET_LOAD_NAME,
+    &&TARGET_BUILD_TUPLE,
+    &&TARGET_BUILD_LIST,
+    &&TARGET_BUILD_SET,
+    &&TARGET_BUILD_MAP,
+    &&TARGET_LOAD_ATTR,
+    &&TARGET_COMPARE_OP,
+    &&TARGET_IMPORT_NAME,
+    &&TARGET_IMPORT_FROM,
+    &&TARGET_JUMP_FORWARD,
+    &&TARGET_JUMP_IF_FALSE_OR_POP,
+    &&TARGET_JUMP_IF_TRUE_OR_POP,
+    &&TARGET_JUMP_ABSOLUTE,
+    &&TARGET_POP_JUMP_IF_FALSE,
+    &&TARGET_POP_JUMP_IF_TRUE,
+    &&TARGET_LOAD_GLOBAL,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&TARGET_CONTINUE_LOOP,
+    &&TARGET_SETUP_LOOP,
+    &&TARGET_SETUP_EXCEPT,
+    &&TARGET_SETUP_FINALLY,
+    &&_unknown_opcode,
+    &&TARGET_LOAD_FAST,
+    &&TARGET_STORE_FAST,
+    &&TARGET_DELETE_FAST,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&TARGET_RAISE_VARARGS,
+    &&TARGET_CALL_FUNCTION,
+    &&TARGET_MAKE_FUNCTION,
+    &&TARGET_BUILD_SLICE,
+    &&TARGET_MAKE_CLOSURE,
+    &&TARGET_LOAD_CLOSURE,
+    &&TARGET_LOAD_DEREF,
+    &&TARGET_STORE_DEREF,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&TARGET_CALL_FUNCTION_VAR,
+    &&TARGET_CALL_FUNCTION_KW,
+    &&TARGET_CALL_FUNCTION_VAR_KW,
+    &&TARGET_SETUP_WITH,
+    &&_unknown_opcode,
+    &&TARGET_EXTENDED_ARG,
+    &&TARGET_SET_ADD,
+    &&TARGET_MAP_ADD,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode,
+    &&_unknown_opcode
+};
diff --git a/configure b/configure
--- a/configure
+++ b/configure
@@ -811,6 +811,7 @@
 with_libc
 enable_big_digits
 enable_unicode
+with_computed_gotos
 with_ensurepip
 '
       ac_precious_vars='build_alias
@@ -1494,6 +1495,9 @@
   --with-fpectl           enable SIGFPE catching
   --with-libm=STRING      math library
   --with-libc=STRING      C library
+  --with(out)-computed-gotos
+                          Use computed gotos in evaluation loop (enabled by
+                          default on supported compilers)
   --with(out)-ensurepip=[=OPTION]
                           "install" or "upgrade" using bundled pip, default is
                           "no"
@@ -14685,6 +14689,85 @@
         mkdir $dir
     fi
 done
+
+# BEGIN_COMPUTED_GOTO
+# Check for --with-computed-gotos
+{ $as_echo "$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 :
+  withval=$with_computed_gotos;
+if test "$withval" = yes
+then
+
+$as_echo "#define USE_COMPUTED_GOTOS 1" >>confdefs.h
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+if test "$withval" = no
+then
+
+$as_echo "#define USE_COMPUTED_GOTOS 0" >>confdefs.h
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no value specified" >&5
+$as_echo "no value specified" >&6; }
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports computed gotos" >&5
+$as_echo_n "checking whether $CC supports computed gotos... " >&6; }
+if ${ac_cv_computed_gotos+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  if test "${with_computed_gotos+set}" = set; then
+   ac_cv_computed_gotos="$with_computed_gotos -- configured --with(out)-computed-gotos"
+ else
+   ac_cv_computed_gotos=no
+ fi
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int main(int argc, char **argv)
+{
+    static void *targets[1] = { &&LABEL1 };
+    goto LABEL2;
+LABEL1:
+    return 0;
+LABEL2:
+    goto *targets[0];
+    return 1;
+}
+
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_computed_gotos=yes
+else
+  ac_cv_computed_gotos=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_computed_gotos" >&5
+$as_echo "$ac_cv_computed_gotos" >&6; }
+case "$ac_cv_computed_gotos" in yes*)
+
+$as_echo "#define HAVE_COMPUTED_GOTOS 1" >>confdefs.h
+
+esac
+# END_COMPUTED_GOTO
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5
 $as_echo "done" >&6; }
 
diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -4557,6 +4557,57 @@
         mkdir $dir
     fi
 done
+
+# BEGIN_COMPUTED_GOTO 
+# Check for --with-computed-gotos
+AC_MSG_CHECKING(for --with-computed-gotos)
+AC_ARG_WITH(computed-gotos,
+            AS_HELP_STRING([--with(out)-computed-gotos],
+                           [Use computed gotos in evaluation loop (enabled by default on supported compilers)]),
+[
+if test "$withval" = yes
+then 
+  AC_DEFINE(USE_COMPUTED_GOTOS, 1,
+  [Define if you want to use computed gotos in ceval.c.]) 
+  AC_MSG_RESULT(yes)
+fi
+if test "$withval" = no
+then 
+  AC_DEFINE(USE_COMPUTED_GOTOS, 0,
+  [Define if you want to use computed gotos in ceval.c.]) 
+  AC_MSG_RESULT(no)
+fi
+],
+[AC_MSG_RESULT(no value specified)])
+
+AC_MSG_CHECKING(whether $CC supports computed gotos)
+AC_CACHE_VAL(ac_cv_computed_gotos,
+AC_RUN_IFELSE([AC_LANG_SOURCE([[[
+int main(int argc, char **argv)
+{
+    static void *targets[1] = { &&LABEL1 };
+    goto LABEL2;
+LABEL1:
+    return 0;
+LABEL2:
+    goto *targets[0];
+    return 1;
+}
+]]])],
+[ac_cv_computed_gotos=yes],
+[ac_cv_computed_gotos=no],
+[if test "${with_computed_gotos+set}" = set; then
+   ac_cv_computed_gotos="$with_computed_gotos -- configured --with(out)-computed-gotos"
+ else
+   ac_cv_computed_gotos=no
+ fi]))
+AC_MSG_RESULT($ac_cv_computed_gotos)
+case "$ac_cv_computed_gotos" in yes*)
+  AC_DEFINE(HAVE_COMPUTED_GOTOS, 1,
+  [Define if the C compiler supports computed gotos.])
+esac
+# END_COMPUTED_GOTO
+
 AC_MSG_RESULT(done)
 
 # ensurepip option
diff --git a/pyconfig.h.in b/pyconfig.h.in
--- a/pyconfig.h.in
+++ b/pyconfig.h.in
@@ -118,6 +118,9 @@
 /* Define to 1 if you have the `clock' function. */
 #undef HAVE_CLOCK
 
+/* Define if the C compiler supports computed gotos. */
+#undef HAVE_COMPUTED_GOTOS
+
 /* 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

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list