diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2013-06-05 08:11:06 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2013-06-05 08:11:06 (GMT) |
commit | 4265e044139d2dd3217a93741524cd31d7d4fa84 (patch) | |
tree | 1c78cdffefc59b1c8cffdea512f701b5eaffa9be /generic/tclCompCmds.c | |
parent | 6f640f9e5701a60ac0fbde981742fd3a80f59d18 (diff) | |
parent | 984c4923d6abb322e755dcde5b14bc19747eb8b8 (diff) | |
download | tcl-4265e044139d2dd3217a93741524cd31d7d4fa84.zip tcl-4265e044139d2dd3217a93741524cd31d7d4fa84.tar.gz tcl-4265e044139d2dd3217a93741524cd31d7d4fa84.tar.bz2 |
[Bugs 2835313, 3614226]: Complete the construction of break/continue compilers
that get the stack cleanup right, even when there's expansion going on.
Diffstat (limited to 'generic/tclCompCmds.c')
-rw-r--r-- | generic/tclCompCmds.c | 70 |
1 files changed, 22 insertions, 48 deletions
diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c index 3046841..365e647 100644 --- a/generic/tclCompCmds.c +++ b/generic/tclCompCmds.c @@ -493,37 +493,24 @@ TclCompileBreakCmd( rangePtr = TclGetInnermostExceptionRange(envPtr, TCL_BREAK, &auxPtr); if (rangePtr && rangePtr->type == LOOP_EXCEPTION_RANGE) { - int toPop = envPtr->currStackDepth - auxPtr->stackDepth; - /* - * Pop off the extra stack frames. + * Found the target! No need for a nasty INST_BREAK here. */ - while (toPop > 0) { - TclEmitOpcode(INST_POP, envPtr); - TclAdjustStackDepth(1, envPtr); - toPop--; - } - - if (envPtr->expandCount == auxPtr->expandTarget) { - /* - * Found the target! Also, no built-up expansion stack. No need - * for a nasty INST_BREAK here. - */ + TclCleanupStackForBreakContinue(envPtr, auxPtr); + TclAddLoopBreakFixup(envPtr, auxPtr); + } else { + /* + * Emit a real break. + */ - TclAddLoopBreakFixup(envPtr, auxPtr); - goto done; - } + PushStringLiteral(envPtr, ""); + TclEmitOpcode(INST_DUP, envPtr); + TclEmitInstInt4(INST_RETURN_IMM, TCL_BREAK, envPtr); + TclEmitInt4(0, envPtr); } /* - * Emit a break instruction. - */ - - TclEmitOpcode(INST_BREAK, envPtr); - - done: - /* * Instructions that raise exceptions don't really have to follow the * usual stack management rules, but the cleanup code does. */ @@ -840,37 +827,24 @@ TclCompileContinueCmd( rangePtr = TclGetInnermostExceptionRange(envPtr, TCL_CONTINUE, &auxPtr); if (rangePtr && rangePtr->type == LOOP_EXCEPTION_RANGE) { - int toPop = envPtr->currStackDepth - auxPtr->stackDepth; - /* - * Pop off the extra stack frames. + * Found the target! No need for a nasty INST_CONTINUE here. */ - while (toPop > 0) { - TclEmitOpcode(INST_POP, envPtr); - TclAdjustStackDepth(1, envPtr); - toPop--; - } - - if (envPtr->expandCount == auxPtr->expandTarget) { - /* - * Found the target! Also, no built-up expansion stack. No need - * for a nasty INST_CONTINUE here. - */ + TclCleanupStackForBreakContinue(envPtr, auxPtr); + TclAddLoopContinueFixup(envPtr, auxPtr); + } else { + /* + * Emit a real continue. + */ - TclAddLoopContinueFixup(envPtr, auxPtr); - goto done; - } + PushStringLiteral(envPtr, ""); + TclEmitOpcode(INST_DUP, envPtr); + TclEmitInstInt4(INST_RETURN_IMM, TCL_CONTINUE, envPtr); + TclEmitInt4(0, envPtr); } /* - * Emit a continue instruction. - */ - - TclEmitOpcode(INST_CONTINUE, envPtr); - - done: - /* * Instructions that raise exceptions don't really have to follow the * usual stack management rules, but the cleanup code does. */ |