diff options
-rw-r--r-- | generic/tclAssembly.c | 4 | ||||
-rw-r--r-- | generic/tclCompCmds.c | 54 | ||||
-rw-r--r-- | generic/tclCompCmdsSZ.c | 34 | ||||
-rw-r--r-- | generic/tclCompExpr.c | 1 | ||||
-rw-r--r-- | generic/tclCompile.c | 3 | ||||
-rw-r--r-- | generic/tclCompile.h | 74 | ||||
-rw-r--r-- | generic/tclEnsemble.c | 3 | ||||
-rw-r--r-- | generic/tclExecute.c | 54 |
8 files changed, 188 insertions, 39 deletions
diff --git a/generic/tclAssembly.c b/generic/tclAssembly.c index 62641e6..617fbbe 100644 --- a/generic/tclAssembly.c +++ b/generic/tclAssembly.c @@ -1345,7 +1345,7 @@ AssembleOneLine( || CheckStrictlyPositive(interp, opnd) != TCL_OK) { goto cleanup; } - BBEmitInstInt4(assemEnvPtr, tblIdx, opnd, opnd+1); + BBEmitInstInt4(assemEnvPtr, tblIdx, opnd+1, opnd+1); break; case ASSEM_DICT_SET: @@ -1361,7 +1361,7 @@ AssembleOneLine( if (localVar < 0) { goto cleanup; } - BBEmitInstInt4(assemEnvPtr, tblIdx, opnd, opnd+1); + BBEmitInstInt4(assemEnvPtr, tblIdx, opnd+1, opnd+1); TclEmitInt4(localVar, envPtr); break; diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c index 10a789e..aea359c 100644 --- a/generic/tclCompCmds.c +++ b/generic/tclCompCmds.c @@ -302,9 +302,17 @@ TclCompileArraySetCmd( } else { TclEmitOpcode( INST_DUP, envPtr); TclEmitOpcode( INST_ARRAY_EXISTS_STK, envPtr); - TclEmitInstInt1(INST_JUMP_TRUE1, 5, envPtr); + TclEmitInstInt1(INST_JUMP_TRUE1, 5 +#ifdef TCL_COMPILE_DEBUG ++10 +#endif +, envPtr); TclEmitOpcode( INST_ARRAY_MAKE_STK, envPtr); - TclEmitInstInt1(INST_JUMP1, 3, envPtr); + TclEmitInstInt1(INST_JUMP1, 3 +#ifdef TCL_COMPILE_DEBUG ++10 +#endif +, envPtr); /* Each branch decrements stack depth, but we only take one. */ TclAdjustStackDepth(1, envPtr); TclEmitOpcode( INST_POP, envPtr); @@ -382,7 +390,11 @@ TclCompileArraySetCmd( } else { TclEmitOpcode( INST_DUP, envPtr); TclEmitOpcode( INST_ARRAY_EXISTS_STK, envPtr); - TclEmitInstInt1(INST_JUMP_TRUE1, 4, envPtr); + TclEmitInstInt1(INST_JUMP_TRUE1, 4 +#ifdef TCL_COMPILE_DEBUG ++15 +#endif +, envPtr); TclEmitOpcode( INST_DUP, envPtr); TclEmitOpcode( INST_ARRAY_MAKE_STK, envPtr); TclEmitInstInt4(INST_FOREACH_START4, infoIndex, envPtr); @@ -442,9 +454,17 @@ TclCompileArrayUnsetCmd( } else { TclEmitOpcode( INST_DUP, envPtr); TclEmitOpcode( INST_ARRAY_EXISTS_STK, envPtr); - TclEmitInstInt1(INST_JUMP_FALSE1, 6, envPtr); + TclEmitInstInt1(INST_JUMP_FALSE1, 6 +#ifdef TCL_COMPILE_DEBUG ++10 +#endif +, envPtr); TclEmitInstInt1(INST_UNSET_STK, 1, envPtr); - TclEmitInstInt1(INST_JUMP1, 3, envPtr); + TclEmitInstInt1(INST_JUMP1, 3 +#ifdef TCL_COMPILE_DEBUG ++10 +#endif +, envPtr); /* Each branch decrements stack depth, but we only take one. */ TclAdjustStackDepth(1, envPtr); TclEmitOpcode( INST_POP, envPtr); @@ -660,7 +680,11 @@ TclCompileCatchCmd( TclEmitOpcode( INST_POP, envPtr); PushStringLiteral(envPtr, "0"); - TclEmitInstInt1( INST_JUMP1, 3, envPtr); + TclEmitInstInt1( INST_JUMP1, 3 +#ifdef TCL_COMPILE_DEBUG ++5 +#endif +, envPtr); envPtr->currStackDepth = savedStackDepth; ExceptionRangeTarget(envPtr, range, catchOffset); TclEmitOpcode( INST_PUSH_RETURN_CODE, envPtr); @@ -920,9 +944,8 @@ TclCompileDictSetCmd( * Now emit the instruction to do the dict manipulation. */ - TclEmitInstInt4( INST_DICT_SET, numWords-2, envPtr); + TclEmitInstInt4( INST_DICT_SET, numWords-1, envPtr); TclEmitInt4( dictVarIndex, envPtr); - TclAdjustStackDepth(-1, envPtr); return TCL_OK; } @@ -1039,8 +1062,7 @@ TclCompileDictGetCmd( CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } - TclEmitInstInt4(INST_DICT_GET, numWords-1, envPtr); - TclAdjustStackDepth(-1, envPtr); + TclEmitInstInt4(INST_DICT_GET, numWords, envPtr); return TCL_OK; } @@ -1076,8 +1098,7 @@ TclCompileDictExistsCmd( CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } - TclEmitInstInt4(INST_DICT_EXISTS, numWords-1, envPtr); - TclAdjustStackDepth(-1, envPtr); + TclEmitInstInt4(INST_DICT_EXISTS, numWords, envPtr); return TCL_OK; } @@ -1224,9 +1245,8 @@ TclCompileDictCreateCmd( tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, i+1); tokenPtr = TokenAfter(tokenPtr); - TclEmitInstInt4( INST_DICT_SET, 1, envPtr); + TclEmitInstInt4( INST_DICT_SET, 2, envPtr); TclEmitInt4( worker, envPtr); - TclAdjustStackDepth(-1, envPtr); TclEmitOpcode( INST_POP, envPtr); } Emit14Inst( INST_LOAD_SCALAR, worker, envPtr); @@ -1306,9 +1326,8 @@ TclCompileDictMergeCmd( TclEmitInstInt4( INST_DICT_FIRST, infoIndex, envPtr); TclEmitInstInt1( INST_JUMP_TRUE1, 24, envPtr); TclEmitInstInt4( INST_REVERSE, 2, envPtr); - TclEmitInstInt4( INST_DICT_SET, 1, envPtr); + TclEmitInstInt4( INST_DICT_SET, 2, envPtr); TclEmitInt4( workerIndex, envPtr); - TclAdjustStackDepth(-1, envPtr); TclEmitOpcode( INST_POP, envPtr); TclEmitInstInt4( INST_DICT_NEXT, infoIndex, envPtr); TclEmitInstInt1( INST_JUMP_FALSE1, -20, envPtr); @@ -1535,9 +1554,8 @@ CompileDictEachCmd( if (collect == TCL_EACH_COLLECT) { Emit14Inst( INST_LOAD_SCALAR, keyVarIndex, envPtr); TclEmitInstInt4(INST_OVER, 1, envPtr); - TclEmitInstInt4(INST_DICT_SET, 1, envPtr); + TclEmitInstInt4(INST_DICT_SET, 2, envPtr); TclEmitInt4( collectVar, envPtr); - TclAdjustStackDepth(-1, envPtr); TclEmitOpcode( INST_POP, envPtr); } TclEmitOpcode( INST_POP, envPtr); diff --git a/generic/tclCompCmdsSZ.c b/generic/tclCompCmdsSZ.c index 7831198..2ce472b 100644 --- a/generic/tclCompCmdsSZ.c +++ b/generic/tclCompCmdsSZ.c @@ -2309,7 +2309,12 @@ IssueTryInstructions( ExceptionRangeEnds(envPtr, range); PUSH( "0"); OP4( REVERSE, 2); - OP1( JUMP1, 4); + OP1( JUMP1, 4 +#ifdef TCL_COMPILE_DEBUG ++10 +#endif +); + TclAdjustStackDepth(-2, envPtr); ExceptionRangeTarget(envPtr, range, catchOffset); OP( PUSH_RETURN_CODE); OP( PUSH_RESULT); @@ -2346,8 +2351,7 @@ IssueTryInstructions( LOAD( optionsVar); PUSH( "-errorcode"); - OP4( DICT_GET, 1); - TclAdjustStackDepth(-1, envPtr); + OP4( DICT_GET, 2); OP44( LIST_RANGE_IMM, 0, len-1); p = Tcl_GetStringFromObj(matchClauses[i], &len); PushLiteral(envPtr, p, len); @@ -2463,7 +2467,13 @@ IssueTryFinallyInstructions( ExceptionRangeEnds(envPtr, range); PUSH( "0"); OP4( REVERSE, 2); - OP1( JUMP1, 4); + OP1( JUMP1, 4 +#ifdef TCL_COMPILE_DEBUG ++10 +#endif +); +// TclAdjustStackDepth(-2, envPtr); + envPtr->currStackDepth = savedStackDepth; ExceptionRangeTarget(envPtr, range, catchOffset); OP( PUSH_RETURN_CODE); OP( PUSH_RESULT); @@ -2473,7 +2483,7 @@ IssueTryFinallyInstructions( OP( POP); STORE( resultVar); OP( POP); - envPtr->currStackDepth = savedStackDepth + 1; +// envPtr->currStackDepth = savedStackDepth + 1; /* * Now we handle all the registered 'on' and 'trap' handlers in order. @@ -2503,8 +2513,7 @@ IssueTryFinallyInstructions( LOAD( optionsVar); PUSH( "-errorcode"); - OP4( DICT_GET, 1); - TclAdjustStackDepth(-1, envPtr); + OP4( DICT_GET, 2); OP44( LIST_RANGE_IMM, 0, len-1); p = Tcl_GetStringFromObj(matchClauses[i], &len); PushLiteral(envPtr, p, len); @@ -2578,12 +2587,17 @@ IssueTryFinallyInstructions( } OP4( BEGIN_CATCH4, range); } - envPtr->currStackDepth = savedStackDepth; +// envPtr->currStackDepth = savedStackDepth + 1; BODY( handlerTokens[i], 5+i*4); ExceptionRangeEnds(envPtr, range); OP( PUSH_RETURN_OPTIONS); OP4( REVERSE, 2); - OP1( JUMP1, 4); + OP1( JUMP1, 4 +#ifdef TCL_COMPILE_DEBUG ++10 +#endif +); + envPtr->currStackDepth = savedStackDepth + 1; forwardsToFix[i] = -1; /* @@ -2629,6 +2643,7 @@ IssueTryFinallyInstructions( * Drop the result code. */ + envPtr->currStackDepth = savedStackDepth + 1; OP( POP); /* @@ -2639,7 +2654,6 @@ IssueTryFinallyInstructions( * next command (or some inter-command manipulation). */ - envPtr->currStackDepth = savedStackDepth; BODY( finallyToken, 3 + 4*numHandlers); OP( POP); LOAD( optionsVar); diff --git a/generic/tclCompExpr.c b/generic/tclCompExpr.c index 3597abe..efdc2b0 100644 --- a/generic/tclCompExpr.c +++ b/generic/tclCompExpr.c @@ -2401,6 +2401,7 @@ CompileExprTree( (nodePtr->lexeme == AND) ? "1" : "0", 1), envPtr); TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpPtr->next->next->jump); + TclAdjustStackDepth(-1, envPtr); TclFixupForwardJumpToHere(envPtr, &jumpPtr->next->jump, 127); if (TclFixupForwardJumpToHere(envPtr, &jumpPtr->jump, 127)) { jumpPtr->next->next->jump.codeOffset += 3; diff --git a/generic/tclCompile.c b/generic/tclCompile.c index 69517bc..950647c 100644 --- a/generic/tclCompile.c +++ b/generic/tclCompile.c @@ -539,6 +539,9 @@ InstructionDesc const tclInstructionTable[] = { /* Concatenates the two lists at the top of the stack into a single * list and pushes that resulting list onto the stack. * Stack: ... list1 list2 => ... [lconcat list1 list2] */ + {"verify", 5, 0, 1, {OPERAND_UINT4}}, + /* Verify the predicted stack depth (operand) is true during + * bytecode execution. */ {"expandDrop", 1, 0, 0, {OPERAND_NONE}}, /* Drops an element from the auxiliary stack, popping stack elements diff --git a/generic/tclCompile.h b/generic/tclCompile.h index 15b5477..ebd57f1 100644 --- a/generic/tclCompile.h +++ b/generic/tclCompile.h @@ -779,8 +779,10 @@ typedef struct ByteCode { #define INST_EXPAND_DROP 165 +#define INST_VERIFY 166 + /* The last opcode */ -#define LAST_INST_OPCODE 165 +#define LAST_INST_OPCODE 166 /* * Table describing the Tcl bytecode instructions: their name (for displaying @@ -1147,6 +1149,27 @@ MODULE_SCOPE Tcl_Obj *TclNewInstNameObj(unsigned char inst); * void TclAdjustStackDepth(int delta, CompileEnv *envPtr); */ +#if defined(TCL_COMPILE_DEBUG) +#define VerifyStackDepth(envPtr) \ + do { \ + int i = (envPtr)->currStackDepth; \ + if (((envPtr)->codeNext + 5) > (envPtr)->codeEnd) { \ + TclExpandCodeArray(envPtr); \ + } \ + *(envPtr)->codeNext++ = (unsigned char) INST_VERIFY; \ + *(envPtr)->codeNext++ = \ + (unsigned char) ((unsigned int) (i) >> 24); \ + *(envPtr)->codeNext++ = \ + (unsigned char) ((unsigned int) (i) >> 16); \ + *(envPtr)->codeNext++ = \ + (unsigned char) ((unsigned int) (i) >> 8); \ + *(envPtr)->codeNext++ = \ + (unsigned char) ((unsigned int) (i) ); \ + } while (0) +#else +#define VerifyStackDepth(envPtr) +#endif + #define TclAdjustStackDepth(delta, envPtr) \ do { \ if ((delta) < 0) { \ @@ -1155,6 +1178,7 @@ MODULE_SCOPE Tcl_Obj *TclNewInstNameObj(unsigned char inst); } \ } \ (envPtr)->currStackDepth += (delta); \ + VerifyStackDepth(envPtr); \ } while (0) /* @@ -1215,14 +1239,61 @@ MODULE_SCOPE Tcl_Obj *TclNewInstNameObj(unsigned char inst); * void TclEmitInt4(int i, CompileEnv *envPtr); */ + +#if defined(TCL_COMPILE_DEBUG) #define TclEmitInt1(i, envPtr) \ do { \ if ((envPtr)->codeNext == (envPtr)->codeEnd) { \ TclExpandCodeArray(envPtr); \ } \ + if ((envPtr)->codeNext[-5] == INST_VERIFY) { \ + memmove((envPtr)->codeNext-4, (envPtr)->codeNext-5, 5); \ + (envPtr)->codeNext[-5] = \ + (unsigned char) ((unsigned int) (i)); \ + (envPtr)->codeNext++; \ + break; \ + } \ *(envPtr)->codeNext++ = (unsigned char) ((unsigned int) (i)); \ } while (0) +#else +#define TclEmitInt1(i, envPtr) \ + do { \ + if ((envPtr)->codeNext == (envPtr)->codeEnd) { \ + TclExpandCodeArray(envPtr); \ + } \ + *(envPtr)->codeNext++ = (unsigned char) ((unsigned int) (i)); \ + } while (0) +#endif +#if defined(TCL_COMPILE_DEBUG) +#define TclEmitInt4(i, envPtr) \ + do { \ + if (((envPtr)->codeNext + 4) > (envPtr)->codeEnd) { \ + TclExpandCodeArray(envPtr); \ + } \ + if ((envPtr)->codeNext[-5] == INST_VERIFY) { \ + memmove((envPtr)->codeNext-1, (envPtr)->codeNext-5, 5); \ + (envPtr)->codeNext[-5] = \ + (unsigned char) ((unsigned int) (i) >> 24); \ + (envPtr)->codeNext[-4] = \ + (unsigned char) ((unsigned int) (i) >> 16); \ + (envPtr)->codeNext[-3] = \ + (unsigned char) ((unsigned int) (i) >> 8); \ + (envPtr)->codeNext[-2] = \ + (unsigned char) ((unsigned int) (i) ); \ + (envPtr)->codeNext += 4; \ + break; \ + } \ + *(envPtr)->codeNext++ = \ + (unsigned char) ((unsigned int) (i) >> 24); \ + *(envPtr)->codeNext++ = \ + (unsigned char) ((unsigned int) (i) >> 16); \ + *(envPtr)->codeNext++ = \ + (unsigned char) ((unsigned int) (i) >> 8); \ + *(envPtr)->codeNext++ = \ + (unsigned char) ((unsigned int) (i) ); \ + } while (0) +#else #define TclEmitInt4(i, envPtr) \ do { \ if (((envPtr)->codeNext + 4) > (envPtr)->codeEnd) { \ @@ -1237,6 +1308,7 @@ MODULE_SCOPE Tcl_Obj *TclNewInstNameObj(unsigned char inst); *(envPtr)->codeNext++ = \ (unsigned char) ((unsigned int) (i) ); \ } while (0) +#endif /* * Macros to emit an instruction with signed or unsigned integer operands. diff --git a/generic/tclEnsemble.c b/generic/tclEnsemble.c index 813e056..24e0f8b 100644 --- a/generic/tclEnsemble.c +++ b/generic/tclEnsemble.c @@ -3198,9 +3198,8 @@ CompileToInvokedCommand( * Do the replacing dispatch. */ - TclEmitInstInt4(INST_INVOKE_REPLACE, parsePtr->numWords, envPtr); + TclEmitInstInt4(INST_INVOKE_REPLACE, parsePtr->numWords+1, envPtr); TclEmitInt1(numWords+1, envPtr); - TclAdjustStackDepth(-1, envPtr); /* Correction to stack depth calcs. */ } /* diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 443fb85..df88bf9 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -202,6 +202,9 @@ typedef struct TEBCdata { #define PUSH_TAUX_OBJ(objPtr) \ do { \ + if (auxObjList) { \ + objPtr->length += auxObjList->length; \ + } \ objPtr->internalRep.ptrAndLongRep.ptr = auxObjList; \ auxObjList = objPtr; \ } while (0) @@ -2320,7 +2323,7 @@ TEBCresume( goto instLoadScalar1; } else if (inst == INST_PUSH1) { PUSH_OBJECT(codePtr->objArrayPtr[TclGetUInt1AtPtr(pc+1)]); - TRACE_WITH_OBJ(("%u => ", TclGetInt1AtPtr(pc+1)), OBJ_AT_TOS); + TRACE_WITH_OBJ(("%u => ", TclGetUInt1AtPtr(pc+1)), OBJ_AT_TOS); inst = *(pc += 2); goto peepholeStart; } else if (inst == INST_START_CMD) { @@ -2715,9 +2718,26 @@ TEBCresume( TclNewObj(objPtr); objPtr->internalRep.ptrAndLongRep.value = CURR_DEPTH; + objPtr->length = 0; PUSH_TAUX_OBJ(objPtr); NEXT_INST_F(1, 0, 0); + case INST_VERIFY : { +#ifdef TCL_COMPILE_DEBUG + /* + * This is how deep the compiler thought the stack would be, + * assuming no expansion. + */ + int estimate = TclGetUInt4AtPtr(pc+1); + + if (CURR_DEPTH != estimate + (auxObjList ? auxObjList->length : 0)) { + Tcl_Panic("Bad stack estimate = %d; truth = %ld", estimate, + CURR_DEPTH - (auxObjList ? auxObjList->length : 0)); + } +#endif + NEXT_INST_F(5, 0, 0); + } + case INST_EXPAND_DROP: /* * Drops an element of the auxObjList, popping stack elements to @@ -2738,6 +2758,18 @@ TEBCresume( int i; ptrdiff_t moved; +#ifdef TCL_COMPILE_DEBUG + /* + * This is how deep the compiler thought the stack would be, + * assuming no expansion. + */ + int estimate = TclGetInt4AtPtr(pc+1); + + if (CURR_DEPTH != estimate + auxObjList->length) { + Tcl_Panic("Bad stack estimate = %d; truth = %ld", estimate, + CURR_DEPTH - auxObjList->length); + } +#endif /* * Make sure that the element at stackTop is a list; if not, just * leave with an error. Note that the element from the expand list @@ -2759,7 +2791,11 @@ TEBCresume( * stack depth, as seen by the compiler. */ - length = objc + (codePtr->maxStackDepth - TclGetInt4AtPtr(pc+1)); + auxObjList->length += objc - 1; + if ((objc > 1) && (auxObjList->length > 0)) { + length = auxObjList->length /* Total expansion room we need */ + + codePtr->maxStackDepth /* Beyond the original max */ + - CURR_DEPTH; /* Relative to where we are */ DECACHE_STACK_INFO(); moved = GrowEvaluationStack(iPtr->execEnvPtr, length, 1) - (Tcl_Obj **) TD; @@ -2776,6 +2812,7 @@ TEBCresume( catchTop += moved; tosPtr += moved; } + } /* * Expand the list at stacktop onto the stack; free the list. Knowing @@ -2975,7 +3012,7 @@ TEBCresume( #endif case INST_INVOKE_REPLACE: - objc = TclGetUInt4AtPtr(pc+1); + objc = TclGetUInt4AtPtr(pc+1) - 1; opnd = TclGetUInt1AtPtr(pc+5); objPtr = POP_OBJECT(); objv = &OBJ_AT_DEPTH(objc-1); @@ -4227,7 +4264,7 @@ TEBCresume( } else { TRACE(("%d => %.20s false, new pc %u\n", jmpOffset[0], O2S(valuePtr), - (unsigned)(pc + jmpOffset[1] - codePtr->codeStart))); + (unsigned)(pc + jmpOffset[0] - codePtr->codeStart))); } } #endif @@ -6150,6 +6187,11 @@ TEBCresume( */ pc += 5; +#ifdef TCL_COMPILE_DEBUG + if (*pc == INST_VERIFY) { + pc +=5; + } +#endif if (*pc == INST_JUMP_FALSE1) { NEXT_INST_F((continueLoop? 2 : TclGetInt1AtPtr(pc+1)), 0, 0); } else { @@ -6246,7 +6288,7 @@ TEBCresume( case INST_DICT_EXISTS: { register Tcl_Interp *interp2 = interp; - opnd = TclGetUInt4AtPtr(pc+1); + opnd = TclGetUInt4AtPtr(pc+1) - 1; TRACE(("%u => ", opnd)); dictPtr = OBJ_AT_DEPTH(opnd); if (*pc == INST_DICT_EXISTS) { @@ -6302,7 +6344,7 @@ TEBCresume( case INST_DICT_SET: case INST_DICT_UNSET: case INST_DICT_INCR_IMM: - opnd = TclGetUInt4AtPtr(pc+1); + opnd = TclGetUInt4AtPtr(pc+1) - (*pc == INST_DICT_SET); opnd2 = TclGetUInt4AtPtr(pc+5); varPtr = LOCAL(opnd2); |