Bug 1247934 - Handle receiving unboxed exports array from self hosted module code r=shu
authorJon Coppeard <jcoppeard@mozilla.com>
Wed, 17 Feb 2016 15:48:15 +0000
changeset 331624 d320678c4fab4b2fad3f71c11b6e148600172316
parent 331623 1594c41619ffbb23ef02de913fc96236d516cac5
child 331625 16f3d1ce559a0c9efe5068ae8fc7a84e959b52e5
push id11020
push userjolesen@mozilla.com
push dateWed, 17 Feb 2016 18:16:38 +0000
reviewersshu
bugs1247934
milestone47.0a1
Bug 1247934 - Handle receiving unboxed exports array from self hosted module code r=shu
js/src/builtin/ModuleObject.cpp
js/src/builtin/ModuleObject.h
js/src/jit-test/tests/modules/bug-1247934.js
js/src/vm/SelfHosting.cpp
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -295,20 +295,20 @@ ModuleNamespaceObject::create(JSContext*
 }
 
 ModuleObject&
 ModuleNamespaceObject::module()
 {
     return GetProxyPrivate(this).toObject().as<ModuleObject>();
 }
 
-ArrayObject&
+JSObject&
 ModuleNamespaceObject::exports()
 {
-    ArrayObject* exports = module().namespaceExports();
+    JSObject* exports = module().namespaceExports();
     MOZ_ASSERT(exports);
     return *exports;
 }
 
 IndirectBindingMap&
 ModuleNamespaceObject::bindings()
 {
     IndirectBindingMap* bindings = module().namespaceBindings();
@@ -493,25 +493,27 @@ ModuleNamespaceObject::ProxyHandler::del
     return result.succeed();
 }
 
 bool
 ModuleNamespaceObject::ProxyHandler::ownPropertyKeys(JSContext* cx, HandleObject proxy,
                                                      AutoIdVector& props) const
 {
     Rooted<ModuleNamespaceObject*> ns(cx, &proxy->as<ModuleNamespaceObject>());
-    RootedArrayObject exports(cx, &ns->exports());
-    uint32_t count = exports->length();
-    if (!props.reserve(props.length() + count))
+    RootedObject exports(cx, &ns->exports());
+    uint32_t count;
+    if (!GetLengthProperty(cx, exports, &count) || !props.reserve(props.length() + count))
         return false;
 
-    for (uint32_t i = 0; i < count; i++) {
-        Value value = exports->getDenseElement(i);
-        props.infallibleAppend(AtomToId(&value.toString()->asAtom()));
-    }
+    Rooted<ValueVector> names(cx, ValueVector(cx));
+    if (!names.resize(count) || !GetElements(cx, exports, count, names.begin()))
+        return false;
+
+    for (uint32_t i = 0; i < count; i++)
+        props.infallibleAppend(AtomToId(&names[i].toString()->asAtom()));
 
     return true;
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // FunctionDeclaration
 
 FunctionDeclaration::FunctionDeclaration(HandleAtom name, HandleFunction fun)
@@ -626,24 +628,24 @@ ModuleObject::hasImportBindings() const
 }
 
 IndirectBindingMap&
 ModuleObject::importBindings()
 {
     return *static_cast<IndirectBindingMap*>(getReservedSlot(ImportBindingsSlot).toPrivate());
 }
 
-ArrayObject*
+JSObject*
 ModuleObject::namespaceExports()
 {
     Value value = getReservedSlot(NamespaceExportsSlot);
     if (value.isUndefined())
         return nullptr;
 
-    return &value.toObject().as<ArrayObject>();
+    return &value.toObject();
 }
 
 IndirectBindingMap*
 ModuleObject::namespaceBindings()
 {
     Value value = getReservedSlot(NamespaceBindingsSlot);
     if (value.isUndefined())
         return nullptr;
@@ -815,19 +817,20 @@ ModuleObject::evaluate(JSContext* cx, Ha
         JS_ReportError(cx, "Module declarations have not yet been instantiated");
         return false;
     }
 
     return Execute(cx, script, *scope, rval.address());
 }
 
 /* static */ ModuleNamespaceObject*
-ModuleObject::createNamespace(JSContext* cx, HandleModuleObject self, HandleArrayObject exports)
+ModuleObject::createNamespace(JSContext* cx, HandleModuleObject self, HandleObject exports)
 {
     MOZ_ASSERT(!self->namespace_());
+    MOZ_ASSERT(exports->is<ArrayObject>() || exports->is<UnboxedArrayObject>());
 
     RootedModuleNamespaceObject ns(cx, ModuleNamespaceObject::create(cx, self));
     if (!ns)
         return nullptr;
 
     Zone* zone = cx->zone();
     IndirectBindingMap* bindings = zone->new_<IndirectBindingMap>(zone);
     if (!bindings || !bindings->init()) {
--- a/js/src/builtin/ModuleObject.h
+++ b/js/src/builtin/ModuleObject.h
@@ -128,17 +128,17 @@ class IndirectBindingMap
 
 class ModuleNamespaceObject : public ProxyObject
 {
   public:
     static bool isInstance(HandleValue value);
     static ModuleNamespaceObject* create(JSContext* cx, HandleModuleObject module);
 
     ModuleObject& module();
-    ArrayObject& exports();
+    JSObject& exports();
     IndirectBindingMap& bindings();
 
     bool addBinding(JSContext* cx, HandleAtom exportedName, HandleModuleObject targetModule,
                     HandleAtom localName);
 
   private:
     struct ProxyHandler : public BaseProxyHandler
     {
@@ -240,29 +240,29 @@ class ModuleObject : public NativeObject
     ModuleNamespaceObject* namespace_();
     bool evaluated() const;
     ArrayObject& requestedModules() const;
     ArrayObject& importEntries() const;
     ArrayObject& localExportEntries() const;
     ArrayObject& indirectExportEntries() const;
     ArrayObject& starExportEntries() const;
     IndirectBindingMap& importBindings();
-    ArrayObject* namespaceExports();
+    JSObject* namespaceExports();
     IndirectBindingMap* namespaceBindings();
 
     void createEnvironment();
 
     bool noteFunctionDeclaration(ExclusiveContext* cx, HandleAtom name, HandleFunction fun);
     static bool instantiateFunctionDeclarations(JSContext* cx, HandleModuleObject self);
 
     void setEvaluated();
     static bool evaluate(JSContext* cx, HandleModuleObject self, MutableHandleValue rval);
 
     static ModuleNamespaceObject* createNamespace(JSContext* cx, HandleModuleObject self,
-                                                  HandleArrayObject exports);
+                                                  HandleObject exports);
 
   private:
     static void trace(JSTracer* trc, JSObject* obj);
     static void finalize(js::FreeOp* fop, JSObject* obj);
 
     bool hasScript() const;
     bool hasImportBindings() const;
     FunctionDeclarationVector* functionDeclarations();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1247934.js
@@ -0,0 +1,11 @@
+// |jit-test| --unboxed-arrays
+
+let moduleRepo = {};
+setModuleResolveHook(function(module, specifier) {
+        return moduleRepo[specifier];
+});
+setJitCompilerOption("ion.warmup.trigger", 50);
+s = "";
+for (i = 0; i < 1024; i++) s += "export let e" + i + "\n";
+moduleRepo['a'] = parseModule(s);
+parseModule("import * as ns from 'a'").declarationInstantiation();
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -1629,17 +1629,17 @@ intrinsic_EvaluateModule(JSContext* cx, 
 }
 
 static bool
 intrinsic_NewModuleNamespace(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 2);
     RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
-    RootedArrayObject exports(cx, &args[1].toObject().as<ArrayObject>());
+    RootedObject exports(cx, &args[1].toObject());
     RootedObject namespace_(cx, ModuleObject::createNamespace(cx, module, exports));
     if (!namespace_)
         return false;
 
     args.rval().setObject(*namespace_);
     return true;
 }