Bug 1183400 - Fold function nodes by kind. r=efaust
authorJeff Walden <jwalden@mit.edu>
Wed, 08 Jul 2015 13:54:14 -0700
changeset 288876 c80e97aaf3b79b7c6329d3c2767436a60cfe60a1
parent 288875 9eb62a986338baa03557126320e8debc95a7e74b
child 288877 d8e044ff83721b62f5bf408840cc7e14edf7cfeb
push id934
push userraliiev@mozilla.com
push dateMon, 26 Oct 2015 12:58:05 +0000
treeherdermozilla-release@05704e35c1d0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersefaust
bugs1183400
milestone42.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 1183400 - Fold function nodes by kind. r=efaust
js/src/frontend/FoldConstants.cpp
--- a/js/src/frontend/FoldConstants.cpp
+++ b/js/src/frontend/FoldConstants.cpp
@@ -1135,16 +1135,40 @@ FoldIf(ExclusiveContext* cx, ParseNode**
                 node->append(discarded);
             parser.freeTree(node);
         }
     } while (nextNode);
 
     return true;
 }
 
+static bool
+FoldFunction(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser,
+             bool inGenexpLambda)
+{
+    MOZ_ASSERT(node->isKind(PNK_FUNCTION));
+    MOZ_ASSERT(node->isArity(PN_CODE));
+
+    // Don't constant-fold inside "use asm" code, as this could create a parse
+    // tree that doesn't type-check as asm.js.
+    if (node->pn_funbox->useAsmOrInsideUseAsm())
+        return true;
+
+    // Note: pn_body is null for lazily-parsed functions.
+    if (ParseNode*& functionBody = node->pn_body) {
+        if (!Fold(cx, &functionBody, parser, node->pn_funbox->inGenexpLambda,
+                  SyntacticContext::Other))
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
 bool
 Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bool inGenexpLambda,
      SyntacticContext sc)
 {
     JS_CHECK_RECURSION(cx, return false);
 
     ParseNode* pn = *pnp;
     ParseNode* pn1 = nullptr;
@@ -1237,16 +1261,19 @@ Fold(ExclusiveContext* cx, ParseNode** p
         if (ParseNode*& expr = pn->pn_kid)
             return Fold(cx, &expr, parser, inGenexpLambda, SyntacticContext::Other);
         return true;
 
       case PNK_AND:
       case PNK_OR:
         return FoldAndOr(cx, pnp, parser, inGenexpLambda, sc);
 
+      case PNK_FUNCTION:
+        return FoldFunction(cx, pn, parser, inGenexpLambda);
+
       case PNK_EXPORT:
       case PNK_ASSIGN:
       case PNK_ADDASSIGN:
       case PNK_SUBASSIGN:
       case PNK_BITORASSIGN:
       case PNK_BITXORASSIGN:
       case PNK_BITANDASSIGN:
       case PNK_LSHASSIGN:
@@ -1320,43 +1347,32 @@ Fold(ExclusiveContext* cx, ParseNode** p
       case PNK_TAGGED_TEMPLATE:
       case PNK_EXPORT_SPEC_LIST:
       case PNK_IMPORT_SPEC_LIST:
       case PNK_CATCHLIST:
       case PNK_LABEL:
       case PNK_DOT:
       case PNK_LEXICALSCOPE:
       case PNK_NAME:
-      case PNK_FUNCTION:
       case PNK_CATCH:
       case PNK_EXPORT_SPEC:
       case PNK_IMPORT_SPEC:
       case PNK_CALLSITEOBJ:
+        MOZ_ASSERT(!pn->isArity(PN_CODE), "only functions are code nodes");
         break; // for now
 
       case PNK_LIMIT: // invalid sentinel value
         MOZ_CRASH("invalid node kind");
     }
 
     // First, recursively fold constants on the children of this node.
     switch (pn->getArity()) {
       case PN_CODE:
-        if (pn->isKind(PNK_FUNCTION) && pn->pn_funbox->useAsmOrInsideUseAsm())
-            return true;
-
-        // Note: pn_body is nullptr for functions which are being lazily parsed.
-        MOZ_ASSERT(pn->getKind() == PNK_FUNCTION);
-        if (pn->pn_body) {
-            if (!Fold(cx, &pn->pn_body, parser, pn->pn_funbox->inGenexpLambda,
-                      SyntacticContext::Other))
-            {
-                return false;
-            }
-        }
-        break;
+        MOZ_ASSERT(pn->isKind(PNK_FUNCTION));
+        MOZ_CRASH("should have been handled above");
 
       case PN_LIST:
       {
         // Don't fold a parenthesized call expression. See bug 537673.
         ParseNode** listp = &pn->pn_head;
         if ((pn->isKind(PNK_CALL) || pn->isKind(PNK_TAGGED_TEMPLATE)) && (*listp)->isInParens())
             listp = &(*listp)->pn_next;
 
@@ -1692,17 +1708,15 @@ Fold(ExclusiveContext* cx, ParseNode** p
     }
 
     return true;
 }
 
 bool
 frontend::FoldConstants(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>* parser)
 {
-    // Don't fold constants if the code has requested "use asm" as
-    // constant-folding will misrepresent the source text for the purpose
-    // of type checking. (Also guard against entering a function containing
-    // "use asm", see PN_FUNC case below.)
+    // Don't constant-fold inside "use asm" code, as this could create a parse
+    // tree that doesn't type-check as asm.js.
     if (parser->pc->useAsmOrInsideUseAsm())
         return true;
 
     return Fold(cx, pnp, *parser, false, SyntacticContext::Other);
 }