Bug 927782 - Part 6: Fix for-let nesting so nonlocal exits are easier. r=luke
☠☠ backed out by 94cdaced90bf ☠ ☠
authorAndy Wingo <wingo@igalia.com>
Tue, 26 Nov 2013 10:13:59 +0100
changeset 173969 f1237f11edcd1fc743d843fa902d086c31523576
parent 173968 d6946bd743b38c99c82eb45cf9203423cda9467c
child 173970 8c74b1f68590e7791ec4a13f2e12196caf053709
push id3224
push userlsblakk@mozilla.com
push dateTue, 04 Feb 2014 01:06:49 +0000
treeherdermozilla-beta@60c04d0987f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs927782
milestone28.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 927782 - Part 6: Fix for-let nesting so nonlocal exits are easier. r=luke
js/src/frontend/BytecodeEmitter.cpp
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -572,45 +572,21 @@ EmitNonLocalJumpFixup(ExclusiveContext *
             npops += 2;
             break;
 
           default:;
         }
 
         if (stmt->isBlockScope) {
             FLUSH_POPS();
-            unsigned blockObjCount = stmt->blockObj->slotCount();
-            if (stmt->isForLetBlock) {
-                /*
-                 * For a for-let-in/of statement, pushing/popping the block is
-                 * interleaved with JSOP_(END)ITER. Just handle both together
-                 * here and skip over the enclosing STMT_FOR_IN_LOOP.
-                 */
-                unsigned popCount = blockObjCount;
-                stmt = stmt->down;
-                if (stmt == toStmt)
-                    break;
-                if (Emit1(cx, bce, JSOP_DEBUGLEAVEBLOCK) < 0)
-                    return false;
-                if (Emit1(cx, bce, JSOP_LEAVEFORLETIN) < 0)
-                    return false;
-                if (stmt->type == STMT_FOR_OF_LOOP) {
-                    popCount += 2;
-                } else {
-                    JS_ASSERT(stmt->type == STMT_FOR_IN_LOOP);
-                    if (!PopIterator(cx, bce))
-                        return false;
-                }
-                EMIT_UINT16_IMM_OP(JSOP_POPN, popCount);
-            } else {
-                /* There is a Block object with locals on the stack to pop. */
-                if (Emit1(cx, bce, JSOP_DEBUGLEAVEBLOCK) < 0)
-                    return false;
-                EMIT_UINT16_IMM_OP(JSOP_LEAVEBLOCK, blockObjCount);
-            }
+            JS_ASSERT(stmt->blockObj);
+            StaticBlockObject &blockObj = *stmt->blockObj;
+            if (Emit1(cx, bce, JSOP_DEBUGLEAVEBLOCK) < 0)
+                return false;
+            EMIT_UINT16_IMM_OP(JSOP_LEAVEBLOCK, blockObj.slotCount());
         }
     }
 
     FLUSH_POPS();
     bce->stackDepth = depth;
     return true;
 
 #undef FLUSH_POPS
@@ -4262,19 +4238,16 @@ EmitWith(ExclusiveContext *cx, BytecodeE
     if (Emit1(cx, bce, JSOP_LEAVEWITH) < 0)
         return false;
     return PopStatementBCE(cx, bce);
 }
 
 static bool
 EmitForOf(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
 {
-    StmtInfoBCE stmtInfo(cx);
-    PushStatementBCE(bce, &stmtInfo, STMT_FOR_OF_LOOP, top);
-
     ParseNode *forHead = pn->pn_left;
     ParseNode *forBody = pn->pn_right;
 
     ParseNode *pn1 = forHead->pn_kid1;
     bool letDecl = pn1 && pn1->isKind(PNK_LEXICALSCOPE);
     JS_ASSERT_IF(letDecl, pn1->isLet());
 
     Rooted<StaticBlockObject*>
@@ -4321,21 +4294,23 @@ EmitForOf(ExclusiveContext *cx, Bytecode
     if (Emit1(cx, bce, JSOP_UNDEFINED) < 0)                    // ITER RESULT
         return false;
 
     // Enter the block before the loop body, after evaluating the obj.
     StmtInfoBCE letStmt(cx);
     if (letDecl) {
         if (!PushBlockScopeBCE(bce, &letStmt, pn1->pn_objbox, bce->offset()))
             return false;
-        letStmt.isForLetBlock = true;
         if (!EmitEnterBlock(cx, bce, pn1, JSOP_ENTERLET2))
             return false;
     }
 
+    StmtInfoBCE stmtInfo(cx);
+    PushStatementBCE(bce, &stmtInfo, STMT_FOR_OF_LOOP, top);
+
     // Jump down to the loop condition to minimize overhead assuming at least
     // one iteration, as the other loop forms do.  Annotate so IonMonkey can
     // find the loop-closing jump.
     int noteIndex = NewSrcNote(cx, bce, SRC_FOR_OF);
     if (noteIndex < 0)
         return false;
     ptrdiff_t jmp = EmitJump(cx, bce, JSOP_GOTO, 0);
     if (jmp < 0)
@@ -4429,19 +4404,16 @@ EmitForOf(ExclusiveContext *cx, Bytecode
     EMIT_UINT16_IMM_OP(JSOP_POPN, blockObjCount + 2);
 
     return true;
 }
 
 static bool
 EmitForIn(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
 {
-    StmtInfoBCE stmtInfo(cx);
-    PushStatementBCE(bce, &stmtInfo, STMT_FOR_IN_LOOP, top);
-
     ParseNode *forHead = pn->pn_left;
     ParseNode *forBody = pn->pn_right;
 
     ParseNode *pn1 = forHead->pn_kid1;
     bool letDecl = pn1 && pn1->isKind(PNK_LEXICALSCOPE);
     JS_ASSERT_IF(letDecl, pn1->isLet());
 
     Rooted<StaticBlockObject*>
@@ -4500,21 +4472,23 @@ EmitForIn(ExclusiveContext *cx, Bytecode
     if (Emit2(cx, bce, JSOP_ITER, (uint8_t) pn->pn_iflags) < 0)
         return false;
 
     /* Enter the block before the loop body, after evaluating the obj. */
     StmtInfoBCE letStmt(cx);
     if (letDecl) {
         if (!PushBlockScopeBCE(bce, &letStmt, pn1->pn_objbox, bce->offset()))
             return false;
-        letStmt.isForLetBlock = true;
         if (!EmitEnterBlock(cx, bce, pn1, JSOP_ENTERLET1))
             return false;
     }
 
+    StmtInfoBCE stmtInfo(cx);
+    PushStatementBCE(bce, &stmtInfo, STMT_FOR_IN_LOOP, top);
+
     /* Annotate so IonMonkey can find the loop-closing jump. */
     int noteIndex = NewSrcNote(cx, bce, SRC_FOR_IN);
     if (noteIndex < 0)
         return false;
 
     /*
      * Jump down to the loop condition to minimize overhead assuming at
      * least one iteration, as the other loop forms do.