Attachment "tclExecute-TEBCinline-compgoto.diff" to
ticket [1820448fff]
added by
das
2007-11-10 02:18:33.
Index: generic/tclExecute.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclExecute.c,v
retrieving revision 1.342
diff -u -p -r1.342 tclExecute.c
--- generic/tclExecute.c 9 Nov 2007 18:55:14 -0000 1.342
+++ generic/tclExecute.c 9 Nov 2007 19:02:11 -0000
@@ -24,6 +24,15 @@
#include <float.h>
/*
+ * FIXME: manual configuration of TEBC inline level & computed goto use:
+ */
+
+#ifndef TEBC_INLINE_LEVEL
+# define TEBC_INLINE_LEVEL 0 /* 0 - 4 */
+# define USE_COMPUTED_GOTO 0 /* 0 or 1 */
+#endif
+
+/*
* Hack to determine whether we may expect IEEE floating point. The hack is
* formally incorrect in that non-IEEE platforms might have the same precision
* and range, but VAX, IBM, and Cray do not; are there any other floating
@@ -187,6 +196,258 @@ VarHashCreateVar(
VarHashCreateVar((tablePtr), (key), NULL)
/*
+ * Use gcc branch prediction builtin when available.
+ */
+
+#ifdef HAVE_BUILTIN_EXPECT
+# ifndef USE_BUILTIN_EXPECT
+# define USE_BUILTIN_EXPECT 1
+# endif
+#else
+# ifndef USE_BUILTIN_EXPECT
+# define USE_BUILTIN_EXPECT 0
+# elif USE_BUILTIN_EXPECT
+# warning __builtin_expect unavailable
+# undef USE_BUILTIN_EXPECT
+# define USE_BUILTIN_EXPECT 0
+# endif
+#endif
+
+#if USE_BUILTIN_EXPECT
+# define LIKELY(t) (__builtin_expect((t), 1))
+# define UNLIKELY(t) (__builtin_expect((t), 0))
+#else
+# define LIKELY(t) (t)
+# define UNLIKELY(t) (t)
+#endif
+
+/*
+ * Use computed goto instead of big switch when available.
+ */
+
+#ifdef HAVE_COMPUTED_GOTO
+# ifndef USE_COMPUTED_GOTO
+# define USE_COMPUTED_GOTO 1
+# endif
+#else
+# ifndef USE_COMPUTED_GOTO
+# define USE_COMPUTED_GOTO 0
+# elif USE_COMPUTED_GOTO
+# warning computed goto unavailable
+# undef USE_COMPUTED_GOTO
+# define USE_COMPUTED_GOTO 0
+# endif
+#endif
+
+/*
+ * Macros to construct the instruction switch resp. jumptable.
+ */
+
+#if !USE_COMPUTED_GOTO
+# define CASE(i) case i
+# define BAD_INST() default
+# define DISPATCH_INST() switch (*pc)
+#else
+# define CASE(i) l_inst_##i
+# define BAD_INST() l_bad_inst
+# define DISPATCH_INST() GOTO_NEXT_INST(); l_top:
+# define CADR(i) ((char*) &&l_inst_##i - (char*) &&l_top)
+# define GOTO_NEXT_INST() \
+ if (LIKELY(*pc <= LAST_INST_OPCODE)) {\
+ goto *(void*)(instJumptable[*pc] + (char*) &&l_top);\
+ } else {\
+ goto BAD_INST();\
+ }
+#endif
+
+/*
+ * Define the NEXT_INST() and NEXT_INST_DISPATCH() macros according to the
+ * chosen level of inlining into the NEXT_INST_F() and NEXT_INST_V() macros:
+ * 0 no inlining
+ * 1 inline cleanup code
+ * 2 also inline async handler and other check code
+ * 3 also inline peephole gotos
+ * 4 also do indirect threading (direct computed goto to next instruction)
+ */
+
+#ifndef TEBC_INLINE_LEVEL
+# define TEBC_INLINE_LEVEL 0
+#endif
+
+#if TEBC_INLINE_LEVEL > 3 && USE_COMPUTED_GOTO
+# define NEXT_INST() \
+ NEXT_INST_CHECKS();\
+ NEXT_INST_PEEPHOLE();\
+ GOTO_NEXT_INST();
+# define NEXT_INST_DISPATCH() \
+ NEXT_INST_CHECKS();\
+ NEXT_INST_PEEPHOLE();\
+ DISPATCH_INST()
+#elif TEBC_INLINE_LEVEL > 2
+# define NEXT_INST() \
+ NEXT_INST_CHECKS();\
+ NEXT_INST_PEEPHOLE();\
+ goto l_next_inst;
+# define NEXT_INST_DISPATCH() \
+ NEXT_INST_CHECKS();\
+ NEXT_INST_PEEPHOLE();\
+ l_next_inst:\
+ DISPATCH_INST()
+#elif TEBC_INLINE_LEVEL > 1
+# define NEXT_INST() \
+ NEXT_INST_CHECKS();\
+ goto l_next_inst;
+# define NEXT_INST_DISPATCH() \
+ NEXT_INST_CHECKS();\
+ l_next_inst:\
+ NEXT_INST_PEEPHOLE();\
+ DISPATCH_INST()
+#elif TEBC_INLINE_LEVEL > 0
+# define NEXT_INST() \
+ goto l_next_inst;
+# define NEXT_INST_DISPATCH() \
+ l_next_inst:\
+ NEXT_INST_CHECKS();\
+ NEXT_INST_PEEPHOLE();\
+ DISPATCH_INST()
+#else
+# define NEXT_INST() \
+ goto l_next_inst;
+# define NEXT_INST_DISPATCH() \
+ goto l_next_inst;\
+ NEXT_INST_CLEANUP();\
+ l_next_inst:\
+ NEXT_INST_CHECKS();\
+ NEXT_INST_PEEPHOLE();\
+ DISPATCH_INST()
+#endif
+
+/*
+ * Macros for pre-instruction-execution checks and stats.
+ */
+
+#define NEXT_INST_CHECKS() \
+ NEXT_INST_STACK_CHECK();\
+ NEXT_INST_STATS();\
+ TCL_DTRACE_INST_NEXT();\
+ NEXT_INST_ASYNC_CHECK()
+
+#ifdef TCL_COMPILE_DEBUG
+ /*
+ * Skip the stack depth check if an expansion is in progress.
+ */
+# define NEXT_INST_STACK_CHECK() \
+ ValidatePcAndStackTop(codePtr, pc, CURR_DEPTH, 0,\
+ /*checkStack*/ expandNestList == NULL);\
+ if (traceInstructions) {\
+ fprintf(stdout, "%2d: %2d ", iPtr->numLevels, (int) CURR_DEPTH);\
+ TclPrintInstruction(codePtr, pc);\
+ fflush(stdout);\
+ }
+#else
+# define NEXT_INST_STACK_CHECK()
+#endif /* TCL_COMPILE_DEBUG */
+
+#ifdef TCL_COMPILE_STATS
+# define NEXT_INST_STATS() iPtr->stats.instructionCount[*pc]++;
+#else
+# define NEXT_INST_STATS()
+#endif
+
+/*
+ * Check for asynchronous handlers [Bug 746722]; we do the check every
+ * ASYNC_CHECK_COUNT_MASK instruction, of the form (2**n-1).
+ */
+
+#define NEXT_INST_ASYNC_CHECK() \
+ if ((instructionCount++ & ASYNC_CHECK_COUNT_MASK) == 0) {\
+ int localResult;\
+ if (Tcl_AsyncReady()) {\
+ DECACHE_STACK_INFO();\
+ localResult = Tcl_AsyncInvoke(interp, result);\
+ CACHE_STACK_INFO();\
+ if (localResult == TCL_ERROR) {\
+ result = localResult;\
+ goto checkForCatch;\
+ }\
+ }\
+ if (TclLimitReady(iPtr->limit)) {\
+ DECACHE_STACK_INFO();\
+ localResult = Tcl_LimitCheck(interp);\
+ CACHE_STACK_INFO();\
+ if (localResult == TCL_ERROR) {\
+ result = localResult;\
+ goto checkForCatch;\
+ }\
+ }\
+ }
+
+/*
+ * These two instructions account for 26% of all instructions (according
+ * to measurements on tclbench by Ben Vitale
+ * [http://www.cs.toronto.edu/syslab/pubs/tcl2005-vitale-zaleski.pdf]
+ * Resolving them before the switch reduces the cost of branch
+ * mispredictions, seems to improve runtime by 5% to 15%, and (amazingly!)
+ * reduces total obj size.
+ */
+
+#define NEXT_INST_PEEPHOLE() \
+ if (*pc == INST_LOAD_SCALAR1) {\
+ goto instLoadScalar1;\
+ } else if (*pc == INST_PUSH1) {\
+ goto instPush1Peephole;\
+ }
+
+/*
+ * Macros for standard instruction endings; unrolled for speed in the most
+ * frequent cases (instructions that consume up to two stack elements).
+ */
+
+#define CLEANUP_POP() {\
+ Tcl_Obj *valuePtr = POP_OBJECT();\
+ TclDecrRefCount(valuePtr);\
+ }
+#define CLEANUP_TOS() {\
+ Tcl_Obj *valuePtr = OBJ_AT_TOS;\
+ TclDecrRefCount(valuePtr);\
+ OBJ_AT_TOS = objResultPtr;\
+ }
+#define CLEANUPV_PUSH_L(l1, l2) \
+ switch (cleanup) {\
+ case 0: *(++tosPtr) = (objResultPtr); break;\
+ default: cleanup -= 2; while (cleanup--) { CLEANUP_POP(); }\
+ case 2: l2 CLEANUP_POP();\
+ case 1: l1 CLEANUP_TOS();\
+ }
+#define CLEANUPV_L(l1, l2) \
+ switch (cleanup) {\
+ default: cleanup -= 2; while (cleanup--) { CLEANUP_POP(); }\
+ case 2: l2 CLEANUP_POP();\
+ case 1: l1 CLEANUP_POP();\
+ case 0: break;\
+ }
+#if TEBC_INLINE_LEVEL > 0
+# define CLEANUP2_PUSH() CLEANUP_POP()
+# define CLEANUP1_PUSH() CLEANUP_TOS()
+# define CLEANUP2() CLEANUP_POP()
+# define CLEANUP1() CLEANUP_POP()
+# define CLEANUPV_PUSH() CLEANUPV_PUSH_L(,)
+# define CLEANUPV() CLEANUPV_L(,)
+#else
+# define CLEANUP2_PUSH() goto l_cleanup2_push;
+# define CLEANUP1_PUSH() goto l_cleanup1_push;
+# define CLEANUP2() goto l_cleanup2;
+# define CLEANUP1() goto l_cleanup1;
+# define CLEANUPV_PUSH() goto l_cleanupV_push;
+# define CLEANUPV() goto l_cleanupV;
+# define NEXT_INST_CLEANUP() \
+ l_cleanupV_push: CLEANUPV_PUSH_L(l_cleanup1_push:, l_cleanup2_push:);\
+ goto l_cleanup_done;\
+ l_cleanupV: CLEANUPV_L(l_cleanup1:, l_cleanup2:);\
+ l_cleanup_done:
+#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
@@ -210,25 +471,25 @@ VarHashCreateVar(
}\
} \
pc += (pcAdjustment);\
- goto cleanup0;\
- } else if (resultHandling != 0) {\
+ } else if (resultHandling) {\
if ((resultHandling) > 0) {\
Tcl_IncrRefCount(objResultPtr);\
}\
pc += (pcAdjustment);\
switch (nCleanup) {\
- case 1: goto cleanup1_pushObjResultPtr;\
- case 2: goto cleanup2_pushObjResultPtr;\
default: Tcl_Panic("bad usage of macro NEXT_INST_F");\
+ case 2: CLEANUP2_PUSH();\
+ case 1: CLEANUP1_PUSH();\
}\
} else {\
pc += (pcAdjustment);\
switch (nCleanup) {\
- case 1: goto cleanup1;\
- case 2: goto cleanup2;\
default: Tcl_Panic("bad usage of macro NEXT_INST_F");\
+ case 2: CLEANUP2();\
+ case 1: CLEANUP1();\
}\
- }
+ }\
+ NEXT_INST();
#define NEXT_INST_V(pcAdjustment, nCleanup, resultHandling) \
pc += (pcAdjustment);\
@@ -237,10 +498,11 @@ VarHashCreateVar(
if ((resultHandling) > 0) {\
Tcl_IncrRefCount(objResultPtr);\
}\
- goto cleanupV_pushObjResultPtr;\
+ CLEANUPV_PUSH();\
} else {\
- goto cleanupV;\
- }
+ CLEANUPV();\
+ }\
+ NEXT_INST();
/*
* Macros used to cache often-referenced Tcl evaluation stack information
@@ -1584,6 +1846,81 @@ TclExecuteByteCode(
#endif
char *curInstName = NULL;
+#if USE_COMPUTED_GOTO
+
+ /*
+ * Instruction jumptable for computed goto dispatch, needs to be kept
+ * in sync with instruction list in tclCompile.h.
+ */
+
+ 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.
@@ -1639,143 +1976,9 @@ TclExecuteByteCode(
* or some error.
*/
- goto cleanup0;
-
- /*
- * Targets for standard instruction endings; unrolled for speed in the
- * most frequent cases (instructions that consume up to two stack
- * elements).
- *
- * This used to be a "for(;;)" loop, with each instruction doing its own
- * cleanup.
- */
-
- {
- Tcl_Obj *valuePtr;
-
- cleanupV_pushObjResultPtr:
- switch (cleanup) {
- case 0:
- *(++tosPtr) = (objResultPtr);
- goto cleanup0;
- default:
- cleanup -= 2;
- while (cleanup--) {
- valuePtr = POP_OBJECT();
- TclDecrRefCount(valuePtr);
- }
- case 2:
- cleanup2_pushObjResultPtr:
- valuePtr = POP_OBJECT();
- TclDecrRefCount(valuePtr);
- case 1:
- cleanup1_pushObjResultPtr:
- valuePtr = OBJ_AT_TOS;
- TclDecrRefCount(valuePtr);
- }
- OBJ_AT_TOS = objResultPtr;
- goto cleanup0;
-
- cleanupV:
- switch (cleanup) {
- default:
- cleanup -= 2;
- while (cleanup--) {
- valuePtr = POP_OBJECT();
- TclDecrRefCount(valuePtr);
- }
- case 2:
- cleanup2:
- valuePtr = POP_OBJECT();
- TclDecrRefCount(valuePtr);
- case 1:
- cleanup1:
- valuePtr = POP_OBJECT();
- TclDecrRefCount(valuePtr);
- case 0:
- /*
- * We really want to do nothing now, but this is needed for some
- * compilers (SunPro CC).
- */
-
- break;
- }
- }
- cleanup0:
-
-#ifdef TCL_COMPILE_DEBUG
- /*
- * Skip the stack depth check if an expansion is in progress.
- */
-
- ValidatePcAndStackTop(codePtr, pc, CURR_DEPTH, 0,
- /*checkStack*/ expandNestList == NULL);
- if (traceInstructions) {
- fprintf(stdout, "%2d: %2d ", iPtr->numLevels, (int) CURR_DEPTH);
- TclPrintInstruction(codePtr, pc);
- fflush(stdout);
- }
-#endif /* TCL_COMPILE_DEBUG */
-
-#ifdef TCL_COMPILE_STATS
- iPtr->stats.instructionCount[*pc]++;
-#endif
-
- TCL_DTRACE_INST_NEXT();
-
- /*
- * Check for asynchronous handlers [Bug 746722]; we do the check every
- * ASYNC_CHECK_COUNT_MASK instruction, of the form (2**n-1).
- */
-
- if ((instructionCount++ & ASYNC_CHECK_COUNT_MASK) == 0) {
- /*
- * Check for asynchronous handlers [Bug 746722]; we do the check every
- * ASYNC_CHECK_COUNT_MASK instruction, of the form (2**n-<1).
- */
-
- if (Tcl_AsyncReady()) {
- int localResult;
-
- DECACHE_STACK_INFO();
- localResult = Tcl_AsyncInvoke(interp, result);
- CACHE_STACK_INFO();
- if (localResult == TCL_ERROR) {
- result = localResult;
- goto checkForCatch;
- }
- }
- if (TclLimitReady(iPtr->limit)) {
- int localResult;
-
- DECACHE_STACK_INFO();
- localResult = Tcl_LimitCheck(interp);
- CACHE_STACK_INFO();
- if (localResult == TCL_ERROR) {
- result = localResult;
- goto checkForCatch;
- }
- }
- }
-
- /*
- * These two instructions account for 26% of all instructions (according
- * to measurements on tclbench by Ben Vitale
- * [http://www.cs.toronto.edu/syslab/pubs/tcl2005-vitale-zaleski.pdf]
- * Resolving them before the switch reduces the cost of branch
- * mispredictions, seems to improve runtime by 5% to 15%, and (amazingly!)
- * reduces total obj size.
- */
-
- if (*pc == INST_LOAD_SCALAR1) {
- goto instLoadScalar1;
- } else if (*pc == INST_PUSH1) {
- goto instPush1Peephole;
- }
-
- switch (*pc) {
- case INST_SYNTAX:
- case INST_RETURN_IMM: {
+ NEXT_INST_DISPATCH() {
+ CASE(INST_SYNTAX):
+ CASE(INST_RETURN_IMM): {
int code = TclGetInt4AtPtr(pc+1);
int level = TclGetUInt4AtPtr(pc+5);
@@ -1799,7 +2002,7 @@ TclExecuteByteCode(
}
}
- case INST_RETURN_STK:
+ CASE(INST_RETURN_STK):
TRACE(("=> "));
objResultPtr = POP_OBJECT();
result = Tcl_SetReturnOptions(interp, OBJ_AT_TOS);
@@ -1814,7 +2017,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 +2040,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 +2057,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 +2085,7 @@ TclExecuteByteCode(
NEXT_INST_F(0, 0, 0);
}
- case INST_START_CMD:
+ CASE(INST_START_CMD):
#if !TCL_COMPILE_DEBUG
instStartCmdPeephole:
#endif
@@ -1923,12 +2126,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 +2140,7 @@ TclExecuteByteCode(
NEXT_INST_F(5, 0, 1);
}
- case INST_REVERSE: {
+ CASE(INST_REVERSE): {
int opnd;
Tcl_Obj **a, **b;
@@ -1953,7 +2156,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 +2231,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 +2254,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 +2318,7 @@ TclExecuteByteCode(
int objc, pcAdjustment;
- case INST_INVOKE_EXPANDED:
+ CASE(INST_INVOKE_EXPANDED):
{
Tcl_Obj *objPtr = expandNestList;
@@ -2137,12 +2340,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 +2437,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 +2485,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 +2523,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 +2579,7 @@ TclExecuteByteCode(
}
}
- case INST_EXPR_STK: {
+ CASE(INST_EXPR_STK): {
Tcl_Obj *objPtr, *valuePtr;
objPtr = OBJ_AT_TOS;
@@ -2409,7 +2612,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 +2635,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 +2657,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 +2697,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 +2775,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 +2807,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 +2852,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 +2914,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 +2963,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 +3046,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 +3065,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 +3101,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 +3128,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 +3310,7 @@ TclExecuteByteCode(
* ---------------------------------------------------------
*/
- case INST_UPVAR: {
+ CASE(INST_UPVAR): {
int opnd;
Var *varPtr, *otherPtr;
@@ -3137,7 +3340,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 +3357,7 @@ TclExecuteByteCode(
result = TCL_ERROR;
goto checkForCatch;
- case INST_NSUPVAR:
+ CASE(INST_NSUPVAR):
TRACE_WITH_OBJ(("nsupvar "), OBJ_UNDER_TOS);
{
@@ -3226,7 +3429,7 @@ TclExecuteByteCode(
NEXT_INST_F(5, 1, 0);
}
- case INST_JUMP1: {
+ CASE(INST_JUMP1): {
int opnd;
opnd = TclGetInt1AtPtr(pc+1);
@@ -3235,7 +3438,7 @@ TclExecuteByteCode(
NEXT_INST_F(opnd, 0, 0);
}
- case INST_JUMP4: {
+ CASE(INST_JUMP4): {
int opnd;
opnd = TclGetInt4AtPtr(pc+1);
@@ -3250,22 +3453,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 +3507,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 +3538,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 +3580,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 +3594,7 @@ TclExecuteByteCode(
NEXT_INST_V(5, opnd, 1);
}
- case INST_LIST_LENGTH: {
+ CASE(INST_LIST_LENGTH): {
Tcl_Obj *valuePtr;
int length;
@@ -3409,7 +3612,7 @@ TclExecuteByteCode(
}
}
- case INST_LIST_INDEX: {
+ CASE(INST_LIST_INDEX): {
/*** lindex with objc == 3 ***/
Tcl_Obj *valuePtr, *value2Ptr;
@@ -3442,7 +3645,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 +3692,7 @@ TclExecuteByteCode(
}
}
- case INST_LIST_INDEX_MULTI: {
+ CASE(INST_LIST_INDEX_MULTI): {
/*
* 'lindex' with multiple index args:
*
@@ -3526,7 +3729,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 +3781,7 @@ TclExecuteByteCode(
}
}
- case INST_LSET_LIST: {
+ CASE(INST_LSET_LIST): {
/*
* 'lset' with 4 args.
*/
@@ -3627,7 +3830,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 +3911,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 +3988,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 +4054,7 @@ TclExecuteByteCode(
NEXT_INST_F(0, 2, 1);
}
- case INST_STR_CMP: {
+ CASE(INST_STR_CMP): {
/*
* String compare.
*/
@@ -3960,7 +4163,7 @@ TclExecuteByteCode(
NEXT_INST_F(1, 2, 1);
}
- case INST_STR_LEN: {
+ CASE(INST_STR_LEN): {
int length;
Tcl_Obj *valuePtr;
@@ -3976,7 +4179,7 @@ TclExecuteByteCode(
NEXT_INST_F(1, 1, 1);
}
- case INST_STR_INDEX: {
+ CASE(INST_STR_INDEX): {
/*
* String compare.
*/
@@ -4041,7 +4244,7 @@ TclExecuteByteCode(
NEXT_INST_F(1, 2, 1);
}
- case INST_STR_MATCH: {
+ CASE(INST_STR_MATCH): {
int nocase, match;
Tcl_Obj *valuePtr, *value2Ptr;
@@ -4086,12 +4289,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;
@@ -4403,9 +4606,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;
@@ -4862,9 +5065,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;
@@ -5105,11 +5308,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;
@@ -5838,7 +6041,7 @@ TclExecuteByteCode(
}
}
- case INST_LNOT: {
+ CASE(INST_LNOT): {
int b;
Tcl_Obj *valuePtr = OBJ_AT_TOS;
@@ -5856,7 +6059,7 @@ TclExecuteByteCode(
NEXT_INST_F(1, 1, 1);
}
- case INST_BITNOT: {
+ CASE(INST_BITNOT): {
mp_int big;
ClientData ptr;
int type;
@@ -5908,7 +6111,7 @@ TclExecuteByteCode(
NEXT_INST_F(1, 0, 0);
}
- case INST_UMINUS: {
+ CASE(INST_UMINUS): {
ClientData ptr;
int type;
Tcl_Obj *valuePtr = OBJ_AT_TOS;
@@ -5999,8 +6202,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
@@ -6085,7 +6288,7 @@ TclExecuteByteCode(
NEXT_INST_F(1, 0, 0);
}
- case INST_BREAK:
+ CASE(INST_BREAK):
/*
DECACHE_STACK_INFO();
Tcl_ResetResult(interp);
@@ -6095,7 +6298,7 @@ TclExecuteByteCode(
cleanup = 0;
goto processExceptionReturn;
- case INST_CONTINUE:
+ CASE(INST_CONTINUE):
/*
DECACHE_STACK_INFO();
Tcl_ResetResult(interp);
@@ -6105,7 +6308,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.
@@ -6144,7 +6347,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.
@@ -6276,7 +6479,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
@@ -6289,14 +6492,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);
@@ -6313,12 +6516,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);
@@ -6329,7 +6532,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);
@@ -6363,9 +6566,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);
@@ -6473,8 +6676,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]);
@@ -6597,7 +6800,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();
@@ -6624,7 +6827,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;
@@ -6648,7 +6851,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;
@@ -6689,7 +6892,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]);
@@ -6744,7 +6947,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]);
@@ -6818,7 +7021,7 @@ TclExecuteByteCode(
NEXT_INST_F(9, 1, 0);
}
- default:
+ BAD_INST():
Tcl_Panic("TclExecuteByteCode: unrecognized opCode %u", *pc);
} /* end of switch on opCode */
Index: unix/configure
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/configure,v
retrieving revision 1.209
diff -u -p -r1.209 configure
--- unix/configure 30 Oct 2007 19:03:56 -0000 1.209
+++ unix/configure 9 Nov 2007 19:02:17 -0000
@@ -17679,6 +17679,139 @@ echo "${ECHO_T}supplied by Tcl" >&6
INSTALL_TZDATA=install-tzdata
fi
+#------------------------------------------------------------------------
+# Check for computed goto and __builtin_expect support.
+#------------------------------------------------------------------------
+
+echo "$as_me:$LINENO: checking for computed goto" >&5
+echo $ECHO_N "checking for computed goto... $ECHO_C" >&6
+if test "${tcl_cv_cc_computed_goto+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stddef.h>
+int
+main ()
+{
+
+ int a; ptrdiff_t offset = (char*) &&l - (char*) &&t;
+ goto *(void*)(offset + (char*) &&t); t: a = 0; l: a = 1;
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ tcl_cv_cc_computed_goto=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_cc_computed_goto=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_cc_computed_goto" >&5
+echo "${ECHO_T}$tcl_cv_cc_computed_goto" >&6
+if test $tcl_cv_cc_computed_goto = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_COMPUTED_GOTO 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for __builtin_expect" >&5
+echo $ECHO_N "checking for __builtin_expect... $ECHO_C" >&6
+if test "${tcl_cv_cc_builtin_expect+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ int a = 1; if (__builtin_expect(a, 1)) {a = 0;}
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ tcl_cv_cc_builtin_expect=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_cc_builtin_expect=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_cc_builtin_expect" >&5
+echo "${ECHO_T}$tcl_cv_cc_builtin_expect" >&6
+if test $tcl_cv_cc_builtin_expect = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_BUILTIN_EXPECT 1
+_ACEOF
+
+fi
+
#--------------------------------------------------------------------
# DTrace support
#--------------------------------------------------------------------
Index: unix/configure.in
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/configure.in,v
retrieving revision 1.167
diff -u -p -r1.167 configure.in
--- unix/configure.in 30 Oct 2007 19:03:57 -0000 1.167
+++ unix/configure.in 9 Nov 2007 19:02:17 -0000
@@ -631,6 +631,27 @@ then
INSTALL_TZDATA=install-tzdata
fi
+#------------------------------------------------------------------------
+# Check for computed goto and __builtin_expect support.
+#------------------------------------------------------------------------
+
+AC_CACHE_CHECK([for computed goto], tcl_cv_cc_computed_goto, [
+ AC_TRY_COMPILE([#include <stddef.h>], [
+ int a; ptrdiff_t offset = (char*) &&l - (char*) &&t;
+ goto *(void*)(offset + (char*) &&t); t: a = 0; l: a = 1;
+ ], tcl_cv_cc_computed_goto=yes, tcl_cv_cc_computed_goto=no)])
+if test $tcl_cv_cc_computed_goto = yes; then
+ AC_DEFINE(HAVE_COMPUTED_GOTO, 1, [Is computed goto available?])
+fi
+
+AC_CACHE_CHECK([for __builtin_expect], tcl_cv_cc_builtin_expect, [
+ AC_TRY_COMPILE(, [
+ int a = 1; if (__builtin_expect(a, 1)) {a = 0;}
+ ], tcl_cv_cc_builtin_expect=yes, tcl_cv_cc_builtin_expect=no)])
+if test $tcl_cv_cc_builtin_expect = yes; then
+ AC_DEFINE(HAVE_BUILTIN_EXPECT, 1, [Is __builtin_expect available?])
+fi
+
#--------------------------------------------------------------------
# DTrace support
#--------------------------------------------------------------------