Bug 1451826 - Part 9: Introduce BCEParserHandle. (r=Waldo)
authorEric Faust <efaustbmo@gmail.com>
Fri, 27 Apr 2018 15:02:31 -0700
changeset 416156 60bdf6086590f974614e0b1d202ff4849f5a2c45
parent 416155 598418d95c96a8edbd3ba2d2f6f231ed37c1d02a
child 416157 e4ce5e759df5b08bfc1bf5f5f5f4892cf46b0dad
push id33917
push userapavel@mozilla.com
push dateSat, 28 Apr 2018 17:30:55 +0000
treeherdermozilla-central@08f68e2c892c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs1451826
milestone61.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 1451826 - Part 9: Introduce BCEParserHandle. (r=Waldo)
js/src/frontend/BCEParserHandle.h
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/EitherParser.h
new file mode 100644
--- /dev/null
+++ b/js/src/frontend/BCEParserHandle.h
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef frontend_BCEParserHandle_h
+#define frontend_BCEParserHandle_h
+
+#include "frontend/ErrorReporter.h"
+#include "frontend/FullParseHandler.h"
+#include "frontend/Parser.h"
+
+namespace js {
+namespace frontend {
+
+class BCEParserHandle {
+    virtual ErrorReporter& errorReporter() = 0;
+    virtual const ErrorReporter& errorReporter() const = 0;
+
+    virtual const JS::ReadOnlyCompileOptions& options() = 0;
+
+    virtual FullParseHandler& astGenerator() = 0;
+    virtual ObjectBox* newObjectBox(JSObject *obj) = 0;
+};
+
+} // namespace frontend
+} // namespace js
+
+#endif // frontend_BCEParserHandle_h
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -7064,30 +7064,30 @@ BytecodeEmitter::emitInitializeForInOrOf
                "must have a per-iteration value for initializing");
 
     ParseNode* target = forHead->pn_kid1;
     MOZ_ASSERT(!forHead->pn_kid2);
 
     // If the for-in/of loop didn't have a variable declaration, per-loop
     // initialization is just assigning the iteration value to a target
     // expression.
-    if (!parser.isDeclarationList(target))
+    if (!parser.astGenerator().isDeclarationList(target))
         return emitAssignment(target, ParseNodeKind::Assign, nullptr); // ... ITERVAL
 
     // Otherwise, per-loop initialization is (possibly) declaration
     // initialization.  If the declaration is a lexical declaration, it must be
     // initialized.  If the declaration is a variable declaration, an
     // assignment to that name (which does *not* necessarily assign to the
     // variable!) must be generated.
 
     if (!updateSourceCoordNotes(target->pn_pos.begin))
         return false;
 
     MOZ_ASSERT(target->isForLoopDeclaration());
-    target = parser.singleBindingFromDeclaration(target);
+    target = parser.astGenerator().singleBindingFromDeclaration(target);
 
     if (target->isKind(ParseNodeKind::Name)) {
         auto emitSwapScopeAndRhs = [](BytecodeEmitter* bce, const NameLocation&,
                                       bool emittedBindOp)
         {
             if (emittedBindOp) {
                 // Per-iteration initialization in for-in/of loops computes the
                 // iteration value *before* initializing.  Thus the
@@ -7317,18 +7317,18 @@ BytecodeEmitter::emitForIn(ParseNode* fo
 
     ParseNode* forInHead = forInLoop->pn_left;
     MOZ_ASSERT(forInHead->isKind(ParseNodeKind::ForIn));
     MOZ_ASSERT(forInHead->isArity(PN_TERNARY));
 
     // Annex B: Evaluate the var-initializer expression if present.
     // |for (var i = initializer in expr) { ... }|
     ParseNode* forInTarget = forInHead->pn_kid1;
-    if (parser.isDeclarationList(forInTarget)) {
-        ParseNode* decl = parser.singleBindingFromDeclaration(forInTarget);
+    if (parser.astGenerator().isDeclarationList(forInTarget)) {
+        ParseNode* decl = parser.astGenerator().singleBindingFromDeclaration(forInTarget);
         if (decl->isKind(ParseNodeKind::Name)) {
             if (ParseNode* initializer = decl->expr()) {
                 MOZ_ASSERT(forInTarget->isKind(ParseNodeKind::Var),
                            "for-in initializers are only permitted for |var| declarations");
 
                 if (!updateSourceCoordNotes(decl->pn_pos.begin))
                     return false;
 
@@ -9121,17 +9121,17 @@ BytecodeEmitter::emitCallee(ParseNode* c
         } else {
             if (!emitTree(callee))
                 return false;
         }
         *callop = false;
         break;
       case ParseNodeKind::SuperBase:
         MOZ_ASSERT(call->isKind(ParseNodeKind::SuperCall));
-        MOZ_ASSERT(parser.isSuperBase(callee));
+        MOZ_ASSERT(parser.astGenerator().isSuperBase(callee));
         if (!emit1(JSOP_SUPERFUN))
             return false;
         break;
       default:
         if (!emitTree(callee))
             return false;
         *callop = false;             /* trigger JSOP_UNDEFINED after */
         break;
--- a/js/src/frontend/EitherParser.h
+++ b/js/src/frontend/EitherParser.h
@@ -15,16 +15,17 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/Move.h"
 #include "mozilla/Tuple.h"
 #include "mozilla/TypeTraits.h"
 #include "mozilla/Variant.h"
 
 #include <utility>
 
+#include "frontend/BCEParserHandle.h"
 #include "frontend/Parser.h"
 #include "frontend/TokenStream.h"
 
 namespace js {
 
 namespace detail {
 
 template<template <class Parser> class GetThis,
@@ -63,24 +64,16 @@ struct InvokeMemberFunction
 
 template<class Parser>
 struct GetParser
 {
     static Parser* get(Parser* parser) { return parser; }
 };
 
 template<class Parser>
-struct GetParseHandler
-{
-    static frontend::FullParseHandler* get(Parser* parser) {
-        return &parser->handler;
-    }
-};
-
-template<class Parser>
 struct GetTokenStream
 {
     static auto get(Parser* parser) -> decltype(&parser->tokenStream) {
         return &parser->tokenStream;
     }
 };
 
 // Member function-computing templates.
@@ -96,42 +89,26 @@ struct ParserOptions
 template<class Parser>
 struct ParserNewObjectBox
 {
     static constexpr auto get() -> decltype(&Parser::newObjectBox) {
         return &Parser::newObjectBox;
     }
 };
 
-template<class Handler>
-struct HandlerSingleBindingFromDeclaration
+// Generic matchers.
+
+struct ParseHandlerMatcher
 {
-    static constexpr auto get() -> decltype(&Handler::singleBindingFromDeclaration) {
-        return &Handler::singleBindingFromDeclaration;
+    template<class Parser>
+    frontend::FullParseHandler& match(Parser *parser) {
+        return parser->handler;
     }
 };
 
-template<class Handler>
-struct HandlerIsDeclarationList
-{
-    static constexpr auto get() -> decltype(&Handler::isDeclarationList) {
-        return &Handler::isDeclarationList;
-    }
-};
-
-template<class Handler>
-struct HandlerIsSuperBase
-{
-    static constexpr auto get() -> decltype(&Handler::isSuperBase) {
-        return &Handler::isSuperBase;
-    }
-};
-
-// Generic matchers.
-
 struct ParserBaseMatcher
 {
     template<class Parser>
     frontend::ParserBase& match(Parser* parser) {
         return *static_cast<frontend::ParserBase*>(parser);
     }
 };
 
@@ -142,72 +119,54 @@ struct ErrorReporterMatcher
         return parser->tokenStream;
     }
 };
 
 } // namespace detail
 
 namespace frontend {
 
-class EitherParser
+class EitherParser : public BCEParserHandle
 {
     // Leave this as a variant, to promote good form until 8-bit parser integration.
     mozilla::Variant<Parser<FullParseHandler, char16_t>* const> parser;
 
     using Node = typename FullParseHandler::Node;
 
     template<template <class Parser> class GetThis,
              template <class This> class GetMemberFunction,
              typename... StoredArgs>
     using InvokeMemberFunction =
         detail::InvokeMemberFunction<GetThis, GetMemberFunction, StoredArgs...>;
 
   public:
     template<class Parser>
     explicit EitherParser(Parser* parser) : parser(parser) {}
 
-    ErrorReporter& errorReporter() {
+    FullParseHandler& astGenerator() final {
+        return parser.match(detail::ParseHandlerMatcher());
+    }
+
+    ErrorReporter& errorReporter() final {
+        return parser.match(detail::ErrorReporterMatcher());
+    }
+    const ErrorReporter& errorReporter() const final {
         return parser.match(detail::ErrorReporterMatcher());
     }
 
-    const ErrorReporter& errorReporter() const {
-        return parser.match(detail::ErrorReporterMatcher());
-    }
-
-    const JS::ReadOnlyCompileOptions& options() {
+    const JS::ReadOnlyCompileOptions& options() final {
         InvokeMemberFunction<detail::GetParser, detail::ParserOptions> optionsMatcher;
         return parser.match(mozilla::Move(optionsMatcher));
     }
 
-    ObjectBox* newObjectBox(JSObject* obj) {
+    ObjectBox* newObjectBox(JSObject* obj) final {
         InvokeMemberFunction<detail::GetParser, detail::ParserNewObjectBox,
                              JSObject*>
             matcher { obj };
         return parser.match(mozilla::Move(matcher));
     }
 
-    Node singleBindingFromDeclaration(Node decl) {
-        InvokeMemberFunction<detail::GetParseHandler, detail::HandlerSingleBindingFromDeclaration,
-                             Node>
-            matcher { decl };
-        return parser.match(mozilla::Move(matcher));
-    }
-
-    bool isDeclarationList(Node node) {
-        InvokeMemberFunction<detail::GetParseHandler, detail::HandlerIsDeclarationList,
-                             Node>
-            matcher { node };
-        return parser.match(mozilla::Move(matcher));
-    }
-
-    bool isSuperBase(Node node) {
-        InvokeMemberFunction<detail::GetParseHandler, detail::HandlerIsSuperBase,
-                             Node>
-            matcher { node };
-        return parser.match(mozilla::Move(matcher));
-    }
-
 };
 
 } /* namespace frontend */
 } /* namespace js */
 
 #endif /* frontend_EitherParser_h */