Bug 1217001 - Part 9: Remove PNX_POPVAR. r=shu.
authorJason Orendorff <jorendorff@mozilla.com>
Wed, 14 Oct 2015 17:26:16 -0500
changeset 305302 f7d59de65bcd8300135a7abbd1aef8fb4a526592
parent 305301 1e0dcdea04ffe410ee31a565b80de1e1ab4c9093
child 305303 8bb80a132a0c33b0abb63b9026888e615ae712ae
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshu
bugs1217001
milestone44.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 1217001 - Part 9: Remove PNX_POPVAR. r=shu.
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/ParseNode.h
js/src/frontend/Parser.cpp
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -4250,17 +4250,16 @@ BytecodeEmitter::emitVariables(ParseNode
             } else {
                 // We're emitting destructuring let binding initialization
                 // for a legacy comprehension expression. See
                 // emitForInOrOfVariables.
 
                 // Lexical bindings cannot be used before they are
                 // initialized. Similar to the JSOP_INITLEXICAL case below.
                 MOZ_ASSERT(emitOption == InitializeVars);
-                MOZ_ASSERT(pn->pn_xflags & PNX_POPVAR);
                 if (!emit1(JSOP_UNDEFINED))
                     return false;
                 if (!emitInitializeDestructuringDecls(pn->getOp(), binding))
                     return false;
                 if (!emit1(JSOP_POP))
                     return false;
             }
         } else if (binding->isKind(PNK_ASSIGN)) {
@@ -4289,18 +4288,16 @@ BytecodeEmitter::emitVariables(ParseNode
                 return false;
 
             if (!emitTree(binding->pn_right))
                 return false;
 
             if (!emitDestructuringOps(initializer, isLetExpr))
                 return false;
 
-            MOZ_ASSERT_IF(emitOption == InitializeVars, pn->pn_xflags & PNX_POPVAR);
-            MOZ_ASSERT_IF(pn->pn_xflags & PNX_POPVAR, emitOption == InitializeVars);
             if (emitOption == InitializeVars) {
                 if (!emit1(JSOP_POP))
                     return false;
             }
         } else {
             /*
              * Load initializer early to share code above that jumps to
              * do_name. NB: if this var redeclares an existing binding, then
@@ -4347,25 +4344,22 @@ BytecodeEmitter::emitVariables(ParseNode
                 emittingForInit = false;
                 if (!emitTree(initializer))
                     return false;
                 emittingForInit = oldEmittingForInit;
             } else if (op == JSOP_INITLEXICAL || op == JSOP_INITGLEXICAL || isLetExpr) {
                 // 'let' bindings cannot be used before they are
                 // initialized. JSOP_INITLEXICAL distinguishes the binding site.
                 MOZ_ASSERT(emitOption != DefineVars);
-                MOZ_ASSERT_IF(emitOption == InitializeVars, pn->pn_xflags & PNX_POPVAR);
                 if (!emit1(JSOP_UNDEFINED))
                     return false;
             }
 
             // If we are not initializing, nothing to pop. If we are initializing
             // lets, we must emit the pops.
-            MOZ_ASSERT_IF(emitOption == InitializeVars, (pn->pn_xflags & PNX_POPVAR) != 0);
-            MOZ_ASSERT_IF((pn->pn_xflags & PNX_POPVAR) != 0, emitOption == InitializeVars);
             if (emitOption == InitializeVars) {
                 MOZ_ASSERT_IF(binding->isDefn(), initializer == binding->pn_expr);
                 if (!binding->pn_scopecoord.isFree()) {
                     if (!emitVarOp(binding, op))
                         return false;
                 } else {
                     if (!emitIndexOp(op, atomIndex))
                         return false;
@@ -5607,27 +5601,26 @@ BytecodeEmitter::emitNormalFor(ParseNode
             // The loop's init declaration was hoisted into an enclosing lexical
             // scope node.  Note that the block scope must be freshened each
             // iteration.
             forLoopRequiresFreshening = true;
         } else {
             emittingForInit = true;
             if (!updateSourceCoordNotes(init->pn_pos.begin))
                 return false;
-            if (init->isKind(PNK_VAR) || init->isKind(PNK_LET) || init->isKind(PNK_CONST)) {
-                init->pn_xflags |= PNX_POPVAR;  // Momentary hack, removed later in this patch stack.
-                if (!emitTree(init))
-                    return false;
-            } else {
-                if (!emitTree(init))
-                    return false;
+            if (!emitTree(init))
+                return false;
+            emittingForInit = false;
+
+            if (!init->isKind(PNK_VAR) && !init->isKind(PNK_LET) && !init->isKind(PNK_CONST)) {
+                // 'init' is an expression, not a declaration. emitTree left
+                // its value on the stack.
                 if (!emit1(JSOP_POP))
                     return false;
             }
-            emittingForInit = false;
         }
     }
 
     /*
      * NB: the SRC_FOR note has offsetBias 1 (JSOP_NOP_LENGTH).
      * Use tmp to hold the biased srcnote "top" offset, which differs
      * from the top local variable by the length of the JSOP_GOTO
      * emitted in between tmp and top if this loop has a condition.
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -309,24 +309,22 @@ IsDeleteKind(ParseNodeKind kind)
  *                          pn_right: PNK_STATEMENTLIST node for this default's
  *                            statements
  *                          pn_val: constant value if lookup or table switch
  * PNK_WHILE    binary      pn_left: cond, pn_right: body
  * PNK_DOWHILE  binary      pn_left: body, pn_right: cond
  * PNK_FOR      binary      pn_left: either PNK_FORIN (for-in statement),
  *                            PNK_FOROF (for-of) or PNK_FORHEAD (for(;;))
  *                          pn_right: body
- * PNK_FORIN    ternary     pn_kid1:  PNK_VAR to left of 'in', or nullptr
- *                            its pn_xflags may have PNX_POPVAR bit set
+ * PNK_FORIN    ternary     pn_kid1: PNK_VAR to left of 'in', or nullptr
  *                          pn_kid2: PNK_NAME or destructuring expr
  *                            to left of 'in'; if pn_kid1, then this
  *                            is a clone of pn_kid1->pn_head
  *                          pn_kid3: object expr to right of 'in'
- * PNK_FOROF    ternary     pn_kid1:  PNK_VAR to left of 'of', or nullptr
- *                            its pn_xflags may have PNX_POPVAR bit set
+ * PNK_FOROF    ternary     pn_kid1: PNK_VAR to left of 'of', or nullptr
  *                          pn_kid2: PNK_NAME or destructuring expr
  *                            to left of 'of'; if pn_kid1, then this
  *                            is a clone of pn_kid1->pn_head
  *                          pn_kid3: expr to right of 'of'
  * PNK_FORHEAD  ternary     pn_kid1:  init expr before first ';' or nullptr
  *                          pn_kid2:  cond expr before second ';' or nullptr
  *                          pn_kid3:  update expr after second ';' or nullptr
  * PNK_THROW    unary       pn_op: JSOP_THROW, pn_kid: exception
@@ -752,25 +750,22 @@ class ParseNode
 #define PND_IMPORT             0x200    /* the definition is a module import. */
 
     static_assert(PND_IMPORT < (1 << NumDefinitionFlagBits), "Not enough bits");
 
 /* Flags to propagate from uses to definition. */
 #define PND_USE2DEF_FLAGS (PND_ASSIGNED | PND_CLOSED)
 
 /* PN_LIST pn_xflags bits. */
-#define PNX_POPVAR      0x01            /* PNK_VAR or PNK_CONST last result
-                                           needs popping */
-#define PNX_FUNCDEFS    0x02            /* contains top-level function statements */
-#define PNX_SETCALL     0x04            /* call expression in lvalue context */
-/* 0x08 is available */
-#define PNX_ARRAYHOLESPREAD 0x10        /* one or more of
+#define PNX_FUNCDEFS    0x01            /* contains top-level function statements */
+#define PNX_SETCALL     0x02            /* call expression in lvalue context */
+#define PNX_ARRAYHOLESPREAD 0x04        /* one or more of
                                            1. array initialiser has holes
                                            2. array initializer has spread node */
-#define PNX_NONCONST    0x20            /* initialiser has non-constants */
+#define PNX_NONCONST    0x08            /* initialiser has non-constants */
 
     static_assert(PNX_NONCONST < (1 << NumListFlagBits), "Not enough bits");
 
     uint32_t frameSlot() const {
         MOZ_ASSERT(pn_arity == PN_CODE || pn_arity == PN_NAME);
         return pn_scopecoord.slot();
     }
 
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -4463,17 +4463,16 @@ Parser<FullParseHandler>::lexicalDeclara
      *
      * See 8.1.1.1.6 and the note in 13.2.1.
      */
     ParseNodeKind kind = isConst ? PNK_CONST : PNK_LET;
     ParseNode* pn = variables(yieldHandling, kind, NotInForInit,
                               nullptr, CurrentLexicalStaticBlock(pc), HoistVars);
     if (!pn)
         return null();
-    pn->pn_xflags = PNX_POPVAR;
     return MatchOrInsertSemicolonAfterExpression(tokenStream) ? pn : nullptr;
 }
 
 template <>
 SyntaxParseHandler::Node
 Parser<SyntaxParseHandler>::lexicalDeclaration(YieldHandling, bool)
 {
     JS_ALWAYS_FALSE(abortIfSyntaxParser());
@@ -4910,20 +4909,17 @@ Parser<FullParseHandler>::exportDeclarat
             return null();
         break;
       }
 
       case TOK_VAR:
         kid = variables(YieldIsName, PNK_VAR, NotInForInit);
         if (!kid)
             return null();
-        kid->pn_xflags = PNX_POPVAR;
-
-        kid = MatchOrInsertSemicolonAfterExpression(tokenStream) ? kid : nullptr;
-        if (!kid)
+        if (!MatchOrInsertSemicolonAfterExpression(tokenStream))
             return null();
 
         MOZ_ASSERT(kid->isArity(PN_LIST));
         for (ParseNode* var = kid->pn_head; var; var = var->pn_next) {
             if (var->isKind(PNK_ASSIGN))
                 var = var->pn_left;
               MOZ_ASSERT(var->isKind(PNK_NAME));
               if (!addExportName(var->pn_atom))
@@ -6732,20 +6728,16 @@ Parser<ParseHandler>::statement(YieldHan
       case TOK_LC:
         return blockStatement(yieldHandling);
 
       // VariableStatement[?Yield]
       case TOK_VAR: {
         Node pn = variables(yieldHandling, PNK_VAR, NotInForInit);
         if (!pn)
             return null();
-
-        // Tell js_EmitTree to generate a final POP.
-        handler.setListFlag(pn, PNX_POPVAR);
-
         if (!MatchOrInsertSemicolonAfterExpression(tokenStream))
             return null();
         return pn;
       }
 
       // EmptyStatement
       case TOK_SEMI:
         return handler.newEmptyStatement(pos());
@@ -7981,17 +7973,16 @@ Parser<FullParseHandler>::legacyComprehe
          * tree in order for ComprehensionTranslator to work.
          *
          * These are lets to tell the bytecode emitter to emit initialization
          * code for the temporal dead zone.
          */
         ParseNode* lets = handler.newDeclarationList(PNK_LET, pn3, JSOP_DEFLET);
         if (!lets)
             return null();
-        lets->pn_xflags |= PNX_POPVAR;
 
         /* Definitions can't be passed directly to EmitAssignment as lhs. */
         pn3 = cloneLeftHandSide(pn3);
         if (!pn3)
             return null();
 
         pn2->pn_left = handler.newTernary(headKind, lets, pn3, pn4);
         if (!pn2->pn_left)