summaryrefslogtreecommitdiffstats
path: root/generic/tclCompCmds.c
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2013-06-01 21:05:55 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2013-06-01 21:05:55 (GMT)
commitd09727e7ff46a2abd069caac727159c92f6c9436 (patch)
treef513d78c6d5a0417959e2f49d777012a853850e7 /generic/tclCompCmds.c
parent8d03d462d4d27ee4a2d6fec72a8d2efe9e90f94a (diff)
downloadtcl-d09727e7ff46a2abd069caac727159c92f6c9436.zip
tcl-d09727e7ff46a2abd069caac727159c92f6c9436.tar.gz
tcl-d09727e7ff46a2abd069caac727159c92f6c9436.tar.bz2
Getting better at doing more efficient break/continue instruction handling.
Diffstat (limited to 'generic/tclCompCmds.c')
-rw-r--r--generic/tclCompCmds.c113
1 files changed, 63 insertions, 50 deletions
diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c
index 1f99a22..6e5d187 100644
--- a/generic/tclCompCmds.c
+++ b/generic/tclCompCmds.c
@@ -480,7 +480,7 @@ TclCompileBreakCmd(
* compiled. */
CompileEnv *envPtr) /* Holds resulting instructions. */
{
- int i, exnIdx;
+ int depth;
ExceptionRange *rangePtr;
if (parsePtr->numWords != 1) {
@@ -488,33 +488,40 @@ TclCompileBreakCmd(
}
/*
- * Find the innermost exception range that contains this command. Relies
- * on the fact that the range has a numCodeBytes = -1 when it is being
- * populated and that inner ranges come after outer ranges.
+ * Find the innermost exception range that contains this command.
*/
- exnIdx = -1;
- for (i=0 ; i<envPtr->exceptArrayNext ; i++) {
- rangePtr = &envPtr->exceptArrayPtr[i];
- if (envPtr->codeStart+rangePtr->codeOffset <= envPtr->codeNext
- && rangePtr->numCodeBytes == -1) {
- exnIdx = i;
+ rangePtr = TclGetInnermostExceptionRange(envPtr, &depth);
+ if (rangePtr && rangePtr->type == LOOP_EXCEPTION_RANGE) {
+ int toPop = envPtr->currStackDepth - depth;
+
+ /*
+ * Pop off the extra stack frames.
+ */
+
+ while (toPop > 0) {
+ TclEmitOpcode(INST_POP, envPtr);
+ toPop--;
+#ifdef TCL_COMPILE_DEBUG
+ /*
+ * Instructions that raise exceptions don't really have to follow
+ * the usual stack management rules. But the checker wants them
+ * followed, so lie about stack usage to make it happy.
+ */
+ TclAdjustStackDepth(1, envPtr);
+#endif
}
- }
- if (exnIdx != -1) {
- rangePtr = &envPtr->exceptArrayPtr[exnIdx];
- if (rangePtr->type == LOOP_EXCEPTION_RANGE) {
- int toPop = envPtr->currStackDepth -
- envPtr->exnStackDepthArrayPtr[exnIdx];
+
+ if (envPtr->expandCount == 0 && rangePtr->breakOffset != -1) {
+ int offset = (rangePtr->breakOffset - CurrentOffset(envPtr));
/*
- * Pop off the extra stack frames.
+ * Found the target! Also, no built-up expansion stack. No need
+ * for a nasty INST_BREAK here.
*/
- while (toPop > 0) {
- TclEmitOpcode(INST_POP, envPtr);
- toPop--;
- }
+ TclEmitInstInt4(INST_JUMP4, offset, envPtr);
+ goto done;
}
}
@@ -523,6 +530,8 @@ TclCompileBreakCmd(
*/
TclEmitOpcode(INST_BREAK, envPtr);
+
+ done:
#ifdef TCL_COMPILE_DEBUG
/*
* Instructions that raise exceptions don't really have to follow
@@ -824,7 +833,7 @@ TclCompileContinueCmd(
* compiled. */
CompileEnv *envPtr) /* Holds resulting instructions. */
{
- int i, exnIdx;
+ int depth;
ExceptionRange *rangePtr;
/*
@@ -837,45 +846,40 @@ TclCompileContinueCmd(
/*
* See if we can find a valid continueOffset (i.e., not -1) in the
- * innermost containing exception range. Relies on the fact that the range
- * has a numCodeBytes = -1 when it is being populated and that inner
- * ranges come after outer ranges.
+ * innermost containing exception range.
*/
- exnIdx = -1;
- for (i=0 ; i<envPtr->exceptArrayNext ; i++) {
- rangePtr = &envPtr->exceptArrayPtr[i];
- if (envPtr->codeStart+rangePtr->codeOffset <= envPtr->codeNext
- && rangePtr->numCodeBytes == -1) {
- exnIdx = i;
- }
- }
- if (exnIdx >= 0) {
- rangePtr = &envPtr->exceptArrayPtr[exnIdx];
- if (rangePtr->type == LOOP_EXCEPTION_RANGE) {
- int toPop = envPtr->currStackDepth -
- envPtr->exnStackDepthArrayPtr[exnIdx];
+ rangePtr = TclGetInnermostExceptionRange(envPtr, &depth);
+ if (rangePtr && rangePtr->type == LOOP_EXCEPTION_RANGE) {
+ int toPop = envPtr->currStackDepth - depth;
+
+ /*
+ * Pop off the extra stack frames.
+ */
+ while (toPop > 0) {
+ TclEmitOpcode(INST_POP, envPtr);
+ toPop--;
+#ifdef TCL_COMPILE_DEBUG
/*
- * Pop off the extra stack frames.
+ * Instructions that raise exceptions don't really have to follow
+ * the usual stack management rules. But the checker wants them
+ * followed, so lie about stack usage to make it happy.
*/
-
- while (toPop > 0) {
- TclEmitOpcode(INST_POP, envPtr);
- toPop--;
- }
+ TclAdjustStackDepth(1, envPtr);
+#endif
}
- if (rangePtr->type == LOOP_EXCEPTION_RANGE
- && rangePtr->continueOffset != -1) {
+
+ if (envPtr->expandCount == 0 && rangePtr->continueOffset != -1) {
int offset = (rangePtr->continueOffset - CurrentOffset(envPtr));
/*
- * Found the target! No need for a nasty INST_CONTINUE here.
+ * Found the target! Also, no built-up expansion stack. No need
+ * for a nasty INST_CONTINUE here.
*/
TclEmitInstInt4(INST_JUMP4, offset, envPtr);
- PushStringLiteral(envPtr, ""); /* Evil hack! */
- return TCL_OK;
+ goto done;
}
}
@@ -884,7 +888,16 @@ TclCompileContinueCmd(
*/
TclEmitOpcode(INST_CONTINUE, envPtr);
- PushStringLiteral(envPtr, ""); /* Evil hack! */
+
+ done:
+#ifdef TCL_COMPILE_DEBUG
+ /*
+ * Instructions that raise exceptions don't really have to follow
+ * the usual stack management rules. But the checker wants them
+ * followed, so lie about stack usage to make it happy.
+ */
+ TclAdjustStackDepth(1, envPtr);
+#endif
return TCL_OK;
}