Bug 1420412 - Move namespace related data to the module's namespace object r=anba
authorJon Coppeard <jcoppeard@mozilla.com>
Fri, 24 Nov 2017 15:52:22 +0000
changeset 393611 6ecf891cc6ce23f8b2a2635f171903220343baf4
parent 393610 ebe3e6a61f6772d6fce2ad5df87e3c8329cec919
child 393612 9029701afb620ea6f13fdf75fe3943151d3defdf
push id32967
push useraciure@mozilla.com
push dateFri, 24 Nov 2017 22:04:51 +0000
treeherdermozilla-central@4ce67352b2a9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersanba
bugs1420412
milestone59.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 1420412 - Move namespace related data to the module's namespace object r=anba
js/src/builtin/ModuleObject.cpp
js/src/builtin/ModuleObject.h
js/src/builtin/SelfHostingDefines.h
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -378,62 +378,62 @@ IndirectBindingMap::lookup(jsid name, Mo
 
 /* static */ bool
 ModuleNamespaceObject::isInstance(HandleValue value)
 {
     return value.isObject() && value.toObject().is<ModuleNamespaceObject>();
 }
 
 /* static */ ModuleNamespaceObject*
-ModuleNamespaceObject::create(JSContext* cx, HandleModuleObject module)
+ModuleNamespaceObject::create(JSContext* cx, HandleModuleObject module, HandleObject exports,
+                              UniquePtr<IndirectBindingMap> bindings)
 {
     RootedValue priv(cx, ObjectValue(*module));
     ProxyOptions options;
     options.setLazyProto(true);
     options.setSingleton(true);
     RootedObject object(cx, NewProxyObject(cx, &proxyHandler, priv, nullptr, options));
     if (!object)
         return nullptr;
 
+    SetProxyReservedSlot(object, ExportsSlot, ObjectValue(*exports));
+    SetProxyReservedSlot(object, BindingsSlot, PrivateValue(bindings.release()));
+
     return &object->as<ModuleNamespaceObject>();
 }
 
 ModuleObject&
 ModuleNamespaceObject::module()
 {
     return GetProxyPrivate(this).toObject().as<ModuleObject>();
 }
 
 JSObject&
 ModuleNamespaceObject::exports()
 {
-    JSObject* exports = module().namespaceExports();
-    MOZ_ASSERT(exports);
-    return *exports;
+    return GetProxyReservedSlot(this, ExportsSlot).toObject();
 }
 
 IndirectBindingMap&
 ModuleNamespaceObject::bindings()
 {
-    IndirectBindingMap* bindings = module().namespaceBindings();
+    Value value = GetProxyReservedSlot(this, BindingsSlot);
+    auto bindings = static_cast<IndirectBindingMap*>(value.toPrivate());
     MOZ_ASSERT(bindings);
     return *bindings;
 }
 
 bool
 ModuleNamespaceObject::addBinding(JSContext* cx, HandleAtom exportedName,
                                   HandleModuleObject targetModule, HandleAtom localName)
 {
-    IndirectBindingMap* bindings(this->module().namespaceBindings());
-    MOZ_ASSERT(bindings);
-
     RootedModuleEnvironmentObject environment(cx, &targetModule->initialEnvironment());
     RootedId exportedNameId(cx, AtomToId(exportedName));
     RootedId localNameId(cx, AtomToId(localName));
-    return bindings->putNew(cx, exportedNameId, environment, localNameId);
+    return bindings().putNew(cx, exportedNameId, environment, localNameId);
 }
 
 const char ModuleNamespaceObject::ProxyHandler::family = 0;
 
 ModuleNamespaceObject::ProxyHandler::ProxyHandler()
   : BaseProxyHandler(&family, false)
 {}
 
@@ -671,16 +671,29 @@ ModuleNamespaceObject::ProxyHandler::own
     for (uint32_t i = 0; i < count; i++)
         props.infallibleAppend(AtomToId(&names[i].toString()->asAtom()));
 
     props.infallibleAppend(SYMBOL_TO_JSID(cx->wellKnownSymbols().toStringTag));
 
     return true;
 }
 
+void
+ModuleNamespaceObject::ProxyHandler::trace(JSTracer* trc, JSObject* proxy) const
+{
+    auto& self = proxy->as<ModuleNamespaceObject>();
+    self.bindings().trace(trc);
+}
+
+void ModuleNamespaceObject::ProxyHandler::finalize(JSFreeOp* fop, JSObject* proxy) const
+{
+    auto& self = proxy->as<ModuleNamespaceObject>();
+    js_delete(&self.bindings());
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // FunctionDeclaration
 
 FunctionDeclaration::FunctionDeclaration(HandleAtom name, HandleFunction fun)
   : name(name), fun(fun)
 {}
 
 void FunctionDeclaration::trace(JSTracer* trc)
@@ -767,18 +780,16 @@ ModuleObject::create(JSContext* cx)
 
 /* static */ void
 ModuleObject::finalize(js::FreeOp* fop, JSObject* obj)
 {
     MOZ_ASSERT(fop->maybeOnHelperThread());
     ModuleObject* self = &obj->as<ModuleObject>();
     if (self->hasImportBindings())
         fop->delete_(&self->importBindings());
-    if (IndirectBindingMap* bindings = self->namespaceBindings())
-        fop->delete_(bindings);
     if (FunctionDeclarationVector* funDecls = self->functionDeclarations())
         fop->delete_(funDecls);
 }
 
 ModuleEnvironmentObject&
 ModuleObject::initialEnvironment() const
 {
     Value value = getReservedSlot(EnvironmentSlot);
@@ -806,36 +817,16 @@ ModuleObject::hasImportBindings() const
 }
 
 IndirectBindingMap&
 ModuleObject::importBindings()
 {
     return *static_cast<IndirectBindingMap*>(getReservedSlot(ImportBindingsSlot).toPrivate());
 }
 
-JSObject*
-ModuleObject::namespaceExports()
-{
-    Value value = getReservedSlot(NamespaceExportsSlot);
-    if (value.isUndefined())
-        return nullptr;
-
-    return &value.toObject();
-}
-
-IndirectBindingMap*
-ModuleObject::namespaceBindings()
-{
-    Value value = getReservedSlot(NamespaceBindingsSlot);
-    if (value.isUndefined())
-        return nullptr;
-
-    return static_cast<IndirectBindingMap*>(value.toPrivate());
-}
-
 ModuleNamespaceObject*
 ModuleObject::namespace_()
 {
     Value value = getReservedSlot(NamespaceSlot);
     if (value.isUndefined())
         return nullptr;
     return &value.toObject().as<ModuleNamespaceObject>();
 }
@@ -1013,18 +1004,16 @@ ModuleObject::trace(JSTracer* trc, JSObj
     if (module.hasScript()) {
         JSScript* script = module.script();
         TraceManuallyBarrieredEdge(trc, &script, "Module script");
         module.setReservedSlot(ScriptSlot, PrivateValue(script));
     }
 
     if (module.hasImportBindings())
         module.importBindings().trace(trc);
-    if (IndirectBindingMap* bindings = module.namespaceBindings())
-        bindings->trace(trc);
 
     if (FunctionDeclarationVector* funDecls = module.functionDeclarations())
         funDecls->trace(trc);
 }
 
 bool
 ModuleObject::noteFunctionDeclaration(JSContext* cx, HandleAtom name, HandleFunction fun)
 {
@@ -1103,31 +1092,28 @@ ModuleObject::execute(JSContext* cx, Han
 }
 
 /* static */ ModuleNamespaceObject*
 ModuleObject::createNamespace(JSContext* cx, HandleModuleObject self, HandleObject exports)
 {
     MOZ_ASSERT(!self->namespace_());
     MOZ_ASSERT(exports->is<ArrayObject>());
 
-    RootedModuleNamespaceObject ns(cx, ModuleNamespaceObject::create(cx, self));
+    Zone* zone = cx->zone();
+    auto bindings = zone->make_unique<IndirectBindingMap>(zone);
+    if (!bindings || !bindings->init()) {
+        ReportOutOfMemory(cx);
+        return nullptr;
+    }
+
+    auto ns = ModuleNamespaceObject::create(cx, self, exports, Move(bindings));
     if (!ns)
         return nullptr;
 
-    Zone* zone = cx->zone();
-    IndirectBindingMap* bindings = zone->new_<IndirectBindingMap>(zone);
-    if (!bindings || !bindings->init()) {
-        ReportOutOfMemory(cx);
-        js_delete<IndirectBindingMap>(bindings);
-        return nullptr;
-    }
-
     self->initReservedSlot(NamespaceSlot, ObjectValue(*ns));
-    self->initReservedSlot(NamespaceExportsSlot, ObjectValue(*exports));
-    self->initReservedSlot(NamespaceBindingsSlot, PrivateValue(bindings));
     return ns;
 }
 
 static bool
 InvokeSelfHostedMethod(JSContext* cx, HandleModuleObject self, HandlePropertyName name)
 {
     RootedValue fval(cx);
     if (!GlobalObject::getSelfHostedFunction(cx, cx->global(), name, name, 0, &fval))
--- a/js/src/builtin/ModuleObject.h
+++ b/js/src/builtin/ModuleObject.h
@@ -8,16 +8,17 @@
 #define builtin_ModuleObject_h
 
 #include "jsapi.h"
 #include "jsatom.h"
 
 #include "builtin/SelfHostingDefines.h"
 #include "js/GCVector.h"
 #include "js/Id.h"
+#include "js/UniquePtr.h"
 #include "vm/NativeObject.h"
 #include "vm/ProxyObject.h"
 
 namespace js {
 
 class ModuleEnvironmentObject;
 class ModuleObject;
 
@@ -162,18 +163,26 @@ class IndirectBindingMap
     typedef HashMap<jsid, Binding, DefaultHasher<jsid>, ZoneAllocPolicy> Map;
 
     Map map_;
 };
 
 class ModuleNamespaceObject : public ProxyObject
 {
   public:
+    enum ModuleNamespaceSlot
+    {
+        ExportsSlot = 0,
+        BindingsSlot
+    };
+
     static bool isInstance(HandleValue value);
-    static ModuleNamespaceObject* create(JSContext* cx, HandleModuleObject module);
+    static ModuleNamespaceObject* create(JSContext* cx, HandleModuleObject module,
+                                         HandleObject exports,
+                                         UniquePtr<IndirectBindingMap> bindings);
 
     ModuleObject& module();
     JSObject& exports();
     IndirectBindingMap& bindings();
 
     bool addBinding(JSContext* cx, HandleAtom exportedName, HandleModuleObject targetModule,
                     HandleAtom localName);
 
@@ -204,16 +213,19 @@ class ModuleNamespaceObject : public Pro
                                ObjectOpResult& result) const override;
         bool isExtensible(JSContext* cx, HandleObject proxy, bool* extensible) const override;
         bool has(JSContext* cx, HandleObject proxy, HandleId id, bool* bp) const override;
         bool get(JSContext* cx, HandleObject proxy, HandleValue receiver,
                  HandleId id, MutableHandleValue vp) const override;
         bool set(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v,
                  HandleValue receiver, ObjectOpResult& result) const override;
 
+        void trace(JSTracer* trc, JSObject* proxy) const override;
+        void finalize(JSFreeOp* fop, JSObject* proxy) const override;
+
         static const char family;
     };
 
   public:
     static const ProxyHandler proxyHandler;
 };
 
 typedef Rooted<ModuleNamespaceObject*> RootedModuleNamespaceObject;
@@ -245,18 +257,16 @@ class ModuleObject : public NativeObject
         ErrorSlot,
         HostDefinedSlot,
         RequestedModulesSlot,
         ImportEntriesSlot,
         LocalExportEntriesSlot,
         IndirectExportEntriesSlot,
         StarExportEntriesSlot,
         ImportBindingsSlot,
-        NamespaceExportsSlot,
-        NamespaceBindingsSlot,
         FunctionDeclarationsSlot,
         DFSIndexSlot,
         DFSAncestorIndexSlot,
         SlotCount
     };
 
     static_assert(EnvironmentSlot == MODULE_OBJECT_ENVIRONMENT_SLOT,
                   "EnvironmentSlot must match self-hosting define");
@@ -296,18 +306,16 @@ class ModuleObject : public NativeObject
     Value error() const;
     Value hostDefinedField() const;
     ArrayObject& requestedModules() const;
     ArrayObject& importEntries() const;
     ArrayObject& localExportEntries() const;
     ArrayObject& indirectExportEntries() const;
     ArrayObject& starExportEntries() const;
     IndirectBindingMap& importBindings();
-    JSObject* namespaceExports();
-    IndirectBindingMap* namespaceBindings();
 
     static bool Instantiate(JSContext* cx, HandleModuleObject self);
     static bool Evaluate(JSContext* cx, HandleModuleObject self);
 
     void setHostDefinedField(const JS::Value& value);
 
     // For BytecodeEmitter.
     bool noteFunctionDeclaration(JSContext* cx, HandleAtom name, HandleFunction fun);
--- a/js/src/builtin/SelfHostingDefines.h
+++ b/js/src/builtin/SelfHostingDefines.h
@@ -98,18 +98,18 @@
 #define REGEXP_GLOBAL_FLAG      0x02
 #define REGEXP_MULTILINE_FLAG   0x04
 #define REGEXP_STICKY_FLAG      0x08
 #define REGEXP_UNICODE_FLAG     0x10
 
 #define MODULE_OBJECT_ENVIRONMENT_SLOT        1
 #define MODULE_OBJECT_STATUS_SLOT             3
 #define MODULE_OBJECT_ERROR_SLOT              4
-#define MODULE_OBJECT_DFS_INDEX_SLOT          15
-#define MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT 16
+#define MODULE_OBJECT_DFS_INDEX_SLOT          13
+#define MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT 14
 
 #define MODULE_STATUS_ERRORED        0
 #define MODULE_STATUS_UNINSTANTIATED 1
 #define MODULE_STATUS_INSTANTIATING  2
 #define MODULE_STATUS_INSTANTIATED   3
 #define MODULE_STATUS_EVALUATING     4
 #define MODULE_STATUS_EVALUATED      5