summaryrefslogtreecommitdiff
path: root/chromium/v8/src/wasm/module-compiler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/v8/src/wasm/module-compiler.cc')
-rw-r--r--chromium/v8/src/wasm/module-compiler.cc607
1 files changed, 211 insertions, 396 deletions
diff --git a/chromium/v8/src/wasm/module-compiler.cc b/chromium/v8/src/wasm/module-compiler.cc
index 4a2e610b99b..0a09feddf2b 100644
--- a/chromium/v8/src/wasm/module-compiler.cc
+++ b/chromium/v8/src/wasm/module-compiler.cc
@@ -207,18 +207,12 @@ class ModuleCompiler {
compiler::ModuleEnv* module_env,
ErrorThrower* thrower);
- static MaybeHandle<WasmModuleObject> CompileToModuleObject(
- Isolate* isolate, ErrorThrower* thrower,
- std::unique_ptr<WasmModule> module, const ModuleWireBytes& wire_bytes,
- Handle<Script> asm_js_script,
- Vector<const byte> asm_js_offset_table_bytes);
-
- private:
MaybeHandle<WasmModuleObject> CompileToModuleObjectInternal(
ErrorThrower* thrower, std::unique_ptr<WasmModule> module,
const ModuleWireBytes& wire_bytes, Handle<Script> asm_js_script,
Vector<const byte> asm_js_offset_table_bytes);
+ private:
Isolate* isolate_;
WasmModule* module_;
const std::shared_ptr<Counters> async_counters_;
@@ -268,7 +262,7 @@ class JSToWasmWrapperCache {
target->builtin_index() == Builtins::kIllegal ||
target->builtin_index() == Builtins::kWasmCompileLazy) {
it.rinfo()->set_target_address(
- isolate, wasm_code.GetCode()->instruction_start());
+ wasm_code.GetCode()->instruction_start());
break;
}
}
@@ -277,9 +271,9 @@ class JSToWasmWrapperCache {
RelocInfo::ModeMask(RelocInfo::JS_TO_WASM_CALL));
DCHECK(!it.done());
it.rinfo()->set_js_to_wasm_address(
- isolate, wasm_code.is_null()
- ? nullptr
- : wasm_code.GetWasmCode()->instructions().start());
+ wasm_code.is_null()
+ ? nullptr
+ : wasm_code.GetWasmCode()->instructions().start());
}
return code;
}
@@ -308,11 +302,12 @@ class InstanceBuilder {
InstanceBuilder(Isolate* isolate, ErrorThrower* thrower,
Handle<WasmModuleObject> module_object,
MaybeHandle<JSReceiver> ffi,
- MaybeHandle<JSArrayBuffer> memory,
- WeakCallbackInfo<void>::Callback instance_finalizer_callback);
+ MaybeHandle<JSArrayBuffer> memory);
// Build an instance, in all of its glory.
MaybeHandle<WasmInstanceObject> Build();
+ // Run the start function, if any.
+ bool ExecuteStartFunction();
private:
// Represents the initialized state of a table.
@@ -340,8 +335,8 @@ class InstanceBuilder {
Handle<WasmCompiledModule> compiled_module_;
std::vector<TableInstance> table_instances_;
std::vector<Handle<JSFunction>> js_wrappers_;
+ Handle<WasmExportedFunction> start_function_;
JSToWasmWrapperCache js_to_wasm_cache_;
- WeakCallbackInfo<void>::Callback instance_finalizer_callback_;
std::vector<SanitizedImport> sanitized_imports_;
const std::shared_ptr<Counters>& async_counters() const {
@@ -424,91 +419,6 @@ class InstanceBuilder {
Handle<WasmInstanceObject> instance);
};
-// TODO(titzer): move to wasm-objects.cc
-void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) {
- DisallowHeapAllocation no_gc;
- JSObject** p = reinterpret_cast<JSObject**>(data.GetParameter());
- WasmInstanceObject* owner = reinterpret_cast<WasmInstanceObject*>(*p);
- Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate());
- // If a link to shared memory instances exists, update the list of memory
- // instances before the instance is destroyed.
- WasmCompiledModule* compiled_module = owner->compiled_module();
- wasm::NativeModule* native_module = compiled_module->GetNativeModule();
- if (FLAG_wasm_jit_to_native) {
- if (native_module) {
- TRACE("Finalizing %zu {\n", native_module->instance_id);
- } else {
- TRACE("Finalized already cleaned up compiled module\n");
- }
- } else {
- TRACE("Finalizing %d {\n", compiled_module->instance_id());
-
- if (compiled_module->use_trap_handler()) {
- // TODO(6792): No longer needed once WebAssembly code is off heap.
- CodeSpaceMemoryModificationScope modification_scope(isolate->heap());
- DisallowHeapAllocation no_gc;
- FixedArray* code_table = compiled_module->code_table();
- for (int i = 0; i < code_table->length(); ++i) {
- Code* code = Code::cast(code_table->get(i));
- int index = code->trap_handler_index()->value();
- if (index >= 0) {
- trap_handler::ReleaseHandlerData(index);
- code->set_trap_handler_index(
- Smi::FromInt(trap_handler::kInvalidIndex));
- }
- }
- }
- }
- WeakCell* weak_wasm_module = compiled_module->weak_wasm_module();
-
- // Since the order of finalizers is not guaranteed, it can be the case
- // that {instance->compiled_module()->module()}, which is a
- // {Managed<WasmModule>} has been collected earlier in this GC cycle.
- // Weak references to this instance won't be cleared until
- // the next GC cycle, so we need to manually break some links (such as
- // the weak references from {WasmMemoryObject::instances}.
- if (owner->has_memory_object()) {
- Handle<WasmMemoryObject> memory(owner->memory_object(), isolate);
- Handle<WasmInstanceObject> instance(owner, isolate);
- WasmMemoryObject::RemoveInstance(isolate, memory, instance);
- }
-
- // weak_wasm_module may have been cleared, meaning the module object
- // was GC-ed. We still want to maintain the links between instances, to
- // release the WasmCompiledModule corresponding to the WasmModuleInstance
- // being finalized here.
- WasmModuleObject* wasm_module = nullptr;
- if (!weak_wasm_module->cleared()) {
- wasm_module = WasmModuleObject::cast(weak_wasm_module->value());
- WasmCompiledModule* current_template = wasm_module->compiled_module();
-
- TRACE("chain before {\n");
- TRACE_CHAIN(current_template);
- TRACE("}\n");
-
- DCHECK(!current_template->has_prev_instance());
- if (current_template == compiled_module) {
- if (!compiled_module->has_next_instance()) {
- WasmCompiledModule::Reset(isolate, compiled_module);
- } else {
- WasmModuleObject::cast(wasm_module)
- ->set_compiled_module(compiled_module->next_instance());
- }
- }
- }
-
- compiled_module->RemoveFromChain();
-
- if (wasm_module != nullptr) {
- TRACE("chain after {\n");
- TRACE_CHAIN(wasm_module->compiled_module());
- TRACE("}\n");
- }
- compiled_module->reset_weak_owning_instance();
- GlobalHandles::Destroy(reinterpret_cast<Object**>(p));
- TRACE("}\n");
-}
-
// This is used in ProcessImports.
// When importing other modules' exports, we need to ask
// the exporter for a WasmToWasm wrapper. To do that, we need to
@@ -517,8 +427,9 @@ void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) {
class SetOfNativeModuleModificationScopes final {
public:
void Add(NativeModule* module) {
- module->SetExecutable(false);
- native_modules_.insert(module);
+ if (native_modules_.insert(module).second) {
+ module->SetExecutable(false);
+ }
}
~SetOfNativeModuleModificationScopes() {
@@ -531,138 +442,28 @@ class SetOfNativeModuleModificationScopes final {
std::unordered_set<NativeModule*> native_modules_;
};
-} // namespace
-
-MaybeHandle<WasmModuleObject> SyncCompileTranslatedAsmJs(
- Isolate* isolate, ErrorThrower* thrower, const ModuleWireBytes& bytes,
- Handle<Script> asm_js_script,
- Vector<const byte> asm_js_offset_table_bytes) {
- ModuleResult result = SyncDecodeWasmModule(isolate, bytes.start(),
- bytes.end(), false, kAsmJsOrigin);
- if (result.failed()) {
- thrower->CompileFailed("Wasm decoding failed", result);
- return {};
+void EnsureWasmContextTable(WasmContext* wasm_context, int table_size) {
+ if (wasm_context->table) return;
+ wasm_context->table_size = table_size;
+ wasm_context->table = reinterpret_cast<IndirectFunctionTableEntry*>(
+ calloc(table_size, sizeof(IndirectFunctionTableEntry)));
+ for (int i = 0; i < table_size; i++) {
+ wasm_context->table[i].sig_id = kInvalidSigIndex;
}
-
- // Transfer ownership of the WasmModule to the {WasmModuleWrapper} generated
- // in {CompileToModuleObject}.
- return ModuleCompiler::CompileToModuleObject(
- isolate, thrower, std::move(result.val), bytes, asm_js_script,
- asm_js_offset_table_bytes);
}
-MaybeHandle<WasmModuleObject> SyncCompile(Isolate* isolate,
- ErrorThrower* thrower,
- const ModuleWireBytes& bytes) {
- ModuleResult result = SyncDecodeWasmModule(isolate, bytes.start(),
- bytes.end(), false, kWasmOrigin);
- if (result.failed()) {
- thrower->CompileFailed("Wasm decoding failed", result);
- return {};
- }
-
- // Transfer ownership of the WasmModule to the {WasmModuleWrapper} generated
- // in {CompileToModuleObject}.
- return ModuleCompiler::CompileToModuleObject(
- isolate, thrower, std::move(result.val), bytes, Handle<Script>(),
- Vector<const byte>());
-}
+} // namespace
-MaybeHandle<WasmInstanceObject> SyncInstantiate(
+MaybeHandle<WasmInstanceObject> InstantiateToInstanceObject(
Isolate* isolate, ErrorThrower* thrower,
Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports,
MaybeHandle<JSArrayBuffer> memory) {
- InstanceBuilder builder(isolate, thrower, module_object, imports, memory,
- &InstanceFinalizer);
- return builder.Build();
-}
-
-MaybeHandle<WasmInstanceObject> SyncCompileAndInstantiate(
- Isolate* isolate, ErrorThrower* thrower, const ModuleWireBytes& bytes,
- MaybeHandle<JSReceiver> imports, MaybeHandle<JSArrayBuffer> memory) {
- MaybeHandle<WasmModuleObject> module = SyncCompile(isolate, thrower, bytes);
- DCHECK_EQ(thrower->error(), module.is_null());
- if (module.is_null()) return {};
-
- return SyncInstantiate(isolate, thrower, module.ToHandleChecked(), imports,
- memory);
-}
-
-void RejectPromise(Isolate* isolate, Handle<Context> context,
- ErrorThrower& thrower, Handle<JSPromise> promise) {
- Local<Promise::Resolver> resolver =
- Utils::PromiseToLocal(promise).As<Promise::Resolver>();
- auto maybe = resolver->Reject(Utils::ToLocal(context),
- Utils::ToLocal(thrower.Reify()));
- CHECK_IMPLIES(!maybe.FromMaybe(false), isolate->has_scheduled_exception());
-}
-
-void ResolvePromise(Isolate* isolate, Handle<Context> context,
- Handle<JSPromise> promise, Handle<Object> result) {
- Local<Promise::Resolver> resolver =
- Utils::PromiseToLocal(promise).As<Promise::Resolver>();
- auto maybe =
- resolver->Resolve(Utils::ToLocal(context), Utils::ToLocal(result));
- CHECK_IMPLIES(!maybe.FromMaybe(false), isolate->has_scheduled_exception());
-}
-
-void AsyncInstantiate(Isolate* isolate, Handle<JSPromise> promise,
- Handle<WasmModuleObject> module_object,
- MaybeHandle<JSReceiver> imports) {
- ErrorThrower thrower(isolate, nullptr);
- MaybeHandle<WasmInstanceObject> instance_object = SyncInstantiate(
- isolate, &thrower, module_object, imports, Handle<JSArrayBuffer>::null());
- if (thrower.error()) {
- RejectPromise(isolate, handle(isolate->context()), thrower, promise);
- return;
+ InstanceBuilder builder(isolate, thrower, module_object, imports, memory);
+ auto instance = builder.Build();
+ if (!instance.is_null() && builder.ExecuteStartFunction()) {
+ return instance;
}
- ResolvePromise(isolate, handle(isolate->context()), promise,
- instance_object.ToHandleChecked());
-}
-
-void AsyncCompile(Isolate* isolate, Handle<JSPromise> promise,
- const ModuleWireBytes& bytes, bool is_shared) {
- if (!FLAG_wasm_async_compilation) {
- // Asynchronous compilation disabled; fall back on synchronous compilation.
- ErrorThrower thrower(isolate, "WasmCompile");
- MaybeHandle<WasmModuleObject> module_object;
- if (is_shared) {
- // Make a copy of the wire bytes to avoid concurrent modification.
- std::unique_ptr<uint8_t[]> copy(new uint8_t[bytes.length()]);
- memcpy(copy.get(), bytes.start(), bytes.length());
- i::wasm::ModuleWireBytes bytes_copy(copy.get(),
- copy.get() + bytes.length());
- module_object = SyncCompile(isolate, &thrower, bytes_copy);
- } else {
- // The wire bytes are not shared, OK to use them directly.
- module_object = SyncCompile(isolate, &thrower, bytes);
- }
- if (thrower.error()) {
- RejectPromise(isolate, handle(isolate->context()), thrower, promise);
- return;
- }
- Handle<WasmModuleObject> module = module_object.ToHandleChecked();
- ResolvePromise(isolate, handle(isolate->context()), promise, module);
- return;
- }
-
- if (FLAG_wasm_test_streaming) {
- std::shared_ptr<StreamingDecoder> streaming_decoder =
- isolate->wasm_engine()
- ->compilation_manager()
- ->StartStreamingCompilation(isolate, handle(isolate->context()),
- promise);
- streaming_decoder->OnBytesReceived(bytes.module_bytes());
- streaming_decoder->Finish();
- return;
- }
- // Make a copy of the wire bytes in case the user program changes them
- // during asynchronous compilation.
- std::unique_ptr<byte[]> copy(new byte[bytes.length()]);
- memcpy(copy.get(), bytes.start(), bytes.length());
- isolate->wasm_engine()->compilation_manager()->StartAsyncCompileJob(
- isolate, std::move(copy), bytes.length(), handle(isolate->context()),
- promise);
+ return {};
}
Handle<Code> CompileLazyOnGCHeap(Isolate* isolate) {
@@ -845,6 +646,7 @@ Address CompileLazy(Isolate* isolate) {
int func_index = static_cast<int>(result->index());
if (!exp_deopt_data_entry.is_null() && exp_deopt_data_entry->IsFixedArray()) {
+ int patched = 0;
Handle<FixedArray> exp_deopt_data =
Handle<FixedArray>::cast(exp_deopt_data_entry);
@@ -854,22 +656,36 @@ Address CompileLazy(Isolate* isolate) {
// See EnsureExportedLazyDeoptData: exp_deopt_data[0...(len-1)] are pairs
// of <export_table, index> followed by undefined values. Use this
// information here to patch all export tables.
+ Address target = result->instructions().start();
Handle<Foreign> foreign_holder =
- isolate->factory()->NewForeign(result->instructions().start(), TENURED);
+ isolate->factory()->NewForeign(target, TENURED);
for (int idx = 0, end = exp_deopt_data->length(); idx < end; idx += 2) {
if (exp_deopt_data->get(idx)->IsUndefined(isolate)) break;
DisallowHeapAllocation no_gc;
int exp_index = Smi::ToInt(exp_deopt_data->get(idx + 1));
FixedArray* exp_table = FixedArray::cast(exp_deopt_data->get(idx));
- exp_table->set(compiler::FunctionTableCodeOffset(exp_index),
- *foreign_holder);
+
+ if (WASM_CONTEXT_TABLES) {
+ // TODO(titzer): patching of function tables for lazy compilation
+ // only works for a single instance.
+ instance->wasm_context()->get()->table[exp_index].target = target;
+ } else {
+ int table_index = compiler::FunctionTableCodeOffset(exp_index);
+ DCHECK_EQ(Foreign::cast(exp_table->get(table_index))->foreign_address(),
+ lazy_stub_or_copy->instructions().start());
+
+ exp_table->set(table_index, *foreign_holder);
+ ++patched;
+ }
}
- // TODO(6792): No longer needed once WebAssembly code is off heap.
- CodeSpaceMemoryModificationScope modification_scope(isolate->heap());
// After processing, remove the list of exported entries, such that we don't
// do the patching redundantly.
compiled_module->lazy_compile_data()->set(
func_index, isolate->heap()->undefined_value());
+ if (!WASM_CONTEXT_TABLES) {
+ DCHECK_LT(0, patched);
+ USE(patched);
+ }
}
return result->instructions().start();
@@ -880,8 +696,7 @@ compiler::ModuleEnv CreateModuleEnvFromCompiledModule(
DisallowHeapAllocation no_gc;
WasmModule* module = compiled_module->shared()->module();
if (FLAG_wasm_jit_to_native) {
- NativeModule* native_module = compiled_module->GetNativeModule();
- compiler::ModuleEnv result(module, native_module->function_tables(),
+ compiler::ModuleEnv result(module, std::vector<Address>{},
std::vector<Handle<Code>>{},
BUILTIN_CODE(isolate, WasmCompileLazy),
compiled_module->use_trap_handler());
@@ -911,6 +726,20 @@ const wasm::WasmCode* LazyCompilationOrchestrator::CompileFunction(
compilation_timer.Start();
Handle<WasmCompiledModule> compiled_module(instance->compiled_module(),
isolate);
+
+ // TODO(wasm): Refactor this to only get the name if it is really needed for
+ // tracing / debugging.
+ std::string func_name;
+ {
+ WasmName name = Vector<const char>::cast(
+ compiled_module->shared()->GetRawFunctionName(func_index));
+ // Copy to std::string, because the underlying string object might move on
+ // the heap.
+ func_name.assign(name.start(), static_cast<size_t>(name.length()));
+ }
+
+ TRACE_LAZY("Compiling function %s, %d.\n", func_name.c_str(), func_index);
+
if (FLAG_wasm_jit_to_native) {
wasm::WasmCode* existing_code = compiled_module->GetNativeModule()->GetCode(
static_cast<uint32_t>(func_index));
@@ -937,16 +766,7 @@ const wasm::WasmCode* LazyCompilationOrchestrator::CompileFunction(
FunctionBody body{func->sig, func->code.offset(),
module_start + func->code.offset(),
module_start + func->code.end_offset()};
- // TODO(wasm): Refactor this to only get the name if it is really needed for
- // tracing / debugging.
- std::string func_name;
- {
- WasmName name = Vector<const char>::cast(
- compiled_module->shared()->GetRawFunctionName(func_index));
- // Copy to std::string, because the underlying string object might move on
- // the heap.
- func_name.assign(name.start(), static_cast<size_t>(name.length()));
- }
+
ErrorThrower thrower(isolate, "WasmLazyCompile");
compiler::WasmCompilationUnit unit(isolate, &module_env,
compiled_module->GetNativeModule(), body,
@@ -989,7 +809,7 @@ const wasm::WasmCode* LazyCompilationOrchestrator::CompileFunction(
if (!code_wrapper.IsCodeObject()) {
const wasm::WasmCode* wasm_code = code_wrapper.GetWasmCode();
- Assembler::FlushICache(isolate, wasm_code->instructions().start(),
+ Assembler::FlushICache(wasm_code->instructions().start(),
wasm_code->instructions().size());
counters->wasm_generated_code_size()->Increment(
static_cast<int>(wasm_code->instructions().size()));
@@ -997,8 +817,7 @@ const wasm::WasmCode* LazyCompilationOrchestrator::CompileFunction(
static_cast<int>(wasm_code->reloc_info().size()));
} else {
- Assembler::FlushICache(isolate, code->instruction_start(),
- code->instruction_size());
+ Assembler::FlushICache(code->instruction_start(), code->instruction_size());
counters->wasm_generated_code_size()->Increment(code->body_size());
counters->wasm_reloc_size()->Increment(code->relocation_info()->length());
}
@@ -1062,8 +881,12 @@ const WasmCode* WasmExtractWasmToWasmCallee(const WasmCodeManager* code_manager,
wasm_to_wasm->constant_pool(), \
RelocInfo::ModeMask(RelocInfo::JS_TO_WASM_CALL)); \
DCHECK(!it.done()); \
- it.rinfo()->set_js_to_wasm_address(isolate, \
- new_target->instructions().start()); \
+ DCHECK_EQ(WasmCode::kLazyStub, \
+ isolate->wasm_engine() \
+ ->code_manager() \
+ ->GetCodeFromStartAddress(it.rinfo()->js_to_wasm_address()) \
+ ->kind()); \
+ it.rinfo()->set_js_to_wasm_address(new_target->instructions().start()); \
it.next(); \
DCHECK(it.done()); \
} while (0)
@@ -1077,7 +900,7 @@ void PatchWasmToWasmWrapper(Isolate* isolate, Code* wasm_to_wasm,
DCHECK_EQ(Builtins::kWasmCompileLazy,
Code::GetCodeFromTargetAddress(it.rinfo()->target_address())
->builtin_index());
- it.rinfo()->set_target_address(isolate, new_target->instruction_start());
+ it.rinfo()->set_target_address(new_target->instruction_start());
#ifdef DEBUG
it.next();
DCHECK(it.done());
@@ -1169,8 +992,6 @@ Handle<Code> LazyCompilationOrchestrator::CompileLazyOnGCHeap(
DCHECK(!non_compiled_functions.empty() || !wasm_to_wasm_callee.is_null());
}
- TRACE_LAZY("Compiling function %d.\n", func_to_return_idx);
-
// TODO(clemensh): compile all functions in non_compiled_functions in
// background, wait for func_to_return_idx.
CompileFunction(isolate, instance, func_to_return_idx);
@@ -1224,8 +1045,7 @@ Handle<Code> LazyCompilationOrchestrator::CompileLazyOnGCHeap(
continue;
}
DCHECK_EQ(Code::WASM_FUNCTION, callee_compiled->kind());
- it.rinfo()->set_target_address(isolate,
- callee_compiled->instruction_start());
+ it.rinfo()->set_target_address(callee_compiled->instruction_start());
++patched;
}
DCHECK_EQ(non_compiled_functions.size(), idx);
@@ -1251,6 +1071,7 @@ const wasm::WasmCode* LazyCompilationOrchestrator::CompileFromJsToWasm(
CompileFunction(isolate, instance, exported_func_index);
{
DisallowHeapAllocation no_gc;
+ int patched = 0;
CodeSpaceMemoryModificationScope modification_scope(isolate->heap());
RelocIterator it(*js_to_wasm_caller,
RelocInfo::ModeMask(RelocInfo::JS_TO_WASM_CALL));
@@ -1263,10 +1084,21 @@ const wasm::WasmCode* LazyCompilationOrchestrator::CompileFromJsToWasm(
DCHECK_NOT_NULL(callee_compiled);
if (current_callee->kind() == WasmCode::kWasmToWasmWrapper) {
WasmPatchWasmToWasmWrapper(isolate, current_callee, callee_compiled);
+ ++patched;
} else {
+ DCHECK_EQ(WasmCode::kLazyStub,
+ isolate->wasm_engine()
+ ->code_manager()
+ ->GetCodeFromStartAddress(it.rinfo()->js_to_wasm_address())
+ ->kind());
it.rinfo()->set_js_to_wasm_address(
- isolate, callee_compiled->instructions().start());
+ callee_compiled->instructions().start());
+ ++patched;
}
+ DCHECK_LT(0, patched);
+ TRACE_LAZY("Patched %d location(s) in the caller.\n", patched);
+ USE(patched);
+
#ifdef DEBUG
it.next();
DCHECK(it.done());
@@ -1313,6 +1145,7 @@ const wasm::WasmCode* LazyCompilationOrchestrator::CompileDirectCall(
->module()
->functions[caller_func_index]
.code.offset();
+ int num_non_compiled_functions = 0;
for (RelocIterator it(wasm_caller->instructions(),
wasm_caller->reloc_info(),
wasm_caller->constant_pool(),
@@ -1333,6 +1166,8 @@ const wasm::WasmCode* LazyCompilationOrchestrator::CompileDirectCall(
non_compiled_functions.push_back(Nothing<uint32_t>());
continue;
}
+ ++num_non_compiled_functions;
+
uint32_t called_func_index =
ExtractDirectCallIndex(decoder, func_bytes + byte_pos);
DCHECK_LT(called_func_index,
@@ -1344,6 +1179,10 @@ const wasm::WasmCode* LazyCompilationOrchestrator::CompileDirectCall(
maybe_func_to_return_idx = Just(called_func_index);
}
}
+
+ TRACE_LAZY("Found %d non-compiled functions in caller.\n",
+ num_non_compiled_functions);
+ USE(num_non_compiled_functions);
}
uint32_t func_to_return_idx = 0;
@@ -1365,10 +1204,12 @@ const wasm::WasmCode* LazyCompilationOrchestrator::CompileDirectCall(
const WasmCode* ret = CompileFunction(isolate, instance, func_to_return_idx);
DCHECK_NOT_NULL(ret);
+ int patched = 0;
if (last_callee->kind() == WasmCode::kWasmToWasmWrapper) {
// We can finish it all here by compiling the target wasm function and
// patching the wasm_to_wasm caller.
WasmPatchWasmToWasmWrapper(isolate, last_callee, ret);
+ ++patched;
} else {
Handle<WasmCompiledModule> compiled_module(instance->compiled_module(),
isolate);
@@ -1376,7 +1217,6 @@ const wasm::WasmCode* LazyCompilationOrchestrator::CompileDirectCall(
// Now patch the code object with all functions which are now compiled. This
// will pick up any other compiled functions, not only {ret}.
size_t idx = 0;
- size_t patched = 0;
for (RelocIterator
it(wasm_caller->instructions(), wasm_caller->reloc_info(),
wasm_caller->constant_pool(),
@@ -1388,13 +1228,22 @@ const wasm::WasmCode* LazyCompilationOrchestrator::CompileDirectCall(
const WasmCode* callee_compiled =
compiled_module->GetNativeModule()->GetCode(lookup);
if (callee_compiled->kind() != WasmCode::kFunction) continue;
+ DCHECK_EQ(WasmCode::kLazyStub,
+ isolate->wasm_engine()
+ ->code_manager()
+ ->GetCodeFromStartAddress(it.rinfo()->wasm_call_address())
+ ->kind());
it.rinfo()->set_wasm_call_address(
- isolate, callee_compiled->instructions().start());
+ callee_compiled->instructions().start());
++patched;
}
DCHECK_EQ(non_compiled_functions.size(), idx);
- TRACE_LAZY("Patched %zu location(s) in the caller.\n", patched);
}
+
+ DCHECK_LT(0, patched);
+ TRACE_LAZY("Patched %d location(s) in the caller.\n", patched);
+ USE(patched);
+
return ret;
}
@@ -1679,8 +1528,7 @@ void ModuleCompiler::ValidateSequentially(const ModuleWireBytes& wire_bytes,
}
}
-// static
-MaybeHandle<WasmModuleObject> ModuleCompiler::CompileToModuleObject(
+MaybeHandle<WasmModuleObject> CompileToModuleObject(
Isolate* isolate, ErrorThrower* thrower, std::unique_ptr<WasmModule> module,
const ModuleWireBytes& wire_bytes, Handle<Script> asm_js_script,
Vector<const byte> asm_js_offset_table_bytes) {
@@ -1703,21 +1551,20 @@ bool compile_lazy(const WasmModule* module) {
(FLAG_asm_wasm_lazy_compilation && module->is_asm_js());
}
-void FlushICache(Isolate* isolate, const wasm::NativeModule* native_module) {
+void FlushICache(const wasm::NativeModule* native_module) {
for (uint32_t i = 0, e = native_module->FunctionCount(); i < e; ++i) {
const wasm::WasmCode* code = native_module->GetCode(i);
if (code == nullptr) continue;
- Assembler::FlushICache(isolate, code->instructions().start(),
+ Assembler::FlushICache(code->instructions().start(),
code->instructions().size());
}
}
-void FlushICache(Isolate* isolate, Handle<FixedArray> functions) {
+void FlushICache(Handle<FixedArray> functions) {
for (int i = 0, e = functions->length(); i < e; ++i) {
if (!functions->get(i)->IsCode()) continue;
Code* code = Code::cast(functions->get(i));
- Assembler::FlushICache(isolate, code->instruction_start(),
- code->instruction_size());
+ Assembler::FlushICache(code->instruction_start(), code->instruction_size());
}
}
@@ -1811,7 +1658,8 @@ WasmCodeWrapper EnsureExportedLazyDeoptData(Isolate* isolate,
return WasmCodeWrapper(code);
}
// Clone the lazy builtin into the native module.
- return WasmCodeWrapper(native_module->CloneLazyBuiltinInto(func_index));
+ return WasmCodeWrapper(
+ native_module->CloneLazyBuiltinInto(code, func_index));
}
}
@@ -1825,7 +1673,7 @@ WasmCodeWrapper EnsureTableExportLazyDeoptData(
Isolate* isolate, Handle<WasmInstanceObject> instance,
Handle<FixedArray> code_table, wasm::NativeModule* native_module,
uint32_t func_index, Handle<FixedArray> export_table, int export_index,
- std::unordered_map<uint32_t, uint32_t>* table_export_count) {
+ std::unordered_map<uint32_t, uint32_t>* num_table_exports) {
if (!FLAG_wasm_jit_to_native) {
Handle<Code> code =
EnsureExportedLazyDeoptData(isolate, instance, code_table,
@@ -1845,10 +1693,10 @@ WasmCodeWrapper EnsureTableExportLazyDeoptData(
// [#4: export table
// #5: export table index]
// ...
- // table_export_count counts down and determines the index for the new
+ // num_table_exports counts down and determines the index for the new
// export table entry.
- auto table_export_entry = table_export_count->find(func_index);
- DCHECK(table_export_entry != table_export_count->end());
+ auto table_export_entry = num_table_exports->find(func_index);
+ DCHECK(table_export_entry != num_table_exports->end());
DCHECK_LT(0, table_export_entry->second);
uint32_t this_idx = 2 * table_export_entry->second;
--table_export_entry->second;
@@ -1881,10 +1729,10 @@ WasmCodeWrapper EnsureTableExportLazyDeoptData(
// [#2: export table
// #3: export table index]
// ...
- // table_export_count counts down and determines the index for the new
+ // num_table_exports counts down and determines the index for the new
// export table entry.
- auto table_export_entry = table_export_count->find(func_index);
- DCHECK(table_export_entry != table_export_count->end());
+ auto table_export_entry = num_table_exports->find(func_index);
+ DCHECK(table_export_entry != num_table_exports->end());
DCHECK_LT(0, table_export_entry->second);
--table_export_entry->second;
uint32_t this_idx = 2 * table_export_entry->second;
@@ -2192,19 +2040,17 @@ MaybeHandle<WasmModuleObject> ModuleCompiler::CompileToModuleObjectInternal(
return result;
}
-InstanceBuilder::InstanceBuilder(
- Isolate* isolate, ErrorThrower* thrower,
- Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> ffi,
- MaybeHandle<JSArrayBuffer> memory,
- WeakCallbackInfo<void>::Callback instance_finalizer_callback)
+InstanceBuilder::InstanceBuilder(Isolate* isolate, ErrorThrower* thrower,
+ Handle<WasmModuleObject> module_object,
+ MaybeHandle<JSReceiver> ffi,
+ MaybeHandle<JSArrayBuffer> memory)
: isolate_(isolate),
module_(module_object->compiled_module()->shared()->module()),
async_counters_(isolate->async_counters()),
thrower_(thrower),
module_object_(module_object),
ffi_(ffi),
- memory_(memory),
- instance_finalizer_callback_(instance_finalizer_callback) {
+ memory_(memory) {
sanitized_imports_.reserve(module_->import_table.size());
}
@@ -2222,12 +2068,8 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
if (thrower_->error()) return {};
// TODO(6792): No longer needed once WebAssembly code is off heap.
- // Use base::Optional to be able to close the scope before executing the start
- // function.
- base::Optional<CodeSpaceMemoryModificationScope> modification_scope(
- base::in_place_t(), isolate_->heap());
+ CodeSpaceMemoryModificationScope modification_scope(isolate_->heap());
// From here on, we expect the build pipeline to run without exiting to JS.
- // Exception is when we run the startup function.
DisallowJavascriptExecution no_js(isolate_);
// Record build time into correct bucket, then build instance.
TimedHistogramScope wasm_instantiate_module_time_scope(
@@ -2238,14 +2080,10 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
//--------------------------------------------------------------------------
// Reuse the compiled module (if no owner), otherwise clone.
//--------------------------------------------------------------------------
- // TODO(mtrofin): remove code_table and old_code_table
+ // TODO(mtrofin): remove code_table
// when FLAG_wasm_jit_to_native is not needed
Handle<FixedArray> code_table;
Handle<FixedArray> wrapper_table;
- // We keep around a copy of the old code table, because we'll be replacing
- // imports for the new instance, and then we need the old imports to be
- // able to relocate.
- Handle<FixedArray> old_code_table;
MaybeHandle<WasmInstanceObject> owner;
// native_module is the one we're building now, old_module
// is the one we clone from. They point to the same place if
@@ -2284,7 +2122,6 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
wrapper_table = handle(compiled_module_->export_wrappers(), isolate_);
} else {
TRACE("Cloning from %d\n", original->instance_id());
- old_code_table = handle(original->code_table(), isolate_);
compiled_module_ = WasmCompiledModule::Clone(isolate_, original);
code_table = handle(compiled_module_->code_table(), isolate_);
wrapper_table = handle(compiled_module_->export_wrappers(), isolate_);
@@ -2345,7 +2182,6 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
compiled_module_->GetNativeModule()->instance_id);
} else {
code_table = handle(compiled_module_->code_table(), isolate_);
- old_code_table = factory->CopyFixedArray(code_table);
TRACE("Reusing existing instance %d\n",
compiled_module_->instance_id());
}
@@ -2549,11 +2385,11 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
code_specialization.ApplyToWholeInstance(*instance, SKIP_ICACHE_FLUSH);
if (FLAG_wasm_jit_to_native) {
- FlushICache(isolate_, native_module);
+ FlushICache(native_module);
} else {
- FlushICache(isolate_, code_table);
+ FlushICache(code_table);
}
- FlushICache(isolate_, wrapper_table);
+ FlushICache(wrapper_table);
//--------------------------------------------------------------------------
// Unpack and notify signal handler of protected instructions.
@@ -2570,8 +2406,6 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
// Insert the compiled module into the weak list of compiled modules.
//--------------------------------------------------------------------------
{
- Handle<Object> global_handle =
- isolate_->global_handles()->Create(*instance);
Handle<WeakCell> link_to_owning_instance = factory->NewWeakCell(instance);
if (!owner.is_null()) {
// Publish the new instance to the instances chain.
@@ -2580,9 +2414,7 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
}
module_object_->set_compiled_module(*compiled_module_);
compiled_module_->set_weak_owning_instance(*link_to_owning_instance);
- GlobalHandles::MakeWeak(global_handle.location(), global_handle.location(),
- instance_finalizer_callback_,
- v8::WeakCallbackType::kFinalizer);
+ WasmInstanceObject::InstallFinalizer(isolate_, instance);
}
//--------------------------------------------------------------------------
@@ -2607,41 +2439,20 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
}
//--------------------------------------------------------------------------
- // Execute the start function if one was specified.
+ // Create a wrapper for the start function.
//--------------------------------------------------------------------------
if (module_->start_function_index >= 0) {
- HandleScope scope(isolate_);
int start_index = module_->start_function_index;
- WasmCodeWrapper startup_code = EnsureExportedLazyDeoptData(
+ WasmCodeWrapper start_code = EnsureExportedLazyDeoptData(
isolate_, instance, code_table, native_module, start_index);
FunctionSig* sig = module_->functions[start_index].sig;
Handle<Code> wrapper_code = js_to_wasm_cache_.CloneOrCompileJSToWasmWrapper(
- isolate_, module_, startup_code, start_index,
+ isolate_, module_, start_code, start_index,
compiled_module_->use_trap_handler());
- Handle<WasmExportedFunction> startup_fct = WasmExportedFunction::New(
+ start_function_ = WasmExportedFunction::New(
isolate_, instance, MaybeHandle<String>(), start_index,
static_cast<int>(sig->parameter_count()), wrapper_code);
- RecordStats(startup_code, counters());
- // Call the JS function.
- Handle<Object> undefined = factory->undefined_value();
- // Close the modification scopes, so we can execute the start function.
- modification_scope.reset();
- native_module_modification_scope.reset();
- {
- // We're OK with JS execution here. The instance is fully setup.
- AllowJavascriptExecution allow_js(isolate_);
- MaybeHandle<Object> retval =
- Execution::Call(isolate_, startup_fct, undefined, 0, nullptr);
-
- if (retval.is_null()) {
- DCHECK(isolate_->has_pending_exception());
- // It's unfortunate that the new instance is already linked in the
- // chain. However, we need to set up everything before executing the
- // startup unction, such that stack trace information can be generated
- // correctly already in the start function.
- return {};
- }
- }
+ RecordStats(start_code, counters());
}
DCHECK(!isolate_->has_pending_exception());
@@ -2655,6 +2466,22 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
return instance;
}
+bool InstanceBuilder::ExecuteStartFunction() {
+ if (start_function_.is_null()) return true; // No start function.
+
+ HandleScope scope(isolate_);
+ // Call the JS function.
+ Handle<Object> undefined = isolate_->factory()->undefined_value();
+ MaybeHandle<Object> retval =
+ Execution::Call(isolate_, start_function_, undefined, 0, nullptr);
+
+ if (retval.is_null()) {
+ DCHECK(isolate_->has_pending_exception());
+ return false;
+ }
+ return true;
+}
+
// Look up an import value in the {ffi_} object.
MaybeHandle<Object> InstanceBuilder::LookupImport(uint32_t index,
Handle<String> module_name,
@@ -2939,6 +2766,11 @@ int InstanceBuilder::ProcessImports(Handle<FixedArray> code_table,
i += kFunctionTableEntrySize) {
table_instance.function_table->set(i, Smi::FromInt(kInvalidSigIndex));
}
+ WasmContext* wasm_context = nullptr;
+ if (WASM_CONTEXT_TABLES) {
+ wasm_context = instance->wasm_context()->get();
+ EnsureWasmContextTable(wasm_context, imported_cur_size);
+ }
// Initialize the dispatch table with the (foreign) JS functions
// that are already in the table.
for (int i = 0; i < imported_cur_size; ++i) {
@@ -2956,7 +2788,7 @@ int InstanceBuilder::ProcessImports(Handle<FixedArray> code_table,
// id, then the signature does not appear at all in this module,
// so putting {-1} in the table will cause checks to always fail.
auto target = Handle<WasmExportedFunction>::cast(val);
- if (!FLAG_wasm_jit_to_native) {
+ if (!WASM_CONTEXT_TABLES) {
FunctionSig* sig = nullptr;
Handle<Code> code =
MakeWasmToWasmWrapper(isolate_, target, nullptr, &sig,
@@ -2968,34 +2800,17 @@ int InstanceBuilder::ProcessImports(Handle<FixedArray> code_table,
table_instance.function_table->set(
compiler::FunctionTableCodeOffset(i), *code);
} else {
- const wasm::WasmCode* exported_code =
- target->GetWasmCode().GetWasmCode();
- wasm::NativeModule* exporting_module = exported_code->owner();
Handle<WasmInstanceObject> imported_instance =
handle(target->instance());
- imported_wasm_instances.Set(imported_instance, imported_instance);
+ const wasm::WasmCode* exported_code =
+ target->GetWasmCode().GetWasmCode();
FunctionSig* sig = imported_instance->module()
->functions[exported_code->index()]
.sig;
- wasm::WasmCode* wrapper_code =
- exporting_module->GetExportedWrapper(exported_code->index());
- if (wrapper_code == nullptr) {
- WasmContext* other_context =
- imported_instance->wasm_context()->get();
- Handle<Code> wrapper = compiler::CompileWasmToWasmWrapper(
- isolate_, target->GetWasmCode(), sig,
- reinterpret_cast<Address>(other_context));
- set_of_native_module_scopes.Add(exporting_module);
- wrapper_code = exporting_module->AddExportedWrapper(
- wrapper, exported_code->index());
- }
- int sig_index = module_->signature_map.Find(sig);
- Handle<Foreign> foreign_holder = isolate_->factory()->NewForeign(
- wrapper_code->instructions().start(), TENURED);
- table_instance.function_table->set(
- compiler::FunctionTableSigOffset(i), Smi::FromInt(sig_index));
- table_instance.function_table->set(
- compiler::FunctionTableCodeOffset(i), *foreign_holder);
+ auto& entry = wasm_context->table[i];
+ entry.context = imported_instance->wasm_context()->get();
+ entry.sig_id = module_->signature_map.Find(sig);
+ entry.target = exported_code->instructions().start();
}
}
@@ -3187,6 +3002,20 @@ void InstanceBuilder::ProcessExports(
// Fill the table to cache the exported JSFunction wrappers.
js_wrappers_.insert(js_wrappers_.begin(), module_->functions.size(),
Handle<JSFunction>::null());
+
+ // If an imported WebAssembly function gets exported, the exported function
+ // has to be identical to to imported function. Therefore we put all
+ // imported WebAssembly functions into the js_wrappers_ list.
+ for (int index = 0, end = static_cast<int>(module_->import_table.size());
+ index < end; ++index) {
+ WasmImport& import = module_->import_table[index];
+ if (import.kind == kExternalFunction) {
+ Handle<Object> value = sanitized_imports_[index].value;
+ if (WasmExportedFunction::IsWasmExportedFunction(*value)) {
+ js_wrappers_[import.index] = Handle<JSFunction>::cast(value);
+ }
+ }
+ }
}
Handle<JSObject> exports_object;
@@ -3345,12 +3174,6 @@ void InstanceBuilder::InitializeTables(
Handle<WasmInstanceObject> instance,
CodeSpecialization* code_specialization) {
size_t function_table_count = module_->function_tables.size();
- std::vector<GlobalHandleAddress> new_function_tables(function_table_count);
-
- wasm::NativeModule* native_module = compiled_module_->GetNativeModule();
- std::vector<GlobalHandleAddress> empty;
- std::vector<GlobalHandleAddress>& old_function_tables =
- FLAG_wasm_jit_to_native ? native_module->function_tables() : empty;
Handle<FixedArray> old_function_tables_gc =
FLAG_wasm_jit_to_native
@@ -3372,9 +3195,7 @@ void InstanceBuilder::InitializeTables(
instance->set_function_tables(*rooted_function_tables);
- if (FLAG_wasm_jit_to_native) {
- DCHECK_EQ(old_function_tables.size(), new_function_tables.size());
- } else {
+ if (!FLAG_wasm_jit_to_native) {
DCHECK_EQ(old_function_tables_gc->length(),
new_function_tables_gc->length());
}
@@ -3386,6 +3207,11 @@ void InstanceBuilder::InitializeTables(
int num_table_entries = static_cast<int>(table.initial_size);
int table_size = compiler::kFunctionTableEntrySize * num_table_entries;
+ if (WASM_CONTEXT_TABLES) {
+ WasmContext* wasm_context = instance->wasm_context()->get();
+ EnsureWasmContextTable(wasm_context, num_table_entries);
+ }
+
if (table_instance.function_table.is_null()) {
// Create a new dispatch table if necessary.
table_instance.function_table =
@@ -3427,24 +3253,18 @@ void InstanceBuilder::InitializeTables(
GlobalHandleAddress new_func_table_addr = global_func_table.address();
GlobalHandleAddress old_func_table_addr;
- if (!FLAG_wasm_jit_to_native) {
+ if (!WASM_CONTEXT_TABLES) {
WasmCompiledModule::SetTableValue(isolate_, new_function_tables_gc,
int_index, new_func_table_addr);
old_func_table_addr =
WasmCompiledModule::GetTableValue(*old_function_tables_gc, int_index);
- } else {
- new_function_tables[int_index] = new_func_table_addr;
-
- old_func_table_addr = old_function_tables[int_index];
+ code_specialization->RelocatePointer(old_func_table_addr,
+ new_func_table_addr);
}
- code_specialization->RelocatePointer(old_func_table_addr,
- new_func_table_addr);
}
- if (FLAG_wasm_jit_to_native) {
- native_module->function_tables() = new_function_tables;
- } else {
+ if (!WASM_CONTEXT_TABLES) {
compiled_module_->set_function_tables(*new_function_tables_gc);
}
}
@@ -3499,10 +3319,12 @@ void InstanceBuilder::LoadTableSegments(Handle<FixedArray> code_table,
uint32_t func_index = table_init.entries[i];
WasmFunction* function = &module_->functions[func_index];
int table_index = static_cast<int>(i + base);
- uint32_t sig_index = module_->signature_ids[function->sig_index];
+
+ // Update the local dispatch table first.
+ uint32_t sig_id = module_->signature_ids[function->sig_index];
table_instance.function_table->set(
compiler::FunctionTableSigOffset(table_index),
- Smi::FromInt(sig_index));
+ Smi::FromInt(sig_id));
WasmCodeWrapper wasm_code = EnsureTableExportLazyDeoptData(
isolate_, instance, code_table, native_module, func_index,
table_instance.function_table, table_index, &num_table_exports);
@@ -3517,7 +3339,17 @@ void InstanceBuilder::LoadTableSegments(Handle<FixedArray> code_table,
table_instance.function_table->set(
compiler::FunctionTableCodeOffset(table_index),
*value_to_update_with);
+
+ if (WASM_CONTEXT_TABLES) {
+ WasmContext* wasm_context = instance->wasm_context()->get();
+ auto& entry = wasm_context->table[table_index];
+ entry.sig_id = sig_id;
+ entry.context = wasm_context;
+ entry.target = wasm_code.instructions().start();
+ }
+
if (!table_instance.table_object.is_null()) {
+ // Update the table object's other dispatch tables.
if (js_wrappers_[func_index].is_null()) {
// No JSFunction entry yet exists for this function. Create one.
// TODO(titzer): We compile JS->wasm wrappers for functions are
@@ -3546,31 +3378,10 @@ void InstanceBuilder::LoadTableSegments(Handle<FixedArray> code_table,
}
table_instance.js_wrappers->set(table_index,
*js_wrappers_[func_index]);
- // When updating dispatch tables, we need to provide a wasm-to-wasm
- // wrapper for wasm_code - unless wasm_code is already a wrapper. If
- // it's a wasm-to-js wrapper, we don't need to construct a
- // wasm-to-wasm wrapper because there's no context switching required.
- // The remaining case is that it's a wasm-to-wasm wrapper, in which
- // case it's already doing "the right thing", and wrapping it again
- // would be redundant.
- if (func_index >= module_->num_imported_functions) {
- value_to_update_with = GetOrCreateIndirectCallWrapper(
- isolate_, instance, wasm_code, func_index, function->sig);
- } else {
- if (wasm_code.IsCodeObject()) {
- DCHECK(wasm_code.GetCode()->kind() == Code::WASM_TO_JS_FUNCTION ||
- wasm_code.GetCode()->kind() ==
- Code::WASM_TO_WASM_FUNCTION);
- } else {
- DCHECK(wasm_code.GetWasmCode()->kind() ==
- WasmCode::kWasmToJsWrapper ||
- wasm_code.GetWasmCode()->kind() ==
- WasmCode::kWasmToWasmWrapper);
- }
- }
- WasmTableObject::UpdateDispatchTables(table_instance.table_object,
- table_index, function->sig,
- value_to_update_with);
+ // UpdateDispatchTables() should update this instance as well.
+ WasmTableObject::UpdateDispatchTables(
+ isolate_, table_instance.table_object, table_index, function->sig,
+ instance, wasm_code, func_index);
}
}
}
@@ -3686,14 +3497,18 @@ void AsyncCompileJob::AsyncCompileFailed(ErrorThrower& thrower) {
// {job} keeps the {this} pointer alive.
std::shared_ptr<AsyncCompileJob> job =
isolate_->wasm_engine()->compilation_manager()->RemoveJob(this);
- RejectPromise(isolate_, context_, thrower, module_promise_);
+ MaybeHandle<Object> promise_result =
+ JSPromise::Reject(module_promise_, thrower.Reify());
+ CHECK_EQ(promise_result.is_null(), isolate_->has_pending_exception());
}
void AsyncCompileJob::AsyncCompileSucceeded(Handle<Object> result) {
// {job} keeps the {this} pointer alive.
std::shared_ptr<AsyncCompileJob> job =
isolate_->wasm_engine()->compilation_manager()->RemoveJob(this);
- ResolvePromise(isolate_, context_, module_promise_, result);
+ MaybeHandle<Object> promise_result =
+ JSPromise::Resolve(module_promise_, result);
+ CHECK_EQ(promise_result.is_null(), isolate_->has_pending_exception());
}
// A closure to run a compilation step (either as foreground or background