diff options
author | Miguel Sofer <miguel.sofer@gmail.com> | 2007-04-06 22:36:48 (GMT) |
---|---|---|
committer | Miguel Sofer <miguel.sofer@gmail.com> | 2007-04-06 22:36:48 (GMT) |
commit | b3bd6ba72b8c833450ca433b5f10621536e7c416 (patch) | |
tree | 230c09968dc212479fb18a5423c9b28606613195 /generic/tclExecute.c | |
parent | 6b34f09a96be35707ad778f648e8e77df1d8c17f (diff) | |
download | tcl-b3bd6ba72b8c833450ca433b5f10621536e7c416.zip tcl-b3bd6ba72b8c833450ca433b5f10621536e7c416.tar.gz tcl-b3bd6ba72b8c833450ca433b5f10621536e7c416.tar.bz2 |
* generic/tclExecute.c (TEBC):
* generic/tclNamespace.c (NsEnsembleImplementationCmd):
* generic/tclProc.c (InitCompiledLocals, ObjInterpProcEx,
TclObjInterpProcCore, ProcCompileProc): code reordering to reduce
branching and improve branch prediction (assume that forward
branches are typically not taken).
Diffstat (limited to 'generic/tclExecute.c')
-rw-r--r-- | generic/tclExecute.c | 599 |
1 files changed, 308 insertions, 291 deletions
diff --git a/generic/tclExecute.c b/generic/tclExecute.c index a652e9f..5ad6717 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -12,7 +12,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.269 2007/04/03 22:55:48 msofer Exp $ + * RCS: @(#) $Id: tclExecute.c,v 1.270 2007/04/06 22:36:49 msofer Exp $ */ #include "tclInt.h" @@ -938,27 +938,7 @@ TclCompEvalObj( * compilation). Otherwise, check that it is "fresh" enough. */ - if (objPtr->typePtr != &tclByteCodeType) { - recompileObj: - iPtr->errorLine = 1; - - /* - * TIP #280. Remember the invoker for a moment in the interpreter - * structures so that the byte code compiler can pick it up when - * initializing the compilation environment, i.e. the extended - * location information. - */ - - iPtr->invokeCmdFramePtr = invoker; - iPtr->invokeWord = word; - result = tclByteCodeType.setFromAnyProc(interp, objPtr); - iPtr->invokeCmdFramePtr = NULL; - if (result != TCL_OK) { - iPtr->numLevels--; - return result; - } - codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr; - } else { + if (objPtr->typePtr == &tclByteCodeType) { /* * Make sure the Bytecode hasn't been invalidated by, e.g., someone * redefining a command with a compile procedure (this might make the @@ -998,22 +978,46 @@ TclCompEvalObj( goto recompileObj; } } - } + /* + * Increment the code's ref count while it is being executed. If + * afterwards no references to it remain, free the code. + */ + + runCompiledObj: + codePtr->refCount++; + result = TclExecuteByteCode(interp, codePtr); + codePtr->refCount--; + if (codePtr->refCount <= 0) { + TclCleanupByteCode(codePtr); + } + iPtr->numLevels--; + return result; + } + + recompileObj: + iPtr->errorLine = 1; + /* - * Increment the code's ref count while it is being executed. If - * afterwards no references to it remain, free the code. + * TIP #280. Remember the invoker for a moment in the interpreter + * structures so that the byte code compiler can pick it up when + * initializing the compilation environment, i.e. the extended + * location information. */ - - codePtr->refCount++; - result = TclExecuteByteCode(interp, codePtr); - codePtr->refCount--; - if (codePtr->refCount <= 0) { - TclCleanupByteCode(codePtr); + + iPtr->invokeCmdFramePtr = invoker; + iPtr->invokeWord = word; + result = tclByteCodeType.setFromAnyProc(interp, objPtr); + iPtr->invokeCmdFramePtr = NULL; + if (result == TCL_OK) { + codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr; + goto runCompiledObj; + } else { + iPtr->numLevels--; + return result; } - iPtr->numLevels--; - return result; } + /* *---------------------------------------------------------------------- @@ -1356,9 +1360,14 @@ TclExecuteByteCode( */ 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(); @@ -1369,7 +1378,7 @@ TclExecuteByteCode( } if (Tcl_LimitReady(interp)) { int localResult; - + DECACHE_STACK_INFO(); localResult = Tcl_LimitCheck(interp); CACHE_STACK_INFO(); @@ -1404,38 +1413,40 @@ TclExecuteByteCode( TRACE(("=> ")); objResultPtr = POP_OBJECT(); result = Tcl_SetReturnOptions(interp, POP_OBJECT()); - if (result != TCL_OK) { + if (result == TCL_OK) { + TRACE_APPEND(("continuing to next instruction (result=\"%.30s\")", + O2S(objResultPtr))); + NEXT_INST_F(1, 0, -1); + } else { Tcl_SetObjResult(interp, objResultPtr); Tcl_DecrRefCount(objResultPtr); cleanup = 0; goto processExceptionReturn; } - TRACE_APPEND(("continuing to next instruction (result=\"%.30s\")", - O2S(objResultPtr))); - NEXT_INST_F(1, 0, -1); case INST_DONE: - if (tosPtr <= eePtr->stackPtr + initStackTop) { + if (tosPtr > eePtr->stackPtr + initStackTop) { + /* + * Set the interpreter's object result to point to the topmost object + * from the stack, and check for a possible [catch]. The stackTop's + * level and refCount will be handled by "processCatch" or + * "abnormalReturn". + */ + + Tcl_SetObjResult(interp, *tosPtr); +#ifdef TCL_COMPILE_DEBUG + TRACE_WITH_OBJ(("=> return code=%d, result=", result), + iPtr->objResultPtr); + if (traceInstructions) { + fprintf(stdout, "\n"); + } +#endif + goto checkForCatch; + } else { tosPtr--; goto abnormalReturn; } - /* - * Set the interpreter's object result to point to the topmost object - * from the stack, and check for a possible [catch]. The stackTop's - * level and refCount will be handled by "processCatch" or - * "abnormalReturn". - */ - - Tcl_SetObjResult(interp, *tosPtr); -#ifdef TCL_COMPILE_DEBUG - TRACE_WITH_OBJ(("=> return code=%d, result=", result), - iPtr->objResultPtr); - if (traceInstructions) { - fprintf(stdout, "\n"); - } -#endif - goto checkForCatch; case INST_PUSH1: #if !TCL_COMPILE_DEBUG @@ -1498,7 +1509,7 @@ TclExecuteByteCode( (((codePtr->compileEpoch == iPtr->compileEpoch) && (codePtr->nsEpoch == namespacePtr->resolverEpoch)) || (codePtr->flags & TCL_BYTECODE_PRECOMPILED))) { -#if !TCL_COMPILE_DEBUG +#if 0 && !TCL_COMPILE_DEBUG /* * Peephole optimisations: check if there are several * INST_START_CMD in a row. Many commands start by pushing a @@ -1713,7 +1724,10 @@ TclExecuteByteCode( TclDecrRefCount(objPtr); } - if (objc == 0) { + if (objc) { + pcAdjustment = 1; + goto doInvocation; + } else { /* * Nothing was expanded, return {}. */ @@ -1722,9 +1736,6 @@ TclExecuteByteCode( NEXT_INST_F(1, 0, 1); } - pcAdjustment = 1; - goto doInvocation; - case INST_INVOKE_STK4: objc = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; @@ -1769,38 +1780,6 @@ TclExecuteByteCode( #endif /*TCL_COMPILE_DEBUG*/ /* - * If trace procedures will be called, we need a command string to - * pass to TclEvalObjvInternal; note that a copy of the string - * will be made there to include the ending \0. - */ - - bytes = NULL; - length = 0; - if (iPtr->tracePtr != NULL) { - Trace *tracePtr, *nextTracePtr; - - for (tracePtr = iPtr->tracePtr; tracePtr != NULL; - tracePtr = nextTracePtr) { - nextTracePtr = tracePtr->nextPtr; - if (tracePtr->level == 0 || - iPtr->numLevels <= tracePtr->level) { - /* - * Traces will be called: get command string - */ - - bytes = GetSrcInfoForPc(pc, codePtr, &length); - break; - } - } - } - if (!bytes) { - cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[0]); - if (!cmdPtr || (cmdPtr->flags & CMD_HAS_EXEC_TRACES)) { - bytes = GetSrcInfoForPc(pc, codePtr, &length); - } - } - - /* * A reference to part of the stack vector itself escapes our * control: increase its refCount to stop it from being * deallocated by a recursive call to ourselves. The extra @@ -1818,6 +1797,7 @@ TclExecuteByteCode( instructionCount = 1; + /* * Finally, let TclEvalObjvInternal handle the command. * @@ -1828,14 +1808,15 @@ TclExecuteByteCode( bcFrame.data.tebc.pc = (char *) pc; iPtr->cmdFramePtr = &bcFrame; DECACHE_STACK_INFO(); - /*Tcl_ResetResult(interp);*/ - if (bytes || (checkInterp && (codePtr->compileEpoch != iPtr->compileEpoch))) { - result = TclEvalObjvInternal(interp, objc, objv, bytes, length, 0); - } else { + cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[0]); + + if (cmdPtr && !(cmdPtr->flags & CMD_HAS_EXEC_TRACES) + && iPtr->tracePtr == NULL + && (!checkInterp || (codePtr->compileEpoch == iPtr->compileEpoch))) { /* * No traces, the interp is ok: avoid the call out to TEOVi */ - + cmdPtr->refCount++; iPtr->cmdCount++; iPtr->ensembleRewrite.sourceObjs = NULL; @@ -1847,7 +1828,41 @@ TclExecuteByteCode( if (result == TCL_OK && Tcl_LimitReady(interp)) { result = Tcl_LimitCheck(interp); } + + } else { + + /* + * If trace procedures will be called, we need a command string to + * pass to TclEvalObjvInternal; note that a copy of the string + * will be made there to include the ending \0. + */ + + if (!cmdPtr || (cmdPtr->flags & CMD_HAS_EXEC_TRACES)) { + bytes = GetSrcInfoForPc(pc, codePtr, &length); + } else { + Trace *tracePtr, *nextTracePtr; + + bytes = NULL; + length = 0; + + for (tracePtr = iPtr->tracePtr; tracePtr != NULL; + tracePtr = nextTracePtr) { + nextTracePtr = tracePtr->nextPtr; + if (tracePtr->level == 0 || + iPtr->numLevels <= tracePtr->level) { + /* + * Traces will be called: get command string + */ + + bytes = GetSrcInfoForPc(pc, codePtr, &length); + break; + } + } + } + + result = TclEvalObjvInternal(interp, objc, objv, bytes, length, 0); } + CACHE_STACK_INFO(); iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr; @@ -1956,14 +1971,15 @@ TclExecuteByteCode( /*Tcl_ResetResult(interp);*/ result = Tcl_ExprObj(interp, objPtr, &valuePtr); CACHE_STACK_INFO(); - if (result != TCL_OK) { + if (result == TCL_OK) { + objResultPtr = valuePtr; + TRACE_WITH_OBJ(("\"%.30s\" => ", O2S(objPtr)), valuePtr); + NEXT_INST_F(1, 1, -1); /* already has right refct */ + } else { TRACE_WITH_OBJ(("\"%.30s\" => ERROR: ", O2S(objPtr)), Tcl_GetObjResult(interp)); goto checkForCatch; } - objResultPtr = valuePtr; - TRACE_WITH_OBJ(("\"%.30s\" => ", O2S(objPtr)), valuePtr); - NEXT_INST_F(1, 1, -1); /* already has right refct */ } /* @@ -2044,22 +2060,23 @@ TclExecuteByteCode( part1 = TclGetString(objPtr); varPtr = TclObjLookupVar(interp, objPtr, part2, TCL_LEAVE_ERR_MSG, "read", /*createPart1*/ 0, /*createPart2*/ 1, &arrayPtr); - if (varPtr == NULL) { + if (varPtr) { + if (TclIsVarDirectReadable(varPtr) + && ((arrayPtr == NULL) || TclIsVarUntraced(arrayPtr))) { + /* + * No errors, no traces: just get the value. + */ + objResultPtr = varPtr->value.objPtr; + TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); + NEXT_INST_V(1, cleanup, 1); + } + pcAdjustment = 1; + goto doCallPtrGetVar; + } else { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); result = TCL_ERROR; goto checkForCatch; } - if (TclIsVarDirectReadable(varPtr) - && ((arrayPtr == NULL) || TclIsVarUntraced(arrayPtr))) { - /* - * No errors, no traces: just get the value. - */ - objResultPtr = varPtr->value.objPtr; - TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); - NEXT_INST_V(1, cleanup, 1); - } - pcAdjustment = 1; - goto doCallPtrGetVar; case INST_LOAD_ARRAY4: opnd = TclGetUInt4AtPtr(pc+1); @@ -2082,15 +2099,13 @@ TclExecuteByteCode( && TclIsVarArray(arrayPtr) && TclIsVarUntraced(arrayPtr)) { Tcl_HashEntry *hPtr = Tcl_FindHashEntry(arrayPtr->value.tablePtr, part2); - if (hPtr == NULL) { - varPtr = NULL; - } else { + if (hPtr) { varPtr = (Var *) Tcl_GetHashValue(hPtr); + } else { + goto doLoadArrayNextBranch; } } else { - varPtr = NULL; - } - if (varPtr == NULL) { + doLoadArrayNextBranch: varPtr = TclLookupArrayElement(interp, part1, part2, TCL_LEAVE_ERR_MSG, "read", 0, 1, arrayPtr); if (varPtr == NULL) { @@ -2122,13 +2137,14 @@ TclExecuteByteCode( objResultPtr = TclPtrGetVar(interp, varPtr, arrayPtr, part1, part2, TCL_LEAVE_ERR_MSG); CACHE_STACK_INFO(); - if (objResultPtr == NULL) { + if (objResultPtr) { + TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); + NEXT_INST_V(pcAdjustment, cleanup, 1); + } else { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); result = TCL_ERROR; goto checkForCatch; } - TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); - NEXT_INST_V(pcAdjustment, cleanup, 1); } /* @@ -2202,14 +2218,15 @@ TclExecuteByteCode( #endif varPtr = TclObjLookupVar(interp, objPtr, part2, TCL_LEAVE_ERR_MSG, "set", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr); - if (varPtr == NULL) { + if (varPtr) { + cleanup = ((part2 == NULL)? 2 : 3); + pcAdjustment = 1; + goto doCallPtrSetVar; + } else { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); result = TCL_ERROR; goto checkForCatch; } - cleanup = ((part2 == NULL)? 2 : 3); - pcAdjustment = 1; - goto doCallPtrSetVar; case INST_LAPPEND_ARRAY4: opnd = TclGetUInt4AtPtr(pc+1); @@ -2253,6 +2270,7 @@ TclExecuteByteCode( part2 = TclGetString(*(tosPtr - 1)); arrayPtr = &(compiledLocals[opnd]); part1 = arrayPtr->name; + cleanup = 2; TRACE(("%u \"%.30s\" <- \"%.30s\" => ", opnd, part2, O2S(valuePtr))); while (TclIsVarLink(arrayPtr)) { arrayPtr = arrayPtr->value.linkPtr; @@ -2261,25 +2279,20 @@ TclExecuteByteCode( && TclIsVarArray(arrayPtr) && TclIsVarUntraced(arrayPtr)) { Tcl_HashEntry *hPtr = Tcl_FindHashEntry(arrayPtr->value.tablePtr, part2); - if (hPtr == NULL) { - varPtr = NULL; - } else { + if (hPtr) { varPtr = (Var *) Tcl_GetHashValue(hPtr); + goto doCallPtrSetVar; } - } else { - varPtr = NULL; } - if (varPtr == NULL) { - varPtr = TclLookupArrayElement(interp, part1, part2, - TCL_LEAVE_ERR_MSG, "set", 1, 1, arrayPtr); - if (varPtr == NULL) { - TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); - result = TCL_ERROR; - goto checkForCatch; - } + varPtr = TclLookupArrayElement(interp, part1, part2, + TCL_LEAVE_ERR_MSG, "set", 1, 1, arrayPtr); + if (varPtr) { + goto doCallPtrSetVar; + } else { + TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); + result = TCL_ERROR; + goto checkForCatch; } - cleanup = 2; - goto doCallPtrSetVar; case INST_LAPPEND_SCALAR4: opnd = TclGetUInt4AtPtr(pc+1); @@ -2365,19 +2378,20 @@ TclExecuteByteCode( objResultPtr = TclPtrSetVar(interp, varPtr, arrayPtr, part1, part2, valuePtr, storeFlags); CACHE_STACK_INFO(); - if (objResultPtr == NULL) { + if (objResultPtr) { +#ifndef TCL_COMPILE_DEBUG + if (*(pc+pcAdjustment) == INST_POP) { + NEXT_INST_V((pcAdjustment+1), cleanup, 0); + } +#endif + TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); + NEXT_INST_V(pcAdjustment, cleanup, 1); + } else { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); result = TCL_ERROR; goto checkForCatch; } } -#ifndef TCL_COMPILE_DEBUG - if (*(pc+pcAdjustment) == INST_POP) { - NEXT_INST_V((pcAdjustment+1), cleanup, 0); - } -#endif - TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); - NEXT_INST_V(pcAdjustment, cleanup, 1); } /* @@ -2450,7 +2464,10 @@ TclExecuteByteCode( varPtr = TclObjLookupVar(interp, objPtr, part2, TCL_LEAVE_ERR_MSG, "read", 1, 1, &arrayPtr); - if (varPtr == NULL) { + if (varPtr) { + cleanup = ((part2 == NULL)? 1 : 2); + goto doIncrVar; + } else { Tcl_AddObjErrorInfo(interp, "\n (reading value of variable to increment)", -1); TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); @@ -2458,8 +2475,6 @@ TclExecuteByteCode( Tcl_DecrRefCount(incrPtr); goto checkForCatch; } - cleanup = ((part2 == NULL)? 1 : 2); - goto doIncrVar; case INST_INCR_ARRAY1_IMM: opnd = TclGetUInt1AtPtr(pc+1); @@ -2472,20 +2487,21 @@ TclExecuteByteCode( part2 = TclGetString(*tosPtr); arrayPtr = &(compiledLocals[opnd]); part1 = arrayPtr->name; + cleanup = 1; while (TclIsVarLink(arrayPtr)) { arrayPtr = arrayPtr->value.linkPtr; } TRACE(("%u \"%.30s\" (by %ld) => ", opnd, part2, i)); varPtr = TclLookupArrayElement(interp, part1, part2, TCL_LEAVE_ERR_MSG, "read", 1, 1, arrayPtr); - if (varPtr == NULL) { + if (varPtr) { + goto doIncrVar; + } else { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); result = TCL_ERROR; Tcl_DecrRefCount(incrPtr); goto checkForCatch; } - cleanup = 1; - goto doIncrVar; case INST_INCR_SCALAR1_IMM: opnd = TclGetUInt1AtPtr(pc+1); @@ -2597,12 +2613,13 @@ TclExecuteByteCode( TclNewLongObj(incrPtr, i); result = TclIncrObj(interp, objResultPtr, incrPtr); Tcl_DecrRefCount(incrPtr); - if (result != TCL_OK) { + if (result == TCL_OK) { + goto doneIncr; + } else { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto checkForCatch; } - goto doneIncr; } /* @@ -2637,7 +2654,9 @@ TclExecuteByteCode( } result = TclIncrObj(interp, objResultPtr, incrPtr); Tcl_DecrRefCount(incrPtr); - if (result != TCL_OK) { + if (result == TCL_OK) { + goto doneIncr; + } else { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto checkForCatch; } @@ -2678,30 +2697,26 @@ TclExecuteByteCode( CallFrame *framePtr, *savedFramePtr; result = TclObjGetFrame(interp, *(tosPtr-1), &framePtr); - if (result == -1) { - result = TCL_ERROR; - goto checkForCatch; - } else { - result = TCL_OK; - } - - /* - * Locate the other variable - */ - - savedFramePtr = iPtr->varFramePtr; - iPtr->varFramePtr = framePtr; - otherPtr = TclObjLookupVar(interp, *tosPtr, NULL, - (TCL_LEAVE_ERR_MSG), "access", - /*createPart1*/ 1, /*createPart2*/ 1, &varPtr); - iPtr->varFramePtr = savedFramePtr; - if (otherPtr == NULL) { - result = TCL_ERROR; - goto checkForCatch; + if (result != -1) { + /* + * Locate the other variable + */ + + savedFramePtr = iPtr->varFramePtr; + iPtr->varFramePtr = framePtr; + otherPtr = TclObjLookupVar(interp, *tosPtr, NULL, + (TCL_LEAVE_ERR_MSG), "access", + /*createPart1*/ 1, /*createPart2*/ 1, &varPtr); + iPtr->varFramePtr = savedFramePtr; + if (otherPtr) { + result = TCL_OK; + goto doLinkVars; + } } + result = TCL_ERROR; + goto checkForCatch; } - goto doLinkVars; - + case INST_VARIABLE: case INST_NSUPVAR: TRACE_WITH_OBJ(("nsupvar "), *(tosPtr-1)); @@ -2710,43 +2725,43 @@ TclExecuteByteCode( Tcl_Namespace *nsPtr, *savedNsPtr; result = TclGetNamespaceFromObj(interp, *(tosPtr-1), &nsPtr); - if (result != TCL_OK) { - goto checkForCatch; - } - if (nsPtr == NULL) { + if ((result == TCL_OK) && nsPtr) { /* - * The namespace does not exist, leave an error message. + * Locate the other variable */ - Tcl_SetObjResult(interp, Tcl_Format(NULL, - "namespace \"%s\" does not exist", 1, - (tosPtr-1))); - result = TCL_ERROR; - goto checkForCatch; - } - - /* - * Locate the other variable - */ - - savedNsPtr = (Tcl_Namespace *) iPtr->varFramePtr->nsPtr; - iPtr->varFramePtr->nsPtr = (Namespace *) nsPtr; - otherPtr = TclObjLookupVar(interp, *tosPtr, NULL, - (TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG), "access", - /*createPart1*/ 1, /*createPart2*/ 1, &varPtr); - iPtr->varFramePtr->nsPtr = (Namespace *) savedNsPtr; - if (otherPtr == NULL) { - result = TCL_ERROR; + + savedNsPtr = (Tcl_Namespace *) iPtr->varFramePtr->nsPtr; + iPtr->varFramePtr->nsPtr = (Namespace *) nsPtr; + otherPtr = TclObjLookupVar(interp, *tosPtr, NULL, + (TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG), "access", + /*createPart1*/ 1, /*createPart2*/ 1, &varPtr); + iPtr->varFramePtr->nsPtr = (Namespace *) savedNsPtr; + if (otherPtr) { + /* + * Do the [variable] magic if necessary + */ + + if ((*pc == INST_VARIABLE) && !TclIsVarNamespaceVar(otherPtr)) { + TclSetVarNamespaceVar(otherPtr); + otherPtr->refCount++; + } + } else { + result = TCL_ERROR; + goto checkForCatch; + } + } else { + if (nsPtr == NULL) { + /* + * The namespace does not exist, leave an error message. + */ + Tcl_SetObjResult(interp, Tcl_Format(NULL, + "namespace \"%s\" does not exist", 1, + (tosPtr-1))); + result = TCL_ERROR; + } goto checkForCatch; } - - /* - * Do the [variable] magic if necessary - */ - if ((*pc == INST_VARIABLE) && !TclIsVarNamespaceVar(otherPtr)) { - TclSetVarNamespaceVar(otherPtr); - otherPtr->refCount++; - } } doLinkVars: @@ -2963,14 +2978,15 @@ TclExecuteByteCode( valuePtr = *tosPtr; result = Tcl_ListObjLength(interp, valuePtr, &length); - if (result != TCL_OK) { + if (result == TCL_OK) { + TclNewIntObj(objResultPtr, length); + TRACE(("%.20s => %d\n", O2S(valuePtr), length)); + NEXT_INST_F(1, 1, 1); + } else { TRACE_WITH_OBJ(("%.30s => ERROR: ", O2S(valuePtr)), Tcl_GetObjResult(interp)); goto checkForCatch; } - TclNewIntObj(objResultPtr, length); - TRACE(("%.20s => %d\n", O2S(valuePtr), length)); - NEXT_INST_F(1, 1, 1); } case INST_LIST_INDEX: { @@ -2990,20 +3006,20 @@ TclExecuteByteCode( */ objResultPtr = TclLindexList(interp, valuePtr, value2Ptr); - if (objResultPtr == NULL) { + if (objResultPtr) { + /* + * Stash the list element on the stack + */ + + TRACE(("%.20s %.20s => %s\n", + O2S(valuePtr), O2S(value2Ptr), O2S(objResultPtr))); + NEXT_INST_F(1, 2, -1); /* already has the correct refCount */ + } else { TRACE_WITH_OBJ(("%.30s %.30s => ERROR: ", O2S(valuePtr), O2S(value2Ptr)), Tcl_GetObjResult(interp)); result = TCL_ERROR; goto checkForCatch; } - - /* - * Stash the list element on the stack - */ - - TRACE(("%.20s %.20s => %s\n", - O2S(valuePtr), O2S(value2Ptr), O2S(objResultPtr))); - NEXT_INST_F(1, 2, -1); /* already has the correct refCount */ } case INST_LIST_INDEX_IMM: { @@ -3026,31 +3042,31 @@ TclExecuteByteCode( */ result = Tcl_ListObjGetElements(interp, valuePtr, &listc, &listv); - if (result != TCL_OK) { + if (result == TCL_OK) { + /* + * Select the list item based on the index. Negative operand means + * end-based indexing. + */ + + if (opnd < -1) { + idx = opnd+1 + listc; + } else { + idx = opnd; + } + if (idx >= 0 && idx < listc) { + objResultPtr = listv[idx]; + } else { + TclNewObj(objResultPtr); + } + + TRACE_WITH_OBJ(("\"%.30s\" %d => ", O2S(valuePtr), opnd), + objResultPtr); + NEXT_INST_F(5, 1, 1); + } else { TRACE_WITH_OBJ(("\"%.30s\" %d => ERROR: ", O2S(valuePtr), opnd), Tcl_GetObjResult(interp)); goto checkForCatch; } - - /* - * Select the list item based on the index. Negative operand means - * end-based indexing. - */ - - if (opnd < -1) { - idx = opnd+1 + listc; - } else { - idx = opnd; - } - if (idx >= 0 && idx < listc) { - objResultPtr = listv[idx]; - } else { - TclNewObj(objResultPtr); - } - - TRACE_WITH_OBJ(("\"%.30s\" %d => ", O2S(valuePtr), opnd), - objResultPtr); - NEXT_INST_F(5, 1, 1); } case INST_LIST_INDEX_MULTI: { @@ -3076,17 +3092,17 @@ TclExecuteByteCode( * Check for errors */ - if (objResultPtr == NULL) { + if (objResultPtr) { + /* + * Set result + */ + TRACE(("%d => %s\n", opnd, O2S(objResultPtr))); + NEXT_INST_V(5, opnd, -1); + } else { TRACE_WITH_OBJ(("%d => ERROR: ", opnd), Tcl_GetObjResult(interp)); result = TCL_ERROR; goto checkForCatch; } - - /* - * Set result - */ - TRACE(("%d => %s\n", opnd, O2S(objResultPtr))); - NEXT_INST_V(5, opnd, -1); } case INST_LSET_FLAT: { @@ -3126,18 +3142,18 @@ TclExecuteByteCode( * Check for errors */ - if (objResultPtr == NULL) { + if (objResultPtr) { + /* + * Set result + */ + + TRACE(("%d => %s\n", opnd, O2S(objResultPtr))); + NEXT_INST_V(5, (numIdx+1), -1); + } else { TRACE_WITH_OBJ(("%d => ERROR: ", opnd), Tcl_GetObjResult(interp)); result = TCL_ERROR; goto checkForCatch; } - - /* - * Set result - */ - - TRACE(("%d => %s\n", opnd, O2S(objResultPtr))); - NEXT_INST_V(5, (numIdx+1), -1); } case INST_LSET_LIST: { @@ -3173,19 +3189,19 @@ TclExecuteByteCode( * Check for errors */ - if (objResultPtr == NULL) { + if (objResultPtr) { + /* + * Set result + */ + + TRACE(("=> %s\n", O2S(objResultPtr))); + NEXT_INST_F(1, 2, -1); + } else { TRACE_WITH_OBJ(("\"%.30s\" => ERROR: ", O2S(value2Ptr)), Tcl_GetObjResult(interp)); result = TCL_ERROR; goto checkForCatch; } - - /* - * Set result - */ - - TRACE(("=> %s\n", O2S(objResultPtr))); - NEXT_INST_F(1, 2, -1); } case INST_LIST_RANGE_IMM: { @@ -3208,22 +3224,23 @@ TclExecuteByteCode( */ result = Tcl_ListObjGetElements(interp, valuePtr, &listc, &listv); - if (result != TCL_OK) { - TRACE_WITH_OBJ(("\"%.30s\" %d %d => ERROR: ", O2S(valuePtr), - fromIdx, toIdx), Tcl_GetObjResult(interp)); - goto checkForCatch; - } /* * Skip a lot of work if we're about to throw the result away (common * with uses of [lassign].) */ + if (result == TCL_OK) { #ifndef TCL_COMPILE_DEBUG - if (*(pc+9) == INST_POP) { - NEXT_INST_F(10, 1, 0); - } + if (*(pc+9) == INST_POP) { + NEXT_INST_F(10, 1, 0); + } #endif + } else { + TRACE_WITH_OBJ(("\"%.30s\" %d %d => ERROR: ", O2S(valuePtr), + fromIdx, toIdx), Tcl_GetObjResult(interp)); + goto checkForCatch; + } /* * Adjust the indices for end-based handling. @@ -5673,15 +5690,16 @@ TclExecuteByteCode( listVarPtr = &(compiledLocals[listTmpIndex]); listPtr = listVarPtr->value.objPtr; result = Tcl_ListObjLength(interp, listPtr, &listLen); - if (result != TCL_OK) { + if (result == TCL_OK) { + if (listLen > (iterNum * numVars)) { + continueLoop = 1; + } + listTmpIndex++; + } else { TRACE_WITH_OBJ(("%u => ERROR converting list %ld, \"%s\": ", opnd, i, O2S(listPtr)), Tcl_GetObjResult(interp)); goto checkForCatch; } - if (listLen > (iterNum * numVars)) { - continueLoop = 1; - } - listTmpIndex++; } /* @@ -5836,24 +5854,23 @@ TclExecuteByteCode( } } result = Tcl_DictObjGet(interp, dictPtr, *tosPtr, &objResultPtr); + if ((result == TCL_OK) && objResultPtr) { + TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); + NEXT_INST_V(5, opnd+1, 1); + } if (result != TCL_OK) { TRACE_WITH_OBJ(( "%u => ERROR reading leaf dictionary key \"%s\": ", opnd, O2S(dictPtr)), Tcl_GetObjResult(interp)); - cleanup = opnd + 1; - goto checkForCatch; - } - if (objResultPtr == NULL) { + } else { /*Tcl_ResetResult(interp);*/ Tcl_AppendResult(interp, "key \"", TclGetString(*tosPtr), "\" not known in dictionary", NULL); TRACE_WITH_OBJ(("%u => ERROR ", opnd), Tcl_GetObjResult(interp)); result = TCL_ERROR; - cleanup = opnd + 1; - goto checkForCatch; } - TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); - NEXT_INST_V(5, opnd+1, 1); + cleanup = opnd + 1; + goto checkForCatch; case INST_DICT_SET: case INST_DICT_UNSET: |