Tcl Source Code

Artifact [885b604b45]
Login

Artifact 885b604b459764e498fdd05c5480b810ee8c4aaa:

Attachment "tclExecute-compgoto.diff" to ticket [1820448fff] added by das 2007-10-26 11:23:11.
Index: generic/tclExecute.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclExecute.c,v
retrieving revision 1.339
diff -u -p -r1.339 tclExecute.c
--- generic/tclExecute.c	20 Oct 2007 02:15:05 -0000	1.339
+++ generic/tclExecute.c	26 Oct 2007 03:59:35 -0000
@@ -187,6 +187,27 @@ VarHashCreateVar(
     VarHashCreateVar((tablePtr), (key), NULL)
 
 /*
+ * Use computed goto instead of big switch in TEBC when available.
+ */
+
+#define USE_COMPUTED_GOTO 1
+
+#ifndef USE_COMPUTED_GOTO
+#   ifdef HAVE_COMPUTED_GOTO
+#	define USE_COMPUTED_GOTO 1
+#   else
+#	define USE_COMPUTED_GOTO 0
+#   endif
+#endif
+
+#if USE_COMPUTED_GOTO
+#   define CASE(i) l_##i
+#   define CADR(i) ((char*) &&l_##i - (char*) &&top)
+#else
+#   define CASE(i) case i
+#endif
+
+/*
  * The new macro for ending an instruction; note that a reasonable C-optimiser
  * will resolve all branches at compile time. (result) is always a constant;
  * the macro NEXT_INST_F handles constant (nCleanup), NEXT_INST_V is resolved
@@ -1584,6 +1605,75 @@ TclExecuteByteCode(
 #endif
     char *curInstName = NULL;
 
+#if USE_COMPUTED_GOTO
+    static const ptrdiff_t instJumptable[] = {
+	CADR(INST_DONE),		CADR(INST_PUSH1),
+	CADR(INST_PUSH4),		CADR(INST_POP),
+	CADR(INST_DUP),			CADR(INST_CONCAT1),
+	CADR(INST_INVOKE_STK1),		CADR(INST_INVOKE_STK4),
+	CADR(INST_EVAL_STK),		CADR(INST_EXPR_STK),
+	CADR(INST_LOAD_SCALAR1),	CADR(INST_LOAD_SCALAR4),
+	CADR(INST_LOAD_SCALAR_STK),	CADR(INST_LOAD_ARRAY1),
+	CADR(INST_LOAD_ARRAY4),		CADR(INST_LOAD_ARRAY_STK),
+	CADR(INST_LOAD_STK),		CADR(INST_STORE_SCALAR1),
+	CADR(INST_STORE_SCALAR4),	CADR(INST_STORE_SCALAR_STK),
+	CADR(INST_STORE_ARRAY1),	CADR(INST_STORE_ARRAY4),
+	CADR(INST_STORE_ARRAY_STK),	CADR(INST_STORE_STK),
+	CADR(INST_INCR_SCALAR1),	CADR(INST_INCR_SCALAR_STK),
+	CADR(INST_INCR_ARRAY1),		CADR(INST_INCR_ARRAY_STK),
+	CADR(INST_INCR_STK),		CADR(INST_INCR_SCALAR1_IMM),
+	CADR(INST_INCR_SCALAR_STK_IMM),	CADR(INST_INCR_ARRAY1_IMM),
+	CADR(INST_INCR_ARRAY_STK_IMM),	CADR(INST_INCR_STK_IMM),
+	CADR(INST_JUMP1),		CADR(INST_JUMP4),
+	CADR(INST_JUMP_TRUE1),		CADR(INST_JUMP_TRUE4),
+	CADR(INST_JUMP_FALSE1),		CADR(INST_JUMP_FALSE4),
+	CADR(INST_LOR),			CADR(INST_LAND),
+	CADR(INST_BITOR),		CADR(INST_BITXOR),
+	CADR(INST_BITAND),		CADR(INST_EQ),
+	CADR(INST_NEQ),			CADR(INST_LT),
+	CADR(INST_GT),			CADR(INST_LE),
+	CADR(INST_GE),			CADR(INST_LSHIFT),
+	CADR(INST_RSHIFT),		CADR(INST_ADD),
+	CADR(INST_SUB),			CADR(INST_MULT),
+	CADR(INST_DIV),			CADR(INST_MOD),
+	CADR(INST_UPLUS),		CADR(INST_UMINUS),
+	CADR(INST_BITNOT),		CADR(INST_LNOT),
+	CADR(INST_CALL_BUILTIN_FUNC1),	CADR(INST_CALL_FUNC1),
+	CADR(INST_TRY_CVT_TO_NUMERIC),	CADR(INST_BREAK),
+	CADR(INST_CONTINUE),		CADR(INST_FOREACH_START4),
+	CADR(INST_FOREACH_STEP4),	CADR(INST_BEGIN_CATCH4),
+	CADR(INST_END_CATCH),		CADR(INST_PUSH_RESULT),
+	CADR(INST_PUSH_RETURN_CODE),	CADR(INST_STR_EQ),
+	CADR(INST_STR_NEQ),		CADR(INST_STR_CMP),
+	CADR(INST_STR_LEN),		CADR(INST_STR_INDEX),
+	CADR(INST_STR_MATCH),		CADR(INST_LIST),
+	CADR(INST_LIST_INDEX),		CADR(INST_LIST_LENGTH),
+	CADR(INST_APPEND_SCALAR1),	CADR(INST_APPEND_SCALAR4),
+	CADR(INST_APPEND_ARRAY1),	CADR(INST_APPEND_ARRAY4),
+	CADR(INST_APPEND_ARRAY_STK),	CADR(INST_APPEND_STK),
+	CADR(INST_LAPPEND_SCALAR1),	CADR(INST_LAPPEND_SCALAR4),
+	CADR(INST_LAPPEND_ARRAY1),	CADR(INST_LAPPEND_ARRAY4),
+	CADR(INST_LAPPEND_ARRAY_STK),	CADR(INST_LAPPEND_STK),
+	CADR(INST_LIST_INDEX_MULTI),	CADR(INST_OVER),
+	CADR(INST_LSET_LIST),		CADR(INST_LSET_FLAT),
+	CADR(INST_RETURN_IMM),		CADR(INST_EXPON),
+	CADR(INST_EXPAND_START),	CADR(INST_EXPAND_STKTOP),
+	CADR(INST_INVOKE_EXPANDED),	CADR(INST_LIST_INDEX_IMM),
+	CADR(INST_LIST_RANGE_IMM),	CADR(INST_START_CMD),
+	CADR(INST_LIST_IN),		CADR(INST_LIST_NOT_IN),
+	CADR(INST_PUSH_RETURN_OPTIONS),	CADR(INST_RETURN_STK),
+	CADR(INST_DICT_GET),		CADR(INST_DICT_SET),
+	CADR(INST_DICT_UNSET),		CADR(INST_DICT_INCR_IMM),
+	CADR(INST_DICT_APPEND),		CADR(INST_DICT_LAPPEND),
+	CADR(INST_DICT_FIRST),		CADR(INST_DICT_NEXT),
+	CADR(INST_DICT_DONE),		CADR(INST_DICT_UPDATE_START),
+	CADR(INST_DICT_UPDATE_END),	CADR(INST_JUMP_TABLE),
+	CADR(INST_UPVAR),		CADR(INST_NSUPVAR),
+	CADR(INST_VARIABLE),		CADR(INST_SYNTAX),
+	CADR(INST_REVERSE),
+    };
+#endif
+
     /*
      * The execution uses a unified stack: first the catch stack, immediately
      * above it a CmdFrame, then the execution stack.
@@ -1772,10 +1862,20 @@ TclExecuteByteCode(
     } else if (*pc == INST_PUSH1) {
 	goto instPush1Peephole;
     }
-    
-    switch (*pc) {
-    case INST_SYNTAX:
-    case INST_RETURN_IMM: {
+
+#if USE_COMPUTED_GOTO
+    if (*pc <= LAST_INST_OPCODE) {
+	goto *(void*)(instJumptable[*pc] + (char*) &&top);
+    } else {
+	Tcl_Panic("TclExecuteByteCode: unrecognized opCode %u", *pc);
+    }
+    top:
+#else
+    switch (*pc)
+#endif
+    {
+    CASE(INST_SYNTAX):
+    CASE(INST_RETURN_IMM): {
 	int code = TclGetInt4AtPtr(pc+1);
 	int level = TclGetUInt4AtPtr(pc+5);
 
@@ -1799,7 +1899,7 @@ TclExecuteByteCode(
 	}
     }
 
-    case INST_RETURN_STK:
+    CASE(INST_RETURN_STK):
 	TRACE(("=> "));
 	objResultPtr = POP_OBJECT();
 	result = Tcl_SetReturnOptions(interp, OBJ_AT_TOS);
@@ -1814,7 +1914,7 @@ TclExecuteByteCode(
 	    goto processExceptionReturn;
 	}
 
-    case INST_DONE:
+    CASE(INST_DONE):
 	if (tosPtr > initTosPtr) {
 	    /*
 	     * Set the interpreter's object result to point to the topmost
@@ -1837,7 +1937,7 @@ TclExecuteByteCode(
 	    goto abnormalReturn;
 	}
 
-    case INST_PUSH1:
+    CASE(INST_PUSH1):
     instPush1Peephole:
 	PUSH_OBJECT(codePtr->objArrayPtr[TclGetUInt1AtPtr(pc+1)]);
 	TRACE_WITH_OBJ(("%u => ", TclGetInt1AtPtr(pc+1)), OBJ_AT_TOS);
@@ -1854,12 +1954,12 @@ TclExecuteByteCode(
 #endif
 	NEXT_INST_F(0, 0, 0);
 
-    case INST_PUSH4:
+    CASE(INST_PUSH4):
 	objResultPtr = codePtr->objArrayPtr[TclGetUInt4AtPtr(pc+1)];
 	TRACE_WITH_OBJ(("%u => ", TclGetUInt4AtPtr(pc+1)), objResultPtr);
 	NEXT_INST_F(5, 0, 1);
 
-    case INST_POP: {
+    CASE(INST_POP): {
 	Tcl_Obj *valuePtr;
 
 	TRACE_WITH_OBJ(("=> discarding "), OBJ_AT_TOS);
@@ -1882,7 +1982,7 @@ TclExecuteByteCode(
 	NEXT_INST_F(0, 0, 0);
     }
 
-    case INST_START_CMD:
+    CASE(INST_START_CMD):
 #if !TCL_COMPILE_DEBUG
     instStartCmdPeephole:
 #endif
@@ -1923,12 +2023,12 @@ TclExecuteByteCode(
 	    NEXT_INST_V(opnd, 0, -1);
 	}
 
-    case INST_DUP:
+    CASE(INST_DUP):
 	objResultPtr = OBJ_AT_TOS;
 	TRACE_WITH_OBJ(("=> "), objResultPtr);
 	NEXT_INST_F(1, 0, 1);
 
-    case INST_OVER: {
+    CASE(INST_OVER): {
 	int opnd;
 
 	opnd = TclGetUInt4AtPtr(pc+1);
@@ -1937,7 +2037,7 @@ TclExecuteByteCode(
 	NEXT_INST_F(5, 0, 1);
     }
 
-    case INST_REVERSE: {
+    CASE(INST_REVERSE): {
 	int opnd;
 	Tcl_Obj **a, **b;
 
@@ -1953,7 +2053,7 @@ TclExecuteByteCode(
 	NEXT_INST_F(5, 0, 0);
     }
 
-    case INST_CONCAT1: {
+    CASE(INST_CONCAT1): {
 	int opnd, length, appendLen = 0;
 	char *bytes, *p;
 	Tcl_Obj **currPtr;
@@ -2028,7 +2128,7 @@ TclExecuteByteCode(
 	NEXT_INST_V(2, opnd, 1);
     }
 
-    case INST_EXPAND_START: {
+    CASE(INST_EXPAND_START): {
 	/*
 	 * Push an element to the expandNestList. This records the current
 	 * stack depth - i.e., the point in the stack where the expanded
@@ -2051,7 +2151,7 @@ TclExecuteByteCode(
 	NEXT_INST_F(1, 0, 0);
     }
 
-    case INST_EXPAND_STKTOP: {
+    CASE(INST_EXPAND_STKTOP): {
 	int objc, length, i;
 	Tcl_Obj **objv, *valuePtr;
 	ptrdiff_t moved;
@@ -2115,7 +2215,7 @@ TclExecuteByteCode(
 
 	int objc, pcAdjustment;
 
-    case INST_INVOKE_EXPANDED:
+    CASE(INST_INVOKE_EXPANDED):
 	{
 	    Tcl_Obj *objPtr = expandNestList;
 
@@ -2137,12 +2237,12 @@ TclExecuteByteCode(
 	    NEXT_INST_F(1, 0, 1);
 	}
 
-    case INST_INVOKE_STK4:
+    CASE(INST_INVOKE_STK4):
 	objc = TclGetUInt4AtPtr(pc+1);
 	pcAdjustment = 5;
 	goto doInvocation;
 
-    case INST_INVOKE_STK1:
+    CASE(INST_INVOKE_STK1):
 	objc = TclGetUInt1AtPtr(pc+1);
 	pcAdjustment = 2;
 
@@ -2234,7 +2334,7 @@ TclExecuteByteCode(
 	}
 
 #if TCL_SUPPORT_84_BYTECODE
-    case INST_CALL_BUILTIN_FUNC1: {
+    CASE(INST_CALL_BUILTIN_FUNC1): {
 	/*
 	 * Call one of the built-in pre-8.5 Tcl math functions. This
 	 * translates to INST_INVOKE_STK1 with the first argument of
@@ -2282,7 +2382,7 @@ TclExecuteByteCode(
 	goto doInvocation;
     }
 
-    case INST_CALL_FUNC1: {
+    CASE(INST_CALL_FUNC1): {
 	/*
 	 * Call a non-builtin Tcl math function previously registered by a
 	 * call to Tcl_CreateMathFunc pre-8.5. This is essentially
@@ -2320,14 +2420,14 @@ TclExecuteByteCode(
      * remains for existing bytecode precompiled files.
      */
 
-    case INST_CALL_BUILTIN_FUNC1:
+    CASE(INST_CALL_BUILTIN_FUNC1):
 	Tcl_Panic("TclExecuteByteCode: obsolete INST_CALL_BUILTIN_FUNC1 found");
-    case INST_CALL_FUNC1:
+    CASE(INST_CALL_FUNC1):
 	Tcl_Panic("TclExecuteByteCode: obsolete INST_CALL_FUNC1 found");
 #endif
     }
 
-    case INST_EVAL_STK: {
+    CASE(INST_EVAL_STK): {
 	/*
 	 * Note to maintainers: it is important that INST_EVAL_STK pop its
 	 * argument from the stack before jumping to checkForCatch! DO NOT
@@ -2376,7 +2476,7 @@ TclExecuteByteCode(
 	}
     }
 
-    case INST_EXPR_STK: {
+    CASE(INST_EXPR_STK): {
 	Tcl_Obj *objPtr, *valuePtr;
 
 	objPtr = OBJ_AT_TOS;
@@ -2409,7 +2509,7 @@ TclExecuteByteCode(
 	Var *varPtr, *arrayPtr;
 	Tcl_Obj *objPtr;
 
-    case INST_LOAD_SCALAR1:
+    CASE(INST_LOAD_SCALAR1):
 	instLoadScalar1:
 	opnd = TclGetUInt1AtPtr(pc+1);
 	varPtr = &(compiledLocals[opnd]);
@@ -2432,7 +2532,7 @@ TclExecuteByteCode(
 	part1Ptr = part2Ptr = NULL;
 	goto doCallPtrGetVar;
 
-    case INST_LOAD_SCALAR4:
+    CASE(INST_LOAD_SCALAR4):
 	opnd = TclGetUInt4AtPtr(pc+1);
 	varPtr = &(compiledLocals[opnd]);
 	while (TclIsVarLink(varPtr)) {
@@ -2454,12 +2554,12 @@ TclExecuteByteCode(
 	part1Ptr = part2Ptr = NULL;
 	goto doCallPtrGetVar;
 
-    case INST_LOAD_ARRAY4:
+    CASE(INST_LOAD_ARRAY4):
 	opnd = TclGetUInt4AtPtr(pc+1);
 	pcAdjustment = 5;
 	goto doLoadArray;
 
-    case INST_LOAD_ARRAY1:
+    CASE(INST_LOAD_ARRAY1):
 	opnd = TclGetUInt1AtPtr(pc+1);
 	pcAdjustment = 2;
 
@@ -2494,15 +2594,15 @@ TclExecuteByteCode(
 	cleanup = 1;
 	goto doCallPtrGetVar;
 
-    case INST_LOAD_ARRAY_STK:
+    CASE(INST_LOAD_ARRAY_STK):
 	cleanup = 2;
 	part2Ptr = OBJ_AT_TOS;		/* element name */
 	objPtr = OBJ_UNDER_TOS;		/* array name */
 	TRACE(("\"%.30s(%.30s)\" => ", O2S(objPtr), O2S(part2Ptr)));
 	goto doLoadStk;
 
-    case INST_LOAD_STK:
-    case INST_LOAD_SCALAR_STK:
+    CASE(INST_LOAD_STK):
+    CASE(INST_LOAD_SCALAR_STK):
 	cleanup = 1;
 	part2Ptr = NULL;
 	objPtr = OBJ_AT_TOS;		/* variable name */
@@ -2572,12 +2672,12 @@ TclExecuteByteCode(
 	Var *varPtr, *arrayPtr;
 	Tcl_Obj *objPtr, *valuePtr;
 
-    case INST_STORE_ARRAY4:
+    CASE(INST_STORE_ARRAY4):
 	opnd = TclGetUInt4AtPtr(pc+1);
 	pcAdjustment = 5;
 	goto doStoreArrayDirect;
 
-    case INST_STORE_ARRAY1:
+    CASE(INST_STORE_ARRAY1):
 	opnd = TclGetUInt1AtPtr(pc+1);
 	pcAdjustment = 2;
 
@@ -2604,12 +2704,12 @@ TclExecuteByteCode(
 	part1Ptr = NULL;
 	goto doStoreArrayDirectFailed;
 
-    case INST_STORE_SCALAR4:
+    CASE(INST_STORE_SCALAR4):
 	opnd = TclGetUInt4AtPtr(pc+1);
 	pcAdjustment = 5;
 	goto doStoreScalarDirect;
 
-    case INST_STORE_SCALAR1:
+    CASE(INST_STORE_SCALAR1):
 	opnd = TclGetUInt1AtPtr(pc+1);
 	pcAdjustment = 2;
 
@@ -2649,40 +2749,40 @@ TclExecuteByteCode(
 	part1Ptr = NULL;
 	goto doStoreScalar;
 
-    case INST_LAPPEND_STK:
+    CASE(INST_LAPPEND_STK):
 	valuePtr = OBJ_AT_TOS; /* value to append */
 	part2Ptr = NULL;
 	storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
 		| TCL_LIST_ELEMENT | TCL_TRACE_READS);
 	goto doStoreStk;
 
-    case INST_LAPPEND_ARRAY_STK:
+    CASE(INST_LAPPEND_ARRAY_STK):
 	valuePtr = OBJ_AT_TOS; /* value to append */
 	part2Ptr = OBJ_UNDER_TOS;
 	storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
 		| TCL_LIST_ELEMENT | TCL_TRACE_READS);
 	goto doStoreStk;
 
-    case INST_APPEND_STK:
+    CASE(INST_APPEND_STK):
 	valuePtr = OBJ_AT_TOS; /* value to append */
 	part2Ptr = NULL;
 	storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
 	goto doStoreStk;
 
-    case INST_APPEND_ARRAY_STK:
+    CASE(INST_APPEND_ARRAY_STK):
 	valuePtr = OBJ_AT_TOS; /* value to append */
 	part2Ptr = OBJ_UNDER_TOS;
 	storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
 	goto doStoreStk;
 
-    case INST_STORE_ARRAY_STK:
+    CASE(INST_STORE_ARRAY_STK):
 	valuePtr = OBJ_AT_TOS;
 	part2Ptr = OBJ_UNDER_TOS;
 	storeFlags = TCL_LEAVE_ERR_MSG;
 	goto doStoreStk;
 
-    case INST_STORE_STK:
-    case INST_STORE_SCALAR_STK:
+    CASE(INST_STORE_STK):
+    CASE(INST_STORE_SCALAR_STK):
 	valuePtr = OBJ_AT_TOS;
 	part2Ptr = NULL;
 	storeFlags = TCL_LEAVE_ERR_MSG;
@@ -2711,27 +2811,27 @@ TclExecuteByteCode(
 	    goto checkForCatch;
 	}
 
-    case INST_LAPPEND_ARRAY4:
+    CASE(INST_LAPPEND_ARRAY4):
 	opnd = TclGetUInt4AtPtr(pc+1);
 	pcAdjustment = 5;
 	storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
 		| TCL_LIST_ELEMENT | TCL_TRACE_READS);
 	goto doStoreArray;
 
-    case INST_LAPPEND_ARRAY1:
+    CASE(INST_LAPPEND_ARRAY1):
 	opnd = TclGetUInt1AtPtr(pc+1);
 	pcAdjustment = 2;
 	storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
 		| TCL_LIST_ELEMENT | TCL_TRACE_READS);
 	goto doStoreArray;
 
-    case INST_APPEND_ARRAY4:
+    CASE(INST_APPEND_ARRAY4):
 	opnd = TclGetUInt4AtPtr(pc+1);
 	pcAdjustment = 5;
 	storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
 	goto doStoreArray;
 
-    case INST_APPEND_ARRAY1:
+    CASE(INST_APPEND_ARRAY1):
 	opnd = TclGetUInt1AtPtr(pc+1);
 	pcAdjustment = 2;
 	storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
@@ -2760,27 +2860,27 @@ TclExecuteByteCode(
 	    goto checkForCatch;
 	}
 
-    case INST_LAPPEND_SCALAR4:
+    CASE(INST_LAPPEND_SCALAR4):
 	opnd = TclGetUInt4AtPtr(pc+1);
 	pcAdjustment = 5;
 	storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
 		| TCL_LIST_ELEMENT | TCL_TRACE_READS);
 	goto doStoreScalar;
 
-    case INST_LAPPEND_SCALAR1:
+    CASE(INST_LAPPEND_SCALAR1):
 	opnd = TclGetUInt1AtPtr(pc+1);
 	pcAdjustment = 2;
 	storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
 		| TCL_LIST_ELEMENT | TCL_TRACE_READS);
 	goto doStoreScalar;
 
-    case INST_APPEND_SCALAR4:
+    CASE(INST_APPEND_SCALAR4):
 	opnd = TclGetUInt4AtPtr(pc+1);
 	pcAdjustment = 5;
 	storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
 	goto doStoreScalar;
 
-    case INST_APPEND_SCALAR1:
+    CASE(INST_APPEND_SCALAR1):
 	opnd = TclGetUInt1AtPtr(pc+1);
 	pcAdjustment = 2;
 	storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
@@ -2843,11 +2943,11 @@ TclExecuteByteCode(
 	Tcl_Obj *part1Ptr, *part2Ptr;
 	Var *varPtr, *arrayPtr;
 
-    case INST_INCR_SCALAR1:
-    case INST_INCR_ARRAY1:
-    case INST_INCR_ARRAY_STK:
-    case INST_INCR_SCALAR_STK:
-    case INST_INCR_STK:
+    CASE(INST_INCR_SCALAR1):
+    CASE(INST_INCR_ARRAY1):
+    CASE(INST_INCR_ARRAY_STK):
+    CASE(INST_INCR_SCALAR_STK):
+    CASE(INST_INCR_STK):
 	opnd = TclGetUInt1AtPtr(pc+1);
 	incrPtr = POP_OBJECT();
 	switch (*pc) {
@@ -2862,9 +2962,9 @@ TclExecuteByteCode(
 	    goto doIncrStk;
 	}
 
-    case INST_INCR_ARRAY_STK_IMM:
-    case INST_INCR_SCALAR_STK_IMM:
-    case INST_INCR_STK_IMM:
+    CASE(INST_INCR_ARRAY_STK_IMM):
+    CASE(INST_INCR_SCALAR_STK_IMM):
+    CASE(INST_INCR_STK_IMM):
 	i = TclGetInt1AtPtr(pc+1);
 	incrPtr = Tcl_NewIntObj(i);
 	Tcl_IncrRefCount(incrPtr);
@@ -2898,7 +2998,7 @@ TclExecuteByteCode(
 	    goto checkForCatch;
 	}
 
-    case INST_INCR_ARRAY1_IMM:
+    CASE(INST_INCR_ARRAY1_IMM):
 	opnd = TclGetUInt1AtPtr(pc+1);
 	i = TclGetInt1AtPtr(pc+2);
 	incrPtr = Tcl_NewIntObj(i);
@@ -2925,7 +3025,7 @@ TclExecuteByteCode(
 	    goto checkForCatch;
 	}
 
-    case INST_INCR_SCALAR1_IMM:
+    CASE(INST_INCR_SCALAR1_IMM):
 	opnd = TclGetUInt1AtPtr(pc+1);
 	i = TclGetInt1AtPtr(pc+2);
 	pcAdjustment = 3;
@@ -3107,7 +3207,7 @@ TclExecuteByteCode(
      * ---------------------------------------------------------
      */
 
-    case INST_UPVAR: {
+    CASE(INST_UPVAR): {
 	int opnd;
 	Var *varPtr, *otherPtr;
 
@@ -3137,7 +3237,7 @@ TclExecuteByteCode(
 	    goto checkForCatch;
 	}
 
-    case INST_VARIABLE:
+    CASE(INST_VARIABLE):
 	TRACE(("variable "));
 	otherPtr = TclObjLookupVarEx(interp, OBJ_AT_TOS, NULL,
 		(TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG), "access",
@@ -3154,7 +3254,7 @@ TclExecuteByteCode(
 	result = TCL_ERROR;
 	goto checkForCatch;
 
-    case INST_NSUPVAR:
+    CASE(INST_NSUPVAR):
 	TRACE_WITH_OBJ(("nsupvar "), OBJ_UNDER_TOS);
 
 	{
@@ -3226,7 +3326,7 @@ TclExecuteByteCode(
 	NEXT_INST_F(5, 1, 0);
     }
 
-    case INST_JUMP1: {
+    CASE(INST_JUMP1): {
 	int opnd;
 
 	opnd = TclGetInt1AtPtr(pc+1);
@@ -3235,7 +3335,7 @@ TclExecuteByteCode(
 	NEXT_INST_F(opnd, 0, 0);
     }
 
-    case INST_JUMP4: {
+    CASE(INST_JUMP4): {
 	int opnd;
 
 	opnd = TclGetInt4AtPtr(pc+1);
@@ -3250,22 +3350,22 @@ TclExecuteByteCode(
 
 	/* TODO: consider rewrite so we don't compute the offset we're not
 	 * going to take. */
-    case INST_JUMP_FALSE4:
+    CASE(INST_JUMP_FALSE4):
 	jmpOffset[0] = TclGetInt4AtPtr(pc+1);	/* FALSE offset */
 	jmpOffset[1] = 5;			/* TRUE offset*/
 	goto doCondJump;
 
-    case INST_JUMP_TRUE4:
+    CASE(INST_JUMP_TRUE4):
 	jmpOffset[0] = 5;
 	jmpOffset[1] = TclGetInt4AtPtr(pc+1);
 	goto doCondJump;
 
-    case INST_JUMP_FALSE1:
+    CASE(INST_JUMP_FALSE1):
 	jmpOffset[0] = TclGetInt1AtPtr(pc+1);
 	jmpOffset[1] = 2;
 	goto doCondJump;
 
-    case INST_JUMP_TRUE1:
+    CASE(INST_JUMP_TRUE1):
 	jmpOffset[0] = 2;
 	jmpOffset[1] = TclGetInt1AtPtr(pc+1);
 
@@ -3304,7 +3404,7 @@ TclExecuteByteCode(
 	NEXT_INST_F(jmpOffset[b], 1, 0);
     }
 
-    case INST_JUMP_TABLE: {
+    CASE(INST_JUMP_TABLE): {
 	Tcl_HashEntry *hPtr;
 	JumptableInfo *jtPtr;
 	int opnd;
@@ -3335,8 +3435,8 @@ TclExecuteByteCode(
      * and LAND is now handled by the expression compiler.
      */
 
-    case INST_LOR:
-    case INST_LAND: {
+    CASE(INST_LOR):
+    CASE(INST_LAND): {
 	/*
 	 * Operands must be boolean or numeric. No int->double conversions are
 	 * performed.
@@ -3377,7 +3477,7 @@ TclExecuteByteCode(
      *	   Start of INST_LIST and related instructions.
      */
 
-    case INST_LIST: {
+    CASE(INST_LIST): {
 	/*
 	 * Pop the opnd (objc) top stack elements into a new list obj and then
 	 * decrement their ref counts.
@@ -3391,7 +3491,7 @@ TclExecuteByteCode(
 	NEXT_INST_V(5, opnd, 1);
     }
 
-    case INST_LIST_LENGTH: {
+    CASE(INST_LIST_LENGTH): {
 	Tcl_Obj *valuePtr;
 	int length;
 
@@ -3409,7 +3509,7 @@ TclExecuteByteCode(
 	}
     }
 
-    case INST_LIST_INDEX: {
+    CASE(INST_LIST_INDEX): {
 	/*** lindex with objc == 3 ***/
 
 	Tcl_Obj *valuePtr, *value2Ptr;
@@ -3442,7 +3542,7 @@ TclExecuteByteCode(
 	}
     }
 
-    case INST_LIST_INDEX_IMM: {
+    CASE(INST_LIST_INDEX_IMM): {
 	/*** lindex with objc==3 and index in bytecode stream ***/
 
 	int listc, idx, opnd;
@@ -3489,7 +3589,7 @@ TclExecuteByteCode(
 	}
     }
 
-    case INST_LIST_INDEX_MULTI: {
+    CASE(INST_LIST_INDEX_MULTI): {
 	/*
 	 * 'lindex' with multiple index args:
 	 *
@@ -3526,7 +3626,7 @@ TclExecuteByteCode(
 	}
     }
 
-    case INST_LSET_FLAT: {
+    CASE(INST_LSET_FLAT): {
 	/*
 	 * Lset with 3, 5, or more args. Get the number of index args.
 	 */
@@ -3578,7 +3678,7 @@ TclExecuteByteCode(
 	}
     }
 
-    case INST_LSET_LIST: {
+    CASE(INST_LSET_LIST): {
 	/*
 	 * 'lset' with 4 args.
 	 */
@@ -3627,7 +3727,7 @@ TclExecuteByteCode(
 	}
     }
 
-    case INST_LIST_RANGE_IMM: {
+    CASE(INST_LIST_RANGE_IMM): {
 	/*** lrange with objc==4 and both indices in bytecode stream ***/
 
 	int listc, fromIdx, toIdx;
@@ -3708,8 +3808,8 @@ TclExecuteByteCode(
 	NEXT_INST_F(9, 1, 1);
     }
 
-    case INST_LIST_IN:
-    case INST_LIST_NOT_IN: {
+    CASE(INST_LIST_IN):
+    CASE(INST_LIST_NOT_IN): {
 	/*
 	 * Basic list containment operators.
 	 */
@@ -3785,8 +3885,8 @@ TclExecuteByteCode(
      * ---------------------------------------------------------
      */
 
-    case INST_STR_EQ:
-    case INST_STR_NEQ: {
+    CASE(INST_STR_EQ):
+    CASE(INST_STR_NEQ): {
 	/*
 	 * String (in)equality check
 	 * TODO: Consider merging into INST_STR_CMP
@@ -3851,7 +3951,7 @@ TclExecuteByteCode(
 	NEXT_INST_F(0, 2, 1);
     }
 
-    case INST_STR_CMP: {
+    CASE(INST_STR_CMP): {
 	/*
 	 * String compare.
 	 */
@@ -3960,7 +4060,7 @@ TclExecuteByteCode(
 	NEXT_INST_F(1, 2, 1);
     }
 
-    case INST_STR_LEN: {
+    CASE(INST_STR_LEN): {
 	int length;
 	Tcl_Obj *valuePtr;
 
@@ -3976,7 +4076,7 @@ TclExecuteByteCode(
 	NEXT_INST_F(1, 1, 1);
     }
 
-    case INST_STR_INDEX: {
+    CASE(INST_STR_INDEX): {
 	/*
 	 * String compare.
 	 */
@@ -4041,7 +4141,7 @@ TclExecuteByteCode(
 	NEXT_INST_F(1, 2, 1);
     }
 
-    case INST_STR_MATCH: {
+    CASE(INST_STR_MATCH): {
 	int nocase, match;
 	Tcl_Obj *valuePtr, *value2Ptr;
 
@@ -4079,12 +4179,12 @@ TclExecuteByteCode(
 	NEXT_INST_F(2, 2, 1);
     }
 
-    case INST_EQ:
-    case INST_NEQ:
-    case INST_LT:
-    case INST_GT:
-    case INST_LE:
-    case INST_GE: {
+    CASE(INST_EQ):
+    CASE(INST_NEQ):
+    CASE(INST_LT):
+    CASE(INST_GT):
+    CASE(INST_LE):
+    CASE(INST_GE): {
 	Tcl_Obj *valuePtr = OBJ_UNDER_TOS;
 	Tcl_Obj *value2Ptr = OBJ_AT_TOS;
 	ClientData ptr1, ptr2;
@@ -4396,9 +4496,9 @@ TclExecuteByteCode(
 	NEXT_INST_F(0, 2, 1);
     }
 
-    case INST_MOD:
-    case INST_LSHIFT:
-    case INST_RSHIFT: {
+    CASE(INST_MOD):
+    CASE(INST_LSHIFT):
+    CASE(INST_RSHIFT): {
 	Tcl_Obj *value2Ptr = OBJ_AT_TOS;
 	Tcl_Obj *valuePtr = OBJ_UNDER_TOS;
 	ClientData ptr1, ptr2;
@@ -4855,9 +4955,9 @@ TclExecuteByteCode(
 	NEXT_INST_F(1, 2, 1);
     }
 
-    case INST_BITOR:
-    case INST_BITXOR:
-    case INST_BITAND: {
+    CASE(INST_BITOR):
+    CASE(INST_BITXOR):
+    CASE(INST_BITAND): {
 	ClientData ptr1, ptr2;
 	int type1, type2;
 	Tcl_Obj *value2Ptr = OBJ_AT_TOS;
@@ -5098,11 +5198,11 @@ TclExecuteByteCode(
 	}
     }
 
-    case INST_EXPON:
-    case INST_ADD:
-    case INST_SUB:
-    case INST_DIV:
-    case INST_MULT: {
+    CASE(INST_EXPON):
+    CASE(INST_ADD):
+    CASE(INST_SUB):
+    CASE(INST_DIV):
+    CASE(INST_MULT): {
 	ClientData ptr1, ptr2;
 	int type1, type2;
 	Tcl_Obj *value2Ptr = OBJ_AT_TOS;
@@ -5831,7 +5931,7 @@ TclExecuteByteCode(
 	}
     }
 
-    case INST_LNOT: {
+    CASE(INST_LNOT): {
 	int b;
 	Tcl_Obj *valuePtr = OBJ_AT_TOS;
 
@@ -5849,7 +5949,7 @@ TclExecuteByteCode(
 	NEXT_INST_F(1, 1, 1);
     }
 
-    case INST_BITNOT: {
+    CASE(INST_BITNOT): {
 	mp_int big;
 	ClientData ptr;
 	int type;
@@ -5901,7 +6001,7 @@ TclExecuteByteCode(
 	NEXT_INST_F(1, 0, 0);
     }
 
-    case INST_UMINUS: {
+    CASE(INST_UMINUS): {
 	ClientData ptr;
 	int type;
 	Tcl_Obj *valuePtr = OBJ_AT_TOS;
@@ -5992,8 +6092,8 @@ TclExecuteByteCode(
 	}
     }
 
-    case INST_UPLUS:
-    case INST_TRY_CVT_TO_NUMERIC: {
+    CASE(INST_UPLUS):
+    CASE(INST_TRY_CVT_TO_NUMERIC): {
 	/*
 	 * Try to convert the topmost stack object to numeric object. This is
 	 * done in order to support [expr]'s policy of interpreting operands
@@ -6078,7 +6178,7 @@ TclExecuteByteCode(
 	NEXT_INST_F(1, 0, 0);
     }
 
-    case INST_BREAK:
+    CASE(INST_BREAK):
 	/*
 	DECACHE_STACK_INFO();
 	Tcl_ResetResult(interp);
@@ -6088,7 +6188,7 @@ TclExecuteByteCode(
 	cleanup = 0;
 	goto processExceptionReturn;
 
-    case INST_CONTINUE:
+    CASE(INST_CONTINUE):
 	/*
 	DECACHE_STACK_INFO();
 	Tcl_ResetResult(interp);
@@ -6098,7 +6198,7 @@ TclExecuteByteCode(
 	cleanup = 0;
 	goto processExceptionReturn;
 
-    case INST_FOREACH_START4: {
+    CASE(INST_FOREACH_START4): {
 	/*
 	 * Initialize the temporary local var that holds the count of the
 	 * number of iterations of the loop body to -1.
@@ -6137,7 +6237,7 @@ TclExecuteByteCode(
 #endif
     }
 
-    case INST_FOREACH_STEP4: {
+    CASE(INST_FOREACH_STEP4): {
 	/*
 	 * "Step" a foreach loop (i.e., begin its next iteration) by assigning
 	 * the next value list element to each loop var.
@@ -6269,7 +6369,7 @@ TclExecuteByteCode(
 	}
     }
 
-    case INST_BEGIN_CATCH4:
+    CASE(INST_BEGIN_CATCH4):
 	/*
 	 * Record start of the catch command with exception range index equal
 	 * to the operand. Push the current stack depth onto the special catch
@@ -6282,14 +6382,14 @@ TclExecuteByteCode(
 		(int) CURR_DEPTH));
 	NEXT_INST_F(5, 0, 0);
 
-    case INST_END_CATCH:
+    CASE(INST_END_CATCH):
 	catchTop--;
 	Tcl_ResetResult(interp);
 	result = TCL_OK;
 	TRACE(("=> catchTop=%d\n", (catchTop - initCatchTop - 1)));
 	NEXT_INST_F(1, 0, 0);
 
-    case INST_PUSH_RESULT:
+    CASE(INST_PUSH_RESULT):
 	objResultPtr = Tcl_GetObjResult(interp);
 	TRACE_WITH_OBJ(("=> "), objResultPtr);
 
@@ -6306,12 +6406,12 @@ TclExecuteByteCode(
 
 	NEXT_INST_F(1, 0, -1);
 
-    case INST_PUSH_RETURN_CODE:
+    CASE(INST_PUSH_RETURN_CODE):
 	TclNewIntObj(objResultPtr, result);
 	TRACE(("=> %u\n", result));
 	NEXT_INST_F(1, 0, 1);
 
-    case INST_PUSH_RETURN_OPTIONS:
+    CASE(INST_PUSH_RETURN_OPTIONS):
 	objResultPtr = Tcl_GetReturnOptions(interp, result);
 	TRACE_WITH_OBJ(("=> "), objResultPtr);
 	NEXT_INST_F(1, 0, 1);
@@ -6322,7 +6422,7 @@ TclExecuteByteCode(
 	Tcl_Obj *dictPtr, *valPtr;
 	Var *varPtr;
 
-    case INST_DICT_GET:
+    CASE(INST_DICT_GET):
 	opnd = TclGetUInt4AtPtr(pc+1);
 	TRACE(("%u => ", opnd));
 	dictPtr = OBJ_AT_DEPTH(opnd);
@@ -6356,9 +6456,9 @@ TclExecuteByteCode(
 	}
 	goto checkForCatch;
 
-    case INST_DICT_SET:
-    case INST_DICT_UNSET:
-    case INST_DICT_INCR_IMM:
+    CASE(INST_DICT_SET):
+    CASE(INST_DICT_UNSET):
+    CASE(INST_DICT_INCR_IMM):
 	opnd = TclGetUInt4AtPtr(pc+1);
 	opnd2 = TclGetUInt4AtPtr(pc+5);
 
@@ -6466,8 +6566,8 @@ TclExecuteByteCode(
 	TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
 	NEXT_INST_V(9, cleanup, 1);
 
-    case INST_DICT_APPEND:
-    case INST_DICT_LAPPEND:
+    CASE(INST_DICT_APPEND):
+    CASE(INST_DICT_LAPPEND):
 	opnd = TclGetUInt4AtPtr(pc+1);
 
 	varPtr = &(compiledLocals[opnd]);
@@ -6590,7 +6690,7 @@ TclExecuteByteCode(
 	Var *varPtr;
 	Tcl_DictSearch *searchPtr;
 
-    case INST_DICT_FIRST:
+    CASE(INST_DICT_FIRST):
 	opnd = TclGetUInt4AtPtr(pc+1);
 	TRACE(("%u => ", opnd));
 	dictPtr = POP_OBJECT();
@@ -6617,7 +6717,7 @@ TclExecuteByteCode(
 	Tcl_IncrRefCount(statePtr);
 	goto pushDictIteratorResult;
 
-    case INST_DICT_NEXT:
+    CASE(INST_DICT_NEXT):
 	opnd = TclGetUInt4AtPtr(pc+1);
 	TRACE(("%u => ", opnd));
 	statePtr = compiledLocals[opnd].value.objPtr;
@@ -6641,7 +6741,7 @@ TclExecuteByteCode(
 	/* TODO: consider opt like INST_FOREACH_STEP4 */
 	NEXT_INST_F(5, 0, 1);
 
-    case INST_DICT_DONE:
+    CASE(INST_DICT_DONE):
 	opnd = TclGetUInt4AtPtr(pc+1);
 	TRACE(("%u => ", opnd));
 	statePtr = compiledLocals[opnd].value.objPtr;
@@ -6682,7 +6782,7 @@ TclExecuteByteCode(
 	DictUpdateInfo *duiPtr;
 	Var *varPtr;
 
-    case INST_DICT_UPDATE_START:
+    CASE(INST_DICT_UPDATE_START):
 	opnd = TclGetUInt4AtPtr(pc+1);
 	opnd2 = TclGetUInt4AtPtr(pc+5);
 	varPtr = &(compiledLocals[opnd]);
@@ -6737,7 +6837,7 @@ TclExecuteByteCode(
 	}
 	NEXT_INST_F(9, 0, 0);
 
-    case INST_DICT_UPDATE_END:
+    CASE(INST_DICT_UPDATE_END):
 	opnd = TclGetUInt4AtPtr(pc+1);
 	opnd2 = TclGetUInt4AtPtr(pc+5);
 	varPtr = &(compiledLocals[opnd]);
@@ -6811,8 +6911,10 @@ TclExecuteByteCode(
 	NEXT_INST_F(9, 1, 0);
     }
 
+#if !USE_COMPUTED_GOTO
     default:
 	Tcl_Panic("TclExecuteByteCode: unrecognized opCode %u", *pc);
+#endif
     } /* end of switch on opCode */
 
     /*