[JSC] Wasm module import should be done in sync when WebAssembly.instantiate gets module
https://bugs.webkit.org/show_bug.cgi?id=235506
Reviewed by Saam Barati.
LayoutTests/imported/w3c:
* web-platform-tests/wasm/jsapi/constructor/instantiate.any-expected.txt:
* web-platform-tests/wasm/jsapi/constructor/instantiate.any.worker-expected.txt:
Source/JavaScriptCore:
According to the spec, module imports need to be done synchronously when WebAssembly.instantiate
is called with a wasm module[1].
To align our implementation to this behavior, we split WebAssemblyModuleRecord::initializeImportsAndExports
into WebAssemblyModuleRecord::initializeImports and WebAssemblyModuleRecord::initializeExports. The former
does not require CalleeGroups so we can execute before compiling CalleeGroups.
[1]: https://webassembly.github.io/spec/js-api/#asynchronously-instantiate-a-webassembly-module
* runtime/AbstractModuleRecord.cpp:
(JSC::AbstractModuleRecord::evaluate):
* wasm/WasmInstance.h:
(JSC::Wasm::Instance::setOwner):
(JSC::Wasm::Instance::finalizeCreation): Deleted.
* wasm/WasmModuleInformation.h:
(JSC::Wasm::ModuleInformation::hasMemoryImport const):
* wasm/js/JSWebAssembly.cpp:
(JSC::instantiate):
(JSC::resolve): Deleted.
* wasm/js/JSWebAssemblyInstance.cpp:
(JSC::JSWebAssemblyInstance::JSWebAssemblyInstance):
(JSC::JSWebAssemblyInstance::initializeImports):
(JSC::JSWebAssemblyInstance::finalizeCreation):
* wasm/js/JSWebAssemblyInstance.h:
* wasm/js/WebAssemblyInstanceConstructor.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
* wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::initializeImports):
(JSC::WebAssemblyModuleRecord::initializeExports):
(JSC::WebAssemblyModuleRecord::initializeImportsAndExports): Deleted.
* wasm/js/WebAssemblyModuleRecord.h:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@288573 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/imported/w3c/ChangeLog b/LayoutTests/imported/w3c/ChangeLog
index c1cb3ce..eaa6af6 100644
--- a/LayoutTests/imported/w3c/ChangeLog
+++ b/LayoutTests/imported/w3c/ChangeLog
@@ -1,3 +1,13 @@
+2022-01-25 Yusuke Suzuki <ysuzuki@apple.com>
+
+ [JSC] Wasm module import should be done in sync when WebAssembly.instantiate gets module
+ https://bugs.webkit.org/show_bug.cgi?id=235506
+
+ Reviewed by Saam Barati.
+
+ * web-platform-tests/wasm/jsapi/constructor/instantiate.any-expected.txt:
+ * web-platform-tests/wasm/jsapi/constructor/instantiate.any.worker-expected.txt:
+
2022-01-25 Antoine Quint <graouts@webkit.org>
Deduplication for @keyframes rules should account for animation-composition
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any-expected.txt
index 8642a5e..1e08a0d 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any-expected.txt
+++ b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any-expected.txt
@@ -52,7 +52,7 @@
PASS stray argument: BufferSource argument
PASS stray argument: Module argument
PASS Synchronous options handling: Buffer argument
-FAIL Synchronous options handling: Module argument assert_array_equals: lengths differ, expected array ["module getter", "global getter"] length 2, got [] length 0
+PASS Synchronous options handling: Module argument
PASS Empty buffer
PASS Invalid code
PASS Changing the buffer
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any.worker-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any.worker-expected.txt
index 8642a5e..1e08a0d 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any.worker-expected.txt
+++ b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any.worker-expected.txt
@@ -52,7 +52,7 @@
PASS stray argument: BufferSource argument
PASS stray argument: Module argument
PASS Synchronous options handling: Buffer argument
-FAIL Synchronous options handling: Module argument assert_array_equals: lengths differ, expected array ["module getter", "global getter"] length 2, got [] length 0
+PASS Synchronous options handling: Module argument
PASS Empty buffer
PASS Invalid code
PASS Changing the buffer
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 519c115..8339965 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,42 @@
+2022-01-25 Yusuke Suzuki <ysuzuki@apple.com>
+
+ [JSC] Wasm module import should be done in sync when WebAssembly.instantiate gets module
+ https://bugs.webkit.org/show_bug.cgi?id=235506
+
+ Reviewed by Saam Barati.
+
+ According to the spec, module imports need to be done synchronously when WebAssembly.instantiate
+ is called with a wasm module[1].
+
+ To align our implementation to this behavior, we split WebAssemblyModuleRecord::initializeImportsAndExports
+ into WebAssemblyModuleRecord::initializeImports and WebAssemblyModuleRecord::initializeExports. The former
+ does not require CalleeGroups so we can execute before compiling CalleeGroups.
+
+ [1]: https://webassembly.github.io/spec/js-api/#asynchronously-instantiate-a-webassembly-module
+
+ * runtime/AbstractModuleRecord.cpp:
+ (JSC::AbstractModuleRecord::evaluate):
+ * wasm/WasmInstance.h:
+ (JSC::Wasm::Instance::setOwner):
+ (JSC::Wasm::Instance::finalizeCreation): Deleted.
+ * wasm/WasmModuleInformation.h:
+ (JSC::Wasm::ModuleInformation::hasMemoryImport const):
+ * wasm/js/JSWebAssembly.cpp:
+ (JSC::instantiate):
+ (JSC::resolve): Deleted.
+ * wasm/js/JSWebAssemblyInstance.cpp:
+ (JSC::JSWebAssemblyInstance::JSWebAssemblyInstance):
+ (JSC::JSWebAssemblyInstance::initializeImports):
+ (JSC::JSWebAssemblyInstance::finalizeCreation):
+ * wasm/js/JSWebAssemblyInstance.h:
+ * wasm/js/WebAssemblyInstanceConstructor.cpp:
+ (JSC::JSC_DEFINE_HOST_FUNCTION):
+ * wasm/js/WebAssemblyModuleRecord.cpp:
+ (JSC::WebAssemblyModuleRecord::initializeImports):
+ (JSC::WebAssemblyModuleRecord::initializeExports):
+ (JSC::WebAssemblyModuleRecord::initializeImportsAndExports): Deleted.
+ * wasm/js/WebAssemblyModuleRecord.h:
+
2022-01-24 Mark Lam <mark.lam@apple.com>
Rename Vector and FixedVector::findMatching to findIf to match stl naming.
diff --git a/Source/JavaScriptCore/runtime/AbstractModuleRecord.cpp b/Source/JavaScriptCore/runtime/AbstractModuleRecord.cpp
index 8fd767c..425b8fa 100644
--- a/Source/JavaScriptCore/runtime/AbstractModuleRecord.cpp
+++ b/Source/JavaScriptCore/runtime/AbstractModuleRecord.cpp
@@ -843,7 +843,9 @@
// WebAssembly imports need to be supplied during evaluation so that, e.g.,
// JS module exports are actually available to be read and installed as import
// bindings.
- wasmModuleRecord->initializeImportsAndExports(globalObject, nullptr, Wasm::CreationMode::FromModuleLoader);
+ wasmModuleRecord->initializeImports(globalObject, nullptr, Wasm::CreationMode::FromModuleLoader);
+ RETURN_IF_EXCEPTION(scope, jsUndefined());
+ wasmModuleRecord->initializeExports(globalObject);
RETURN_IF_EXCEPTION(scope, jsUndefined());
RELEASE_AND_RETURN(scope, wasmModuleRecord->evaluate(globalObject));
}
diff --git a/Source/JavaScriptCore/wasm/WasmInstance.h b/Source/JavaScriptCore/wasm/WasmInstance.h
index 740e79c..710b876 100644
--- a/Source/JavaScriptCore/wasm/WasmInstance.h
+++ b/Source/JavaScriptCore/wasm/WasmInstance.h
@@ -56,7 +56,7 @@
static Ref<Instance> create(Context*, Ref<Module>&&, EntryFrame** pointerToTopEntryFrame, void** pointerToActualStackLimit, StoreTopCallFrameCallback&&);
- void finalizeCreation(void* owner)
+ void setOwner(void* owner)
{
m_owner = owner;
}
diff --git a/Source/JavaScriptCore/wasm/WasmModuleInformation.h b/Source/JavaScriptCore/wasm/WasmModuleInformation.h
index 21a3927..a61f692 100644
--- a/Source/JavaScriptCore/wasm/WasmModuleInformation.h
+++ b/Source/JavaScriptCore/wasm/WasmModuleInformation.h
@@ -94,6 +94,8 @@
bool isDeclaredException(uint32_t index) const { return m_declaredExceptions.contains(index); }
void addDeclaredException(uint32_t index) { m_declaredExceptions.set(index); }
+ bool hasMemoryImport() const { return memory.isImport(); }
+
Vector<Import> imports;
Vector<SignatureIndex> importFunctionSignatureIndices;
Vector<SignatureIndex> internalFunctionSignatureIndices;
diff --git a/Source/JavaScriptCore/wasm/js/JSWebAssembly.cpp b/Source/JavaScriptCore/wasm/js/JSWebAssembly.cpp
index 4d1ea41..82d6319 100644
--- a/Source/JavaScriptCore/wasm/js/JSWebAssembly.cpp
+++ b/Source/JavaScriptCore/wasm/js/JSWebAssembly.cpp
@@ -137,32 +137,6 @@
return JSValue::encode(promise);
}
-enum class Resolve { WithInstance, WithModuleRecord, WithModuleAndInstance };
-static void resolve(VM& vm, JSGlobalObject* globalObject, JSPromise* promise, JSWebAssemblyInstance* instance, JSWebAssemblyModule* module, JSObject* importObject, Ref<Wasm::CalleeGroup>&& calleeGroup, Resolve resolveKind, Wasm::CreationMode creationMode)
-{
- auto scope = DECLARE_THROW_SCOPE(vm);
- instance->finalizeCreation(vm, globalObject, WTFMove(calleeGroup), importObject, creationMode);
- if (UNLIKELY(scope.exception())) {
- promise->rejectWithCaughtException(globalObject, scope);
- return;
- }
-
- scope.release();
- if (resolveKind == Resolve::WithInstance)
- promise->resolve(globalObject, instance);
- else if (resolveKind == Resolve::WithModuleRecord) {
- auto* moduleRecord = instance->moduleRecord();
- if (UNLIKELY(Options::dumpModuleRecord()))
- moduleRecord->dump();
- promise->resolve(globalObject, moduleRecord);
- } else {
- JSObject* result = constructEmptyObject(globalObject);
- result->putDirect(vm, Identifier::fromString(vm, "module"_s), module);
- result->putDirect(vm, Identifier::fromString(vm, "instance"_s), instance);
- promise->resolve(globalObject, result);
- }
-}
-
void JSWebAssembly::webAssemblyModuleValidateAsync(JSGlobalObject* globalObject, JSPromise* promise, Vector<uint8_t>&& source)
{
VM& vm = globalObject->vm();
@@ -186,6 +160,7 @@
}));
}
+enum class Resolve { WithInstance, WithModuleRecord, WithModuleAndInstance };
static void instantiate(VM& vm, JSGlobalObject* globalObject, JSPromise* promise, JSWebAssemblyModule* module, JSObject* importObject, const Identifier& moduleKey, Resolve resolveKind, Wasm::CreationMode creationMode)
{
auto scope = DECLARE_THROW_SCOPE(vm);
@@ -197,18 +172,51 @@
return;
}
+ instance->initializeImports(globalObject, importObject, creationMode);
+ if (UNLIKELY(scope.exception())) {
+ promise->rejectWithCaughtException(globalObject, scope);
+ return;
+ }
+
Vector<Strong<JSCell>> dependencies;
// The instance keeps the module alive.
dependencies.append(Strong<JSCell>(vm, promise));
- dependencies.append(Strong<JSCell>(vm, importObject));
+ scope.release();
auto ticket = vm.deferredWorkTimer->addPendingWork(vm, instance, WTFMove(dependencies));
// Note: This completion task may or may not get called immediately.
- module->module().compileAsync(&vm.wasmContext, instance->memoryMode(), createSharedTask<Wasm::CalleeGroup::CallbackType>([ticket, promise, instance, module, importObject, resolveKind, creationMode, &vm] (Ref<Wasm::CalleeGroup>&& refCalleeGroup) mutable {
+ module->module().compileAsync(&vm.wasmContext, instance->memoryMode(), createSharedTask<Wasm::CalleeGroup::CallbackType>([ticket, promise, instance, module, resolveKind, creationMode, &vm] (Ref<Wasm::CalleeGroup>&& refCalleeGroup) mutable {
RefPtr<Wasm::CalleeGroup> calleeGroup = WTFMove(refCalleeGroup);
- vm.deferredWorkTimer->scheduleWorkSoon(ticket, [promise, instance, module, importObject, resolveKind, creationMode, &vm, calleeGroup = WTFMove(calleeGroup)](DeferredWorkTimer::Ticket) mutable {
+ vm.deferredWorkTimer->scheduleWorkSoon(ticket, [promise, instance, module, resolveKind, creationMode, &vm, calleeGroup = WTFMove(calleeGroup)](DeferredWorkTimer::Ticket) mutable {
+ auto scope = DECLARE_THROW_SCOPE(vm);
JSGlobalObject* globalObject = instance->globalObject();
- resolve(vm, globalObject, promise, instance, module, importObject, calleeGroup.releaseNonNull(), resolveKind, creationMode);
+ instance->finalizeCreation(vm, globalObject, calleeGroup.releaseNonNull(), creationMode);
+ if (UNLIKELY(scope.exception())) {
+ promise->rejectWithCaughtException(globalObject, scope);
+ return;
+ }
+
+ scope.release();
+ switch (resolveKind) {
+ case Resolve::WithInstance: {
+ promise->resolve(globalObject, instance);
+ break;
+ }
+ case Resolve::WithModuleRecord: {
+ auto* moduleRecord = instance->moduleRecord();
+ if (UNLIKELY(Options::dumpModuleRecord()))
+ moduleRecord->dump();
+ promise->resolve(globalObject, moduleRecord);
+ break;
+ }
+ case Resolve::WithModuleAndInstance: {
+ JSObject* result = constructEmptyObject(globalObject);
+ result->putDirect(vm, Identifier::fromString(vm, "module"_s), module);
+ result->putDirect(vm, Identifier::fromString(vm, "instance"_s), instance);
+ promise->resolve(globalObject, result);
+ break;
+ }
+ }
});
}));
}
diff --git a/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp b/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp
index 7b86753..e75918b 100644
--- a/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp
+++ b/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp
@@ -53,6 +53,7 @@
, m_globalObject(vm, this, structure->globalObject())
, m_tables(m_instance->module().moduleInformation().tableCount())
{
+ m_instance->setOwner(this);
for (unsigned i = 0; i < this->instance().numImportFunctions(); ++i)
new (this->instance().importFunction<WriteBarrier<JSObject>>(i)) WriteBarrier<JSObject>();
}
@@ -104,10 +105,22 @@
DEFINE_VISIT_CHILDREN(JSWebAssemblyInstance);
-void JSWebAssemblyInstance::finalizeCreation(VM& vm, JSGlobalObject* globalObject, Ref<Wasm::CalleeGroup>&& wasmCalleeGroup, JSObject* importObject, Wasm::CreationMode creationMode)
+void JSWebAssemblyInstance::initializeImports(JSGlobalObject* globalObject, JSObject* importObject, Wasm::CreationMode creationMode)
{
- m_instance->finalizeCreation(this);
+ VM& vm = globalObject->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ m_moduleRecord->prepareLink(vm, this);
+ if (creationMode == Wasm::CreationMode::FromJS) {
+ m_moduleRecord->link(globalObject, jsNull());
+ RETURN_IF_EXCEPTION(scope, void());
+ m_moduleRecord->initializeImports(globalObject, importObject, creationMode);
+ RETURN_IF_EXCEPTION(scope, void());
+ }
+}
+
+void JSWebAssemblyInstance::finalizeCreation(VM& vm, JSGlobalObject* globalObject, Ref<Wasm::CalleeGroup>&& wasmCalleeGroup, Wasm::CreationMode creationMode)
+{
auto scope = DECLARE_THROW_SCOPE(vm);
if (!wasmCalleeGroup->runnable()) {
@@ -121,31 +134,16 @@
// results, so that later when memory imports become available, the appropriate CalleeGroup can be used.
// If LLInt is disabled, we instead defer compilation to module evaluation.
// If the code is already compiled, e.g. the module was already instantiated before, we do not re-initialize.
- bool hasMemoryImport = module()->moduleInformation().memory.isImport();
- if (Options::useWasmLLInt() && hasMemoryImport) {
- Wasm::MemoryMode initialMode = Wasm::MemoryMode::BoundsChecking;
- ASSERT(memoryMode() == initialMode);
- module()->module().copyInitialCalleeGroupToAllMemoryModes(initialMode);
-
- for (unsigned i = 0; i < Wasm::NumberOfMemoryModes; i++) {
- if (i == static_cast<uint8_t>(initialMode))
- continue;
- Wasm::MemoryMode memoryMode = static_cast<Wasm::MemoryMode>(i);
- module()->module().calleeGroupFor(memoryMode); // Materialize Wasm::CalleeGroup.
- }
- }
+ if (Options::useWasmLLInt() && module()->moduleInformation().hasMemoryImport())
+ module()->module().copyInitialCalleeGroupToAllMemoryModes(memoryMode());
for (unsigned importFunctionNum = 0; importFunctionNum < instance().numImportFunctions(); ++importFunctionNum) {
auto* info = instance().importFunctionInfo(importFunctionNum);
info->wasmToEmbedderStub = m_module->wasmToEmbedderStub(importFunctionNum);
}
- m_moduleRecord->prepareLink(vm, this);
-
if (creationMode == Wasm::CreationMode::FromJS) {
- m_moduleRecord->link(globalObject, jsNull());
- RETURN_IF_EXCEPTION(scope, void());
- m_moduleRecord->initializeImportsAndExports(globalObject, importObject, creationMode);
+ m_moduleRecord->initializeExports(globalObject);
RETURN_IF_EXCEPTION(scope, void());
JSValue startResult = m_moduleRecord->evaluate(globalObject);
diff --git a/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h b/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h
index 0b1b7a7..d4151c3 100644
--- a/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h
+++ b/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h
@@ -67,7 +67,8 @@
DECLARE_EXPORT_INFO;
- void finalizeCreation(VM&, JSGlobalObject*, Ref<Wasm::CalleeGroup>&&, JSObject* importObject, Wasm::CreationMode);
+ void initializeImports(JSGlobalObject*, JSObject* importObject, Wasm::CreationMode);
+ void finalizeCreation(VM&, JSGlobalObject*, Ref<Wasm::CalleeGroup>&&, Wasm::CreationMode);
Wasm::Instance& instance() { return m_instance.get(); }
WebAssemblyModuleRecord* moduleRecord() { return m_moduleRecord.get(); }
diff --git a/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp b/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp
index 7a107e2..7523333 100644
--- a/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp
+++ b/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp
@@ -72,7 +72,10 @@
JSWebAssemblyInstance* instance = JSWebAssemblyInstance::tryCreate(vm, globalObject, JSWebAssemblyInstance::createPrivateModuleKey(), module, importObject, instanceStructure, Ref<Wasm::Module>(module->module()), Wasm::CreationMode::FromJS);
RETURN_IF_EXCEPTION(scope, { });
- instance->finalizeCreation(vm, globalObject, module->module().compileSync(&vm.wasmContext, instance->memoryMode()), importObject, Wasm::CreationMode::FromJS);
+ instance->initializeImports(globalObject, importObject, Wasm::CreationMode::FromJS);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ instance->finalizeCreation(vm, globalObject, module->module().compileSync(&vm.wasmContext, instance->memoryMode()), Wasm::CreationMode::FromJS);
RETURN_IF_EXCEPTION(scope, { });
return JSValue::encode(instance);
}
diff --git a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp b/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp
index 599e234f6..7fa81e7 100644
--- a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp
+++ b/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp
@@ -113,11 +113,11 @@
return Synchronousness::Sync;
}
-void WebAssemblyModuleRecord::initializeImportsAndExports(JSGlobalObject* globalObject, JSObject* importObject, Wasm::CreationMode creationMode)
+// https://webassembly.github.io/spec/js-api/#read-the-imports
+void WebAssemblyModuleRecord::initializeImports(JSGlobalObject* globalObject, JSObject* importObject, Wasm::CreationMode creationMode)
{
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- UNUSED_PARAM(scope);
RELEASE_ASSERT(m_instance);
@@ -422,21 +422,39 @@
// iii. Append v.[[Memory]] to imports.
m_instance->setMemory(vm, memory);
RETURN_IF_EXCEPTION(scope, void());
-
- // Usually at this point the module's code block in any memory mode should be
- // runnable due to the LLint tier code being shared among all modes. However,
- // if LLInt is disabled, it is possible that the code needs to be compiled at
- // this point when we know which memory mode to use.
- Wasm::CalleeGroup* calleeGroup = m_instance->instance().calleeGroup();
- if (!calleeGroup || !calleeGroup->runnable()) {
- calleeGroup = m_instance->module()->module().compileSync(&vm.wasmContext, memory->memory().mode()).ptr();
- if (!calleeGroup->runnable())
- return exception(createJSWebAssemblyLinkError(globalObject, vm, calleeGroup->errorMessage()));
- }
- RELEASE_ASSERT(calleeGroup->isSafeToRun(memory->memory().mode()));
break;
}
}
+}
+
+// https://webassembly.github.io/spec/js-api/#create-an-exports-object
+void WebAssemblyModuleRecord::initializeExports(JSGlobalObject* globalObject)
+{
+ VM& vm = globalObject->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ RELEASE_ASSERT(m_instance);
+
+ JSWebAssemblyModule* module = m_instance->module();
+ const Wasm::ModuleInformation& moduleInformation = module->moduleInformation();
+
+ auto exception = [&] (JSObject* error) {
+ throwException(globalObject, scope, error);
+ };
+
+ if (moduleInformation.hasMemoryImport()) {
+ // Usually at this point the module's code block in any memory mode should be
+ // runnable due to the LLint tier code being shared among all modes. However,
+ // if LLInt is disabled, it is possible that the code needs to be compiled at
+ // this point when we know which memory mode to use.
+ Wasm::CalleeGroup* calleeGroup = m_instance->instance().calleeGroup();
+ if (!calleeGroup || !calleeGroup->runnable()) {
+ calleeGroup = m_instance->module()->module().compileSync(&vm.wasmContext, m_instance->instance().memory()->mode()).ptr();
+ if (!calleeGroup->runnable())
+ return exception(createJSWebAssemblyLinkError(globalObject, vm, calleeGroup->errorMessage()));
+ }
+ RELEASE_ASSERT(calleeGroup->isSafeToRun(m_instance->instance().memory()->mode()));
+ }
for (unsigned i = 0; i < moduleInformation.tableCount(); ++i) {
if (moduleInformation.tables[i].isImport()) {
diff --git a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.h b/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.h
index f948ab0..fd92c94 100644
--- a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.h
+++ b/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.h
@@ -60,7 +60,8 @@
void prepareLink(VM&, JSWebAssemblyInstance*);
Synchronousness link(JSGlobalObject*, JSValue scriptFetcher);
- void initializeImportsAndExports(JSGlobalObject*, JSObject* importObject, Wasm::CreationMode);
+ void initializeImports(JSGlobalObject*, JSObject* importObject, Wasm::CreationMode);
+ void initializeExports(JSGlobalObject*);
JS_EXPORT_PRIVATE JSValue evaluate(JSGlobalObject*);
JSObject* exportsObject() const { return m_exportsObject.get(); }