Tcl Source Code

Artifact [1526c14b0e]
Login

Artifact 1526c14b0e59b3fe95da4a5d64cc26f5a779f4d9:

Attachment "465811.patch" to ticket [465811ffff] added by msofer 2002-02-09 00:07:24.
Index: generic/tclCompCmds.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclCompCmds.c,v
retrieving revision 1.24
diff -u -r1.24 tclCompCmds.c
--- generic/tclCompCmds.c	7 Feb 2002 01:04:00 -0000	1.24
+++ generic/tclCompCmds.c	8 Feb 2002 16:59:17 -0000
@@ -501,10 +501,9 @@
     CompileEnv *envPtr;		/* Holds resulting instructions. */
 {
     Tcl_Token *startTokenPtr, *testTokenPtr, *nextTokenPtr, *bodyTokenPtr;
-    JumpFixup jumpFalseFixup;
-    int jumpBackDist, jumpBackOffset, testCodeOffset, jumpDist;
+    JumpFixup jumpEvalCondFixup;
+    int testCodeOffset, bodyCodeOffset, jumpDist;
     int bodyRange, nextRange, code;
-    unsigned char *jumpPc;
     char buffer[32 + TCL_INTEGER_SPACE];
     int savedStackDepth = envPtr->currStackDepth;
 
@@ -566,33 +565,31 @@
 	goto done;
     }
     TclEmitOpcode(INST_POP, envPtr);
-    
+   
     /*
-     * Compile the test then emit the conditional jump that exits the for.
+     * Jump to the evaluation of the condition. This code uses the "loop
+     * rotation" optimisation (which eliminates one branch from the loop).
+     * "for start cond next body" produces then:
+     *       start
+     *       goto A
+     *    B: body
+     *       next
+     *    A: cond -> result
+     *       if (result) goto B
      */
 
-    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,
-		    "\n    (\"for\" test expression)", -1);
-        }
-	goto done;
-    }
-    TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpFalseFixup);
+    TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpEvalCondFixup);
 
     /*
      * Compile the loop body.
      */
 
-    envPtr->currStackDepth = savedStackDepth;
-    envPtr->exceptArrayPtr[bodyRange].codeOffset =
-	    (envPtr->codeNext - envPtr->codeStart);
+    bodyCodeOffset = (envPtr->codeNext - envPtr->codeStart);
+    envPtr->exceptArrayPtr[bodyRange].codeOffset = bodyCodeOffset;
+
     code = TclCompileCmdWord(interp, bodyTokenPtr+1,
 	    bodyTokenPtr->numComponents, envPtr);
+    envPtr->currStackDepth = savedStackDepth + 1;
     if (code != TCL_OK) {
 	if (code == TCL_ERROR) {
 	    sprintf(buffer, "\n    (\"for\" body line %d)",
@@ -602,10 +599,10 @@
 	goto done;
     }
     envPtr->exceptArrayPtr[bodyRange].numCodeBytes =
-	    (envPtr->codeNext - envPtr->codeStart)
-	    - envPtr->exceptArrayPtr[bodyRange].codeOffset;
+	    (envPtr->codeNext - envPtr->codeStart) - bodyCodeOffset;
     TclEmitOpcode(INST_POP, envPtr);
 
+
     /*
      * Compile the "next" subcommand.
      */
@@ -630,51 +627,34 @@
 	    - 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
-     * if the distance to the test is > 120 bytes. This is conservative and
-     * ensures that we won't have to replace this jump if we later need to
-     * replace the ifFalse jump with a 4 byte jump.
-     */
-
-    jumpBackOffset = (envPtr->codeNext - envPtr->codeStart);
-    jumpBackDist = (jumpBackOffset - testCodeOffset);
-    if (jumpBackDist > 120) {
-	TclEmitInstInt4(INST_JUMP4, -jumpBackDist, envPtr);
-    } else {
-	TclEmitInstInt1(INST_JUMP1, -jumpBackDist, envPtr);
-    }
 
     /*
-     * Fix the target of the jumpFalse after the test.
+     * Compile the test expression then emit the conditional jump that
+     * terminates the for.
      */
 
-    jumpDist = (envPtr->codeNext - envPtr->codeStart)
-	    - jumpFalseFixup.codeOffset;
-    if (TclFixupForwardJump(envPtr, &jumpFalseFixup, jumpDist, 127)) {
-	/*
-	 * Update the loop body and "next" command ExceptionRanges since
-	 * they moved down.
-	 */
-
-	envPtr->exceptArrayPtr[bodyRange].codeOffset += 3;
-	envPtr->exceptArrayPtr[bodyRange].continueOffset += 3;
-	envPtr->exceptArrayPtr[nextRange].codeOffset += 3;
-
-	/*
-	 * Update the jump back to the test at the top of the loop since it
-	 * also moved down 3 bytes.
-	 */
-
-	jumpBackOffset += 3;
-	jumpPc = (envPtr->codeStart + jumpBackOffset);
-	jumpBackDist += 3;
-	if (jumpBackDist > 120) {
-	    TclUpdateInstInt4AtPc(INST_JUMP4, -jumpBackDist, jumpPc);
-	} else {
-	    TclUpdateInstInt1AtPc(INST_JUMP1, -jumpBackDist, jumpPc);
+    testCodeOffset = (envPtr->codeNext - envPtr->codeStart);
+    jumpDist = testCodeOffset - jumpEvalCondFixup.codeOffset;
+    if (TclFixupForwardJump(envPtr, &jumpEvalCondFixup, jumpDist, 127)) {
+	bodyCodeOffset += 3;
+    }
+    
+    envPtr->currStackDepth = savedStackDepth;
+    code = TclCompileExprWords(interp, testTokenPtr, 1, envPtr);
+    if (code != TCL_OK) {
+	if (code == TCL_ERROR) {
+	    Tcl_AddObjErrorInfo(interp,
+				"\n    (\"for\" test expression)", -1);
 	}
+	goto done;
+    }
+    envPtr->currStackDepth = savedStackDepth + 1;
+    
+    jumpDist = (envPtr->codeNext - envPtr->codeStart) - bodyCodeOffset;
+    if (jumpDist > 127) {
+	TclEmitInstInt4(INST_JUMP_TRUE4, -jumpDist, envPtr);
+    } else {
+	TclEmitInstInt1(INST_JUMP_TRUE1, -jumpDist, envPtr);
     }
     
     /*
@@ -689,6 +669,7 @@
      * The for command's result is an empty string.
      */
 
+    envPtr->currStackDepth = savedStackDepth;
     TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0), envPtr);
     code = TCL_OK;
 
@@ -1175,6 +1156,10 @@
                                 /* 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. */
+    char *condStart, *savedPos, savedChar;
+    int realCond = 1;           /* set to 0 for static conditions: "if 0 {..}" */
+    int boolVal;                /* value of static condition */
+    int compileScripts = 1;            
 
     /*
      * Only compile the "if" command if all arguments are simple
@@ -1209,9 +1194,6 @@
 	 * Stop looping if the token isn't "if" or "elseif".
 	 */
 
-	if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
-	    break;
-	}
 	word = tokenPtr[1].start;
 	numBytes = tokenPtr[1].size;
 	if ((tokenPtr == parsePtr->tokenPtr)
@@ -1233,28 +1215,63 @@
 
 	/*
 	 * Compile the test expression then emit the conditional jump
-	 * around the "then" part. If the expression word isn't simple,
-	 * we back off and compile the if command out-of-line.
+	 * around the "then" part. 
 	 */
 	
 	envPtr->currStackDepth = savedStackDepth;
 	testTokenPtr = tokenPtr;
-	code = TclCompileExprWords(interp, testTokenPtr, 1, envPtr);
-	if (code != TCL_OK) {
-	    if (code == TCL_ERROR) {
-		Tcl_AddObjErrorInfo(interp,
-		        "\n    (\"if\" test expression)", -1);
+
+
+	if (realCond) {
+	    /*
+	     * Find out if the condition is a constant. 
+	     */
+	
+	    condStart = testTokenPtr[1].start;
+	    savedPos = condStart + testTokenPtr[1].size - 1;
+	    
+	    while (*condStart == ' ') {
+		condStart++;
+	    }
+	    while (*savedPos == ' ') {
+		savedPos--;
+	    }
+	    savedPos++;
+	    
+	    savedChar = *savedPos;
+	    *savedPos = '\0';
+	    
+	    if (Tcl_GetBoolean(interp, condStart, &boolVal) != TCL_ERROR) { 
+		/*
+		 * A static condition
+		 */
+		*savedPos = savedChar;
+		realCond = 0;
+		if (!boolVal) {
+		    compileScripts = 0;
+		}
+	    } else {
+		*savedPos = savedChar;
+		Tcl_ResetResult(interp);
+		code = TclCompileExprWords(interp, testTokenPtr, 1, envPtr);
+		if (code != TCL_OK) {
+		    if (code == TCL_ERROR) {
+			Tcl_AddObjErrorInfo(interp,
+			        "\n    (\"if\" test expression)", -1);
+		    }
+		    goto done;
+		}
+		if (jumpFalseFixupArray.next >= jumpFalseFixupArray.end) {
+		    TclExpandJumpFixupArray(&jumpFalseFixupArray);
+		}
+		jumpIndex = jumpFalseFixupArray.next;
+		jumpFalseFixupArray.next++;
+		TclEmitForwardJump(envPtr, TCL_FALSE_JUMP,
+			       &(jumpFalseFixupArray.fixup[jumpIndex]));	    
 	    }
-	    goto done;
 	}
-	if (jumpFalseFixupArray.next >= jumpFalseFixupArray.end) {
-	    TclExpandJumpFixupArray(&jumpFalseFixupArray);
-	}
-	jumpIndex = jumpFalseFixupArray.next;
-	jumpFalseFixupArray.next++;
-	TclEmitForwardJump(envPtr, TCL_FALSE_JUMP,
-		&(jumpFalseFixupArray.fixup[jumpIndex]));
-	
+
+
 	/*
 	 * Skip over the optional "then" before the then clause.
 	 */
@@ -1288,49 +1305,68 @@
 	 * Compile the "then" command body.
 	 */
 
-	envPtr->currStackDepth = savedStackDepth;
-	code = TclCompileCmdWord(interp, tokenPtr+1,
-		tokenPtr->numComponents, envPtr);
-	if (code != TCL_OK) {
-	    if (code == TCL_ERROR) {
-		sprintf(buffer, "\n    (\"if\" then script line %d)",
-		        interp->errorLine);
-		Tcl_AddObjErrorInfo(interp, buffer, -1);
-	    }
-	    goto done;
+	if (compileScripts) {
+	    envPtr->currStackDepth = savedStackDepth;
+	    code = TclCompileCmdWord(interp, tokenPtr+1,
+	            tokenPtr->numComponents, envPtr);
+	    if (code != TCL_OK) {
+		if (code == TCL_ERROR) {
+		    sprintf(buffer, "\n    (\"if\" then script line %d)",
+		            interp->errorLine);
+		    Tcl_AddObjErrorInfo(interp, buffer, -1);
+		}
+		goto done;
+	    }	
 	}
 
-	/*
-	 * Jump to the end of the "if" command. Both jumpFalseFixupArray and
-	 * jumpEndFixupArray are indexed by "jumpIndex".
-	 */
+	if (realCond) {
+	    /*
+	     * Jump to the end of the "if" command. Both jumpFalseFixupArray and
+	     * jumpEndFixupArray are indexed by "jumpIndex".
+	     */
+	    
+	    if (jumpEndFixupArray.next >= jumpEndFixupArray.end) {
+		TclExpandJumpFixupArray(&jumpEndFixupArray);
+	    }
+	    jumpEndFixupArray.next++;
+	    TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP,
+	            &(jumpEndFixupArray.fixup[jumpIndex]));
+	    
+	    /*
+	     * Fix the target of the jumpFalse after the test. Generate a 4 byte
+	     * jump if the distance is > 120 bytes. This is conservative, and
+	     * ensures that we won't have to replace this jump if we later also
+	     * need to replace the proceeding jump to the end of the "if" with a
+	     * 4 byte jump.
+	     */
 
-	if (jumpEndFixupArray.next >= jumpEndFixupArray.end) {
-	    TclExpandJumpFixupArray(&jumpEndFixupArray);
-	}
-	jumpEndFixupArray.next++;
-	TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP,
-		&(jumpEndFixupArray.fixup[jumpIndex]));
-
- 	/*
-	 * Fix the target of the jumpFalse after the test. Generate a 4 byte
-	 * jump if the distance is > 120 bytes. This is conservative, and
-	 * ensures that we won't have to replace this jump if we later also
-	 * need to replace the proceeding jump to the end of the "if" with a
-	 * 4 byte jump.
-	 */
+	    jumpDist = (envPtr->codeNext - envPtr->codeStart)
+	            - jumpFalseFixupArray.fixup[jumpIndex].codeOffset;
+	    if (TclFixupForwardJump(envPtr,
+	            &(jumpFalseFixupArray.fixup[jumpIndex]), jumpDist, 120)) {
+		/*
+		 * Adjust the code offset for the proceeding jump to the end
+		 * of the "if" command.
+		 */
+		
+		jumpEndFixupArray.fixup[jumpIndex].codeOffset += 3;
+	    }
+	} else if (boolVal) {
+	    /* 
+	     *We were processing an "if 1 {...}"; stop compiling
+	     * scripts
+	     */
 
-	jumpDist = (envPtr->codeNext - envPtr->codeStart)
-	        - jumpFalseFixupArray.fixup[jumpIndex].codeOffset;
-	if (TclFixupForwardJump(envPtr,
-	        &(jumpFalseFixupArray.fixup[jumpIndex]), jumpDist, 120)) {
-	    /*
-	     * Adjust the code offset for the proceeding jump to the end
-	     * of the "if" command.
+	    compileScripts = 0;
+	} else {
+	    /* 
+	     *We were processing an "if 0 {...}"; reset so that
+	     * the rest (elseif, else) is compiled correctly
 	     */
 
-	    jumpEndFixupArray.fixup[jumpIndex].codeOffset += 3;
-	}
+	    realCond = 1;
+	    compileScripts = 1;
+	} 
 
 	tokenPtr += (tokenPtr->numComponents + 1);
 	wordIdx++;
@@ -1344,7 +1380,8 @@
     envPtr->currStackDepth = savedStackDepth;
 
     /*
-     * Check for the optional else clause.
+     * Check for the optional else clause. Do not compile
+     * anything if this was an "if 1 {...}" case.
      */
 
     if ((wordIdx < numWords)
@@ -1367,19 +1404,21 @@
 	    }
 	}
 
-	/*
-	 * Compile the else command body.
-	 */
-	
-	code = TclCompileCmdWord(interp, tokenPtr+1,
-		tokenPtr->numComponents, envPtr);
-	if (code != TCL_OK) {
-	    if (code == TCL_ERROR) {
-		sprintf(buffer, "\n    (\"if\" else script line %d)",
-			interp->errorLine);
-		Tcl_AddObjErrorInfo(interp, buffer, -1);
+	if (compileScripts) {
+	    /*
+	     * Compile the else command body.
+	     */
+	    
+	    code = TclCompileCmdWord(interp, tokenPtr+1,
+		    tokenPtr->numComponents, envPtr);
+	    if (code != TCL_OK) {
+		if (code == TCL_ERROR) {
+		    sprintf(buffer, "\n    (\"if\" else script line %d)",
+			    interp->errorLine);
+		    Tcl_AddObjErrorInfo(interp, buffer, -1);
+		}
+		goto done;
 	    }
-	    goto done;
 	}
 
 	/*
@@ -1399,7 +1438,9 @@
 	 * No else clause: the "if" command's result is an empty string.
 	 */
 
-	TclEmitPush(TclRegisterLiteral(envPtr, "", 0,/*onHeap*/ 0), envPtr);
+	if (compileScripts) {
+	    TclEmitPush(TclRegisterLiteral(envPtr, "", 0,/*onHeap*/ 0), envPtr);
+	}
     }
 
     /*
@@ -2834,12 +2875,15 @@
     CompileEnv *envPtr;		/* Holds resulting instructions. */
 {
     Tcl_Token *testTokenPtr, *bodyTokenPtr;
-    JumpFixup jumpFalseFixup;
-    unsigned char *jumpPc;
-    int testCodeOffset, jumpDist, jumpBackDist, jumpBackOffset;
+    JumpFixup jumpEvalCondFixup;
+    int testCodeOffset, bodyCodeOffset, jumpDist;
     int range, code;
     char buffer[32 + TCL_INTEGER_SPACE];
     int savedStackDepth = envPtr->currStackDepth;
+    int finiteLoop = 1;
+    int boolVal;
+    char *condStart;
+    char savedChar, *savedPos;
 
     if (parsePtr->numWords != 3) {
 	Tcl_ResetResult(interp);
@@ -2866,6 +2910,41 @@
     }
 
     /*
+     * Find out if the condition is a constant. 
+     */
+
+    condStart = testTokenPtr[1].start;
+    savedPos = condStart + testTokenPtr[1].size - 1;
+
+    while (*condStart == ' ') {
+	condStart++;
+    }
+    while (*savedPos == ' ') {
+	savedPos--;
+    }
+    savedPos++;
+
+    savedChar = *savedPos;
+    *savedPos = '\0';
+    
+    if (Tcl_GetBoolean(interp, condStart, &boolVal) != TCL_ERROR) { 
+	if (boolVal) {
+	    finiteLoop = 0;
+	} else {
+	    /*
+	     * This is an empty loop: "while 0 {...}" or such.
+	     * Compile no bytecodes.
+	     */
+
+	    *savedPos = savedChar;
+	    goto pushResult;
+	}
+    } else {
+	Tcl_ResetResult(interp);	
+    }
+    *savedPos = savedChar;
+	
+    /* 
      * Create a ExceptionRange record for the loop body. This is used to
      * implement break and continue.
      */
@@ -2874,34 +2953,32 @@
     envPtr->maxExceptDepth =
 	TclMax(envPtr->exceptDepth, envPtr->maxExceptDepth);
     range = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr);
-    envPtr->exceptArrayPtr[range].continueOffset =
-	    (envPtr->codeNext - envPtr->codeStart);
 
     /*
-     * Compile the test expression then emit the conditional jump that
-     * terminates the while. We already know it's a simple word.
+     * Jump to the evaluation of the condition. This code uses the "loop
+     * rotation" optimisation (which eliminates one branch from the loop).
+     * "while cond body" produces then:
+     *       goto A
+     *    B: body
+     *    A: cond -> result
+     *       if (result) goto B
      */
 
-    testCodeOffset = (envPtr->codeNext - envPtr->codeStart);
-    envPtr->exceptArrayPtr[range].continueOffset = testCodeOffset;
-    code = TclCompileExprWords(interp, testTokenPtr, 1, envPtr);
-    if (code != TCL_OK) {
-	if (code == TCL_ERROR) {
-            Tcl_AddObjErrorInfo(interp,
-		    "\n    (\"while\" test expression)", -1);
-        }
-	goto error;
+    if (finiteLoop) {
+	TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpEvalCondFixup);
+    } else {
+	testCodeOffset = (envPtr->codeNext - envPtr->codeStart);
+	envPtr->exceptArrayPtr[range].continueOffset = testCodeOffset;
     }
-    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);
+    bodyCodeOffset = (envPtr->codeNext - envPtr->codeStart);
+    envPtr->exceptArrayPtr[range].codeOffset = bodyCodeOffset;
+
     code = TclCompileCmdWord(interp, bodyTokenPtr+1,
 	    bodyTokenPtr->numComponents, envPtr);
     envPtr->currStackDepth = savedStackDepth + 1;
@@ -2914,53 +2991,49 @@
 	goto error;
     }
     envPtr->exceptArrayPtr[range].numCodeBytes =
-	    (envPtr->codeNext - envPtr->codeStart)
-	    - envPtr->exceptArrayPtr[range].codeOffset;
+	    (envPtr->codeNext - envPtr->codeStart) - bodyCodeOffset;
     TclEmitOpcode(INST_POP, envPtr);
-	
-    /*
-     * Jump back to the test at the top of the loop. Generate a 4 byte jump
-     * if the distance to the test is > 120 bytes. This is conservative and
-     * ensures that we won't have to replace this jump if we later need to
-     * replace the ifFalse jump with a 4 byte jump.
-     */
-
-    jumpBackOffset = (envPtr->codeNext - envPtr->codeStart);
-    jumpBackDist = (jumpBackOffset - testCodeOffset);
-    if (jumpBackDist > 120) {
-	TclEmitInstInt4(INST_JUMP4, -jumpBackDist, envPtr);
-    } else {
-	TclEmitInstInt1(INST_JUMP1, -jumpBackDist, envPtr);
-    }
 
     /*
-     * Fix the target of the jumpFalse after the test. 
+     * Compile the test expression then emit the conditional jump that
+     * terminates the while. We already know it's a simple word.
      */
 
-    jumpDist = (envPtr->codeNext - envPtr->codeStart)
-	    - jumpFalseFixup.codeOffset;
-    if (TclFixupForwardJump(envPtr, &jumpFalseFixup, jumpDist, 127)) {
-	/*
-	 * Update the loop body's starting PC offset since it moved down.
-	 */
-
-	envPtr->exceptArrayPtr[range].codeOffset += 3;
-
-	/*
-	 * Update the jump back to the test at the top of the loop since it
-	 * also moved down 3 bytes.
-	 */
-
-	jumpBackOffset += 3;
-	jumpPc = (envPtr->codeStart + jumpBackOffset);
-	jumpBackDist += 3;
-	if (jumpBackDist > 120) {
-	    TclUpdateInstInt4AtPc(INST_JUMP4, -jumpBackDist, jumpPc);
+    if (finiteLoop) {
+	testCodeOffset = (envPtr->codeNext - envPtr->codeStart);
+	envPtr->exceptArrayPtr[range].continueOffset = testCodeOffset;
+	jumpDist = testCodeOffset - jumpEvalCondFixup.codeOffset;
+	if (TclFixupForwardJump(envPtr, &jumpEvalCondFixup, jumpDist, 127)) {
+	    bodyCodeOffset += 3;
+	}
+	
+	envPtr->currStackDepth = savedStackDepth;
+	code = TclCompileExprWords(interp, testTokenPtr, 1, envPtr);
+	if (code != TCL_OK) {
+	    if (code == TCL_ERROR) {
+		Tcl_AddObjErrorInfo(interp,
+				    "\n    (\"while\" test expression)", -1);
+	    }
+	    goto error;
+	}
+	envPtr->currStackDepth = savedStackDepth + 1;
+    
+	jumpDist = (envPtr->codeNext - envPtr->codeStart) - bodyCodeOffset;
+	if (jumpDist > 127) {
+	    TclEmitInstInt4(INST_JUMP_TRUE4, -jumpDist, envPtr);
 	} else {
-	    TclUpdateInstInt1AtPc(INST_JUMP1, -jumpBackDist, jumpPc);
+	    TclEmitInstInt1(INST_JUMP_TRUE1, -jumpDist, envPtr);
 	}
+    } else {
+	jumpDist = (envPtr->codeNext - envPtr->codeStart) - bodyCodeOffset;
+	if (jumpDist > 127) {
+	    TclEmitInstInt4(INST_JUMP4, -jumpDist, envPtr);
+	} else {
+	    TclEmitInstInt1(INST_JUMP1, -jumpDist, envPtr);
+	}	
     }
 
+
     /*
      * Set the loop's break target.
      */
@@ -2972,6 +3045,7 @@
      * The while command's result is an empty string.
      */
 
+    pushResult:
     envPtr->currStackDepth = savedStackDepth;
     TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0), envPtr);
     envPtr->exceptDepth--;