Bug 1227677 - Rename the misnomer |letDecl| variable associated with for-in/of loop variables to |letBlockScope|, as that's much closer to its actual meaning. (Notably, |for (let x of []);| does *not* mean |*letDecl|.) r=shu
authorJeff Walden <jwalden@mit.edu>
Tue, 24 Nov 2015 11:00:44 -0800
changeset 309917 781b2dc8f21621fed3f5cadbaebcb110e5736369
parent 309916 e17be37dbd32eefe47f41395aa89d7353dec4b55
child 309918 1d30a3fecc3a9f29dd0c4215f8b0f2618a27d4b4
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshu
bugs1227677
milestone45.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 1227677 - Rename the misnomer |letDecl| variable associated with for-in/of loop variables to |letBlockScope|, as that's much closer to its actual meaning. (Notably, |for (let x of []);| does *not* mean |*letDecl|.) r=shu
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/BytecodeEmitter.h
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -5377,41 +5377,41 @@ BytecodeEmitter::emitIterator()
         return false;
     if (!emitCall(JSOP_CALL, 0))                                  // ITER
         return false;
     checkTypeSet(JSOP_CALL);
     return true;
 }
 
 bool
-BytecodeEmitter::emitForInOrOfVariables(ParseNode* pn, bool* letDecl)
+BytecodeEmitter::emitForInOrOfVariables(ParseNode* pn, bool* letBlockScope)
 {
     // ES6 specifies that loop variables get a fresh binding in each iteration.
     // This is currently implemented for C-style for(;;) loops, but not
     // for-in/of loops, though a similar approach should work. See bug 449811.
     //
     // In `for (let x in/of EXPR)`, ES6 specifies that EXPR is evaluated in a
     // scope containing an uninitialized `x`. If EXPR accesses `x`, we should
     // get a ReferenceError due to the TDZ violation. This is not yet
     // implemented. See bug 1069480.
 
-    *letDecl = pn->isKind(PNK_LEXICALSCOPE);
-    MOZ_ASSERT_IF(*letDecl, pn->isLexical());
+    *letBlockScope = pn->isKind(PNK_LEXICALSCOPE);
+    MOZ_ASSERT_IF(*letBlockScope, pn->isLexical());
 
     // If the left part is 'var x', emit code to define x if necessary using a
     // prologue opcode, but do not emit a pop. If it is 'let x', enterBlockScope
     // will initialize let bindings in emitForOf and emitForIn with
     // undefineds.
     //
     // Due to the horror of legacy comprehensions, there is a third case where
     // we have PNK_LET without a lexical scope, because those expressions are
     // parsed with single lexical scope for the entire comprehension. In this
     // case we must initialize the lets to not trigger dead zone checks via
     // InitializeVars.
-    if (!*letDecl) {
+    if (!*letBlockScope) {
         emittingForInit = true;
         if (pn->isKind(PNK_VAR)) {
             if (!emitVariables(pn, DefineVars))
                 return false;
         } else {
             MOZ_ASSERT(pn->isKind(PNK_LET));
             if (!emitVariables(pn, InitializeVars))
                 return false;
@@ -5436,18 +5436,18 @@ BytecodeEmitter::emitForOf(StmtType type
 #endif
 
     ptrdiff_t top = offset();
     ParseNode* forHead = pn ? pn->pn_left : nullptr;
     ParseNode* forHeadExpr = forHead ? forHead->pn_kid3 : nullptr;
     ParseNode* forBody = pn ? pn->pn_right : nullptr;
 
     ParseNode* loopDecl = forHead ? forHead->pn_kid1 : nullptr;
-    bool letDecl = false;
-    if (loopDecl && !emitForInOrOfVariables(loopDecl, &letDecl))
+    bool letBlockScope = false;
+    if (loopDecl && !emitForInOrOfVariables(loopDecl, &letBlockScope))
         return false;
 
     if (type == StmtType::FOR_OF_LOOP) {
         // For-of loops run with two values on the stack: the iterator and the
         // current result object.
 
         // Compile the object expression to the right of 'of'.
         if (!emitTree(forHeadExpr))
@@ -5459,17 +5459,17 @@ BytecodeEmitter::emitForOf(StmtType type
         if (!emit1(JSOP_UNDEFINED))                // ITER RESULT
             return false;
     }
 
     // Enter the block before the loop body, after evaluating the obj.
     // Initialize let bindings with undefined when entering, as the name
     // assigned to is a plain assignment.
     StmtInfoBCE letStmt(cx);
-    if (letDecl) {
+    if (letBlockScope) {
         if (!enterBlockScope(&letStmt, loopDecl->pn_objbox, JSOP_UNDEFINED, 0))
             return false;
     }
 
     LoopStmtInfo stmtInfo(cx);
     pushLoopStatement(&stmtInfo, type, top);
 
     // Jump down to the loop condition to minimize overhead assuming at least
@@ -5561,17 +5561,17 @@ BytecodeEmitter::emitForOf(StmtType type
 
     // Fixup breaks and continues.
     // For StmtType::SPREAD, just pop innermostStmt().
     popStatement();
 
     if (!tryNoteList.append(JSTRY_FOR_OF, stackDepth, top, offset()))
         return false;
 
-    if (letDecl) {
+    if (letBlockScope) {
         if (!leaveNestedScope(&letStmt))
             return false;
     }
 
     if (type == StmtType::SPREAD) {
         if (!emit2(JSOP_PICK, 3))      // ARR I RESULT ITER
             return false;
     }
@@ -5583,18 +5583,18 @@ BytecodeEmitter::emitForOf(StmtType type
 bool
 BytecodeEmitter::emitForIn(ParseNode* pn)
 {
     ptrdiff_t top = offset();
     ParseNode* forHead = pn->pn_left;
     ParseNode* forBody = pn->pn_right;
 
     ParseNode* loopDecl = forHead->pn_kid1;
-    bool letDecl = false;
-    if (loopDecl && !emitForInOrOfVariables(loopDecl, &letDecl))
+    bool letBlockScope = false;
+    if (loopDecl && !emitForInOrOfVariables(loopDecl, &letBlockScope))
         return false;
 
     /* Compile the object expression to the right of 'in'. */
     if (!emitTree(forHead->pn_kid3))
         return false;
 
     /*
      * Emit a bytecode to convert top of stack value to the iterator
@@ -5609,17 +5609,17 @@ BytecodeEmitter::emitForIn(ParseNode* pn
     // undefined to balance the stack.
     if (!emit1(JSOP_UNDEFINED))
         return false;
 
     // Enter the block before the loop body, after evaluating the obj.
     // Initialize let bindings with undefined when entering, as the name
     // assigned to is a plain assignment.
     StmtInfoBCE letStmt(cx);
-    if (letDecl) {
+    if (letBlockScope) {
         if (!enterBlockScope(&letStmt, loopDecl->pn_objbox, JSOP_UNDEFINED, 0))
             return false;
     }
 
     LoopStmtInfo stmtInfo(cx);
     pushLoopStatement(&stmtInfo, StmtType::FOR_IN_LOOP, top);
 
     /* Annotate so IonMonkey can find the loop-closing jump. */
@@ -5689,17 +5689,17 @@ BytecodeEmitter::emitForIn(ParseNode* pn
     if (!emit1(JSOP_POP))
         return false;
 
     if (!tryNoteList.append(JSTRY_FOR_IN, this->stackDepth, top, offset()))
         return false;
     if (!emit1(JSOP_ENDITER))
         return false;
 
-    if (letDecl) {
+    if (letBlockScope) {
         if (!leaveNestedScope(&letStmt))
             return false;
     }
 
     return true;
 }
 
 /* C-style `for (init; cond; update) ...` loop. */
@@ -5892,41 +5892,41 @@ BytecodeEmitter::emitFor(ParseNode* pn)
     if (pn->pn_left->isKind(PNK_FORIN))
         return emitForIn(pn);
 
     MOZ_ASSERT(pn->pn_left->isKind(PNK_FOROF));
     return emitForOf(StmtType::FOR_OF_LOOP, pn);
 }
 
 bool
-BytecodeEmitter::emitComprehensionForInOrOfVariables(ParseNode* pn, bool* letDecl)
+BytecodeEmitter::emitComprehensionForInOrOfVariables(ParseNode* pn, bool* letBlockScope)
 {
     // ES6 specifies that loop variables get a fresh binding in each iteration.
     // This is currently implemented for C-style for(;;) loops, but not
     // for-in/of loops, though a similar approach should work. See bug 449811.
     //
     // In `for (let x in/of EXPR)`, ES6 specifies that EXPR is evaluated in a
     // scope containing an uninitialized `x`. If EXPR accesses `x`, we should
     // get a ReferenceError due to the TDZ violation. This is not yet
     // implemented. See bug 1069480.
 
-    *letDecl = pn->isKind(PNK_LEXICALSCOPE);
-    MOZ_ASSERT_IF(*letDecl, pn->isLexical());
+    *letBlockScope = pn->isKind(PNK_LEXICALSCOPE);
+    MOZ_ASSERT_IF(*letBlockScope, pn->isLexical());
 
     // If the left part is 'var x', emit code to define x if necessary using a
     // prologue opcode, but do not emit a pop. If it is 'let x', enterBlockScope
     // will initialize let bindings in emitForOf and emitForIn with
     // undefineds.
     //
     // Due to the horror of legacy comprehensions, there is a third case where
     // we have PNK_LET without a lexical scope, because those expressions are
     // parsed with single lexical scope for the entire comprehension. In this
     // case we must initialize the lets to not trigger dead zone checks via
     // InitializeVars.
-    if (!*letDecl) {
+    if (!*letBlockScope) {
         emittingForInit = true;
         if (pn->isKind(PNK_VAR)) {
             if (!emitVariables(pn, DefineVars))
                 return false;
         } else {
             MOZ_ASSERT(pn->isKind(PNK_LET));
             if (!emitVariables(pn, InitializeVars))
                 return false;
@@ -5937,28 +5937,27 @@ BytecodeEmitter::emitComprehensionForInO
     return true;
 }
 
 bool
 BytecodeEmitter::emitComprehensionForOf(ParseNode* pn)
 {
     MOZ_ASSERT(pn->isKind(PNK_COMPREHENSIONFOR));
 
-    ParseNode* forHead = pn ? pn->pn_left : nullptr;
+    ParseNode* forHead = pn->pn_left;
     MOZ_ASSERT(forHead->isKind(PNK_FOROF));
 
-    ParseNode* forHeadExpr = forHead ? forHead->pn_kid3 : nullptr;
-
-    ParseNode* forBody = pn ? pn->pn_right : nullptr;
+    ParseNode* forHeadExpr = forHead->pn_kid3;
+    ParseNode* forBody = pn->pn_right;
 
     ptrdiff_t top = offset();
 
-    ParseNode* loopDecl = forHead ? forHead->pn_kid1 : nullptr;
-    bool letDecl = false;
-    if (loopDecl && !emitComprehensionForInOrOfVariables(loopDecl, &letDecl))
+    ParseNode* loopDecl = forHead->pn_kid1;
+    bool letBlockScope = false;
+    if (loopDecl && !emitComprehensionForInOrOfVariables(loopDecl, &letBlockScope))
         return false;
 
     // For-of loops run with two values on the stack: the iterator and the
     // current result object.
 
     // Compile the object expression to the right of 'of'.
     if (!emitTree(forHeadExpr))                // EXPR
         return false;
@@ -5968,17 +5967,17 @@ BytecodeEmitter::emitComprehensionForOf(
     // Push a dummy result so that we properly enter iteration midstream.
     if (!emit1(JSOP_UNDEFINED))                // ITER RESULT
         return false;
 
     // Enter the block before the loop body, after evaluating the obj.
     // Initialize let bindings with undefined when entering, as the name
     // assigned to is a plain assignment.
     StmtInfoBCE letStmt(cx);
-    if (letDecl) {
+    if (letBlockScope) {
         if (!enterBlockScope(&letStmt, loopDecl->pn_objbox, JSOP_UNDEFINED, 0))
             return false;
     }
 
     LoopStmtInfo stmtInfo(cx);
     pushLoopStatement(&stmtInfo, StmtType::FOR_OF_LOOP, top);
 
     // Jump down to the loop condition to minimize overhead assuming at least
@@ -6050,17 +6049,17 @@ BytecodeEmitter::emitComprehensionForOf(
         return false;
 
     // Fixup breaks and continues.
     popStatement();
 
     if (!tryNoteList.append(JSTRY_FOR_OF, stackDepth, top, offset()))
         return false;
 
-    if (letDecl) {
+    if (letBlockScope) {
         if (!leaveNestedScope(&letStmt))
             return false;
     }
 
     // Pop the result and the iter.
     return emitUint16Operand(JSOP_POPN, 2);               //
 }
 
@@ -6072,18 +6071,18 @@ BytecodeEmitter::emitComprehensionForIn(
     ptrdiff_t top = offset();
 
     ParseNode* forHead = pn->pn_left;
     MOZ_ASSERT(forHead->isKind(PNK_FORIN));
 
     ParseNode* forBody = pn->pn_right;
 
     ParseNode* loopDecl = forHead->pn_kid1;
-    bool letDecl = false;
-    if (loopDecl && !emitComprehensionForInOrOfVariables(loopDecl, &letDecl))
+    bool letBlockScope = false;
+    if (loopDecl && !emitComprehensionForInOrOfVariables(loopDecl, &letBlockScope))
         return false;
 
     /* Compile the object expression to the right of 'in'. */
     if (!emitTree(forHead->pn_kid3))
         return false;
 
     /*
      * Emit a bytecode to convert top of stack value to the iterator
@@ -6098,17 +6097,17 @@ BytecodeEmitter::emitComprehensionForIn(
     // undefined to balance the stack.
     if (!emit1(JSOP_UNDEFINED))
         return false;
 
     // Enter the block before the loop body, after evaluating the obj.
     // Initialize let bindings with undefined when entering, as the name
     // assigned to is a plain assignment.
     StmtInfoBCE letStmt(cx);
-    if (letDecl) {
+    if (letBlockScope) {
         if (!enterBlockScope(&letStmt, loopDecl->pn_objbox, JSOP_UNDEFINED, 0))
             return false;
     }
 
     LoopStmtInfo stmtInfo(cx);
     pushLoopStatement(&stmtInfo, StmtType::FOR_IN_LOOP, top);
 
     /* Annotate so IonMonkey can find the loop-closing jump. */
@@ -6178,17 +6177,17 @@ BytecodeEmitter::emitComprehensionForIn(
     if (!emit1(JSOP_POP))
         return false;
 
     if (!tryNoteList.append(JSTRY_FOR_IN, this->stackDepth, top, offset()))
         return false;
     if (!emit1(JSOP_ENDITER))
         return false;
 
-    if (letDecl) {
+    if (letBlockScope) {
         if (!leaveNestedScope(&letStmt))
             return false;
     }
 
     return true;
 }
 
 bool
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -598,23 +598,23 @@ struct BytecodeEmitter
 
     bool emitCallOrNew(ParseNode* pn);
     bool emitSelfHostedCallFunction(ParseNode* pn);
     bool emitSelfHostedResumeGenerator(ParseNode* pn);
     bool emitSelfHostedForceInterpreter(ParseNode* pn);
 
     bool emitComprehensionFor(ParseNode* compFor);
     bool emitComprehensionForIn(ParseNode* pn);
-    bool emitComprehensionForInOrOfVariables(ParseNode* pn, bool* letDecl);
+    bool emitComprehensionForInOrOfVariables(ParseNode* pn, bool* letBlockScope);
     bool emitComprehensionForOf(ParseNode* pn);
 
     bool emitDo(ParseNode* pn);
     bool emitFor(ParseNode* pn);
     bool emitForIn(ParseNode* pn);
-    bool emitForInOrOfVariables(ParseNode* pn, bool* letDecl);
+    bool emitForInOrOfVariables(ParseNode* pn, bool* letBlockScope);
     bool emitCStyleFor(ParseNode* pn);
     bool emitWhile(ParseNode* pn);
 
     bool emitBreak(PropertyName* label);
     bool emitContinue(PropertyName* label);
 
     bool emitArgsBody(ParseNode* pn);
     bool emitDefaultsAndDestructuring(ParseNode* pn);