diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2009-12-08 13:58:04 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2009-12-08 13:58:04 (GMT) |
commit | 4fcf95fb18b11889ef2fbd9ed8a4ae6a04756425 (patch) | |
tree | aa54020a35ee7fbaa108194900b48552383b9348 | |
parent | 1421cacb4e078cf96950f34ed3f3dabe6153ec26 (diff) | |
download | tcl-4fcf95fb18b11889ef2fbd9ed8a4ae6a04756425.zip tcl-4fcf95fb18b11889ef2fbd9ed8a4ae6a04756425.tar.gz tcl-4fcf95fb18b11889ef2fbd9ed8a4ae6a04756425.tar.bz2 |
Reduce size of TEBC activation record a bit.
-rw-r--r-- | ChangeLog | 33 | ||||
-rw-r--r-- | generic/tclExecute.c | 755 |
2 files changed, 409 insertions, 379 deletions
@@ -1,31 +1,38 @@ +2009-12-08 Donal K. Fellows <dkf@users.sf.net> + + * generic/tclExecute.c (TclExecuteByteCode): Make the dict opcodes + more sparing in their use of C variables, to reduce size of TEBC + activiation record a little bit. + 2009-12-07 Miguel Sofer <msofer@users.sf.net> - * generic/tclExecute.c (TEBC): Grouping "slow" variables into - structs, to reduce register pressure and help the compiler with - variable allocation. + * generic/tclExecute.c (TEBC): Grouping "slow" variables into structs, + to reduce register pressure and help the compiler with variable + allocation. 2009-12-07 Miguel Sofer <msofer@users.sf.net> * generic/tclExecute.c: Start cleaning the TEBC stables * generic/tclInt.h: - * generic/tclCmdIL.c: Fix of [Bug #2910094] by aku + * generic/tclCmdIL.c: [Bug 2910094]: Fix by aku * tests/coroutine.test: - * generic/tclBasic.c: arrange for [tailcall] to be created with - the other builtins: was being created in a separate call, leftover - from pre-tip days. + * generic/tclBasic.c: Arrange for [tailcall] to be created with the + other builtins: was being created in a separate call, leftover from + pre-tip days. 2009-12-07 Don Porter <dgp@users.sourceforge.net> - * generic/tclStrToD.c: Correct conditional compile directives to - better detect the toolchain that needs extra work for proper underflow - treatment instead of merely detecting the mips platform. [Bug 2902010]. + * generic/tclStrToD.c: [Bug 2902010]: Correct conditional compile + directives to better detect the toolchain that needs extra work for + proper underflow treatment instead of merely detecting the MIPS + platform. 2009-12-07 Miguel Sofer <msofer@users.sf.net> - * generic/tclBasic.c: add ::tcl::unsupported::yieldTo - * generic/tclInt.h: [Patch 2910056] + * generic/tclBasic.c: [Patch 2910056]: Add ::tcl::unsupported::yieldTo + * generic/tclInt.h: 2009-12-07 Donal K. Fellows <dkf@users.sf.net> @@ -38,7 +45,7 @@ * generic/tclExecute.c: and coroutine code. * tests/coroutine.test: - * tests/tailcall.test: remove some old unused crud; improved the + * tests/tailcall.test: Remove some old unused crud; improved the stack depth tests. * generic/tclBasic.c: Fixed things so that you can tailcall diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 5835792..e552dad 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -14,7 +14,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclExecute.c,v 1.452 2009/12/08 04:20:24 msofer Exp $ + * RCS: @(#) $Id: tclExecute.c,v 1.453 2009/12/08 13:58:04 dkf Exp $ */ #include "tclInt.h" @@ -165,7 +165,7 @@ static BuiltinFunc const tclBuiltinFuncTable[] = { #define LAST_BUILTIN_FUNC 25 #endif - + /* * NR_TEBC * Helpers for NR - non-recursive calls to TEBC @@ -174,43 +174,52 @@ static BuiltinFunc const tclBuiltinFuncTable[] = { typedef struct BottomData { struct BottomData *prevBottomPtr; - TEOV_callback *rootPtr; /* State when this bytecode execution began: */ - ByteCode *codePtr; /* constant until it returns */ - /* ------------------------------------------*/ - const unsigned char *pc; /* These fields are used on return TO this */ - ptrdiff_t *catchTop; /* this level: they record the state when a */ - int cleanup; /* new codePtr was received for NR execution */ - Tcl_Obj *auxObjList; + TEOV_callback *rootPtr; /* State when this bytecode execution + * began: */ + ByteCode *codePtr; /* constant until it returns */ + /* -----------------------------------------*/ + const unsigned char *pc; /* These fields are used on return TO this */ + ptrdiff_t *catchTop; /* this level: they record the state when a */ + int cleanup; /* new codePtr was received for NR */ + Tcl_Obj *auxObjList; /* execution. */ } BottomData; -#define NR_DATA_INIT() \ - BP->prevBottomPtr = OBP; \ - BP->rootPtr = TOP_CB(iPtr); \ - BP->codePtr = codePtr; \ - -#define NR_DATA_BURY() \ - BP->pc = pc; \ - BP->cleanup = cleanup; \ - OBP = BP - -#define NR_DATA_DIG() \ - pc = BP->pc; \ - codePtr = BP->codePtr; \ - cleanup = BP->cleanup; \ - TAUX.esPtr = iPtr->execEnvPtr->execStackPtr; \ - tosPtr = TAUX.esPtr->tosPtr - -#define PUSH_TAUX_OBJ(objPtr) \ - objPtr->internalRep.twoPtrValue.ptr2 = auxObjList; \ - auxObjList = objPtr - -#define POP_TAUX_OBJ() \ - { \ +#define NR_DATA_INIT() \ + do { \ + BP->prevBottomPtr = OBP; \ + BP->rootPtr = TOP_CB(iPtr); \ + BP->codePtr = codePtr; \ + } while (0) + +#define NR_DATA_BURY() \ + do { \ + BP->pc = pc; \ + BP->cleanup = cleanup; \ + OBP = BP; \ + } while (0) + +#define NR_DATA_DIG() \ + do { \ + pc = BP->pc; \ + codePtr = BP->codePtr; \ + cleanup = BP->cleanup; \ + TAUX.esPtr = iPtr->execEnvPtr->execStackPtr; \ + tosPtr = TAUX.esPtr->tosPtr; \ + } while (0) + +#define PUSH_TAUX_OBJ(objPtr) \ + do { \ + objPtr->internalRep.twoPtrValue.ptr2 = auxObjList; \ + auxObjList = objPtr; \ + } while (0) + +#define POP_TAUX_OBJ() \ + do { \ Tcl_Obj *tmpPtr = auxObjList; \ auxObjList = (Tcl_Obj *) tmpPtr->internalRep.twoPtrValue.ptr2; \ Tcl_DecrRefCount(tmpPtr); \ - } - + } while (0) + /* * These variable-access macros have to coincide with those in tclVar.c */ @@ -235,7 +244,7 @@ VarHashCreateVar( #define VarHashFindVar(tablePtr, key) \ VarHashCreateVar((tablePtr), (key), NULL) - + /* * 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; @@ -254,45 +263,49 @@ VarHashCreateVar( */ #define NEXT_INST_F(pcAdjustment, nCleanup, resultHandling) \ - TCL_CT_ASSERT((nCleanup >= 0) && (nCleanup <= 2)); \ - if (nCleanup == 0) { \ - if (resultHandling != 0) { \ - if ((resultHandling) > 0) { \ - PUSH_OBJECT(objResultPtr); \ - } else { \ - *(++tosPtr) = objResultPtr; \ - } \ - } \ - pc += (pcAdjustment); \ - goto cleanup0; \ - } else if (resultHandling != 0) { \ - if ((resultHandling) > 0) { \ - Tcl_IncrRefCount(objResultPtr); \ - } \ - pc += (pcAdjustment); \ - switch (nCleanup) { \ - case 1: goto cleanup1_pushObjResultPtr; \ - case 2: goto cleanup2_pushObjResultPtr; \ - }\ - } else {\ - pc += (pcAdjustment);\ - switch (nCleanup) {\ - case 1: goto cleanup1;\ - case 2: goto cleanup2;\ - }\ - } + do { \ + TCL_CT_ASSERT((nCleanup >= 0) && (nCleanup <= 2)); \ + if (nCleanup == 0) { \ + if (resultHandling != 0) { \ + if ((resultHandling) > 0) { \ + PUSH_OBJECT(objResultPtr); \ + } else { \ + *(++tosPtr) = objResultPtr; \ + } \ + } \ + pc += (pcAdjustment); \ + goto cleanup0; \ + } else if (resultHandling != 0) { \ + if ((resultHandling) > 0) { \ + Tcl_IncrRefCount(objResultPtr); \ + } \ + pc += (pcAdjustment); \ + switch (nCleanup) { \ + case 1: goto cleanup1_pushObjResultPtr; \ + case 2: goto cleanup2_pushObjResultPtr; \ + } \ + } else { \ + pc += (pcAdjustment); \ + switch (nCleanup) { \ + case 1: goto cleanup1; \ + case 2: goto cleanup2; \ + } \ + } \ + } while (0) #define NEXT_INST_V(pcAdjustment, nCleanup, resultHandling) \ - pc += (pcAdjustment);\ - cleanup = (nCleanup);\ - if (resultHandling) {\ - if ((resultHandling) > 0) {\ - Tcl_IncrRefCount(objResultPtr);\ - }\ - goto cleanupV_pushObjResultPtr;\ - } else {\ - goto cleanupV;\ - } + do { \ + pc += (pcAdjustment); \ + cleanup = (nCleanup); \ + if (resultHandling) { \ + if ((resultHandling) > 0) { \ + Tcl_IncrRefCount(objResultPtr); \ + } \ + goto cleanupV_pushObjResultPtr; \ + } else { \ + goto cleanupV; \ + } \ + } while (0) /* * Macros used to cache often-referenced Tcl evaluation stack information @@ -306,8 +319,10 @@ VarHashCreateVar( TAUX.checkInterp = 1 #define DECACHE_STACK_INFO() \ - TAUX.esPtr->tosPtr = tosPtr; \ - iPtr->execEnvPtr->bottomPtr = BP + do { \ + TAUX.esPtr->tosPtr = tosPtr; \ + iPtr->execEnvPtr->bottomPtr = BP; \ + } while (0) /* * Macros used to access items on the Tcl evaluation stack. PUSH_OBJECT @@ -345,26 +360,29 @@ VarHashCreateVar( #ifdef TCL_COMPILE_DEBUG # define TRACE(a) \ - if (traceInstructions) { \ - fprintf(stdout, "%2d: %2d (%u) %s ", iPtr->numLevels, \ - (int) CURR_DEPTH, \ - (unsigned)(pc - codePtr->codeStart), \ - GetOpcodeName(pc)); \ - printf a; \ + while (traceInstructions) { \ + fprintf(stdout, "%2d: %2d (%u) %s ", iPtr->numLevels, \ + (int) CURR_DEPTH, \ + (unsigned) (pc - codePtr->codeStart), \ + GetOpcodeName(pc)); \ + printf a; \ + break; \ } # define TRACE_APPEND(a) \ - if (traceInstructions) { \ - printf a; \ + while (traceInstructions) { \ + printf a; \ + break; \ } # define TRACE_WITH_OBJ(a, objPtr) \ - if (traceInstructions) { \ - fprintf(stdout, "%2d: %2d (%u) %s ", iPtr->numLevels, \ - (int) CURR_DEPTH, \ - (unsigned)(pc - codePtr->codeStart), \ - GetOpcodeName(pc)); \ - printf a; \ - TclPrintObject(stdout, objPtr, 30); \ - fprintf(stdout, "\n"); \ + while (traceInstructions) { \ + fprintf(stdout, "%2d: %2d (%u) %s ", iPtr->numLevels, \ + (int) CURR_DEPTH, \ + (unsigned) (pc - codePtr->codeStart), \ + GetOpcodeName(pc)); \ + printf a; \ + TclPrintObject(stdout, objPtr, 30); \ + fprintf(stdout, "\n"); \ + break; \ } # define O2S(objPtr) \ (objPtr ? TclGetString(objPtr) : "") @@ -380,25 +398,29 @@ VarHashCreateVar( */ #define TCL_DTRACE_INST_NEXT() \ - if (TCL_DTRACE_INST_DONE_ENABLED()) {\ - if (TAUX.curInstName) {\ - TCL_DTRACE_INST_DONE(TAUX.curInstName, (int) CURR_DEPTH,\ - tosPtr);\ - }\ - TAUX.curInstName = tclInstructionTable[*pc].name;\ - if (TCL_DTRACE_INST_START_ENABLED()) {\ - TCL_DTRACE_INST_START(TAUX.curInstName, (int) CURR_DEPTH,\ - tosPtr);\ - }\ - } else if (TCL_DTRACE_INST_START_ENABLED()) {\ - TCL_DTRACE_INST_START(tclInstructionTable[*pc].name,\ - (int) CURR_DEPTH, tosPtr);\ - } + do { \ + if (TCL_DTRACE_INST_DONE_ENABLED()) { \ + if (TAUX.curInstName) { \ + TCL_DTRACE_INST_DONE(TAUX.curInstName, (int) CURR_DEPTH, \ + tosPtr); \ + } \ + TAUX.curInstName = tclInstructionTable[*pc].name; \ + if (TCL_DTRACE_INST_START_ENABLED()) { \ + TCL_DTRACE_INST_START(TAUX.curInstName, (int) CURR_DEPTH, \ + tosPtr); \ + } \ + } else if (TCL_DTRACE_INST_START_ENABLED()) { \ + TCL_DTRACE_INST_START(tclInstructionTable[*pc].name, \ + (int) CURR_DEPTH, tosPtr); \ + } \ + } while (0) #define TCL_DTRACE_INST_LAST() \ - if (TCL_DTRACE_INST_DONE_ENABLED() && TAUX.curInstName) {\ - TCL_DTRACE_INST_DONE(TAUX.curInstName, (int) CURR_DEPTH, tosPtr);\ - } - + do { \ + if (TCL_DTRACE_INST_DONE_ENABLED() && TAUX.curInstName) { \ + TCL_DTRACE_INST_DONE(TAUX.curInstName, (int) CURR_DEPTH, tosPtr);\ + } \ + } while (0) + /* * Macro used in this file to save a function call for common uses of * TclGetNumberFromObj(). The ANSI C "prototype" is: @@ -408,8 +430,7 @@ VarHashCreateVar( */ #ifdef NO_WIDE_TYPE - -#define GetNumberFromObj(interp, objPtr, ptrPtr, tPtr) \ +#define GetNumberFromObj(interp, objPtr, ptrPtr, tPtr) \ (((objPtr)->typePtr == &tclIntType) \ ? (*(tPtr) = TCL_NUMBER_LONG, \ *(ptrPtr) = (ClientData) \ @@ -424,10 +445,8 @@ VarHashCreateVar( (((objPtr)->bytes != NULL) && ((objPtr)->length == 0))) \ ? TCL_ERROR : \ TclGetNumberFromObj((interp), (objPtr), (ptrPtr), (tPtr))) - -#else - -#define GetNumberFromObj(interp, objPtr, ptrPtr, tPtr) \ +#else /* !NO_WIDE_TYPE */ +#define GetNumberFromObj(interp, objPtr, ptrPtr, tPtr) \ (((objPtr)->typePtr == &tclIntType) \ ? (*(tPtr) = TCL_NUMBER_LONG, \ *(ptrPtr) = (ClientData) \ @@ -446,8 +465,7 @@ VarHashCreateVar( (((objPtr)->bytes != NULL) && ((objPtr)->length == 0))) \ ? TCL_ERROR : \ TclGetNumberFromObj((interp), (objPtr), (ptrPtr), (tPtr))) - -#endif +#endif /* NO_WIDE_TYPE */ /* * Macro used in this file to save a function call for common uses of @@ -457,7 +475,7 @@ VarHashCreateVar( * int *boolPtr); */ -#define TclGetBooleanFromObj(interp, objPtr, boolPtr) \ +#define TclGetBooleanFromObj(interp, objPtr, boolPtr) \ ((((objPtr)->typePtr == &tclIntType) \ || ((objPtr)->typePtr == &tclBooleanType)) \ ? (*(boolPtr) = ((objPtr)->internalRep.longValue!=0), TCL_OK) \ @@ -472,12 +490,12 @@ VarHashCreateVar( */ #ifdef NO_WIDE_TYPE -#define TclGetWideIntFromObj(interp, objPtr, wideIntPtr) \ +#define TclGetWideIntFromObj(interp, objPtr, wideIntPtr) \ (((objPtr)->typePtr == &tclIntType) \ ? (*(wideIntPtr) = (Tcl_WideInt) \ ((objPtr)->internalRep.longValue), TCL_OK) : \ Tcl_GetWideIntFromObj((interp), (objPtr), (wideIntPtr))) -#else +#else /* !NO_WIDE_TYPE */ #define TclGetWideIntFromObj(interp, objPtr, wideIntPtr) \ (((objPtr)->typePtr == &tclWideIntType) \ ? (*(wideIntPtr) = (objPtr)->internalRep.wideValue, TCL_OK) : \ @@ -485,7 +503,7 @@ VarHashCreateVar( ? (*(wideIntPtr) = (Tcl_WideInt) \ ((objPtr)->internalRep.longValue), TCL_OK) : \ Tcl_GetWideIntFromObj((interp), (objPtr), (wideIntPtr))) -#endif +#endif /* NO_WIDE_TYPE */ /* * Macro used to make the check for type overflow more mnemonic. This works by @@ -509,16 +527,16 @@ static const Tcl_ObjType dictIteratorType = { "dictIterator", NULL, NULL, NULL, NULL }; - + /* - * Auxiliary tables used to compute powers of small integers + * Auxiliary tables used to compute powers of small integers. */ #if (LONG_MAX == 0x7fffffff) /* * Maximum base that, when raised to powers 2, 3, ... 8, fits in a 32-bit - * signed integer + * signed integer. */ static const long MaxBase32[] = {46340, 1290, 215, 73, 35, 21, 14}; @@ -533,7 +551,8 @@ static const size_t MaxBase32Size = sizeof(MaxBase32)/sizeof(long); static const unsigned short Exp32Index[] = { 0, 11, 18, 23, 26, 29, 31, 32, 33 }; -static const size_t Exp32IndexSize = sizeof(Exp32Index)/sizeof(unsigned short); +static const size_t Exp32IndexSize = + sizeof(Exp32Index) / sizeof(unsigned short); static const long Exp32Value[] = { 19683, 59049, 177147, 531441, 1594323, 4782969, 14348907, 43046721, 129140163, 387420489, 1162261467, 262144, 1048576, 4194304, @@ -543,7 +562,6 @@ static const long Exp32Value[] = { 1000000000 }; static const size_t Exp32ValueSize = sizeof(Exp32Value)/sizeof(long); - #endif /* LONG_MAX == 0x7fffffff -- 32 bit machine */ #if (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG) @@ -563,14 +581,15 @@ static const Tcl_WideInt MaxBase64[] = { static const size_t MaxBase64Size = sizeof(MaxBase64)/sizeof(Tcl_WideInt); /* - *Table giving 3, 4, ..., 13 raised to powers greater than 16 when the + * Table giving 3, 4, ..., 13 raised to powers greater than 16 when the * results fit in a 64-bit signed integer. */ static const unsigned short Exp64Index[] = { 0, 23, 38, 49, 57, 63, 67, 70, 72, 74, 75, 76 }; -static const size_t Exp64IndexSize = sizeof(Exp64Index)/sizeof(unsigned short); +static const size_t Exp64IndexSize = + sizeof(Exp64Index) / sizeof(unsigned short); static const Tcl_WideInt Exp64Value[] = { (Tcl_WideInt)243*243*243*3*3, (Tcl_WideInt)243*243*243*3*3*3, @@ -649,10 +668,9 @@ static const Tcl_WideInt Exp64Value[] = { (Tcl_WideInt)248832*248832*248832*12*12, (Tcl_WideInt)371293*371293*371293*13*13 }; -static const size_t Exp64ValueSize = sizeof(Exp64Value)/sizeof(Tcl_WideInt); - -#endif - +static const size_t Exp64ValueSize = sizeof(Exp64Value) / sizeof(Tcl_WideInt); +#endif /* (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG) */ + /* * Declarations for local procedures to this file: */ @@ -675,10 +693,10 @@ static void DeleteExecStack(ExecStack *esPtr); static void DupExprCodeInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); static void FreeExprCodeInternalRep(Tcl_Obj *objPtr); -static ExceptionRange * GetExceptRangeForPc(const unsigned char *pc, int catchOnly, - ByteCode *codePtr); -static const char * GetSrcInfoForPc(const unsigned char *pc, ByteCode *codePtr, - int *lengthPtr); +static ExceptionRange * GetExceptRangeForPc(const unsigned char *pc, + int catchOnly, ByteCode *codePtr); +static const char * GetSrcInfoForPc(const unsigned char *pc, + ByteCode *codePtr, int *lengthPtr); static Tcl_Obj ** GrowEvaluationStack(ExecEnv *eePtr, int growth, int move); static void IllegalExprOperandType(Tcl_Interp *interp, @@ -688,7 +706,6 @@ static inline int OFFSET(void *ptr); /* Useful elsewhere, make available in tclInt.h or stubs? */ static Tcl_Obj ** StackAllocWords(Tcl_Interp *interp, int numWords); static Tcl_Obj ** StackReallocWords(Tcl_Interp *interp, int numWords); - static Tcl_NRPostProc CopyCallback; static Tcl_NRPostProc ExprObjCallback; @@ -769,7 +786,7 @@ ExecEnv * TclCreateExecEnv( Tcl_Interp *interp, /* Interpreter for which the execution * environment is being created. */ - int size) /* the initial stack size, in number of words + int size) /* The initial stack size, in number of words * [sizeof(Tcl_Obj*)] */ { ExecEnv *eePtr = (ExecEnv *) ckalloc(sizeof(ExecEnv)); @@ -926,10 +943,9 @@ OFFSET( * Given a marker, compute where the following aligned memory starts. */ -#define MEMSTART(markerPtr) \ +#define MEMSTART(markerPtr) \ ((markerPtr) + OFFSET(markerPtr)) - /* *---------------------------------------------------------------------- * @@ -1444,17 +1460,17 @@ CompileExprObj( * DupExprCodeInternalRep -- * * Part of the Tcl object type implementation for Tcl expression - * bytecode. We do not copy the bytecode intrep. Instead, we - * return without setting copyPtr->typePtr, so the copy is a plain - * string copy of the expression value, and if it is to be used - * as a compiled expression, it will just need a recompile. - * - * This makes sense, because with Tcl's copy-on-write practices, - * the usual (only?) time Tcl_DuplicateObj() will be called is - * when the copy is about to be modified, which would invalidate - * any copied bytecode anyway. The only reason it might make sense - * to copy the bytecode is if we had some modifying routines that - * operated directly on the intrep, like we do for lists and dicts. + * bytecode. We do not copy the bytecode intrep. Instead, we return + * without setting copyPtr->typePtr, so the copy is a plain string copy + * of the expression value, and if it is to be used as a compiled + * expression, it will just need a recompile. + * + * This makes sense, because with Tcl's copy-on-write practices, the + * usual (only?) time Tcl_DuplicateObj() will be called is when the copy + * is about to be modified, which would invalidate any copied bytecode + * anyway. The only reason it might make sense to copy the bytecode is if + * we had some modifying routines that operated directly on the intrep, + * like we do for lists and dicts. * * Results: * None. @@ -1479,14 +1495,15 @@ DupExprCodeInternalRep( * FreeExprCodeInternalRep -- * * Part of the Tcl object type implementation for Tcl expression - * bytecode. Frees the storage allocated to hold the internal rep, - * unless ref counts indicate bytecode execution is still in progress. + * bytecode. Frees the storage allocated to hold the internal rep, unless + * ref counts indicate bytecode execution is still in progress. * * Results: * None. * * Side effects: - * May free allocated memory. Leaves objPtr untyped. + * May free allocated memory. Leaves objPtr untyped. + * *---------------------------------------------------------------------- */ @@ -1611,28 +1628,30 @@ TclCompileObj( */ { - Tcl_HashEntry *hePtr = Tcl_FindHashEntry(iPtr->lineBCPtr, - (char *) codePtr); + Tcl_HashEntry *hePtr = + Tcl_FindHashEntry(iPtr->lineBCPtr, (char *) codePtr); + if (hePtr) { ExtCmdLoc *eclPtr = Tcl_GetHashValue(hePtr); int redo = 0; if (invoker) { - CmdFrame *ctxPtr = (CmdFrame *) - TclStackAlloc(interp, sizeof(CmdFrame)); + CmdFrame *ctxPtr = TclStackAlloc(interp,sizeof(CmdFrame)); *ctxPtr = *invoker; if (invoker->type == TCL_LOCATION_BC) { /* * Note: Type BC => ctx.data.eval.path is not used. - * ctx.data.tebc.codePtr is used instead. + * ctx.data.tebc.codePtr used instead */ TclGetSrcInfoForPc(ctxPtr); if (ctxPtr->type == TCL_LOCATION_SOURCE) { /* - * The reference made by 'TclGetSrcInfoForPc' is dead. + * The reference made by 'TclGetSrcInfoForPc' is + * dead. */ + Tcl_DecrRefCount(ctxPtr->data.eval.path); ctxPtr->data.eval.path = NULL; } @@ -1649,12 +1668,11 @@ TclCompileObj( * test info-32.0 using literal of info-24.8 * (dict with ... vs set body ...). */ - redo = - ((eclPtr->type == TCL_LOCATION_SOURCE) && - (eclPtr->start != ctxPtr->line[word])) || - ((eclPtr->type == TCL_LOCATION_BC) && - (ctxPtr->type == TCL_LOCATION_SOURCE)) - ; + + redo = ((eclPtr->type == TCL_LOCATION_SOURCE) + && (eclPtr->start != ctxPtr->line[word])) + || ((eclPtr->type == TCL_LOCATION_BC) + && (ctxPtr->type == TCL_LOCATION_SOURCE)); } TclStackFree(interp, ctxPtr); @@ -1675,7 +1693,7 @@ TclCompileObj( return codePtr; } - recompileObj: + recompileObj: iPtr->errorLine = 1; /* @@ -1689,7 +1707,7 @@ TclCompileObj( iPtr->invokeWord = word; tclByteCodeType.setFromAnyProc(interp, objPtr); iPtr->invokeCmdFramePtr = NULL; - codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr; + codePtr = objPtr->internalRep.otherValuePtr; if (iPtr->varFramePtr->localCachePtr) { codePtr->localCachePtr = iPtr->varFramePtr->localCachePtr; codePtr->localCachePtr->refCount++; @@ -1873,7 +1891,7 @@ TclExecuteByteCode( struct auxTEBCdata { ExecStack *esPtr; Var *compiledLocals; - BottomData *bottomPtr; /* Bottom of stack holds NR data */ + BottomData *bottomPtr; /* Bottom of stack holds NR data */ BottomData *oldBottomPtr; Tcl_Obj **constants; int instructionCount; /* Counter that is used to work out when to @@ -1881,10 +1899,10 @@ TclExecuteByteCode( int checkInterp; /* Indicates when a check of interp readyness * is necessary. Set by CACHE_STACK_INFO() */ const char *curInstName; - int result; /* Return code returned after execution. + int result; /* Return code returned after execution. * Result variable - needed only when going to * checkForcatch or other error handlers; also - * used as local in some opcodes. */ + * used as local in some opcodes. */ } TAUX = { NULL, NULL, @@ -1897,28 +1915,28 @@ TclExecuteByteCode( TCL_OK }; -#define LOCAL(i) (&(TAUX.compiledLocals[(i)])) -#define TCONST(i) (TAUX.constants[(i)]) -#define BP (TAUX.bottomPtr) -#define OBP (TAUX.oldBottomPtr) -#define TRESULT (TAUX.result) - +#define LOCAL(i) (&(TAUX.compiledLocals[(i)])) +#define TCONST(i) (TAUX.constants[(i)]) +#define BP (TAUX.bottomPtr) +#define OBP (TAUX.oldBottomPtr) +#define TRESULT (TAUX.result) + /* * These macros are just meant to save some global variables that are not * used too frequently */ -#define bcFramePtr ((CmdFrame *) (BP + 1)) -#define initCatchTop (((ptrdiff_t *) (bcFramePtr + 1)) - 1) -#define initTosPtr ((Tcl_Obj **) (initCatchTop + codePtr->maxExceptDepth)) -#define auxObjList (BP->auxObjList) -#define catchTop (BP->catchTop) - + +#define bcFramePtr ((CmdFrame *) (BP + 1)) +#define initCatchTop (((ptrdiff_t *) (bcFramePtr + 1)) - 1) +#define initTosPtr ((Tcl_Obj **) (initCatchTop+codePtr->maxExceptDepth)) +#define auxObjList (BP->auxObjList) +#define catchTop (BP->catchTop) + /* * Globals: variables that store state, must remain valid at all times. */ - Tcl_Obj **tosPtr = NULL; - /* Cached pointer to top of evaluation + Tcl_Obj **tosPtr = NULL; /* Cached pointer to top of evaluation * stack. */ const unsigned char *pc = NULL; /* The current program counter. */ @@ -1953,10 +1971,10 @@ TclExecuteByteCode( */ if (!codePtr) { - resumeCoroutine: + resumeCoroutine: /* - * Reawakening a suspended coroutine: the [yield] command - * is returning. + * Reawakening a suspended coroutine: the [yield] command is + * returning. */ NRE_ASSERT(iPtr->execEnvPtr->corPtr->eePtr == iPtr->execEnvPtr); @@ -1972,7 +1990,7 @@ TclExecuteByteCode( goto returnToCaller; } - nonRecursiveCallStart: + nonRecursiveCallStart: codePtr->refCount++; BP = (BottomData *) GrowEvaluationStack(iPtr->execEnvPtr, sizeof(BottomData) + codePtr->maxExceptDepth + sizeof(CmdFrame) @@ -1993,11 +2011,11 @@ TclExecuteByteCode( pc = codePtr->codeStart; catchTop = initCatchTop; tosPtr = initTosPtr; - + /* * TIP #280: Initialize the frame. Do not push it yet. */ - + bcFramePtr->type = ((codePtr->flags & TCL_BYTECODE_PRECOMPILED) ? TCL_LOCATION_PREBC : TCL_LOCATION_BC); bcFramePtr->level = (iPtr->cmdFramePtr ? iPtr->cmdFramePtr->level+1 : 1); @@ -2011,7 +2029,7 @@ TclExecuteByteCode( bcFramePtr->data.tebc.pc = NULL; bcFramePtr->cmd.str.cmd = NULL; bcFramePtr->cmd.str.len = 0; - + if (iPtr->execEnvPtr->rewind) { TRESULT = TCL_ERROR; goto abnormalReturn; @@ -2318,12 +2336,12 @@ TclExecuteByteCode( cleanup = 0; if (TRESULT == TCL_ERROR) { /* - * Tcl_EvalEx already did the task of logging - * the error to the stack trace for us, so set - * a flag to prevent the TEBC exception handling - * machinery from trying to do it again. - * Tcl Bug 2037338. See test execute-8.4. + * Tcl_EvalEx already did the task of logging the error to + * the stack trace for us, so set a flag to prevent the + * TEBC exception handling machinery from trying to do it + * again. See test execute-8.4. [Bug 2037338] */ + iPtr->flags |= ERR_ALREADY_LOGGED; } goto processExceptionReturn; @@ -2363,6 +2381,7 @@ TclExecuteByteCode( b = tosPtr; while (a<b) { Tcl_Obj *temp = *a; + *a = *b; *b = temp; a++; b--; @@ -2759,8 +2778,8 @@ TclExecuteByteCode( TAUX.instructionCount = 1; - TclArgumentBCEnter((Tcl_Interp*) iPtr, objv, objc, - codePtr, bcFramePtr, pc - codePtr->codeStart); + TclArgumentBCEnter((Tcl_Interp *) iPtr, objv, objc, + codePtr, bcFramePtr, pc - codePtr->codeStart); DECACHE_STACK_INFO(); @@ -2783,81 +2802,86 @@ TclExecuteByteCode( TOP_CB(interp) = callbackPtr->nextPtr; TCLNR_FREE(interp, callbackPtr); - + NR_DATA_BURY(); switch (type) { - case TCL_NR_BC_TYPE: - /* - * A request to run a bytecode: record this - * level's state variables, swap codePtr and start - * running the new one. - */ + case TCL_NR_BC_TYPE: + /* + * A request to run a bytecode: record this level's + * state variables, swap codePtr and start running the + * new one. + */ - if (param) { - codePtr = param; - goto nonRecursiveCallStart; - } - /* NOT CALLED, does not (yet?) work */ - goto resumeCoroutine; - break; - case TCL_NR_TAILCALL_TYPE: { - /* - * A request to perform a tailcall: just drop this - * bytecode. */ + if (param) { + codePtr = param; + goto nonRecursiveCallStart; + } + /* NOT CALLED, does not (yet?) work */ + goto resumeCoroutine; + case TCL_NR_TAILCALL_TYPE: + /* + * A request to perform a tailcall: just drop this + * bytecode. + */ #ifdef TCL_COMPILE_DEBUG - if (traceInstructions) { - fprintf(stdout, " Tailcall request received\n"); - } -#endif - if (catchTop != initCatchTop) { - TEOV_callback *tailcallPtr = iPtr->varFramePtr->tailcallPtr; - - TclClearTailcall(interp, tailcallPtr); - iPtr->varFramePtr->tailcallPtr = NULL; - TRESULT = TCL_ERROR; - Tcl_SetResult(interp,"Tailcall called from within a catch environment", - TCL_STATIC); - pc--; - goto checkForCatch; - } - goto abnormalReturn; + if (traceInstructions) { + fprintf(stdout, " Tailcall request received\n"); } - case TCL_NR_YIELD_TYPE: { /*[yield] */ - CoroutineData *corPtr = iPtr->execEnvPtr->corPtr; - - if (!corPtr) { - Tcl_SetResult(interp, - "yield can only be called in a coroutine", - TCL_STATIC); - Tcl_SetErrorCode(interp, "COROUTINE_ILLEGAL_YIELD", NULL); - TRESULT = TCL_ERROR; - pc--; - goto checkForCatch; - } - NRE_ASSERT(iPtr->execEnvPtr == corPtr->eePtr); - NRE_ASSERT(corPtr->stackLevel != NULL); - NRE_ASSERT(BP == corPtr->eePtr->bottomPtr); - if (corPtr->stackLevel != &TAUX) { - Tcl_SetResult(interp, "cannot yield: C stack busy", - TCL_STATIC); - Tcl_SetErrorCode(interp, "COROUTINE_CANT_YIELD", NULL); - TRESULT = TCL_ERROR; - pc--; - goto checkForCatch; - } - - /* - * Save our state and return - */ - - NR_DATA_BURY(); - TAUX.esPtr->tosPtr = tosPtr; - iPtr->execEnvPtr->bottomPtr = BP; - return TCL_OK; +#endif /* TCL_COMPILE_DEBUG */ + if (catchTop != initCatchTop) { + TEOV_callback *tailcallPtr = + iPtr->varFramePtr->tailcallPtr; + + TclClearTailcall(interp, tailcallPtr); + iPtr->varFramePtr->tailcallPtr = NULL; + TRESULT = TCL_ERROR; + Tcl_SetResult(interp, + "Tailcall called from within a catch environment", + TCL_STATIC); + Tcl_SetErrorCode(interp, "TCL", "TAILCALL", + "ILLEGAL", NULL); + pc--; + goto checkForCatch; } - default: - Tcl_Panic("TEBC: TRCB sent us a callback we cannot handle!"); + goto abnormalReturn; + case TCL_NR_YIELD_TYPE: { /* [yield] */ + CoroutineData *corPtr = iPtr->execEnvPtr->corPtr; + + if (!corPtr) { + Tcl_SetResult(interp, + "yield can only be called in a coroutine", + TCL_STATIC); + Tcl_SetErrorCode(interp, "TCL", "COROUTINE", + "ILLEGAL_YIELD", NULL); + TRESULT = TCL_ERROR; + pc--; + goto checkForCatch; + } + NRE_ASSERT(iPtr->execEnvPtr == corPtr->eePtr); + NRE_ASSERT(corPtr->stackLevel != NULL); + NRE_ASSERT(BP == corPtr->eePtr->bottomPtr); + if (corPtr->stackLevel != &TAUX) { + Tcl_SetResult(interp, + "cannot yield: C stack busy", TCL_STATIC); + Tcl_SetErrorCode(interp, "TCL", "COROUTINE", + "CANT_YIELD", NULL); + TRESULT = TCL_ERROR; + pc--; + goto checkForCatch; + } + + /* + * Save our state and return + */ + + NR_DATA_BURY(); + TAUX.esPtr->tosPtr = tosPtr; + iPtr->execEnvPtr->bottomPtr = BP; + return TCL_OK; + } + default: + Tcl_Panic("TEBC: TRCB sent us a callback we cannot handle!"); } } } @@ -2868,12 +2892,12 @@ TclExecuteByteCode( NRE_ASSERT(iPtr->cmdFramePtr == bcFramePtr); iPtr->cmdFramePtr = bcFramePtr->nextPtr; - TclArgumentBCRelease((Tcl_Interp*) iPtr, bcFramePtr); + TclArgumentBCRelease((Tcl_Interp *) iPtr, bcFramePtr); /* * If the CallFrame is marked as tailcalling, keep tailcalling */ - + if (iPtr->varFramePtr->tailcallPtr) { if (catchTop != initCatchTop) { TclClearTailcall(interp, iPtr->varFramePtr->tailcallPtr); @@ -2886,12 +2910,12 @@ TclExecuteByteCode( } goto abnormalReturn; } - + if (iPtr->execEnvPtr->rewind) { TRESULT = TCL_ERROR; goto abnormalReturn; } - + if (TRESULT == TCL_OK) { Tcl_Obj *objPtr; #ifndef TCL_COMPILE_DEBUG @@ -3994,7 +4018,7 @@ TclExecuteByteCode( * going to take. */ case INST_JUMP_FALSE4: jmpOffset[0] = TclGetInt4AtPtr(pc+1); /* FALSE offset */ - jmpOffset[1] = 5; /* TRUE offset*/ + jmpOffset[1] = 5; /* TRUE offset */ goto doCondJump; case INST_JUMP_TRUE4: @@ -5469,7 +5493,8 @@ TclExecuteByteCode( * place to draw the line. */ - Tcl_SetResult(interp, "integer value too large to represent", TCL_STATIC); + Tcl_SetResult(interp, "integer value too large to represent", + TCL_STATIC); TRESULT = TCL_ERROR; goto checkForCatch; } @@ -6163,15 +6188,16 @@ TclExecuteByteCode( NEXT_INST_F(1, 2, 1); } } + /* - * We refuse to accept exponent arguments that exceed - * one mp_digit which means the max exponent value is - * 2**28-1 = 0x0fffffff = 268435455, which fits into - * a signed 32 bit int which is within the range of the - * long int type. This means any numeric Tcl_Obj value - * not using TCL_NUMBER_LONG type must hold a value larger + * We refuse to accept exponent arguments that exceed one mp_digit + * which means the max exponent value is 2**28-1 = 0x0fffffff = + * 268435455, which fits into a signed 32 bit int which is within + * the range of the long int type. This means any numeric Tcl_Obj + * value not using TCL_NUMBER_LONG type must hold a value larger * than we accept. */ + if (type2 != TCL_NUMBER_LONG) { Tcl_SetResult(interp, "exponent too large", TCL_STATIC); TRESULT = TCL_ERROR; @@ -6324,7 +6350,7 @@ TclExecuteByteCode( w1 = l1; #ifndef NO_WIDE_TYPE } else if (type1 == TCL_NUMBER_WIDE) { - w1 = *((const Tcl_WideInt*) ptr1); + w1 = *((const Tcl_WideInt *) ptr1); #endif } else { goto overflow; @@ -6409,7 +6435,6 @@ TclExecuteByteCode( wResult *= wResult; /* b**8 */ wResult *= wResult; /* b**16 */ break; - } TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr))); objResultPtr = Tcl_NewWideIntObj(wResult); @@ -6421,6 +6446,7 @@ TclExecuteByteCode( * Handle cases of powers > 16 that still fit in a 64-bit word by * doing table lookup. */ + if (w1 - 3 >= 0 && w1 - 2 < (long)Exp64IndexSize && l2 - 2 < (long)(Exp64ValueSize + MaxBase64Size)) { unsigned short base = Exp64Index[w1 - 3] @@ -7133,10 +7159,9 @@ TclExecuteByteCode( NEXT_INST_F(2*code -1, 1, 0); } -/* TODO: normalize "valPtr" to "valuePtr" */ { int opnd, opnd2, allocateDict; - Tcl_Obj *dictPtr, *valPtr; + Tcl_Obj *dictPtr, *valuePtr, *val2Ptr; Var *varPtr; case INST_DICT_GET: @@ -7210,25 +7235,24 @@ TclExecuteByteCode( case INST_DICT_INCR_IMM: cleanup = 1; opnd = TclGetInt4AtPtr(pc+1); - TRESULT = Tcl_DictObjGet(interp, dictPtr, OBJ_AT_TOS, &valPtr); + TRESULT = Tcl_DictObjGet(interp, dictPtr, OBJ_AT_TOS, &valuePtr); if (TRESULT != TCL_OK) { break; } - if (valPtr == NULL) { + if (valuePtr == NULL) { Tcl_DictObjPut(NULL, dictPtr, OBJ_AT_TOS,Tcl_NewIntObj(opnd)); } else { - Tcl_Obj *incrPtr = Tcl_NewIntObj(opnd); - - Tcl_IncrRefCount(incrPtr); - if (Tcl_IsShared(valPtr)) { - valPtr = Tcl_DuplicateObj(valPtr); - Tcl_DictObjPut(NULL, dictPtr, OBJ_AT_TOS, valPtr); + val2Ptr = Tcl_NewIntObj(opnd); + Tcl_IncrRefCount(val2Ptr); + if (Tcl_IsShared(valuePtr)) { + valuePtr = Tcl_DuplicateObj(valuePtr); + Tcl_DictObjPut(NULL, dictPtr, OBJ_AT_TOS, valuePtr); } - TRESULT = TclIncrObj(interp, valPtr, incrPtr); + TRESULT = TclIncrObj(interp, valuePtr, val2Ptr); if (TRESULT == TCL_OK) { Tcl_InvalidateStringRep(dictPtr); } - TclDecrRefCount(incrPtr); + TclDecrRefCount(val2Ptr); } break; case INST_DICT_UNSET: @@ -7252,11 +7276,10 @@ TclExecuteByteCode( if (TclIsVarDirectWritable(varPtr)) { if (allocateDict) { - Tcl_Obj *oldValuePtr = varPtr->value.objPtr; - + val2Ptr = varPtr->value.objPtr; Tcl_IncrRefCount(dictPtr); - if (oldValuePtr != NULL) { - TclDecrRefCount(oldValuePtr); + if (val2Ptr != NULL) { + TclDecrRefCount(val2Ptr); } varPtr->value.objPtr = dictPtr; } @@ -7309,7 +7332,7 @@ TclExecuteByteCode( } } - TRESULT = Tcl_DictObjGet(interp, dictPtr, OBJ_UNDER_TOS, &valPtr); + TRESULT = Tcl_DictObjGet(interp, dictPtr, OBJ_UNDER_TOS, &valuePtr); if (TRESULT != TCL_OK) { if (allocateDict) { TclDecrRefCount(dictPtr); @@ -7318,20 +7341,20 @@ TclExecuteByteCode( } /* - * Note that a non-existent key results in a NULL valPtr, which is a + * Note that a non-existent key results in a NULL valuePtr, which is a * case handled separately below. What we *can* say at this point is * that the write-back will always succeed. */ switch (*pc) { case INST_DICT_APPEND: - if (valPtr == NULL) { - valPtr = OBJ_AT_TOS; + if (valuePtr == NULL) { + valuePtr = OBJ_AT_TOS; } else { - if (Tcl_IsShared(valPtr)) { - valPtr = Tcl_DuplicateObj(valPtr); + if (Tcl_IsShared(valuePtr)) { + valuePtr = Tcl_DuplicateObj(valuePtr); } - Tcl_AppendObjToObj(valPtr, OBJ_AT_TOS); + Tcl_AppendObjToObj(valuePtr, OBJ_AT_TOS); } break; case INST_DICT_LAPPEND: @@ -7339,20 +7362,22 @@ TclExecuteByteCode( * More complex because list-append can fail. */ - if (valPtr == NULL) { - valPtr = Tcl_NewListObj(1, &OBJ_AT_TOS); - } else if (Tcl_IsShared(valPtr)) { - valPtr = Tcl_DuplicateObj(valPtr); - TRESULT = Tcl_ListObjAppendElement(interp, valPtr, OBJ_AT_TOS); + if (valuePtr == NULL) { + valuePtr = Tcl_NewListObj(1, &OBJ_AT_TOS); + } else if (Tcl_IsShared(valuePtr)) { + valuePtr = Tcl_DuplicateObj(valuePtr); + TRESULT = Tcl_ListObjAppendElement(interp, valuePtr, + OBJ_AT_TOS); if (TRESULT != TCL_OK) { - TclDecrRefCount(valPtr); + TclDecrRefCount(valuePtr); if (allocateDict) { TclDecrRefCount(dictPtr); } goto checkForCatch; } } else { - TRESULT = Tcl_ListObjAppendElement(interp, valPtr, OBJ_AT_TOS); + TRESULT = Tcl_ListObjAppendElement(interp, valuePtr, + OBJ_AT_TOS); if (TRESULT != TCL_OK) { if (allocateDict) { TclDecrRefCount(dictPtr); @@ -7365,15 +7390,14 @@ TclExecuteByteCode( Tcl_Panic("Should not happen!"); } - Tcl_DictObjPut(NULL, dictPtr, OBJ_UNDER_TOS, valPtr); + Tcl_DictObjPut(NULL, dictPtr, OBJ_UNDER_TOS, valuePtr); if (TclIsVarDirectWritable(varPtr)) { if (allocateDict) { - Tcl_Obj *oldValuePtr = varPtr->value.objPtr; - + val2Ptr = varPtr->value.objPtr; Tcl_IncrRefCount(dictPtr); - if (oldValuePtr != NULL) { - TclDecrRefCount(oldValuePtr); + if (val2Ptr != NULL) { + TclDecrRefCount(val2Ptr); } varPtr->value.objPtr = dictPtr; } @@ -7420,8 +7444,8 @@ TclExecuteByteCode( } TclNewObj(statePtr); statePtr->typePtr = &dictIteratorType; - statePtr->internalRep.twoPtrValue.ptr1 = (void *) searchPtr; - statePtr->internalRep.twoPtrValue.ptr2 = (void *) dictPtr; + statePtr->internalRep.twoPtrValue.ptr1 = searchPtr; + statePtr->internalRep.twoPtrValue.ptr2 = dictPtr; varPtr = LOCAL(opnd);// if (varPtr->value.objPtr) { if (varPtr->value.objPtr->typePtr != &dictIteratorType) { @@ -7441,7 +7465,7 @@ TclExecuteByteCode( if (statePtr == NULL || statePtr->typePtr != &dictIteratorType) { Tcl_Panic("mis-issued dictNext!"); } - searchPtr = (Tcl_DictSearch *) statePtr->internalRep.twoPtrValue.ptr1; + searchPtr = statePtr->internalRep.twoPtrValue.ptr1; Tcl_DictObjNext(searchPtr, &keyPtr, &valuePtr, &done); pushDictIteratorResult: if (done) { @@ -7472,12 +7496,11 @@ TclExecuteByteCode( * dictionary that we were holding. */ - searchPtr = (Tcl_DictSearch *) - statePtr->internalRep.twoPtrValue.ptr1; + searchPtr = statePtr->internalRep.twoPtrValue.ptr1; Tcl_DictObjDone(searchPtr); ckfree((char *) searchPtr); - dictPtr = (Tcl_Obj *) statePtr->internalRep.twoPtrValue.ptr2; + dictPtr = statePtr->internalRep.twoPtrValue.ptr2; TclDecrRefCount(dictPtr); /* @@ -7495,7 +7518,7 @@ TclExecuteByteCode( { int opnd, opnd2, i, length, allocdict; - Tcl_Obj **keyPtrPtr, *dictPtr; + Tcl_Obj **keyPtrPtr, *dictPtr, *valuePtr; DictUpdateInfo *duiPtr; Var *varPtr; @@ -7527,10 +7550,8 @@ TclExecuteByteCode( Tcl_Panic("dictUpdateStart argument length mismatch"); } for (i=0 ; i<length ; i++) { - Tcl_Obj *valPtr; - if (Tcl_DictObjGet(interp, dictPtr, keyPtrPtr[i], - &valPtr) != TCL_OK) { + &valuePtr) != TCL_OK) { goto dictUpdateStartFailed; } varPtr = LOCAL(duiPtr->varIndices[i]); @@ -7538,21 +7559,22 @@ TclExecuteByteCode( varPtr = varPtr->value.linkPtr; } DECACHE_STACK_INFO(); - if (valPtr == NULL) { + if (valuePtr == NULL) { TclObjUnsetVar2(interp, localName(iPtr->varFramePtr, duiPtr->varIndices[i]), NULL, 0); } else if (TclPtrSetVar(interp, varPtr, NULL, NULL, NULL, - valPtr, TCL_LEAVE_ERR_MSG, + valuePtr, TCL_LEAVE_ERR_MSG, duiPtr->varIndices[i]) == NULL) { CACHE_STACK_INFO(); - dictUpdateStartFailed: - TRESULT = TCL_ERROR; - goto checkForCatch; + goto dictUpdateStartFailed; } CACHE_STACK_INFO(); } NEXT_INST_F(9, 0, 0); + dictUpdateStartFailed: + TRESULT = TCL_ERROR; + goto checkForCatch; case INST_DICT_UPDATE_END: opnd = TclGetUInt4AtPtr(pc+1); @@ -7584,28 +7606,26 @@ TclExecuteByteCode( dictPtr = Tcl_DuplicateObj(dictPtr); } for (i=0 ; i<length ; i++) { - Tcl_Obj *valPtr; - Var *var2Ptr; + Var *var2Ptr = LOCAL(duiPtr->varIndices[i]); - var2Ptr = LOCAL(duiPtr->varIndices[i]); while (TclIsVarLink(var2Ptr)) { var2Ptr = var2Ptr->value.linkPtr; } if (TclIsVarDirectReadable(var2Ptr)) { - valPtr = var2Ptr->value.objPtr; + valuePtr = var2Ptr->value.objPtr; } else { DECACHE_STACK_INFO(); - valPtr = TclPtrGetVar(interp, var2Ptr, NULL, NULL, NULL, 0, + valuePtr = TclPtrGetVar(interp, var2Ptr, NULL, NULL, NULL, 0, duiPtr->varIndices[i]); CACHE_STACK_INFO(); } - if (valPtr == NULL) { + if (valuePtr == NULL) { Tcl_DictObjRemove(interp, dictPtr, keyPtrPtr[i]); - } else if (dictPtr == valPtr) { + } else if (dictPtr == valuePtr) { Tcl_DictObjPut(interp, dictPtr, keyPtrPtr[i], - Tcl_DuplicateObj(valPtr)); + Tcl_DuplicateObj(valuePtr)); } else { - Tcl_DictObjPut(interp, dictPtr, keyPtrPtr[i], valPtr); + Tcl_DictObjPut(interp, dictPtr, keyPtrPtr[i], valuePtr); } } if (TclIsVarDirectWritable(varPtr)) { @@ -7637,7 +7657,7 @@ TclExecuteByteCode( * "goto divideByZero". */ - divideByZero: + divideByZero: Tcl_SetResult(interp, "divide by zero", TCL_STATIC); Tcl_SetErrorCode(interp, "ARITH", "DIVZERO", "divide by zero", NULL); @@ -7649,8 +7669,9 @@ TclExecuteByteCode( * only reaches this point by "goto exponOfZero". */ - exponOfZero: - Tcl_SetResult(interp, "exponentiation of zero by negative power", TCL_STATIC); + exponOfZero: + Tcl_SetResult(interp, "exponentiation of zero by negative power", + TCL_STATIC); Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", "exponentiation of zero by negative power", NULL); TRESULT = TCL_ERROR; @@ -7742,10 +7763,12 @@ TclExecuteByteCode( } else if (traceInstructions) { if ((TRESULT != TCL_ERROR) && (TRESULT != TCL_RETURN)) { Tcl_Obj *objPtr = Tcl_GetObjResult(interp); + TRACE_APPEND(("OTHER RETURN CODE %d, result= \"%s\"\n ", TRESULT, O2S(objPtr))); } else { Tcl_Obj *objPtr = Tcl_GetObjResult(interp); + TRACE_APPEND(("%s, result= \"%s\"\n", StringForResultCode(TRESULT), O2S(objPtr))); } @@ -7780,9 +7803,8 @@ TclExecuteByteCode( */ while (auxObjList) { - if ((catchTop != initCatchTop) && - (*catchTop > - (ptrdiff_t) auxObjList->internalRep.twoPtrValue.ptr1)) { + if ((catchTop != initCatchTop) && (*catchTop > + (ptrdiff_t) auxObjList->internalRep.twoPtrValue.ptr1)) { break; } POP_TAUX_OBJ(); @@ -7790,12 +7812,13 @@ TclExecuteByteCode( /* * We must not catch if the script in progress has been canceled with - * the TCL_CANCEL_UNWIND flag. Instead, it blows outwards until we + * the TCL_CANCEL_UNWIND flag. Instead, it blows outwards until we * either hit another interpreter (presumably where the script in - * progress has not been canceled) or we get to the top-level. We - * do NOT modify the interpreter result here because we know it will + * progress has not been canceled) or we get to the top-level. We do + * NOT modify the interpreter result here because we know it will * already be set prior to vectoring down to this point in the code. */ + if (Tcl_Canceled(interp, 0) == TCL_ERROR) { #ifdef TCL_COMPILE_DEBUG if (traceInstructions) { @@ -7938,7 +7961,7 @@ TclExecuteByteCode( * with tailcalls. */ - BP = OBP; /* back to old bc */ + BP = OBP; /* back to old bc */ rerunCallbacks: TRESULT = TclNRRunCallbacks(interp, TRESULT, BP->rootPtr, 1); @@ -7950,7 +7973,7 @@ TclExecuteByteCode( * caller's arguments and keep processing the caller. */ - TAUX.esPtr = iPtr->execEnvPtr->execStackPtr; + TAUX.esPtr = iPtr->execEnvPtr->execStackPtr; TAUX.compiledLocals = iPtr->varFramePtr->compiledLocals; goto nonRecursiveCallReturn; @@ -7962,24 +7985,24 @@ TclExecuteByteCode( NRE_ASSERT(TRESULT == TCL_OK); switch (type) { - case TCL_NR_BC_TYPE: - /* - * One of the callbacks requested a new execution: a - * tailcall! Start the new bytecode. - */ + case TCL_NR_BC_TYPE: + /* + * One of the callbacks requested a new execution: a tailcall! + * Start the new bytecode. + */ - goto nonRecursiveCallSetup; - case TCL_NR_TAILCALL_TYPE: - TOP_CB(iPtr) = callbackPtr->nextPtr; - TCLNR_FREE(interp, callbackPtr); + goto nonRecursiveCallSetup; + case TCL_NR_TAILCALL_TYPE: + TOP_CB(iPtr) = callbackPtr->nextPtr; + TCLNR_FREE(interp, callbackPtr); - Tcl_SetResult(interp, - "atProcExit/tailcall cannot be invoked recursively", - TCL_STATIC); - TRESULT = TCL_ERROR; - goto rerunCallbacks; - default: - Tcl_Panic("TEBC: TRCB sent us a callback we cannot handle!"); + Tcl_SetResult(interp, + "atProcExit/tailcall cannot be invoked recursively", + TCL_STATIC); + TRESULT = TCL_ERROR; + goto rerunCallbacks; + default: + Tcl_Panic("TEBC: TRCB sent us a callback we cannot handle!"); } } } |