WebAssembly JS API: export a module namespace object instead of a module environment
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 1 Dec 2016 03:54:24 +0000 (03:54 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 1 Dec 2016 03:54:24 +0000 (03:54 +0000)
https://bugs.webkit.org/show_bug.cgi?id=165121

Reviewed by Saam Barati.

This patch setup AbstractModuleRecord further for WebAssemblyModuleRecord.
For exported entries in a wasm instance, we set up exported entries for
AbstractModuleRecord. This allows us to export WASM exported functions in
the module handling code.

Since the exported entries in the abstract module record are correctly
instantiated, the module namespace object for WASM module also starts
working correctly. So we start exposing the module namespace object
as `instance.exports` instead of the module environment object.

And we move SourceCode, lexicalVariables, and declaredVariables fields to
JSModuleRecord since they are related to JS source code (in the spec words,
they are related to the source text module record).

* runtime/AbstractModuleRecord.cpp:
(JSC::AbstractModuleRecord::AbstractModuleRecord):
* runtime/AbstractModuleRecord.h:
(JSC::AbstractModuleRecord::sourceCode): Deleted.
(JSC::AbstractModuleRecord::declaredVariables): Deleted.
(JSC::AbstractModuleRecord::lexicalVariables): Deleted.
* runtime/JSModuleRecord.cpp:
(JSC::JSModuleRecord::JSModuleRecord):
* runtime/JSModuleRecord.h:
(JSC::JSModuleRecord::sourceCode):
(JSC::JSModuleRecord::declaredVariables):
(JSC::JSModuleRecord::lexicalVariables):
* wasm/WasmFormat.cpp:
* wasm/js/JSWebAssemblyInstance.cpp:
(JSC::JSWebAssemblyInstance::finishCreation):
* wasm/js/WebAssemblyFunction.cpp:
* wasm/js/WebAssemblyInstanceConstructor.cpp:
(JSC::constructJSWebAssemblyInstance):
* wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::create):
(JSC::WebAssemblyModuleRecord::WebAssemblyModuleRecord):
(JSC::WebAssemblyModuleRecord::finishCreation):
WebAssemblyModuleRecord::link should perform linking things.
So allocating exported entries should be done here.
(JSC::WebAssemblyModuleRecord::link):
* wasm/js/WebAssemblyModuleRecord.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@209171 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/runtime/AbstractModuleRecord.cpp
Source/JavaScriptCore/runtime/AbstractModuleRecord.h
Source/JavaScriptCore/runtime/JSModuleRecord.cpp
Source/JavaScriptCore/runtime/JSModuleRecord.h
Source/JavaScriptCore/wasm/WasmFormat.cpp
Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.h

index be1c7fe..eb57d30 100644 (file)
@@ -1,3 +1,51 @@
+2016-11-30  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        WebAssembly JS API: export a module namespace object instead of a module environment
+        https://bugs.webkit.org/show_bug.cgi?id=165121
+
+        Reviewed by Saam Barati.
+
+        This patch setup AbstractModuleRecord further for WebAssemblyModuleRecord.
+        For exported entries in a wasm instance, we set up exported entries for
+        AbstractModuleRecord. This allows us to export WASM exported functions in
+        the module handling code.
+
+        Since the exported entries in the abstract module record are correctly
+        instantiated, the module namespace object for WASM module also starts
+        working correctly. So we start exposing the module namespace object
+        as `instance.exports` instead of the module environment object.
+
+        And we move SourceCode, lexicalVariables, and declaredVariables fields to
+        JSModuleRecord since they are related to JS source code (in the spec words,
+        they are related to the source text module record).
+
+        * runtime/AbstractModuleRecord.cpp:
+        (JSC::AbstractModuleRecord::AbstractModuleRecord):
+        * runtime/AbstractModuleRecord.h:
+        (JSC::AbstractModuleRecord::sourceCode): Deleted.
+        (JSC::AbstractModuleRecord::declaredVariables): Deleted.
+        (JSC::AbstractModuleRecord::lexicalVariables): Deleted.
+        * runtime/JSModuleRecord.cpp:
+        (JSC::JSModuleRecord::JSModuleRecord):
+        * runtime/JSModuleRecord.h:
+        (JSC::JSModuleRecord::sourceCode):
+        (JSC::JSModuleRecord::declaredVariables):
+        (JSC::JSModuleRecord::lexicalVariables):
+        * wasm/WasmFormat.cpp:
+        * wasm/js/JSWebAssemblyInstance.cpp:
+        (JSC::JSWebAssemblyInstance::finishCreation):
+        * wasm/js/WebAssemblyFunction.cpp:
+        * wasm/js/WebAssemblyInstanceConstructor.cpp:
+        (JSC::constructJSWebAssemblyInstance):
+        * wasm/js/WebAssemblyModuleRecord.cpp:
+        (JSC::WebAssemblyModuleRecord::create):
+        (JSC::WebAssemblyModuleRecord::WebAssemblyModuleRecord):
+        (JSC::WebAssemblyModuleRecord::finishCreation):
+        WebAssemblyModuleRecord::link should perform linking things.
+        So allocating exported entries should be done here.
+        (JSC::WebAssemblyModuleRecord::link):
+        * wasm/js/WebAssemblyModuleRecord.h:
+
 2016-11-30  Mark Lam  <mark.lam@apple.com>
 
         TypeInfo::OutOfLineTypeFlags should be 16 bits in size.
index a5be604..ebe5f5d 100644 (file)
@@ -38,12 +38,9 @@ namespace JSC {
 
 const ClassInfo AbstractModuleRecord::s_info = { "AbstractModuleRecord", &Base::s_info, 0, CREATE_METHOD_TABLE(AbstractModuleRecord) };
 
-AbstractModuleRecord::AbstractModuleRecord(VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables)
+AbstractModuleRecord::AbstractModuleRecord(VM& vm, Structure* structure, const Identifier& moduleKey)
     : Base(vm, structure)
     , m_moduleKey(moduleKey)
-    , m_sourceCode(sourceCode)
-    , m_declaredVariables(declaredVariables)
-    , m_lexicalVariables(lexicalVariables)
 {
 }
 
index ec6992d..04af126 100644 (file)
@@ -88,16 +88,12 @@ public:
     std::optional<ImportEntry> tryGetImportEntry(UniquedStringImpl* localName);
     std::optional<ExportEntry> tryGetExportEntry(UniquedStringImpl* exportName);
 
-    const SourceCode& sourceCode() const { return m_sourceCode; }
     const Identifier& moduleKey() const { return m_moduleKey; }
     const OrderedIdentifierSet& requestedModules() const { return m_requestedModules; }
     const ExportEntries& exportEntries() const { return m_exportEntries; }
     const ImportEntries& importEntries() const { return m_importEntries; }
     const OrderedIdentifierSet& starExportEntries() const { return m_starExportEntries; }
 
-    const VariableEnvironment& declaredVariables() const { return m_declaredVariables; }
-    const VariableEnvironment& lexicalVariables() const { return m_lexicalVariables; }
-
     void dump();
 
     struct Resolution {
@@ -126,7 +122,7 @@ public:
     }
 
 protected:
-    AbstractModuleRecord(VM&, Structure*, const Identifier&, const SourceCode&, const VariableEnvironment&, const VariableEnvironment&);
+    AbstractModuleRecord(VM&, Structure*, const Identifier&);
     void finishCreation(ExecState*, VM&);
 
     static void visitChildren(JSCell*, SlotVisitor&);
@@ -143,11 +139,6 @@ private:
     // The loader resolves the given module name to the module key. The module key is the unique value to represent this module.
     Identifier m_moduleKey;
 
-    SourceCode m_sourceCode;
-
-    VariableEnvironment m_declaredVariables;
-    VariableEnvironment m_lexicalVariables;
-
     // Currently, we don't keep the occurrence order of the import / export entries.
     // So, we does not guarantee the order of the errors.
     // e.g. The import declaration that occurr later than the another import declaration may
index c2e6156..40819d7 100644 (file)
@@ -50,7 +50,10 @@ JSModuleRecord* JSModuleRecord::create(ExecState* exec, VM& vm, Structure* struc
     return instance;
 }
 JSModuleRecord::JSModuleRecord(VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables)
-    : Base(vm, structure, moduleKey, sourceCode, declaredVariables, lexicalVariables)
+    : Base(vm, structure, moduleKey)
+    , m_sourceCode(sourceCode)
+    , m_declaredVariables(declaredVariables)
+    , m_lexicalVariables(lexicalVariables)
 {
 }
 
index af0161c..9e69b0f 100644 (file)
@@ -51,6 +51,10 @@ public:
     void link(ExecState*);
     JS_EXPORT_PRIVATE JSValue evaluate(ExecState*);
 
+    const SourceCode& sourceCode() const { return m_sourceCode; }
+    const VariableEnvironment& declaredVariables() const { return m_declaredVariables; }
+    const VariableEnvironment& lexicalVariables() const { return m_lexicalVariables; }
+
     ModuleProgramExecutable* moduleProgramExecutable() const { return m_moduleProgramExecutable.get(); }
 
 private:
@@ -63,6 +67,9 @@ private:
 
     void instantiateDeclarations(ExecState*, ModuleProgramExecutable*);
 
+    SourceCode m_sourceCode;
+    VariableEnvironment m_declaredVariables;
+    VariableEnvironment m_lexicalVariables;
     WriteBarrier<ModuleProgramExecutable> m_moduleProgramExecutable;
 };
 
index bf8e356..20c9e3d 100644 (file)
 
 #include "WasmMemory.h"
 
+#if COMPILER(GCC) && ASSERT_DISABLED
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wreturn-type"
+#endif // COMPILER(GCC) && ASSERT_DISABLED
+
 namespace JSC { namespace Wasm {
 
 const char* toString(Type type)
@@ -53,4 +58,8 @@ ModuleInformation::~ModuleInformation() { }
 
 } } // namespace JSC::Wasm
 
+#if COMPILER(GCC) && ASSERT_DISABLED
+#pragma GCC diagnostic pop
+#endif // COMPILER(GCC) && ASSERT_DISABLED
+
 #endif // ENABLE(WEBASSEMBLY)
index ce3fdc7..0ad2019 100644 (file)
@@ -56,10 +56,10 @@ JSWebAssemblyInstance::JSWebAssemblyInstance(VM& vm, Structure* structure)
 void JSWebAssemblyInstance::finishCreation(VM& vm, JSWebAssemblyModule* module, JSModuleNamespaceObject* moduleNamespaceObject)
 {
     Base::finishCreation(vm);
+    ASSERT(inherits(info()));
     m_module.set(vm, this, module);
     m_moduleNamespaceObject.set(vm, this, moduleNamespaceObject);
-    // FIXME this should put the module namespace object onto the exports object, instead of moduleEnvironment in WebAssemblyInstanceConstructor. https://bugs.webkit.org/show_bug.cgi?id=165121
-    ASSERT(inherits(info()));
+    putDirect(vm, Identifier::fromString(&vm, "exports"), moduleNamespaceObject, None);
 }
 
 void JSWebAssemblyInstance::destroy(JSCell* cell)
index 9ff6c2a..c5c10ff 100644 (file)
@@ -33,7 +33,7 @@
 #include "JSFunctionInlines.h"
 #include "JSObject.h"
 #include "JSWebAssemblyInstance.h"
-#include "LLintThunks.h"
+#include "LLIntThunks.h"
 #include "ProtoCallFrame.h"
 #include "VM.h"
 #include "WasmFormat.h"
index 88cf973..2952dd0 100644 (file)
@@ -72,10 +72,7 @@ static EncodedJSValue JSC_HOST_CALL constructJSWebAssemblyInstance(ExecState* st
         return JSValue::encode(throwException(state, scope, createTypeError(state, ASCIILiteral("second argument to WebAssembly.Instance must be Object because the WebAssembly.Module has imports"), defaultSourceAppender, runtimeTypeForValue(importArgument))));
 
     Identifier moduleKey = Identifier::fromUid(PrivateName(PrivateName::Description, "WebAssemblyInstance"));
-    SourceCode sourceCode;
-    VariableEnvironment declaredVariables;
-    VariableEnvironment lexicalVariables;
-    WebAssemblyModuleRecord* moduleRecord = WebAssemblyModuleRecord::create(state, vm, globalObject->webAssemblyModuleRecordStructure(), moduleKey, sourceCode, declaredVariables, lexicalVariables);
+    WebAssemblyModuleRecord* moduleRecord = WebAssemblyModuleRecord::create(state, vm, globalObject->webAssemblyModuleRecordStructure(), moduleKey, moduleInformation);
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     Structure* instanceStructure = InternalFunction::createSubclassStructure(state, state->newTarget(), globalObject->WebAssemblyInstanceStructure());
@@ -88,8 +85,6 @@ static EncodedJSValue JSC_HOST_CALL constructJSWebAssemblyInstance(ExecState* st
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
     if (verbose)
         moduleRecord->dump();
-    // FIXME the following should be in JSWebAssemblyInstance instead of here. https://bugs.webkit.org/show_bug.cgi?id=165121
-    instance->putDirect(vm, Identifier::fromString(&vm, "exports"), JSValue(moduleRecord->moduleEnvironment()), None);
     JSValue startResult = moduleRecord->evaluate(state);
     UNUSED_PARAM(startResult);
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
index dab5b82..a618e05 100644 (file)
@@ -46,15 +46,15 @@ Structure* WebAssemblyModuleRecord::createStructure(VM& vm, JSGlobalObject* glob
     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
 }
 
-WebAssemblyModuleRecord* WebAssemblyModuleRecord::create(ExecState* exec, VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables)
+WebAssemblyModuleRecord* WebAssemblyModuleRecord::create(ExecState* exec, VM& vm, Structure* structure, const Identifier& moduleKey, const Wasm::ModuleInformation& moduleInformation)
 {
-    WebAssemblyModuleRecord* instance = new (NotNull, allocateCell<WebAssemblyModuleRecord>(vm.heap)) WebAssemblyModuleRecord(vm, structure, moduleKey, sourceCode, declaredVariables, lexicalVariables);
-    instance->finishCreation(exec, vm);
+    WebAssemblyModuleRecord* instance = new (NotNull, allocateCell<WebAssemblyModuleRecord>(vm.heap)) WebAssemblyModuleRecord(vm, structure, moduleKey);
+    instance->finishCreation(exec, vm, moduleInformation);
     return instance;
 }
 
-WebAssemblyModuleRecord::WebAssemblyModuleRecord(VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables)
-    : Base(vm, structure, moduleKey, sourceCode, declaredVariables, lexicalVariables)
+WebAssemblyModuleRecord::WebAssemblyModuleRecord(VM& vm, Structure* structure, const Identifier& moduleKey)
+    : Base(vm, structure, moduleKey)
 {
 }
 
@@ -64,10 +64,31 @@ void WebAssemblyModuleRecord::destroy(JSCell* cell)
     thisObject->WebAssemblyModuleRecord::~WebAssemblyModuleRecord();
 }
 
-void WebAssemblyModuleRecord::finishCreation(ExecState* exec, VM& vm)
+void WebAssemblyModuleRecord::finishCreation(ExecState* exec, VM& vm, const Wasm::ModuleInformation& moduleInformation)
 {
     Base::finishCreation(exec, vm);
     ASSERT(inherits(info()));
+    for (const auto& exp : moduleInformation.exports) {
+        switch (exp.kind) {
+        case Wasm::External::Function: {
+            addExportEntry(ExportEntry::createLocal(exp.field, exp.field));
+            break;
+        }
+        case Wasm::External::Table: {
+            // FIXME https://bugs.webkit.org/show_bug.cgi?id=164135
+            break;
+        }
+        case Wasm::External::Memory: {
+            // FIXME https://bugs.webkit.org/show_bug.cgi?id=164134
+            break;
+        }
+        case Wasm::External::Global: {
+            // FIXME https://bugs.webkit.org/show_bug.cgi?id=164133
+            // In the MVP, only immutable global variables can be exported.
+            break;
+        }
+        }
+    }
 }
 
 void WebAssemblyModuleRecord::visitChildren(JSCell* cell, SlotVisitor& visitor)
@@ -92,11 +113,8 @@ void WebAssemblyModuleRecord::link(ExecState* state, JSWebAssemblyInstance* inst
 
     // Let exports be a list of (string, JS value) pairs that is mapped from each external value e in instance.exports as follows:
     JSModuleEnvironment* moduleEnvironment = JSModuleEnvironment::create(vm, globalObject, nullptr, exportSymbolTable, JSValue(), this);
-    unsigned offset = 0;
     for (const auto& exp : moduleInformation.exports) {
         JSValue exportedValue;
-        PutPropertySlot slot(this);
-        slot.setNewProperty(this, offset++);
         switch (exp.kind) {
         case Wasm::External::Function: {
             // 1. If e is a closure c:
index aab353a..a02f9ed 100644 (file)
@@ -28,6 +28,7 @@
 #if ENABLE(WEBASSEMBLY)
 
 #include "AbstractModuleRecord.h"
+#include "WasmFormat.h"
 
 namespace JSC {
 
@@ -43,15 +44,15 @@ public:
     DECLARE_EXPORT_INFO;
 
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
-    static WebAssemblyModuleRecord* create(ExecState*, VM&, Structure*, const Identifier&, const SourceCode&, const VariableEnvironment&, const VariableEnvironment&);
+    static WebAssemblyModuleRecord* create(ExecState*, VM&, Structure*, const Identifier&, const Wasm::ModuleInformation&);
 
     void link(ExecState*, JSWebAssemblyInstance*);
     JS_EXPORT_PRIVATE JSValue evaluate(ExecState*);
 
 private:
-    WebAssemblyModuleRecord(VM&, Structure*, const Identifier&, const SourceCode&, const VariableEnvironment&, const VariableEnvironment&);
+    WebAssemblyModuleRecord(VM&, Structure*, const Identifier&);
 
-    void finishCreation(ExecState*, VM&);
+    void finishCreation(ExecState*, VM&, const Wasm::ModuleInformation&);
     static void destroy(JSCell*);
 
     static void visitChildren(JSCell*, SlotVisitor&);