Bug 1071646 - Cast ParseNode to Definition using as<T>. (r=jorendorff)
authorShu-yu Guo <shu@rfrn.org>
Wed, 09 Dec 2015 07:52:58 -0800
changeset 297663 52ad4194c0b33df6f30b8149f415303a52d18591
parent 297662 a44b841c33fb129b236e5dceab9129370511f418
child 297664 23e4475338c51a284b44c6c462d13a57ae81452e
push id8824
push userraliiev@mozilla.com
push dateMon, 14 Dec 2015 20:18:56 +0000
treeherdermozilla-aurora@e2031358e2a6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs1071646
milestone45.0a1
Bug 1071646 - Cast ParseNode to Definition using as<T>. (r=jorendorff)
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
@@ -1733,17 +1733,17 @@ BytecodeEmitter::bindNameToSlotHelper(Pa
      */
     Definition* dn;
     if (pn->isUsed()) {
         MOZ_ASSERT(pn->pn_scopecoord.isFree());
         dn = pn->pn_lexdef;
         MOZ_ASSERT(dn->isDefn());
         pn->pn_dflags |= (dn->pn_dflags & PND_CONST);
     } else if (pn->isDefn()) {
-        dn = (Definition*) pn;
+        dn = &pn->as<Definition>();
     } else {
         return true;
     }
 
     if (dn->pn_scopecoord.isFree()) {
         if (evalCaller) {
             MOZ_ASSERT(script->treatAsRunOnce() || sc->isFunctionBox());
 
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -1607,16 +1607,18 @@ struct Definition : public ParseNode
         CONSTANT,
         LET,
         ARG,
         NAMED_LAMBDA,
         PLACEHOLDER,
         IMPORT
     };
 
+    static bool test(const ParseNode& pn) { return pn.isDefn(); }
+
     bool canHaveInitializer() { return int(kind()) <= int(ARG); }
 
     static const char* kindString(Kind kind);
 
     Kind kind() {
         if (getKind() == PNK_FUNCTION) {
             if (isOp(JSOP_GETARG))
                 return ARG;
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -98,19 +98,17 @@ ParseContext<FullParseHandler>::checkLoc
         return false;
     }
     return true;
 }
 
 static void
 MarkUsesAsHoistedLexical(ParseNode* pn)
 {
-    MOZ_ASSERT(pn->isDefn());
-
-    Definition* dn = (Definition*)pn;
+    Definition* dn = &pn->as<Definition>();
     ParseNode** pnup = &dn->dn_uses;
     ParseNode* pnu;
     unsigned start = pn->pn_blockid;
 
     // In ES6, lexical bindings cannot be accessed until initialized.
     // Distinguish hoisted uses as a different JSOp for easier compilation.
     while ((pnu = *pnup) != nullptr && pnu->pn_blockid >= start) {
         MOZ_ASSERT(pnu->isUsed());
@@ -213,16 +211,18 @@ SharedContext::markSuperScopeNeedsHomeOb
 template <>
 bool
 ParseContext<FullParseHandler>::define(TokenStream& ts,
                                        HandlePropertyName name, ParseNode* pn, Definition::Kind kind)
 {
     MOZ_ASSERT(!pn->isUsed());
     MOZ_ASSERT_IF(pn->isDefn(), pn->isPlaceholder());
 
+    pn->setDefn(true);
+
     Definition* prevDef = nullptr;
     if (kind == Definition::LET || kind == Definition::CONSTANT)
         prevDef = decls_.lookupFirst(name);
     else
         MOZ_ASSERT(!decls_.lookupFirst(name));
 
     if (!prevDef)
         prevDef = lexdeps.lookupDefn<FullParseHandler>(name);
@@ -231,17 +231,17 @@ ParseContext<FullParseHandler>::define(T
         ParseNode** pnup = &prevDef->dn_uses;
         ParseNode* pnu;
         unsigned start = (kind == Definition::LET || kind == Definition::CONSTANT)
                          ? pn->pn_blockid : bodyid;
 
         while ((pnu = *pnup) != nullptr && pnu->pn_blockid >= start) {
             MOZ_ASSERT(pnu->pn_blockid >= bodyid);
             MOZ_ASSERT(pnu->isUsed());
-            pnu->pn_lexdef = (Definition*) pn;
+            pnu->pn_lexdef = &pn->as<Definition>();
             pn->pn_dflags |= pnu->pn_dflags & PND_USE2DEF_FLAGS;
             pnup = &pnu->pn_link;
         }
 
         if (!pnu || pnu != prevDef->dn_uses) {
             *pnup = pn->dn_uses;
             pn->dn_uses = prevDef->dn_uses;
             prevDef->dn_uses = pnu;
@@ -249,22 +249,21 @@ ParseContext<FullParseHandler>::define(T
             if (!pnu && prevDef->isPlaceholder())
                 lexdeps->remove(name);
         }
 
         pn->pn_dflags |= prevDef->pn_dflags & PND_CLOSED;
     }
 
     MOZ_ASSERT_IF(kind != Definition::LET && kind != Definition::CONSTANT, !lexdeps->lookup(name));
-    pn->setDefn(true);
     pn->pn_dflags &= ~PND_PLACEHOLDER;
     if (kind == Definition::CONSTANT)
         pn->pn_dflags |= PND_CONST;
 
-    Definition* dn = (Definition*)pn;
+    Definition* dn = &pn->as<Definition>();
     switch (kind) {
       case Definition::ARG:
         MOZ_ASSERT(sc->isFunctionBox());
         dn->setOp((CodeSpec[dn->getOp()].format & JOF_SET) ? JSOP_SETARG : JSOP_GETARG);
         dn->pn_blockid = bodyid;
         dn->pn_dflags |= PND_BOUND;
         if (!dn->pn_scopecoord.setSlot(ts, args_.length()))
             return false;
@@ -384,17 +383,17 @@ ParseContext<ParseHandler>::prepareToAdd
 
 template <typename ParseHandler>
 void
 ParseContext<ParseHandler>::updateDecl(TokenStream& ts, JSAtom* atom, Node pn)
 {
     Definition* oldDecl = decls_.lookupFirst(atom);
 
     pn->setDefn(true);
-    Definition* newDecl = (Definition*)pn;
+    Definition* newDecl = &pn->template as<Definition>();
     decls_.updateFirst(atom, newDecl);
 
     if (sc->isGlobalContext() || oldDecl->isDeoptimized()) {
         MOZ_ASSERT(newDecl->isFreeVar());
         // Global 'var' bindings have no slots, but are still tracked for
         // redeclaration checks.
         for (uint32_t i = 0; i < vars_.length(); i++) {
             if (vars_[i] == oldDecl) {
@@ -1384,17 +1383,17 @@ Parser<FullParseHandler>::makeDefIntoUse
 {
     /* Turn pn into a definition. */
     pc->updateDecl(tokenStream, atom, pn);
 
     /* Change all uses of dn to be uses of pn. */
     for (ParseNode* pnu = dn->dn_uses; pnu; pnu = pnu->pn_link) {
         MOZ_ASSERT(pnu->isUsed());
         MOZ_ASSERT(!pnu->isDefn());
-        pnu->pn_lexdef = (Definition*) pn;
+        pnu->pn_lexdef = &pn->as<Definition>();
         pn->pn_dflags |= pnu->pn_dflags & PND_USE2DEF_FLAGS;
     }
     pn->pn_dflags |= dn->pn_dflags & PND_USE2DEF_FLAGS;
     pn->dn_uses = dn;
 
     /*
      * A PNK_FUNCTION node must be a definition, so convert shadowed function
      * statements into nops. This is valid since all body-level function
@@ -1427,28 +1426,28 @@ Parser<FullParseHandler>::makeDefIntoUse
      */
     if (dn->canHaveInitializer()) {
         if (ParseNode* rhs = dn->expr()) {
             ParseNode* lhs = handler.makeAssignment(dn, rhs);
             if (!lhs)
                 return false;
             pn->dn_uses = lhs;
             dn->pn_link = nullptr;
-            dn = (Definition*) lhs;
+            dn = &lhs->as<Definition>();
         }
     }
 
     /* Turn dn into a use of pn. */
     MOZ_ASSERT(dn->isKind(PNK_NAME));
     MOZ_ASSERT(dn->isArity(PN_NAME));
     MOZ_ASSERT(dn->pn_atom == atom);
     dn->setOp((CodeSpec[dn->getOp()].format & JOF_SET) ? JSOP_SETNAME : JSOP_GETNAME);
     dn->setDefn(false);
     dn->setUsed(true);
-    dn->pn_lexdef = (Definition*) pn;
+    dn->pn_lexdef = &pn->as<Definition>();
     dn->pn_scopecoord.makeFree();
     dn->pn_dflags &= ~PND_BOUND;
     return true;
 }
 
 /*
  * Helper class for creating bindings.
  *
@@ -2386,18 +2385,17 @@ Parser<FullParseHandler>::checkFunctionD
                     varNode->pn_blockid = pc->bodyid;
 
                     BindData<FullParseHandler> data(context);
                     data.initAnnexBVar();
                     data.setNameNode(varNode);
                     if (!data.bind(funName, this))
                         return false;
 
-                    MOZ_ASSERT(varNode->isDefn());
-                    annexDef = static_cast<Definition*>(varNode);
+                    annexDef = &varNode->as<Definition>();
 
                     synthesizedDeclarationList = handler.newDeclarationList(PNK_VAR, JSOP_DEFVAR);
                     if (!synthesizedDeclarationList)
                         return false;
                     handler.addList(synthesizedDeclarationList, annexDef);
                 }
             }