Commit 2e8d8f8f authored by Manos Koukoutos's avatar Manos Koukoutos Committed by V8 LUCI CQ

[wasm] Restore eager parallel export-wrapper compilation

As part of moving export wrappers to the isolate, it was tried to
compile them lazily on the main thread. This resulted in large
slowdowns in some cases, therefore we restore the eager parallel
compilation.

Bug: chromium:1365726
Change-Id: I9cc8d5728f3a5c71099f0e0fdcc605b37d4d6618
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3905193Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#83339}
parent 67106ff4
......@@ -616,6 +616,7 @@ class CompilationStateImpl {
std::shared_ptr<JSToWasmWrapperCompilationUnit>
GetNextJSToWasmWrapperCompilationUnit();
void FinalizeJSToWasmWrappers(Isolate* isolate, const WasmModule* module);
void OnFinishedUnits(base::Vector<WasmCode*>);
void OnFinishedJSToWasmWrapperUnits(int num);
......@@ -1509,6 +1510,13 @@ void TierUpNowForTesting(Isolate* isolate, WasmInstanceObject instance,
namespace {
void RecordStats(CodeT codet, Counters* counters) {
if (codet.is_off_heap_trampoline()) return;
Code code = FromCodeT(codet);
counters->wasm_generated_code_size()->Increment(code.raw_body_size());
counters->wasm_reloc_size()->Increment(code.relocation_info().length());
}
enum CompilationExecutionResult : int8_t { kNoMoreUnits, kYield };
CompilationExecutionResult ExecuteJSToWasmWrapperCompilationUnits(
......@@ -1932,6 +1940,8 @@ void CompileNativeModule(Isolate* isolate,
return;
}
compilation_state->FinalizeJSToWasmWrappers(isolate, native_module->module());
compilation_state->WaitForCompilationEvent(
CompilationEvent::kFinishedBaselineCompilation);
......@@ -1994,6 +2004,7 @@ std::shared_ptr<NativeModule> CompileToNativeModule(
std::shared_ptr<NativeModule> native_module = engine->MaybeGetNativeModule(
wasm_module->origin, wire_bytes_copy.as_vector(), isolate);
if (native_module) {
CompileJsToWasmWrappers(isolate, wasm_module);
return native_module;
}
......@@ -2028,6 +2039,7 @@ std::shared_ptr<NativeModule> CompileToNativeModule(
if (thrower->error()) return {};
if (cache_hit) {
CompileJsToWasmWrappers(isolate, wasm_module);
return native_module;
}
......@@ -2303,6 +2315,17 @@ void AsyncCompileJob::FinishCompile(bool is_after_cache_hit) {
isolate_->debug()->OnAfterCompile(script);
}
// TODO(bbudge) Allow deserialization without wrapper compilation, so we can
// just compile wrappers here.
if (!is_after_deserialization) {
if (is_after_cache_hit) {
// TODO(thibaudm): Look into sharing wrappers.
CompileJsToWasmWrappers(isolate_, module);
} else {
compilation_state->FinalizeJSToWasmWrappers(isolate_, module);
}
}
// We can only update the feature counts once the entire compile is done.
compilation_state->PublishDetectedFeatures(isolate_);
......@@ -3524,6 +3547,30 @@ CompilationStateImpl::GetNextJSToWasmWrapperCompilationUnit() {
return js_to_wasm_wrapper_units_[outstanding_units - 1];
}
void CompilationStateImpl::FinalizeJSToWasmWrappers(Isolate* isolate,
const WasmModule* module) {
// TODO(6792): Wrappers below are allocated with {Factory::NewCode}. As an
// optimization we create a code memory modification scope that avoids
// changing the page permissions back-and-forth between RWX and RX, because
// many such wrapper are allocated in sequence below.
TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("v8.wasm.detailed"),
"wasm.FinalizeJSToWasmWrappers", "wrappers",
js_to_wasm_wrapper_units_.size());
isolate->heap()->EnsureWasmCanonicalRttsSize(module->MaxCanonicalTypeIndex() +
1);
CodePageCollectionMemoryModificationScope modification_scope(isolate->heap());
for (auto& unit : js_to_wasm_wrapper_units_) {
DCHECK_EQ(isolate, unit->isolate());
Handle<CodeT> code = unit->Finalize();
uint32_t index =
GetExportWrapperIndex(unit->canonical_sig_index(), unit->is_import());
isolate->heap()->js_to_wasm_wrappers().Set(index,
MaybeObject::FromObject(*code));
RecordStats(*code, isolate->counters());
}
}
CompilationUnitQueues::Queue* CompilationStateImpl::GetQueueForCompileTask(
int task_id) {
return compilation_unit_queues_.GetQueueForTask(task_id);
......@@ -3898,6 +3945,78 @@ class CompileJSToWasmWrapperJob final : public JobTask {
};
} // namespace
void CompileJsToWasmWrappers(Isolate* isolate, const WasmModule* module) {
TRACE_EVENT0("v8.wasm", "wasm.CompileJsToWasmWrappers");
isolate->heap()->EnsureWasmCanonicalRttsSize(module->MaxCanonicalTypeIndex() +
1);
JSToWasmWrapperQueue queue;
JSToWasmWrapperUnitMap compilation_units;
WasmFeatures enabled_features = WasmFeatures::FromIsolate(isolate);
// Prepare compilation units in the main thread.
for (auto exp : module->export_table) {
if (exp.kind != kExternalFunction) continue;
auto& function = module->functions[exp.index];
uint32_t canonical_type_index =
module->isorecursive_canonical_type_ids[function.sig_index];
int wrapper_index =
GetExportWrapperIndex(canonical_type_index, function.imported);
auto existing_wrapper =
isolate->heap()->js_to_wasm_wrappers().Get(wrapper_index);
if (existing_wrapper.IsStrongOrWeak() &&
!existing_wrapper.GetHeapObject().IsUndefined()) {
continue;
}
JSToWasmWrapperKey key(function.imported, canonical_type_index);
if (queue.insert(key, nullptr)) {
auto unit = std::make_unique<JSToWasmWrapperCompilationUnit>(
isolate, function.sig, canonical_type_index, module,
function.imported, enabled_features,
JSToWasmWrapperCompilationUnit::kAllowGeneric);
compilation_units.emplace(key, std::move(unit));
}
}
{
// This is nested inside the event above, so the name can be less
// descriptive. It's mainly to log the number of wrappers.
TRACE_EVENT1("v8.wasm", "wasm.JsToWasmWrapperCompilation", "num_wrappers",
compilation_units.size());
auto job =
std::make_unique<CompileJSToWasmWrapperJob>(&queue, &compilation_units);
if (v8_flags.wasm_num_compilation_tasks > 0) {
auto job_handle = V8::GetCurrentPlatform()->CreateJob(
TaskPriority::kUserVisible, std::move(job));
// Wait for completion, while contributing to the work.
job_handle->Join();
} else {
job->Run(nullptr);
}
}
// Finalize compilation jobs in the main thread.
// TODO(6792): Wrappers below are allocated with {Factory::NewCode}. As an
// optimization we create a code memory modification scope that avoids
// changing the page permissions back-and-forth between RWX and RX, because
// many such wrapper are allocated in sequence below.
CodePageCollectionMemoryModificationScope modification_scope(isolate->heap());
for (auto& pair : compilation_units) {
JSToWasmWrapperKey key = pair.first;
JSToWasmWrapperCompilationUnit* unit = pair.second.get();
DCHECK_EQ(isolate, unit->isolate());
Handle<CodeT> code = unit->Finalize();
int wrapper_index = GetExportWrapperIndex(key.second, key.first);
isolate->heap()->js_to_wasm_wrappers().Set(
wrapper_index, HeapObjectReference::Strong(*code));
RecordStats(*code, isolate->counters());
}
}
WasmCode* CompileImportWrapper(
NativeModule* native_module, Counters* counters,
compiler::WasmImportCallKind kind, const FunctionSig* sig,
......
......@@ -62,6 +62,9 @@ std::shared_ptr<NativeModule> CompileToNativeModule(
void RecompileNativeModule(NativeModule* native_module,
TieringState new_tiering_state);
V8_EXPORT_PRIVATE
void CompileJsToWasmWrappers(Isolate* isolate, const WasmModule* module);
// Compiles the wrapper for this (kind, sig) pair and sets the corresponding
// cache entry. Assumes the key already exists in the cache but has not been
// compiled yet.
......
......@@ -1370,9 +1370,11 @@ WasmInstanceObject::GetOrCreateWasmInternalFunction(
wrapper = wasm::JSToWasmWrapperCompilationUnit::CompileJSToWasmWrapper(
isolate, function.sig, canonical_sig_index, instance->module(),
function.imported);
isolate->heap()->js_to_wasm_wrappers().Set(
wrapper_index, HeapObjectReference::Weak(*wrapper));
}
// Store the wrapper in the isolate, or make its reference weak now that we
// have a function referencing it.
isolate->heap()->js_to_wasm_wrappers().Set(
wrapper_index, HeapObjectReference::Weak(*wrapper));
auto external = Handle<WasmExternalFunction>::cast(WasmExportedFunction::New(
isolate, instance, function_index,
static_cast<int>(function.sig->parameter_count()), wrapper));
......
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