diff options
author | Miguel Sofer <miguel.sofer@gmail.com> | 2001-12-10 15:44:34 (GMT) |
---|---|---|
committer | Miguel Sofer <miguel.sofer@gmail.com> | 2001-12-10 15:44:34 (GMT) |
commit | 22f99d42b260461aacb728ca3326315bd4eb2041 (patch) | |
tree | 3537073577782a6683cee13a0a237de6e91a0e33 /generic/tclCompCmds.c | |
parent | 2cbac63a7dc061dc68347e297b82609c9802bb95 (diff) | |
download | tcl-22f99d42b260461aacb728ca3326315bd4eb2041.zip tcl-22f99d42b260461aacb728ca3326315bd4eb2041.tar.gz tcl-22f99d42b260461aacb728ca3326315bd4eb2041.tar.bz2 |
fixed the calculation of the maximal stack depth required by bytecodes [Bug 483611].
Diffstat (limited to 'generic/tclCompCmds.c')
-rw-r--r-- | generic/tclCompCmds.c | 287 |
1 files changed, 53 insertions, 234 deletions
diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c index 14a82f4..c94aeff 100644 --- a/generic/tclCompCmds.c +++ b/generic/tclCompCmds.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclCompCmds.c,v 1.16 2001/11/19 12:25:08 msofer Exp $ + * RCS: @(#) $Id: tclCompCmds.c,v 1.17 2001/12/10 15:44:34 msofer Exp $ */ #include "tclInt.h" @@ -24,8 +24,7 @@ static ClientData DupForeachInfo _ANSI_ARGS_((ClientData clientData)); static void FreeForeachInfo _ANSI_ARGS_((ClientData clientData)); static int TclPushVarName _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Token *varTokenPtr, CompileEnv *envPtr, int flags, - int *localIndexPtr, int *maxDepthPtr, int *simpleVarNamePtr, - int *isScalarPtr)); + int *localIndexPtr, int *simpleVarNamePtr, int *isScalarPtr)); /* * Flags bits used by TclPushVarName. @@ -60,9 +59,6 @@ AuxDataType tclForeachInfoType = { * command should be compiled "out of line" by emitting code to * invoke its command procedure (Tcl_AppendObjCmd) at runtime. * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the incr command. - * * Side effects: * Instructions are added to envPtr to execute the "append" command * at runtime. @@ -79,10 +75,8 @@ TclCompileAppendCmd(interp, parsePtr, envPtr) { Tcl_Token *varTokenPtr, *valueTokenPtr; int simpleVarName, isScalar, localIndex, numWords; - int maxDepth = 0; int code = TCL_OK; - envPtr->maxStackDepth = 0; numWords = parsePtr->numWords; if (numWords == 1) { Tcl_ResetResult(interp); @@ -115,7 +109,7 @@ TclCompileAppendCmd(interp, parsePtr, envPtr) code = TclPushVarName(interp, varTokenPtr, envPtr, ((numWords > 2) ? TCL_CREATE_VAR : 0), - &localIndex, &maxDepth, &simpleVarName, &isScalar); + &localIndex, &simpleVarName, &isScalar); if (code != TCL_OK) { goto done; } @@ -131,14 +125,12 @@ TclCompileAppendCmd(interp, parsePtr, envPtr) if (valueTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { TclEmitPush(TclRegisterLiteral(envPtr, valueTokenPtr[1].start, valueTokenPtr[1].size, /*onHeap*/ 0), envPtr); - maxDepth += 1; } else { code = TclCompileTokens(interp, valueTokenPtr+1, valueTokenPtr->numComponents, envPtr); if (code != TCL_OK) { goto done; } - maxDepth += envPtr->maxStackDepth; } } @@ -173,7 +165,6 @@ TclCompileAppendCmd(interp, parsePtr, envPtr) } done: - envPtr->maxStackDepth = maxDepth; return code; } @@ -189,9 +180,6 @@ TclCompileAppendCmd(interp, parsePtr, envPtr) * there was an error during compilation. If an error occurs then * the interpreter's result contains a standard error message. * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the command. - * * Side effects: * Instructions are added to envPtr to execute the "break" command * at runtime. @@ -210,7 +198,6 @@ TclCompileBreakCmd(interp, parsePtr, envPtr) Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "wrong # args: should be \"break\"", -1); - envPtr->maxStackDepth = 0; return TCL_ERROR; } @@ -219,7 +206,6 @@ TclCompileBreakCmd(interp, parsePtr, envPtr) */ TclEmitOpcode(INST_BREAK, envPtr); - envPtr->maxStackDepth = 0; return TCL_OK; } @@ -239,9 +225,6 @@ TclCompileBreakCmd(interp, parsePtr, envPtr) * should be compiled "out of line" by emitting code to invoke its * command procedure at runtime. * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the command. - * * Side effects: * Instructions are added to envPtr to execute the "catch" command * at runtime. @@ -259,11 +242,11 @@ TclCompileCatchCmd(interp, parsePtr, envPtr) JumpFixup jumpFixup; Tcl_Token *cmdTokenPtr, *nameTokenPtr; char *name; - int localIndex, nameChars, range, maxDepth, startOffset, jumpDist; + int localIndex, nameChars, range, startOffset, jumpDist; int code; char buffer[32 + TCL_INTEGER_SPACE]; + int savedStackDepth = envPtr->currStackDepth; - envPtr->maxStackDepth = 0; if ((parsePtr->numWords != 2) && (parsePtr->numWords != 3)) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), @@ -309,8 +292,6 @@ TclCompileCatchCmd(interp, parsePtr, envPtr) * We will compile the catch command. Emit a beginCatch instruction at * the start of the catch body: the subcommand it controls. */ - - maxDepth = 0; envPtr->exceptDepth++; envPtr->maxExceptDepth = @@ -347,7 +328,6 @@ TclCompileCatchCmd(interp, parsePtr, envPtr) } goto done; } - maxDepth = envPtr->maxStackDepth; envPtr->exceptArrayPtr[range].numCodeBytes = (envPtr->codeNext - envPtr->codeStart) - startOffset; @@ -367,9 +347,6 @@ TclCompileCatchCmd(interp, parsePtr, envPtr) TclEmitOpcode(INST_POP, envPtr); TclEmitPush(TclRegisterLiteral(envPtr, "0", 1, /*onHeap*/ 0), envPtr); - if (maxDepth == 0) { - maxDepth = 1; - } TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup); /* @@ -378,6 +355,7 @@ TclCompileCatchCmd(interp, parsePtr, envPtr) * the catch's error target. */ + envPtr->currStackDepth = savedStackDepth; envPtr->exceptArrayPtr[range].catchOffset = (envPtr->codeNext - envPtr->codeStart); if (localIndex != -1) { @@ -391,6 +369,7 @@ TclCompileCatchCmd(interp, parsePtr, envPtr) } TclEmitOpcode(INST_PUSH_RETURN_CODE, envPtr); + /* * Update the target of the jump after the "no errors" code, then emit * an endCatch instruction at the end of the catch command. @@ -404,8 +383,8 @@ TclCompileCatchCmd(interp, parsePtr, envPtr) TclEmitOpcode(INST_END_CATCH, envPtr); done: + envPtr->currStackDepth = savedStackDepth + 1; envPtr->exceptDepth--; - envPtr->maxStackDepth = maxDepth; return code; } @@ -421,9 +400,6 @@ TclCompileCatchCmd(interp, parsePtr, envPtr) * there was an error while parsing string. If an error occurs then * the interpreter's result contains a standard error message. * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the command. - * * Side effects: * Instructions are added to envPtr to execute the "continue" command * at runtime. @@ -446,7 +422,6 @@ TclCompileContinueCmd(interp, parsePtr, envPtr) Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "wrong # args: should be \"continue\"", -1); - envPtr->maxStackDepth = 0; return TCL_ERROR; } @@ -455,7 +430,6 @@ TclCompileContinueCmd(interp, parsePtr, envPtr) */ TclEmitOpcode(INST_CONTINUE, envPtr); - envPtr->maxStackDepth = 0; return TCL_OK; } @@ -471,9 +445,6 @@ TclCompileContinueCmd(interp, parsePtr, envPtr) * unless there was an error while parsing string. If an error occurs * then the interpreter's result contains a standard error message. * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the "expr" command. - * * Side effects: * Instructions are added to envPtr to execute the "expr" command * at runtime. @@ -490,7 +461,6 @@ TclCompileExprCmd(interp, parsePtr, envPtr) { Tcl_Token *firstWordPtr; - envPtr->maxStackDepth = 0; if (parsePtr->numWords == 1) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), @@ -516,9 +486,6 @@ TclCompileExprCmd(interp, parsePtr, envPtr) * there was an error while parsing string. If an error occurs then * the interpreter's result contains a standard error message. * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the command. - * * Side effects: * Instructions are added to envPtr to execute the "for" command * at runtime. @@ -535,12 +502,12 @@ TclCompileForCmd(interp, parsePtr, envPtr) { Tcl_Token *startTokenPtr, *testTokenPtr, *nextTokenPtr, *bodyTokenPtr; JumpFixup jumpFalseFixup; - int maxDepth, jumpBackDist, jumpBackOffset, testCodeOffset, jumpDist; + int jumpBackDist, jumpBackOffset, testCodeOffset, jumpDist; int bodyRange, nextRange, code; unsigned char *jumpPc; char buffer[32 + TCL_INTEGER_SPACE]; + int savedStackDepth = envPtr->currStackDepth; - envPtr->maxStackDepth = 0; if (parsePtr->numWords != 5) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), @@ -589,7 +556,6 @@ TclCompileForCmd(interp, parsePtr, envPtr) * Inline compile the initial command. */ - maxDepth = 0; code = TclCompileCmdWord(interp, startTokenPtr+1, startTokenPtr->numComponents, envPtr); if (code != TCL_OK) { @@ -599,15 +565,16 @@ TclCompileForCmd(interp, parsePtr, envPtr) } goto done; } - maxDepth = envPtr->maxStackDepth; TclEmitOpcode(INST_POP, envPtr); /* * Compile the test then emit the conditional jump that exits the for. */ + envPtr->currStackDepth = savedStackDepth; testCodeOffset = (envPtr->codeNext - envPtr->codeStart); code = TclCompileExprWords(interp, testTokenPtr, 1, envPtr); + envPtr->currStackDepth = savedStackDepth + 1; if (code != TCL_OK) { if (code == TCL_ERROR) { Tcl_AddObjErrorInfo(interp, @@ -615,13 +582,13 @@ TclCompileForCmd(interp, parsePtr, envPtr) } goto done; } - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpFalseFixup); /* * Compile the loop body. */ + envPtr->currStackDepth = savedStackDepth; envPtr->exceptArrayPtr[bodyRange].codeOffset = (envPtr->codeNext - envPtr->codeStart); code = TclCompileCmdWord(interp, bodyTokenPtr+1, @@ -634,7 +601,6 @@ TclCompileForCmd(interp, parsePtr, envPtr) } goto done; } - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); envPtr->exceptArrayPtr[bodyRange].numCodeBytes = (envPtr->codeNext - envPtr->codeStart) - envPtr->exceptArrayPtr[bodyRange].codeOffset; @@ -644,12 +610,14 @@ TclCompileForCmd(interp, parsePtr, envPtr) * Compile the "next" subcommand. */ + envPtr->currStackDepth = savedStackDepth; envPtr->exceptArrayPtr[bodyRange].continueOffset = (envPtr->codeNext - envPtr->codeStart); envPtr->exceptArrayPtr[nextRange].codeOffset = (envPtr->codeNext - envPtr->codeStart); code = TclCompileCmdWord(interp, nextTokenPtr+1, nextTokenPtr->numComponents, envPtr); + envPtr->currStackDepth = savedStackDepth + 1; if (code != TCL_OK) { if (code == TCL_ERROR) { Tcl_AddObjErrorInfo(interp, @@ -657,11 +625,11 @@ TclCompileForCmd(interp, parsePtr, envPtr) } goto done; } - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); envPtr->exceptArrayPtr[nextRange].numCodeBytes = (envPtr->codeNext - envPtr->codeStart) - envPtr->exceptArrayPtr[nextRange].codeOffset; TclEmitOpcode(INST_POP, envPtr); + envPtr->currStackDepth = savedStackDepth; /* * Jump back to the test at the top of the loop. Generate a 4 byte jump @@ -722,13 +690,9 @@ TclCompileForCmd(interp, parsePtr, envPtr) */ TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0), envPtr); - if (maxDepth == 0) { - maxDepth = 1; - } code = TCL_OK; done: - envPtr->maxStackDepth = maxDepth; envPtr->exceptDepth--; return code; } @@ -749,9 +713,6 @@ TclCompileForCmd(interp, parsePtr, envPtr) * should be compiled "out of line" by emitting code to invoke its * command procedure at runtime. * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the "while" command. - * * Side effects: * Instructions are added to envPtr to execute the "foreach" command * at runtime. @@ -778,10 +739,12 @@ TclCompileForeachCmd(interp, parsePtr, envPtr) char *varList; unsigned char *jumpPc; JumpFixup jumpFalseFixup; - int jumpDist, jumpBackDist, jumpBackOffset, maxDepth, infoIndex, range; + int jumpDist, jumpBackDist, jumpBackOffset, infoIndex, range; int numWords, numLists, numVars, loopIndex, tempVar, i, j, code; char savedChar; char buffer[32 + TCL_INTEGER_SPACE]; + int savedStackDepth = envPtr->currStackDepth; + /* * We parse the variable list argument words and create two arrays: @@ -800,13 +763,10 @@ TclCompileForeachCmd(interp, parsePtr, envPtr) * the payoff is too small. */ - envPtr->maxStackDepth = 0; if (procPtr == NULL) { return TCL_OUT_LINE_COMPILE; } - maxDepth = 0; - numWords = parsePtr->numWords; if ((numWords < 4) || (numWords%2 != 0)) { Tcl_ResetResult(interp); @@ -958,7 +918,6 @@ TclCompileForeachCmd(interp, parsePtr, envPtr) if (code != TCL_OK) { goto done; } - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); tempVar = (firstValueTemp + loopIndex); if (tempVar <= 255) { @@ -995,6 +954,7 @@ TclCompileForeachCmd(interp, parsePtr, envPtr) (envPtr->codeNext - envPtr->codeStart); code = TclCompileCmdWord(interp, bodyTokenPtr+1, bodyTokenPtr->numComponents, envPtr); + envPtr->currStackDepth = savedStackDepth + 1; if (code != TCL_OK) { if (code == TCL_ERROR) { sprintf(buffer, "\n (\"foreach\" body line %d)", @@ -1003,7 +963,6 @@ TclCompileForeachCmd(interp, parsePtr, envPtr) } goto done; } - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); envPtr->exceptArrayPtr[range].numCodeBytes = (envPtr->codeNext - envPtr->codeStart) - envPtr->exceptArrayPtr[range].codeOffset; @@ -1064,10 +1023,9 @@ TclCompileForeachCmd(interp, parsePtr, envPtr) * The foreach command's result is an empty string. */ + envPtr->currStackDepth = savedStackDepth; TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0), envPtr); - if (maxDepth == 0) { - maxDepth = 1; - } + envPtr->currStackDepth = savedStackDepth + 1; done: for (loopIndex = 0; loopIndex < numLists; loopIndex++) { @@ -1079,7 +1037,6 @@ TclCompileForeachCmd(interp, parsePtr, envPtr) ckfree((char *) varcList); ckfree((char *) varvList); } - envPtr->maxStackDepth = maxDepth; envPtr->exceptDepth--; return code; } @@ -1188,9 +1145,6 @@ FreeForeachInfo(clientData) * should be compiled "out of line" by emitting code to invoke its * command procedure at runtime. * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the command. - * * Side effects: * Instructions are added to envPtr to execute the "if" command * at runtime. @@ -1214,9 +1168,13 @@ TclCompileIfCmd(interp, parsePtr, envPtr) * is determined. */ Tcl_Token *tokenPtr, *testTokenPtr; int jumpDist, jumpFalseDist, jumpIndex; - int numWords, wordIdx, numBytes, maxDepth, j, code; + int numWords, wordIdx, numBytes, j, code; char *word; char buffer[100]; + int savedStackDepth = envPtr->currStackDepth; + /* Saved stack depth at the start of the first + * test; the envPtr current depth is restored + * to this value at the start of each test. */ /* * Only compile the "if" command if all arguments are simple @@ -1237,7 +1195,6 @@ TclCompileIfCmd(interp, parsePtr, envPtr) TclInitJumpFixupArray(&jumpFalseFixupArray); TclInitJumpFixupArray(&jumpEndFixupArray); - maxDepth = 0; code = TCL_OK; /* @@ -1280,6 +1237,7 @@ TclCompileIfCmd(interp, parsePtr, envPtr) * we back off and compile the if command out-of-line. */ + envPtr->currStackDepth = savedStackDepth; testTokenPtr = tokenPtr; code = TclCompileExprWords(interp, testTokenPtr, 1, envPtr); if (code != TCL_OK) { @@ -1289,7 +1247,6 @@ TclCompileIfCmd(interp, parsePtr, envPtr) } goto done; } - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); if (jumpFalseFixupArray.next >= jumpFalseFixupArray.end) { TclExpandJumpFixupArray(&jumpFalseFixupArray); } @@ -1331,6 +1288,7 @@ TclCompileIfCmd(interp, parsePtr, envPtr) * Compile the "then" command body. */ + envPtr->currStackDepth = savedStackDepth; code = TclCompileCmdWord(interp, tokenPtr+1, tokenPtr->numComponents, envPtr); if (code != TCL_OK) { @@ -1341,7 +1299,6 @@ TclCompileIfCmd(interp, parsePtr, envPtr) } goto done; } - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); /* * Jump to the end of the "if" command. Both jumpFalseFixupArray and @@ -1380,6 +1337,13 @@ TclCompileIfCmd(interp, parsePtr, envPtr) } /* + * Restore the current stack depth in the environment; the + * "else" clause (or its default) will add 1 to this. + */ + + envPtr->currStackDepth = savedStackDepth; + + /* * Check for the optional else clause. */ @@ -1388,7 +1352,7 @@ TclCompileIfCmd(interp, parsePtr, envPtr) /* * There is an else clause. Skip over the optional "else" word. */ - + word = tokenPtr[1].start; numBytes = tokenPtr[1].size; if ((numBytes == 4) && (strncmp(word, "else", 4) == 0)) { @@ -1417,7 +1381,6 @@ TclCompileIfCmd(interp, parsePtr, envPtr) } goto done; } - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); /* * Make sure there are no words after the else clause. @@ -1437,7 +1400,6 @@ TclCompileIfCmd(interp, parsePtr, envPtr) */ TclEmitPush(TclRegisterLiteral(envPtr, "", 0,/*onHeap*/ 0), envPtr); - maxDepth = TclMax(1, maxDepth); } /* @@ -1477,9 +1439,9 @@ TclCompileIfCmd(interp, parsePtr, envPtr) */ done: + envPtr->currStackDepth = savedStackDepth + 1; TclFreeJumpFixupArray(&jumpFalseFixupArray); TclFreeJumpFixupArray(&jumpEndFixupArray); - envPtr->maxStackDepth = maxDepth; return code; } @@ -1499,9 +1461,6 @@ TclCompileIfCmd(interp, parsePtr, envPtr) * should be compiled "out of line" by emitting code to invoke its * command procedure at runtime. * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the "incr" command. - * * Side effects: * Instructions are added to envPtr to execute the "incr" command * at runtime. @@ -1518,10 +1477,8 @@ TclCompileIncrCmd(interp, parsePtr, envPtr) { Tcl_Token *varTokenPtr, *incrTokenPtr; int simpleVarName, isScalar, localIndex, haveImmValue, immValue; - int maxDepth = 0; int code = TCL_OK; - envPtr->maxStackDepth = 0; if ((parsePtr->numWords != 2) && (parsePtr->numWords != 3)) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), @@ -1533,7 +1490,7 @@ TclCompileIncrCmd(interp, parsePtr, envPtr) + (parsePtr->tokenPtr->numComponents + 1); code = TclPushVarName(interp, varTokenPtr, envPtr, TCL_NO_LARGE_INDEX, - &localIndex, &maxDepth, &simpleVarName, &isScalar); + &localIndex, &simpleVarName, &isScalar); if (code != TCL_OK) { goto done; } @@ -1572,7 +1529,6 @@ TclCompileIncrCmd(interp, parsePtr, envPtr) if (!haveImmValue) { TclEmitPush(TclRegisterLiteral(envPtr, word, numBytes, /*onHeap*/ 0), envPtr); - maxDepth += 1; } } else { code = TclCompileTokens(interp, incrTokenPtr+1, @@ -1584,7 +1540,6 @@ TclCompileIncrCmd(interp, parsePtr, envPtr) } goto done; } - maxDepth += envPtr->maxStackDepth; } } else { /* no incr amount given so use 1 */ haveImmValue = 1; @@ -1636,7 +1591,6 @@ TclCompileIncrCmd(interp, parsePtr, envPtr) } done: - envPtr->maxStackDepth = maxDepth; return code; } @@ -1656,9 +1610,6 @@ TclCompileIncrCmd(interp, parsePtr, envPtr) * command should be compiled "out of line" by emitting code to * invoke its command procedure (Tcl_LappendObjCmd) at runtime. * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the incr command. - * * Side effects: * Instructions are added to envPtr to execute the "lappend" command * at runtime. @@ -1675,7 +1626,6 @@ TclCompileLappendCmd(interp, parsePtr, envPtr) { Tcl_Token *varTokenPtr, *valueTokenPtr; int numValues, simpleVarName, isScalar, localIndex, numWords; - int maxDepth = 0; int code = TCL_OK; /* @@ -1685,7 +1635,6 @@ TclCompileLappendCmd(interp, parsePtr, envPtr) return TCL_OUT_LINE_COMPILE; } - envPtr->maxStackDepth = 0; numWords = parsePtr->numWords; if (numWords == 1) { Tcl_ResetResult(interp); @@ -1713,7 +1662,7 @@ TclCompileLappendCmd(interp, parsePtr, envPtr) + (parsePtr->tokenPtr->numComponents + 1); code = TclPushVarName(interp, varTokenPtr, envPtr, TCL_CREATE_VAR, - &localIndex, &maxDepth, &simpleVarName, &isScalar); + &localIndex, &simpleVarName, &isScalar); if (code != TCL_OK) { goto done; } @@ -1728,14 +1677,12 @@ TclCompileLappendCmd(interp, parsePtr, envPtr) if (valueTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { TclEmitPush(TclRegisterLiteral(envPtr, valueTokenPtr[1].start, valueTokenPtr[1].size, /*onHeap*/ 0), envPtr); - maxDepth += 1; } else { code = TclCompileTokens(interp, valueTokenPtr+1, valueTokenPtr->numComponents, envPtr); if (code != TCL_OK) { goto done; } - maxDepth += envPtr->maxStackDepth; } #if 0 } else { @@ -1745,7 +1692,6 @@ TclCompileLappendCmd(interp, parsePtr, envPtr) */ TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0), envPtr); - maxDepth += 1; numValues = 1; #endif } @@ -1785,7 +1731,6 @@ TclCompileLappendCmd(interp, parsePtr, envPtr) } done: - envPtr->maxStackDepth = maxDepth; return code; } @@ -1803,9 +1748,6 @@ TclCompileLappendCmd(interp, parsePtr, envPtr) * interpreter's result contains an error message, and TCL_ERROR is * returned. * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the command. - * * Side effects: * Instructions are added to envPtr to execute the "lindex" command * at runtime. @@ -1821,7 +1763,7 @@ TclCompileLindexCmd(interp, parsePtr, envPtr) CompileEnv *envPtr; /* Holds resulting instructions. */ { Tcl_Token *varTokenPtr; - int code, depth, i; + int code, i; int numWords; numWords = parsePtr->numWords; @@ -1837,8 +1779,6 @@ TclCompileLindexCmd(interp, parsePtr, envPtr) varTokenPtr = parsePtr->tokenPtr + (parsePtr->tokenPtr->numComponents + 1); - depth = 0; - /* * Push the operands onto the stack. */ @@ -1850,15 +1790,12 @@ TclCompileLindexCmd(interp, parsePtr, envPtr) varTokenPtr[1].size, 0), envPtr); - depth++; } else { code = TclCompileTokens(interp, varTokenPtr+1, varTokenPtr->numComponents, envPtr); if (code != TCL_OK) { - envPtr->maxStackDepth = depth; return code; } - depth += envPtr->maxStackDepth; } varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1); } @@ -1868,7 +1805,6 @@ TclCompileLindexCmd(interp, parsePtr, envPtr) * if there are multiple index args. */ - envPtr->maxStackDepth = depth; if ( numWords == 3 ) { TclEmitOpcode( INST_LIST_INDEX, envPtr ); } else { @@ -1895,9 +1831,6 @@ TclCompileLindexCmd(interp, parsePtr, envPtr) * command should be compiled "out of line" by emitting code to * invoke its command procedure (Tcl_ListObjCmd) at runtime. * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the incr command. - * * Side effects: * Instructions are added to envPtr to execute the "list" command * at runtime. @@ -1919,20 +1852,18 @@ TclCompileListCmd(interp, parsePtr, envPtr) return TCL_OUT_LINE_COMPILE; } - envPtr->maxStackDepth = 0; if (parsePtr->numWords == 1) { /* * Empty args case */ TclEmitPush(TclRegisterLiteral(envPtr, "", 0, 0), envPtr); - envPtr->maxStackDepth = 1; } else { /* * Push the all values onto the stack. */ Tcl_Token *valueTokenPtr; - int i, code, numWords, depth = 0; + int i, code, numWords; numWords = parsePtr->numWords; @@ -1943,19 +1874,15 @@ TclCompileListCmd(interp, parsePtr, envPtr) TclEmitPush(TclRegisterLiteral(envPtr, valueTokenPtr[1].start, valueTokenPtr[1].size, /*onHeap*/ 0), envPtr); - depth++; } else { code = TclCompileTokens(interp, valueTokenPtr+1, valueTokenPtr->numComponents, envPtr); if (code != TCL_OK) { - envPtr->maxStackDepth = depth; return code; } - depth += envPtr->maxStackDepth; } valueTokenPtr = valueTokenPtr + (valueTokenPtr->numComponents + 1); } - envPtr->maxStackDepth = depth; TclEmitInstInt4(INST_LIST, numWords - 1, envPtr); } @@ -1976,9 +1903,6 @@ TclCompileListCmd(interp, parsePtr, envPtr) * interpreter's result contains an error message, and TCL_ERROR is * returned. * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the command. - * * Side effects: * Instructions are added to envPtr to execute the "llength" command * at runtime. @@ -2011,7 +1935,6 @@ TclCompileLlengthCmd(interp, parsePtr, envPtr) */ TclEmitPush(TclRegisterLiteral(envPtr, varTokenPtr[1].start, varTokenPtr[1].size, 0), envPtr); - envPtr->maxStackDepth = 1; } else { code = TclCompileTokens(interp, varTokenPtr+1, varTokenPtr->numComponents, envPtr); @@ -2038,9 +1961,6 @@ TclCompileLlengthCmd(interp, parsePtr, envPtr) * (that is, not byte-compiled). If an error occurs, TCL_ERROR is * returned, and the interpreter result contains an error message. * - * envPtr->maxStackDepth is updated with a conservative estimate - * of the number of stack elements needed to execute the command. - * * Side effects: * Instructions are added to envPtr to execute the "lset" command * at runtime. @@ -2078,12 +1998,8 @@ TclCompileLsetCmd( interp, parsePtr, envPtr ) CompileEnv* envPtr; /* Holds the resulting instructions */ { - int depth = 0; /* Current depth of stack */ int tempDepth; /* Depth used for emitting one part * of the code burst. */ - int maxDepth = 0; /* Max depth used anywhere in the - * code burst */ - Tcl_Token* varTokenPtr; /* Pointer to the Tcl_Token representing * the parse of the variable name */ @@ -2112,32 +2028,12 @@ TclCompileLsetCmd( interp, parsePtr, envPtr ) varTokenPtr = parsePtr->tokenPtr + (parsePtr->tokenPtr->numComponents + 1); - tempDepth = 0; result = TclPushVarName( interp, varTokenPtr, envPtr, 0, - &localIndex, &tempDepth, - &simpleVarName, &isScalar ); - if ( tempDepth > maxDepth ) { - maxDepth = tempDepth; - } + &localIndex, &simpleVarName, &isScalar ); if (result != TCL_OK) { - envPtr->maxStackDepth = maxDepth; return result; } - /* Figure out how much is now on stack. */ - - depth = 0; - if ( simpleVarName ) { - if ( localIndex < 0 ) { - ++depth; /* We have pushed a variable name. */ - } - if ( !isScalar ) { - ++depth; /* We have pushed an array element */ - } - } else { - ++depth; /* Variable is complex; it's pushed to stack */ - } - /* Push the "index" args and the new element value. */ for ( i = 2; i < parsePtr->numWords; ++i ) { @@ -2154,20 +2050,10 @@ TclCompileLsetCmd( interp, parsePtr, envPtr ) varTokenPtr[1].size, 0), envPtr); - ++depth; - if ( depth > maxDepth ) { - maxDepth = depth; - } } else { - envPtr->maxStackDepth = depth; result = TclCompileTokens(interp, varTokenPtr+1, varTokenPtr->numComponents, envPtr); - ++depth; - if ( envPtr->maxStackDepth > maxDepth ) { - maxDepth = envPtr->maxStackDepth; - } if ( result != TCL_OK ) { - envPtr->maxStackDepth = maxDepth; return result; } } @@ -2184,10 +2070,6 @@ TclCompileLsetCmd( interp, parsePtr, envPtr ) tempDepth = parsePtr->numWords - 1; } TclEmitInstInt4( INST_OVER, tempDepth, envPtr ); - ++depth; - if ( depth > maxDepth ) { - maxDepth = depth; - } } /* @@ -2201,10 +2083,6 @@ TclCompileLsetCmd( interp, parsePtr, envPtr ) tempDepth = parsePtr->numWords - 2; } TclEmitInstInt4( INST_OVER, tempDepth, envPtr ); - ++depth; - if ( depth > maxDepth ) { - maxDepth = depth; - } } /* @@ -2232,17 +2110,6 @@ TclCompileLsetCmd( interp, parsePtr, envPtr ) } /* - * Stack has now reached the maximum depth it will attain - * during this code burst. - */ - - ++depth; - if ( depth > maxDepth ) { - maxDepth = depth; - } - envPtr->maxStackDepth = maxDepth; - - /* * Emit the correct variety of 'lset' instruction */ @@ -2296,9 +2163,6 @@ TclCompileLsetCmd( interp, parsePtr, envPtr ) * If an error occurs then the interpreter's result contains a standard * error message. * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the command. - * * Side effects: * Instructions are added to envPtr to execute the "return" command * at runtime. @@ -2331,7 +2195,6 @@ TclCompileReturnCmd(interp, parsePtr, envPtr) * Just push the literal string "". */ TclEmitPush(TclRegisterLiteral(envPtr, "", 0, 0), envPtr); - envPtr->maxStackDepth = 1; break; } case 2: { @@ -2350,7 +2213,6 @@ TclCompileReturnCmd(interp, parsePtr, envPtr) */ TclEmitPush(TclRegisterLiteral(envPtr, varTokenPtr[1].start, varTokenPtr[1].size, /*onHeap*/ 0), envPtr); - envPtr->maxStackDepth = 1; } else { /* * Parse token is more complex, so compile it; this handles the @@ -2401,9 +2263,6 @@ TclCompileReturnCmd(interp, parsePtr, envPtr) * set command should be compiled "out of line" by emitting code to * invoke its command procedure (Tcl_SetCmd) at runtime. * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the incr command. - * * Side effects: * Instructions are added to envPtr to execute the "set" command * at runtime. @@ -2420,10 +2279,8 @@ TclCompileSetCmd(interp, parsePtr, envPtr) { Tcl_Token *varTokenPtr, *valueTokenPtr; int isAssignment, isScalar, simpleVarName, localIndex, numWords; - int maxDepth = 0; int code = TCL_OK; - envPtr->maxStackDepth = 0; numWords = parsePtr->numWords; if ((numWords != 2) && (numWords != 3)) { Tcl_ResetResult(interp); @@ -2446,7 +2303,7 @@ TclCompileSetCmd(interp, parsePtr, envPtr) code = TclPushVarName(interp, varTokenPtr, envPtr, (isAssignment ? TCL_CREATE_VAR : 0), - &localIndex, &maxDepth, &simpleVarName, &isScalar); + &localIndex, &simpleVarName, &isScalar); if (code != TCL_OK) { goto done; } @@ -2460,14 +2317,12 @@ TclCompileSetCmd(interp, parsePtr, envPtr) if (valueTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { TclEmitPush(TclRegisterLiteral(envPtr, valueTokenPtr[1].start, valueTokenPtr[1].size, /*onHeap*/ 0), envPtr); - maxDepth += 1; } else { code = TclCompileTokens(interp, valueTokenPtr+1, valueTokenPtr->numComponents, envPtr); if (code != TCL_OK) { goto done; } - maxDepth += envPtr->maxStackDepth; } } @@ -2512,7 +2367,6 @@ TclCompileSetCmd(interp, parsePtr, envPtr) } done: - envPtr->maxStackDepth = maxDepth; return code; } @@ -2530,9 +2384,6 @@ TclCompileSetCmd(interp, parsePtr, envPtr) * interpreter's result contains an error message, and TCL_ERROR is * returned. * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the command. - * * Side effects: * Instructions are added to envPtr to execute the "string" command * at runtime. @@ -2612,7 +2463,7 @@ TclCompileStringCmd(interp, parsePtr, envPtr) case STR_COMPARE: case STR_EQUAL: { - int i, depth; + int i; /* * If there are any flags to the command, we can't byte compile it * because the INST_STR_EQ bytecode doesn't support flags. @@ -2622,8 +2473,6 @@ TclCompileStringCmd(interp, parsePtr, envPtr) return TCL_OUT_LINE_COMPILE; } - depth = 0; - /* * Push the two operands onto the stack. */ @@ -2633,25 +2482,22 @@ TclCompileStringCmd(interp, parsePtr, envPtr) TclEmitPush(TclRegisterLiteral(envPtr, varTokenPtr[1].start, varTokenPtr[1].size, 0), envPtr); - depth++; } else { code = TclCompileTokens(interp, varTokenPtr+1, varTokenPtr->numComponents, envPtr); if (code != TCL_OK) { return code; } - depth += envPtr->maxStackDepth; } varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1); } - envPtr->maxStackDepth = depth; TclEmitOpcode(((((enum options) index) == STR_COMPARE) ? INST_STR_CMP : INST_STR_EQ), envPtr); return TCL_OK; } case STR_INDEX: { - int i, depth; + int i; if (parsePtr->numWords != 4) { Tcl_SetResult(interp, "wrong # args: should be " @@ -2659,8 +2505,6 @@ TclCompileStringCmd(interp, parsePtr, envPtr) return TCL_ERROR; } - depth = 0; - /* * Push the two operands onto the stack. */ @@ -2670,19 +2514,16 @@ TclCompileStringCmd(interp, parsePtr, envPtr) TclEmitPush(TclRegisterLiteral(envPtr, varTokenPtr[1].start, varTokenPtr[1].size, 0), envPtr); - depth++; } else { code = TclCompileTokens(interp, varTokenPtr+1, varTokenPtr->numComponents, envPtr); if (code != TCL_OK) { return code; } - depth += envPtr->maxStackDepth; } varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1); } - envPtr->maxStackDepth = depth; TclEmitOpcode(INST_STR_INDEX, envPtr); return TCL_OK; } @@ -2715,7 +2556,7 @@ TclCompileStringCmd(interp, parsePtr, envPtr) return TCL_OK; } case STR_MATCH: { - int i, length, exactMatch = 0, nocase = 0, depth = 0; + int i, length, exactMatch = 0, nocase = 0; char c, *str; if (parsePtr->numWords < 4 || parsePtr->numWords > 5) { @@ -2767,14 +2608,12 @@ TclCompileStringCmd(interp, parsePtr, envPtr) } TclEmitPush(TclRegisterLiteral(envPtr, str, length, 0), envPtr); - depth++; } else { code = TclCompileTokens(interp, varTokenPtr+1, varTokenPtr->numComponents, envPtr); if (code != TCL_OK) { return code; } - depth += envPtr->maxStackDepth; } varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1); } @@ -2784,7 +2623,6 @@ TclCompileStringCmd(interp, parsePtr, envPtr) } else { TclEmitInstInt1(INST_STR_MATCH, nocase, envPtr); } - envPtr->maxStackDepth = depth; return TCL_OK; } } @@ -2808,9 +2646,6 @@ TclCompileStringCmd(interp, parsePtr, envPtr) * indicating that the while command should be compiled "out of line" * by emitting code to invoke its command procedure at runtime. * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the "while" command. - * * Side effects: * Instructions are added to envPtr to execute the "while" command * at runtime. @@ -2829,11 +2664,10 @@ TclCompileWhileCmd(interp, parsePtr, envPtr) JumpFixup jumpFalseFixup; unsigned char *jumpPc; int testCodeOffset, jumpDist, jumpBackDist, jumpBackOffset; - int range, maxDepth, code; + int range, code; char buffer[32 + TCL_INTEGER_SPACE]; + int savedStackDepth = envPtr->currStackDepth; - envPtr->maxStackDepth = 0; - maxDepth = 0; if (parsePtr->numWords != 3) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), @@ -2885,18 +2719,19 @@ TclCompileWhileCmd(interp, parsePtr, envPtr) } goto error; } - maxDepth = envPtr->maxStackDepth; TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpFalseFixup); /* * Compile the loop body. */ + envPtr->currStackDepth = savedStackDepth; bodyTokenPtr = testTokenPtr + (testTokenPtr->numComponents + 1); envPtr->exceptArrayPtr[range].codeOffset = (envPtr->codeNext - envPtr->codeStart); code = TclCompileCmdWord(interp, bodyTokenPtr+1, bodyTokenPtr->numComponents, envPtr); + envPtr->currStackDepth = savedStackDepth + 1; if (code != TCL_OK) { if (code == TCL_ERROR) { sprintf(buffer, "\n (\"while\" body line %d)", @@ -2905,7 +2740,6 @@ TclCompileWhileCmd(interp, parsePtr, envPtr) } goto error; } - maxDepth = TclMax(envPtr->maxStackDepth, maxDepth); envPtr->exceptArrayPtr[range].numCodeBytes = (envPtr->codeNext - envPtr->codeStart) - envPtr->exceptArrayPtr[range].codeOffset; @@ -2965,16 +2799,12 @@ TclCompileWhileCmd(interp, parsePtr, envPtr) * The while command's result is an empty string. */ + envPtr->currStackDepth = savedStackDepth; TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0), envPtr); - if (maxDepth == 0) { - maxDepth = 1; - } - envPtr->maxStackDepth = maxDepth; envPtr->exceptDepth--; return TCL_OK; error: - envPtr->maxStackDepth = maxDepth; envPtr->exceptDepth--; return code; } @@ -2992,9 +2822,6 @@ TclCompileWhileCmd(interp, parsePtr, envPtr) * unless there was an error while parsing string. If an error occurs * then the interpreter's result contains a standard error message. * - * envPtr->maxStackDepth is updated with the maximum number of stack - * elements needed to execute the incr command. - * * Side effects: * Instructions are added to envPtr to execute the "set" command * at runtime. @@ -3004,15 +2831,13 @@ TclCompileWhileCmd(interp, parsePtr, envPtr) static int TclPushVarName(interp, varTokenPtr, envPtr, flags, localIndexPtr, - maxDepthPtr, simpleVarNamePtr, isScalarPtr) + simpleVarNamePtr, isScalarPtr) Tcl_Interp *interp; /* Used for error reporting. */ Tcl_Token *varTokenPtr; /* Points to a variable token. */ CompileEnv *envPtr; /* Holds resulting instructions. */ int flags; /* takes TCL_CREATE_VAR or * TCL_LARGE_INDEX_OK */ int *localIndexPtr; /* must not be NULL */ - int *maxDepthPtr; /* must not be NULL, should already have a - * value set in the parent. */ int *simpleVarNamePtr; /* must not be NULL */ int *isScalarPtr; /* must not be NULL */ { @@ -3022,7 +2847,6 @@ TclPushVarName(interp, varTokenPtr, envPtr, flags, localIndexPtr, char *name, *elName; register int i, n; int nameChars, elNameChars, simpleVarName, localIndex; - int maxDepth = 0; int code = TCL_OK; /* @@ -3149,7 +2973,6 @@ TclPushVarName(interp, varTokenPtr, envPtr, flags, localIndexPtr, if (localIndex < 0) { TclEmitPush(TclRegisterLiteral(envPtr, name, nameChars, /*onHeap*/ 0), envPtr); - maxDepth = 1; } /* @@ -3181,11 +3004,9 @@ TclPushVarName(interp, varTokenPtr, envPtr, flags, localIndexPtr, if (code != TCL_OK) { goto done; } - maxDepth += envPtr->maxStackDepth; } else { TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*alreadyAlloced*/ 0), envPtr); - maxDepth += 1; } } } else { @@ -3198,7 +3019,6 @@ TclPushVarName(interp, varTokenPtr, envPtr, flags, localIndexPtr, if (code != TCL_OK) { goto done; } - maxDepth += envPtr->maxStackDepth; } done: @@ -3206,7 +3026,6 @@ TclPushVarName(interp, varTokenPtr, envPtr, flags, localIndexPtr, Tcl_FreeParse(&elemParse); } *localIndexPtr = localIndex; - *maxDepthPtr += maxDepth; *simpleVarNamePtr = simpleVarName; *isScalarPtr = (elName == NULL); return code; |