Commit 1c9bb77d authored by Thibaud Michaud's avatar Thibaud Michaud Committed by Commit Bot

[wasm] Share native modules for async compilation

Use the native module cache for asynchronous, non-streaming compilation.

R=clemensb@chromium.org

Bug: v8:6847
Change-Id: Ie4c9469ee8cfdd6b987b70be6e237734a5de9733
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2002542
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65887}
parent 498be7bd
......@@ -1402,6 +1402,7 @@ AsyncCompileJob::AsyncCompileJob(
wire_bytes_(bytes_copy_.get(), bytes_copy_.get() + length),
resolver_(std::move(resolver)) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"), "new AsyncCompileJob");
CHECK(!FLAG_jitless);
v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
v8::Platform* platform = V8::GetCurrentPlatform();
foreground_task_runner_ = platform->GetForegroundTaskRunner(v8_isolate);
......@@ -1515,6 +1516,7 @@ void AsyncCompileJob::CreateNativeModule(
void AsyncCompileJob::PrepareRuntimeObjects() {
// Create heap objects for script and module bytes to be stored in the
// module object. Asm.js is not compiled asynchronously.
DCHECK(module_object_.is_null());
const WasmModule* module = native_module_->module();
auto source_url = stream_ ? stream_->url() : Vector<const char>();
Handle<Script> script =
......@@ -1615,6 +1617,11 @@ class AsyncCompileJob::CompilationStateCallback {
case CompilationEvent::kFinishedBaselineCompilation:
DCHECK(!last_event_.has_value());
if (job_->DecrementAndCheckFinisherCount()) {
// TODO(v8:6847): Also share streaming compilation result.
if (job_->stream_ == nullptr) {
job_->isolate_->wasm_engine()->UpdateNativeModuleCache(
job_->native_module_, false);
}
job_->DoSync<CompileFinished>();
}
break;
......@@ -1626,6 +1633,11 @@ class AsyncCompileJob::CompilationStateCallback {
case CompilationEvent::kFailedCompilation: {
DCHECK(!last_event_.has_value());
if (job_->DecrementAndCheckFinisherCount()) {
// TODO(v8:6847): Also share streaming compilation result.
if (job_->stream_ == nullptr) {
job_->isolate_->wasm_engine()->UpdateNativeModuleCache(
job_->native_module_, true);
}
job_->DoSync<CompileFailed>();
}
break;
......@@ -1878,6 +1890,23 @@ class AsyncCompileJob::PrepareAndStartCompile : public CompileStep {
void RunInForeground(AsyncCompileJob* job) override {
TRACE_COMPILE("(2) Prepare and start compile...\n");
// TODO(v8:6847): Also share streaming compilation result.
if (job->stream_ == nullptr) {
auto cached_native_module =
job->isolate_->wasm_engine()->MaybeGetNativeModule(
module_->origin, job->wire_bytes_.module_bytes());
if (cached_native_module != nullptr) {
job->native_module_ = std::move(cached_native_module);
job->PrepareRuntimeObjects();
Handle<FixedArray> export_wrappers;
CompileJsToWasmWrappers(job->isolate_, job->native_module_->module(),
&export_wrappers);
job->module_object_->set_export_wrappers(*export_wrappers);
job->FinishCompile();
return;
}
}
// Make sure all compilation tasks stopped running. Decoding (async step)
// is done.
job->background_task_manager_.CancelAndWait();
......
......@@ -776,7 +776,7 @@ void WasmEngine::FreeNativeModule(NativeModule* native_module) {
}
auto cache_it = native_module_cache_.find(native_module->wire_bytes());
// Not all native modules are stored in the cache currently. In particular
// asynchronous compilation and asmjs compilation results are not. So make
// streaming compilation and asmjs compilation results are not. So make
// sure that we only delete existing and expired entries.
// Do not erase {nullopt} values either, as they indicate that the
// {NativeModule} is currently being created in another thread.
......
......@@ -273,6 +273,7 @@ v8_source_set("cctest_sources") {
"unicode-helpers.cc",
"unicode-helpers.h",
"wasm/test-c-wasm-entry.cc",
"wasm/test-compilation-cache.cc",
"wasm/test-grow-memory.cc",
"wasm/test-jump-table-assembler.cc",
"wasm/test-liftoff-inspection.cc",
......
......@@ -561,6 +561,7 @@
'serializer-tester/SerializeInlinedClosure': [SKIP],
'serializer-tester/SerializeInlinedFunction': [SKIP],
'test-api/TurboAsmDisablesDetach': [SKIP],
'test-compilation-cache/TestAsyncCache': [SKIP],
'test-cpu-profiler/TickLinesOptimized': [SKIP],
'test-heap/TestOptimizeAfterBytecodeFlushingCandidate': [SKIP],
'test-run-wasm-exceptions/RunWasmInterpreter_TryCatchCallDirect': [SKIP],
......
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/api/api-inl.h"
#include "src/init/v8.h"
#include "src/wasm/wasm-code-manager.h"
#include "src/wasm/wasm-engine.h"
#include "src/wasm/wasm-module-builder.h"
#include "test/cctest/cctest.h"
#include "test/common/wasm/test-signatures.h"
#include "test/common/wasm/wasm-macro-gen.h"
namespace v8 {
namespace internal {
namespace wasm {
namespace {
class TestResolver : public CompilationResultResolver {
public:
explicit TestResolver(std::atomic<int>* pending)
: native_module_(nullptr), pending_(pending) {}
void OnCompilationSucceeded(i::Handle<i::WasmModuleObject> module) override {
if (!module.is_null()) {
native_module_ = module->shared_native_module();
pending_->fetch_sub(1);
}
}
void OnCompilationFailed(i::Handle<i::Object> error_reason) override {
CHECK(false);
}
std::shared_ptr<NativeModule> native_module() { return native_module_; }
private:
std::shared_ptr<NativeModule> native_module_;
std::atomic<int>* pending_;
};
// Create a valid module such that the bytes depend on {n}.
ZoneBuffer GetValidModuleBytes(Zone* zone, int n) {
ZoneBuffer buffer(zone);
TestSignatures sigs;
WasmModuleBuilder builder(zone);
{
WasmFunctionBuilder* f = builder.AddFunction(sigs.v_v());
uint8_t code[] = {kExprI32Const, n, kExprDrop, kExprEnd};
f->EmitCode(code, arraysize(code));
}
builder.WriteTo(&buffer);
return buffer;
}
} // namespace
TEST(TestAsyncCache) {
CcTest::InitializeVM();
i::HandleScope internal_scope_(CcTest::i_isolate());
AccountingAllocator allocator;
Zone zone(&allocator, "CompilationCacheTester");
auto bufferA = GetValidModuleBytes(&zone, 0);
auto bufferB = GetValidModuleBytes(&zone, 1);
std::atomic<int> pending(3);
auto resolverA1 = std::make_shared<TestResolver>(&pending);
auto resolverA2 = std::make_shared<TestResolver>(&pending);
auto resolverB = std::make_shared<TestResolver>(&pending);
CcTest::i_isolate()->wasm_engine()->AsyncCompile(
CcTest::i_isolate(), WasmFeatures::All(), resolverA1,
ModuleWireBytes(bufferA.begin(), bufferA.end()), true,
"WebAssembly.compile");
CcTest::i_isolate()->wasm_engine()->AsyncCompile(
CcTest::i_isolate(), WasmFeatures::All(), resolverA2,
ModuleWireBytes(bufferA.begin(), bufferA.end()), true,
"WebAssembly.compile");
CcTest::i_isolate()->wasm_engine()->AsyncCompile(
CcTest::i_isolate(), WasmFeatures::All(), resolverB,
ModuleWireBytes(bufferB.begin(), bufferB.end()), true,
"WebAssembly.compile");
while (pending > 0) {
v8::platform::PumpMessageLoop(i::V8::GetCurrentPlatform(),
CcTest::isolate());
}
CHECK_EQ(resolverA1->native_module(), resolverA2->native_module());
CHECK_NE(resolverA1->native_module(), resolverB->native_module());
}
} // namespace wasm
} // namespace internal
} // namespace v8
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