Commit a874463a authored by Thibaud Michaud's avatar Thibaud Michaud Committed by Commit Bot

Reland "[wasm] Cleanup wasm script creation"

This is a reland of f902ef32

Original change's description:
> [wasm] Cleanup wasm script creation
> 
> - Do not expose CreateWasmScript since we should now use
> WasmEngine:GetOrCreateScript instead,
> - Initialize all Script fields in CreateWasmScript, not in
> WasmModuleObject::New,
> - Do not pass code size estimate argument, since we can always use the
> actual native module's committed code space.
> 
> R=clemensb@chromium.org
> 
> Bug: v8:10349
> Change-Id: If9250d62ffc271ab6efc3b9c45958a305c9d1827
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2135633
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#67083}

Bug: v8:10349
Change-Id: I38c8b6beb07a1e5d565c6a5fd749daea147817bb
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2144064Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67087}
parent 93b4f186
...@@ -92,11 +92,12 @@ class Managed : public Foreign { ...@@ -92,11 +92,12 @@ class Managed : public Foreign {
// Create a {Managed<CppType>} from an existing {std::shared_ptr<CppType>}. // Create a {Managed<CppType>} from an existing {std::shared_ptr<CppType>}.
static Handle<Managed<CppType>> FromSharedPtr( static Handle<Managed<CppType>> FromSharedPtr(
Isolate* isolate, size_t estimated_size, Isolate* isolate, size_t estimated_size,
const std::shared_ptr<CppType>& shared_ptr) { std::shared_ptr<CppType> shared_ptr) {
reinterpret_cast<v8::Isolate*>(isolate) reinterpret_cast<v8::Isolate*>(isolate)
->AdjustAmountOfExternalAllocatedMemory(estimated_size); ->AdjustAmountOfExternalAllocatedMemory(estimated_size);
auto destructor = new ManagedPtrDestructor( auto destructor = new ManagedPtrDestructor(
estimated_size, new std::shared_ptr<CppType>{shared_ptr}, Destructor); estimated_size, new std::shared_ptr<CppType>{std::move(shared_ptr)},
Destructor);
Handle<Managed<CppType>> handle = Handle<Managed<CppType>>::cast( Handle<Managed<CppType>> handle = Handle<Managed<CppType>>::cast(
isolate->factory()->NewForeign(reinterpret_cast<Address>(destructor))); isolate->factory()->NewForeign(reinterpret_cast<Address>(destructor)));
Handle<Object> global_handle = isolate->global_handles()->Create(*handle); Handle<Object> global_handle = isolate->global_handles()->Create(*handle);
......
...@@ -1602,11 +1602,9 @@ void AsyncCompileJob::PrepareRuntimeObjects() { ...@@ -1602,11 +1602,9 @@ void AsyncCompileJob::PrepareRuntimeObjects() {
// Create heap objects for script and module bytes to be stored in the // Create heap objects for script and module bytes to be stored in the
// module object. Asm.js is not compiled asynchronously. // module object. Asm.js is not compiled asynchronously.
DCHECK(module_object_.is_null()); DCHECK(module_object_.is_null());
const WasmModule* module = native_module_->module();
auto source_url = stream_ ? stream_->url() : Vector<const char>(); auto source_url = stream_ ? stream_->url() : Vector<const char>();
auto script = isolate_->wasm_engine()->GetOrCreateScript( auto script = isolate_->wasm_engine()->GetOrCreateScript(
isolate_, native_module_.get(), VectorOf(module->source_map_url), isolate_, native_module_, source_url);
module->name, source_url);
Handle<WasmModuleObject> module_object = Handle<WasmModuleObject> module_object =
WasmModuleObject::New(isolate_, native_module_, script); WasmModuleObject::New(isolate_, native_module_, script);
...@@ -2996,71 +2994,6 @@ WasmCode* CompileImportWrapper( ...@@ -2996,71 +2994,6 @@ WasmCode* CompileImportWrapper(
return published_code; return published_code;
} }
Handle<Script> CreateWasmScript(Isolate* isolate,
Vector<const uint8_t> wire_bytes,
Vector<const char> source_map_url,
WireBytesRef name,
Vector<const char> source_url) {
Handle<Script> script =
isolate->factory()->NewScript(isolate->factory()->empty_string());
script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
script->set_context_data(isolate->native_context()->debug_context_id());
script->set_type(Script::TYPE_WASM);
int hash = StringHasher::HashSequentialString(
reinterpret_cast<const char*>(wire_bytes.begin()), wire_bytes.length(),
kZeroHashSeed);
const int kBufferSize = 32;
char buffer[kBufferSize];
// Script name is "<module_name>-hash" if name is available and "hash"
// otherwise.
Handle<String> name_str;
if (name.is_set()) {
int name_chars = SNPrintF(ArrayVector(buffer), "-%08x", hash);
DCHECK(name_chars >= 0 && name_chars < kBufferSize);
Handle<String> name_hash =
isolate->factory()
->NewStringFromOneByte(
VectorOf(reinterpret_cast<uint8_t*>(buffer), name_chars),
AllocationType::kOld)
.ToHandleChecked();
Handle<String> module_name =
WasmModuleObject::ExtractUtf8StringFromModuleBytes(
isolate, wire_bytes, name, kNoInternalize);
name_str = isolate->factory()
->NewConsString(module_name, name_hash)
.ToHandleChecked();
} else {
int name_chars = SNPrintF(ArrayVector(buffer), "%08x", hash);
DCHECK(name_chars >= 0 && name_chars < kBufferSize);
name_str = isolate->factory()
->NewStringFromOneByte(
VectorOf(reinterpret_cast<uint8_t*>(buffer), name_chars),
AllocationType::kOld)
.ToHandleChecked();
}
script->set_name(*name_str);
MaybeHandle<String> url_str;
if (!source_url.empty()) {
url_str =
isolate->factory()->NewStringFromUtf8(source_url, AllocationType::kOld);
} else {
Handle<String> url_prefix =
isolate->factory()->InternalizeString(StaticCharVector("wasm://wasm/"));
url_str = isolate->factory()->NewConsString(url_prefix, name_str);
}
script->set_source_url(*url_str.ToHandleChecked());
if (!source_map_url.empty()) {
MaybeHandle<String> src_map_str = isolate->factory()->NewStringFromUtf8(
source_map_url, AllocationType::kOld);
script->set_source_mapping_url(*src_map_str.ToHandleChecked());
}
return script;
}
} // namespace wasm } // namespace wasm
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -60,11 +60,6 @@ WasmCode* CompileImportWrapper( ...@@ -60,11 +60,6 @@ WasmCode* CompileImportWrapper(
compiler::WasmImportCallKind kind, const FunctionSig* sig, compiler::WasmImportCallKind kind, const FunctionSig* sig,
WasmImportWrapperCache::ModificationScope* cache_scope); WasmImportWrapperCache::ModificationScope* cache_scope);
V8_EXPORT_PRIVATE Handle<Script> CreateWasmScript(
Isolate* isolate, Vector<const uint8_t> wire_bytes,
Vector<const char> source_map_url, WireBytesRef name,
Vector<const char> source_url = {});
// Triggered by the WasmCompileLazy builtin. The return value indicates whether // Triggered by the WasmCompileLazy builtin. The return value indicates whether
// compilation was successful. Lazy compilation can fail only if validation is // compilation was successful. Lazy compilation can fail only if validation is
// also lazy. // also lazy.
......
...@@ -489,10 +489,7 @@ MaybeHandle<WasmModuleObject> WasmEngine::SyncCompile( ...@@ -489,10 +489,7 @@ MaybeHandle<WasmModuleObject> WasmEngine::SyncCompile(
} }
#endif #endif
Handle<Script> script = Handle<Script> script = GetOrCreateScript(isolate, native_module);
GetOrCreateScript(isolate, native_module.get(),
VectorOf(native_module->module()->source_map_url),
native_module->module()->name);
// Create the compiled module object and populate with compiled functions // Create the compiled module object and populate with compiled functions
// and information needed at instantiation time. This object needs to be // and information needed at instantiation time. This object needs to be
...@@ -656,19 +653,97 @@ std::shared_ptr<NativeModule> WasmEngine::ExportNativeModule( ...@@ -656,19 +653,97 @@ std::shared_ptr<NativeModule> WasmEngine::ExportNativeModule(
return module_object->shared_native_module(); return module_object->shared_native_module();
} }
namespace {
Handle<Script> CreateWasmScript(Isolate* isolate,
std::shared_ptr<NativeModule> native_module,
Vector<const char> source_url = {}) {
Handle<Script> script =
isolate->factory()->NewScript(isolate->factory()->empty_string());
script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
script->set_context_data(isolate->native_context()->debug_context_id());
script->set_type(Script::TYPE_WASM);
Vector<const uint8_t> wire_bytes = native_module->wire_bytes();
int hash = StringHasher::HashSequentialString(
reinterpret_cast<const char*>(wire_bytes.begin()), wire_bytes.length(),
kZeroHashSeed);
const int kBufferSize = 32;
char buffer[kBufferSize];
// Script name is "<module_name>-hash" if name is available and "hash"
// otherwise.
const WasmModule* module = native_module->module();
Handle<String> name_str;
if (module->name.is_set()) {
int name_chars = SNPrintF(ArrayVector(buffer), "-%08x", hash);
DCHECK(name_chars >= 0 && name_chars < kBufferSize);
Handle<String> name_hash =
isolate->factory()
->NewStringFromOneByte(
VectorOf(reinterpret_cast<uint8_t*>(buffer), name_chars),
AllocationType::kOld)
.ToHandleChecked();
Handle<String> module_name =
WasmModuleObject::ExtractUtf8StringFromModuleBytes(
isolate, wire_bytes, module->name, kNoInternalize);
name_str = isolate->factory()
->NewConsString(module_name, name_hash)
.ToHandleChecked();
} else {
int name_chars = SNPrintF(ArrayVector(buffer), "%08x", hash);
DCHECK(name_chars >= 0 && name_chars < kBufferSize);
name_str = isolate->factory()
->NewStringFromOneByte(
VectorOf(reinterpret_cast<uint8_t*>(buffer), name_chars),
AllocationType::kOld)
.ToHandleChecked();
}
script->set_name(*name_str);
MaybeHandle<String> url_str;
if (!source_url.empty()) {
url_str =
isolate->factory()->NewStringFromUtf8(source_url, AllocationType::kOld);
} else {
Handle<String> url_prefix =
isolate->factory()->InternalizeString(StaticCharVector("wasm://wasm/"));
url_str = isolate->factory()->NewConsString(url_prefix, name_str);
}
script->set_source_url(*url_str.ToHandleChecked());
auto source_map_url = VectorOf(module->source_map_url);
if (!source_map_url.empty()) {
MaybeHandle<String> src_map_str = isolate->factory()->NewStringFromUtf8(
source_map_url, AllocationType::kOld);
script->set_source_mapping_url(*src_map_str.ToHandleChecked());
}
// Use the given shared {NativeModule}, but increase its reference count by
// allocating a new {Managed<T>} that the {Script} references.
size_t code_size_estimate = native_module->committed_code_space();
size_t memory_estimate =
code_size_estimate +
wasm::WasmCodeManager::EstimateNativeModuleMetaDataSize(module);
Handle<Managed<wasm::NativeModule>> managed_native_module =
Managed<wasm::NativeModule>::FromSharedPtr(isolate, memory_estimate,
std::move(native_module));
script->set_wasm_managed_native_module(*managed_native_module);
script->set_wasm_breakpoint_infos(ReadOnlyRoots(isolate).empty_fixed_array());
script->set_wasm_weak_instance_list(
ReadOnlyRoots(isolate).empty_weak_array_list());
return script;
}
} // namespace
Handle<WasmModuleObject> WasmEngine::ImportNativeModule( Handle<WasmModuleObject> WasmEngine::ImportNativeModule(
Isolate* isolate, std::shared_ptr<NativeModule> shared_native_module) { Isolate* isolate, std::shared_ptr<NativeModule> shared_native_module) {
NativeModule* native_module = shared_native_module.get(); NativeModule* native_module = shared_native_module.get();
ModuleWireBytes wire_bytes(native_module->wire_bytes()); ModuleWireBytes wire_bytes(native_module->wire_bytes());
Handle<Script> script = Handle<Script> script = GetOrCreateScript(isolate, shared_native_module);
CreateWasmScript(isolate, wire_bytes.module_bytes(),
VectorOf(native_module->module()->source_map_url),
native_module->module()->name);
Handle<FixedArray> export_wrappers; Handle<FixedArray> export_wrappers;
CompileJsToWasmWrappers(isolate, native_module->module(), &export_wrappers); CompileJsToWasmWrappers(isolate, native_module->module(), &export_wrappers);
Handle<WasmModuleObject> module_object = WasmModuleObject::New( Handle<WasmModuleObject> module_object = WasmModuleObject::New(
isolate, std::move(shared_native_module), script, export_wrappers, isolate, std::move(shared_native_module), script, export_wrappers);
native_module->committed_code_space());
{ {
base::MutexGuard lock(&mutex_); base::MutexGuard lock(&mutex_);
DCHECK_EQ(1, isolates_.count(isolate)); DCHECK_EQ(1, isolates_.count(isolate));
...@@ -1118,16 +1193,14 @@ void WasmEngine::FreeDeadCodeLocked(const DeadCodeMap& dead_code) { ...@@ -1118,16 +1193,14 @@ void WasmEngine::FreeDeadCodeLocked(const DeadCodeMap& dead_code) {
} }
} }
Handle<Script> WasmEngine::GetOrCreateScript(Isolate* isolate, Handle<Script> WasmEngine::GetOrCreateScript(
NativeModule* native_module, Isolate* isolate, const std::shared_ptr<NativeModule>& native_module,
Vector<const char> source_map_url, Vector<const char> source_url) {
WireBytesRef name,
Vector<const char> source_url) {
{ {
base::MutexGuard guard(&mutex_); base::MutexGuard guard(&mutex_);
DCHECK_EQ(1, isolates_.count(isolate)); DCHECK_EQ(1, isolates_.count(isolate));
auto& scripts = isolates_[isolate]->scripts; auto& scripts = isolates_[isolate]->scripts;
auto it = scripts.find(native_module); auto it = scripts.find(native_module.get());
if (it != scripts.end()) { if (it != scripts.end()) {
Handle<Script> weak_global_handle = it->second.handle(); Handle<Script> weak_global_handle = it->second.handle();
if (weak_global_handle.is_null()) { if (weak_global_handle.is_null()) {
...@@ -1138,14 +1211,13 @@ Handle<Script> WasmEngine::GetOrCreateScript(Isolate* isolate, ...@@ -1138,14 +1211,13 @@ Handle<Script> WasmEngine::GetOrCreateScript(Isolate* isolate,
} }
} }
// Temporarily release the mutex to let the GC collect native modules. // Temporarily release the mutex to let the GC collect native modules.
auto script = CreateWasmScript(isolate, native_module->wire_bytes(), auto script = CreateWasmScript(isolate, native_module, source_url);
source_map_url, name, source_url);
{ {
base::MutexGuard guard(&mutex_); base::MutexGuard guard(&mutex_);
DCHECK_EQ(1, isolates_.count(isolate)); DCHECK_EQ(1, isolates_.count(isolate));
auto& scripts = isolates_[isolate]->scripts; auto& scripts = isolates_[isolate]->scripts;
DCHECK_EQ(0, scripts.count(native_module)); DCHECK_EQ(0, scripts.count(native_module.get()));
scripts.emplace(native_module, WeakScriptHandle(script)); scripts.emplace(native_module.get(), WeakScriptHandle(script));
return script; return script;
} }
} }
......
...@@ -335,9 +335,8 @@ class V8_EXPORT_PRIVATE WasmEngine { ...@@ -335,9 +335,8 @@ class V8_EXPORT_PRIVATE WasmEngine {
void FreeDeadCode(const DeadCodeMap&); void FreeDeadCode(const DeadCodeMap&);
void FreeDeadCodeLocked(const DeadCodeMap&); void FreeDeadCodeLocked(const DeadCodeMap&);
Handle<Script> GetOrCreateScript(Isolate*, NativeModule*, Handle<Script> GetOrCreateScript(Isolate*,
Vector<const char> source_map_url, const std::shared_ptr<NativeModule>&,
WireBytesRef name,
Vector<const char> source_url = {}); Vector<const char> source_url = {});
// Call on process start and exit. // Call on process start and exit.
......
...@@ -165,43 +165,24 @@ Handle<WasmModuleObject> WasmModuleObject::New( ...@@ -165,43 +165,24 @@ Handle<WasmModuleObject> WasmModuleObject::New(
Handle<WasmModuleObject> WasmModuleObject::New( Handle<WasmModuleObject> WasmModuleObject::New(
Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module, Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module,
Handle<Script> script, Handle<FixedArray> export_wrappers) { Handle<Script> script, Handle<FixedArray> export_wrappers) {
const WasmModule* module = native_module->module(); Handle<Managed<wasm::NativeModule>> managed_native_module;
const bool uses_liftoff = if (script->type() == Script::TYPE_WASM) {
FLAG_liftoff && native_module->module()->origin == wasm::kWasmOrigin; managed_native_module = handle(
size_t code_size_estimate = Managed<wasm::NativeModule>::cast(script->wasm_managed_native_module()),
wasm::WasmCodeManager::EstimateNativeModuleCodeSize(module, uses_liftoff); isolate);
return New(isolate, std::move(native_module), script, export_wrappers, } else {
code_size_estimate); const WasmModule* module = native_module->module();
} size_t memory_estimate =
native_module->committed_code_space() +
// static wasm::WasmCodeManager::EstimateNativeModuleMetaDataSize(module);
Handle<WasmModuleObject> WasmModuleObject::New( managed_native_module = Managed<wasm::NativeModule>::FromSharedPtr(
Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module, isolate, memory_estimate, std::move(native_module));
Handle<Script> script, Handle<FixedArray> export_wrappers, }
size_t code_size_estimate) {
const WasmModule* module = native_module->module();
// Use the given shared {NativeModule}, but increase its reference count by
// allocating a new {Managed<T>} that the {WasmModuleObject} references.
size_t memory_estimate =
code_size_estimate +
wasm::WasmCodeManager::EstimateNativeModuleMetaDataSize(module);
Handle<Managed<wasm::NativeModule>> managed_native_module =
Managed<wasm::NativeModule>::FromSharedPtr(isolate, memory_estimate,
std::move(native_module));
Handle<WasmModuleObject> module_object = Handle<WasmModuleObject>::cast( Handle<WasmModuleObject> module_object = Handle<WasmModuleObject>::cast(
isolate->factory()->NewJSObject(isolate->wasm_module_constructor())); isolate->factory()->NewJSObject(isolate->wasm_module_constructor()));
module_object->set_export_wrappers(*export_wrappers); module_object->set_export_wrappers(*export_wrappers);
if (script->type() == Script::TYPE_WASM) {
script->set_wasm_breakpoint_infos(
ReadOnlyRoots(isolate).empty_fixed_array());
script->set_wasm_managed_native_module(*managed_native_module);
script->set_wasm_weak_instance_list(
ReadOnlyRoots(isolate).empty_weak_array_list());
}
module_object->set_script(*script);
module_object->set_managed_native_module(*managed_native_module); module_object->set_managed_native_module(*managed_native_module);
module_object->set_script(*script);
return module_object; return module_object;
} }
......
...@@ -150,10 +150,6 @@ class WasmModuleObject : public JSObject { ...@@ -150,10 +150,6 @@ class WasmModuleObject : public JSObject {
V8_EXPORT_PRIVATE static Handle<WasmModuleObject> New( V8_EXPORT_PRIVATE static Handle<WasmModuleObject> New(
Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module, Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module,
Handle<Script> script, Handle<FixedArray> export_wrappers); Handle<Script> script, Handle<FixedArray> export_wrappers);
V8_EXPORT_PRIVATE static Handle<WasmModuleObject> New(
Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module,
Handle<Script> script, Handle<FixedArray> export_wrappers,
size_t code_size_estimate);
// Check whether this module was generated from asm.js source. // Check whether this module was generated from asm.js source.
inline bool is_asm_js(); inline bool is_asm_js();
......
...@@ -611,9 +611,6 @@ MaybeHandle<WasmModuleObject> DeserializeNativeModule( ...@@ -611,9 +611,6 @@ MaybeHandle<WasmModuleObject> DeserializeNativeModule(
if (decode_result.failed()) return {}; if (decode_result.failed()) return {};
std::shared_ptr<WasmModule> module = std::move(decode_result.value()); std::shared_ptr<WasmModule> module = std::move(decode_result.value());
CHECK_NOT_NULL(module); CHECK_NOT_NULL(module);
Handle<Script> script = CreateWasmScript(isolate, wire_bytes_vec,
VectorOf(module->source_map_url),
module->name, source_url);
auto shared_native_module = wasm_engine->MaybeGetNativeModule( auto shared_native_module = wasm_engine->MaybeGetNativeModule(
module->origin, wire_bytes_vec, isolate); module->origin, wire_bytes_vec, isolate);
...@@ -641,6 +638,8 @@ MaybeHandle<WasmModuleObject> DeserializeNativeModule( ...@@ -641,6 +638,8 @@ MaybeHandle<WasmModuleObject> DeserializeNativeModule(
CompileJsToWasmWrappers(isolate, shared_native_module->module(), CompileJsToWasmWrappers(isolate, shared_native_module->module(),
&export_wrappers); &export_wrappers);
Handle<Script> script =
wasm_engine->GetOrCreateScript(isolate, shared_native_module);
Handle<WasmModuleObject> module_object = WasmModuleObject::New( Handle<WasmModuleObject> module_object = WasmModuleObject::New(
isolate, std::move(shared_native_module), script, export_wrappers); isolate, std::move(shared_native_module), script, export_wrappers);
......
...@@ -364,10 +364,6 @@ const WasmGlobal* TestingModuleBuilder::AddGlobal(ValueType type) { ...@@ -364,10 +364,6 @@ const WasmGlobal* TestingModuleBuilder::AddGlobal(ValueType type) {
} }
Handle<WasmInstanceObject> TestingModuleBuilder::InitInstanceObject() { Handle<WasmInstanceObject> TestingModuleBuilder::InitInstanceObject() {
Handle<Script> script =
isolate_->factory()->NewScript(isolate_->factory()->empty_string());
script->set_type(Script::TYPE_WASM);
const bool kUsesLiftoff = true; const bool kUsesLiftoff = true;
size_t code_size_estimate = size_t code_size_estimate =
wasm::WasmCodeManager::EstimateNativeModuleCodeSize(test_module_.get(), wasm::WasmCodeManager::EstimateNativeModuleCodeSize(test_module_.get(),
...@@ -375,6 +371,8 @@ Handle<WasmInstanceObject> TestingModuleBuilder::InitInstanceObject() { ...@@ -375,6 +371,8 @@ Handle<WasmInstanceObject> TestingModuleBuilder::InitInstanceObject() {
auto native_module = isolate_->wasm_engine()->NewNativeModule( auto native_module = isolate_->wasm_engine()->NewNativeModule(
isolate_, enabled_features_, test_module_, code_size_estimate); isolate_, enabled_features_, test_module_, code_size_estimate);
native_module->SetWireBytes(OwnedVector<const uint8_t>()); native_module->SetWireBytes(OwnedVector<const uint8_t>());
Handle<Script> script =
isolate_->wasm_engine()->GetOrCreateScript(isolate_, native_module);
Handle<WasmModuleObject> module_object = Handle<WasmModuleObject> module_object =
WasmModuleObject::New(isolate_, std::move(native_module), script); WasmModuleObject::New(isolate_, std::move(native_module), script);
......
...@@ -80,6 +80,7 @@ assertEquals(0, %WasmGetNumberOfInstances(module)); ...@@ -80,6 +80,7 @@ assertEquals(0, %WasmGetNumberOfInstances(module));
instance4 = new WebAssembly.Instance(module, {"": {getValue: () => 4}}); instance4 = new WebAssembly.Instance(module, {"": {getValue: () => 4}});
assertEquals(4, instance4.exports.f()); assertEquals(4, instance4.exports.f());
module = null; module = null;
instance4 = null;
})(); })();
// Note that two GC's are required because weak slots clearing is deferred. // Note that two GC's are required because weak slots clearing is deferred.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment