Bug 568953 - Implement ModuleBox; r=jorendorff
authorEddy Bruel <ejpbruel@mozilla.com>
Fri, 18 Jan 2013 14:24:09 +0100
changeset 119252 a9676f4f869b6bab95fb65ba97b49f7eb5cc45cb
parent 119251 4bee0517d440f222505c2d1bc8af8841bc66338d
child 119253 4a3bcda8d1f832742645eeccce47d7b91844461b
push id24195
push userMs2ger@gmail.com
push dateSat, 19 Jan 2013 16:10:11 +0000
treeherdermozilla-central@02e12a80aef9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs568953
milestone21.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 568953 - Implement ModuleBox; r=jorendorff
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/ParseNode.cpp
js/src/frontend/ParseNode.h
js/src/frontend/Parser.cpp
js/src/frontend/SharedContext-inl.h
js/src/frontend/SharedContext.h
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -1668,17 +1668,20 @@ BytecodeEmitter::checkSingletonContext()
 }
 
 bool
 BytecodeEmitter::needsImplicitThis()
 {
     if (!script->compileAndGo)
         return true;
 
-    if (sc->isFunctionBox()) {
+    if (sc->isModuleBox()) {
+        /* Modules can never occur inside a with-statement */
+        return false;
+    } if (sc->isFunctionBox()) {
         if (sc->asFunctionBox()->inWith)
             return true;
     } else {
         JSObject *scope = sc->asGlobalSharedContext()->scopeChain();
         while (scope) {
             if (scope->isWith())
                 return true;
             scope = scope->enclosingScope();
--- a/js/src/frontend/ParseNode.cpp
+++ b/js/src/frontend/ParseNode.cpp
@@ -1,15 +1,15 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sw=4 et 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/. */
-
+#include "builtin/Module.h"
 #include "frontend/ParseNode.h"
 #include "frontend/Parser.h"
 
 #include "jsscriptinlines.h"
 
 #include "frontend/ParseMaps-inl.h"
 #include "frontend/ParseNode-inl.h"
 #include "frontend/Parser-inl.h"
@@ -803,26 +803,43 @@ ObjectBox::ObjectBox(JSFunction *functio
   : object(function),
     traceLink(traceLink),
     emitLink(NULL)
 {
     JS_ASSERT(object->isFunction());
     JS_ASSERT(asFunctionBox()->function() == function);
 }
 
+ModuleBox *
+ObjectBox::asModuleBox()
+{
+    JS_ASSERT(isModuleBox());
+    return static_cast<ModuleBox *>(this);
+}
+
 FunctionBox *
 ObjectBox::asFunctionBox()
 {
     JS_ASSERT(isFunctionBox());
     return static_cast<FunctionBox *>(this);
 }
 
+ObjectBox::ObjectBox(Module *module, ObjectBox* traceLink)
+  : object(module),
+    traceLink(traceLink),
+    emitLink(NULL)
+{
+    JS_ASSERT(object->isModule());
+}
+
 void
 ObjectBox::trace(JSTracer *trc)
 {
     ObjectBox *box = this;
     while (box) {
         MarkObjectRoot(trc, &box->object, "parser.object");
+        if (box->isModuleBox())
+            box->asModuleBox()->bindings.trace(trc);
         if (box->isFunctionBox())
             box->asFunctionBox()->bindings.trace(trc);
         box = box->traceLink;
     }
 }
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -599,18 +599,18 @@ struct ParseNode {
             ParseNode   *kid;
             bool        hidden;         /* hidden genexp-induced JSOP_YIELD
                                            or directive prologue member (as
                                            pn_prologue) */
         } unary;
         struct {                        /* name, labeled statement, etc. */
             union {
                 JSAtom        *atom;    /* lexical name or label atom */
+                ObjectBox     *objbox;  /* block or regexp object */
                 FunctionBox   *funbox;  /* function object */
-                ObjectBox     *objbox;  /* block or regexp object */
             };
             union {
                 ParseNode    *expr;     /* function body, var initializer, argument default,
                                            or base object of PNK_DOT */
                 Definition   *lexdef;   /* lexical definition for this use */
             };
             UpvarCookie cookie;         /* upvar cookie with absolute frame
                                            level (not relative skip), possibly
@@ -1492,30 +1492,35 @@ LinkUseToDef(ParseNode *pn, Definition *
     JS_ASSERT(pn != dn->dn_uses);
     pn->pn_link = dn->dn_uses;
     dn->dn_uses = pn;
     dn->pn_dflags |= pn->pn_dflags & PND_USE2DEF_FLAGS;
     pn->setUsed(true);
     pn->pn_lexdef = dn;
 }
 
+class ModuleBox;
+
 class ObjectBox {
   public:
     JSObject *object;
 
     ObjectBox(JSObject *object, ObjectBox *traceLink);
+    bool isModuleBox() { return object->isModule(); }
     bool isFunctionBox() { return object->isFunction(); }
+    ModuleBox *asModuleBox();
     FunctionBox *asFunctionBox();
     void trace(JSTracer *trc);
 
   protected:
     friend struct CGObjectList;
 
     ObjectBox *traceLink;
     ObjectBox *emitLink;
 
     ObjectBox(JSFunction *function, ObjectBox *traceLink);
+    ObjectBox(Module *module, ObjectBox *traceLink);
 };
 
 } /* namespace frontend */
 } /* namespace js */
 
 #endif /* ParseNode_h__ */
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -389,17 +389,17 @@ FunctionBox::FunctionBox(JSContext *cx, 
         // This covers cases that don't involve eval().  For example:
         //
         //   with (o) { (function() { g(); })(); }
         //
         // In this case, |outerpc| corresponds to global code, and
         // outerpc->parsingWith is true.
         inWith = true;
 
-    } else if (!outerpc->sc->isFunctionBox()) {
+    } else if (outerpc->sc->isGlobalSharedContext()) {
         // This covers the case where a function is nested within an eval()
         // within a |with| statement.
         //
         //   with (o) { eval("(function() { g(); })();"); }
         //
         // In this case, |outerpc| corresponds to the eval(),
         // outerpc->parsingWith is false because the eval() breaks the
         // ParseContext chain, and |parent| is NULL (again because of the
@@ -444,16 +444,23 @@ Parser::newFunctionBox(JSFunction *fun, 
         return NULL;
     }
 
     traceListHead = funbox;
 
     return funbox;
 }
 
+ModuleBox::ModuleBox(JSContext *cx, ParseContext *pc, Module *module,
+                     ObjectBox *traceListHead)
+    : ObjectBox(module, traceListHead),
+      SharedContext(cx, true)
+{
+}
+
 void
 Parser::trace(JSTracer *trc)
 {
     traceListHead->trace(trc);
 }
 
 static bool
 GenerateBlockIdForStmtNode(ParseNode *pn, ParseContext *pc)
--- a/js/src/frontend/SharedContext-inl.h
+++ b/js/src/frontend/SharedContext-inl.h
@@ -30,16 +30,23 @@ SharedContext::needStrictChecks()
 
 inline GlobalSharedContext *
 SharedContext::asGlobalSharedContext()
 {
     JS_ASSERT(isGlobalSharedContext());
     return static_cast<GlobalSharedContext*>(this);
 }
 
+inline ModuleBox *
+SharedContext::asModuleBox()
+{
+    JS_ASSERT(isModuleBox());
+    return static_cast<ModuleBox*>(this);
+}
+
 inline FunctionBox *
 SharedContext::asFunctionBox()
 {
     JS_ASSERT(isFunctionBox());
     return static_cast<FunctionBox*>(this);
 }
 
 GlobalSharedContext::GlobalSharedContext(JSContext *cx, JSObject *scopeChain, bool strict)
--- a/js/src/frontend/SharedContext.h
+++ b/js/src/frontend/SharedContext.h
@@ -142,18 +142,20 @@ class SharedContext
     bool strict;
 
     // If it's function code, funbox must be non-NULL and scopeChain must be NULL.
     // If it's global code, funbox must be NULL.
     inline SharedContext(JSContext *cx, bool strict);
 
     virtual ObjectBox *toObjectBox() = 0;
     inline bool isGlobalSharedContext() { return toObjectBox() == NULL; }
+    inline bool isModuleBox() { return toObjectBox() && toObjectBox()->isModuleBox(); }
     inline bool isFunctionBox() { return toObjectBox() && toObjectBox()->isFunctionBox(); }
     inline GlobalSharedContext *asGlobalSharedContext();
+    inline ModuleBox *asModuleBox();
     inline FunctionBox *asFunctionBox();
 
     bool hasExplicitUseStrict()        const { return anyCxFlags.hasExplicitUseStrict; }
     bool bindingsAccessedDynamically() const { return anyCxFlags.bindingsAccessedDynamically; }
 
     void setExplicitUseStrict()           { anyCxFlags.hasExplicitUseStrict        = true; }
     void setBindingsAccessedDynamically() { anyCxFlags.bindingsAccessedDynamically = true; }
 
@@ -168,16 +170,29 @@ class GlobalSharedContext : public Share
 
   public:
     inline GlobalSharedContext(JSContext *cx, JSObject *scopeChain, bool strict);
 
     ObjectBox *toObjectBox() { return NULL; }
     JSObject *scopeChain() const { return scopeChain_; }
 };
 
+
+class ModuleBox : public ObjectBox, public SharedContext {
+public:
+    size_t      bufStart;
+    size_t      bufEnd;
+    Bindings    bindings;
+
+    ModuleBox(JSContext *cx, ParseContext *pc, Module *module,
+              ObjectBox *traceListHead);
+    ObjectBox *toObjectBox() { return this; }
+    Module *module() const { return &object->asModule(); }
+};
+
 class FunctionBox : public ObjectBox, public SharedContext
 {
   public:
     Bindings        bindings;               /* bindings for this function */
     size_t          bufStart;
     size_t          bufEnd;
     uint16_t        ndefaults;
     bool            inWith:1;               /* some enclosing scope is a with-statement