Commit 8d3ababb authored by Clemens Backes's avatar Clemens Backes Committed by Commit Bot

[wasm] Wait until top tier finished before serializing

We only want to serialize TurboFan code, because Liftoff code could
contain breakpoints, and we start thinking about embedding other
non-relocatable constants.
Thus, wait until top-tier compilation finished before triggering
serialization.

A follow-up CL will make serialization fail if any Liftoff code is
encountered.

R=ahaas@chromium.org

Bug: v8:10777
Change-Id: I73d6c2d868545fcd4069a8cf9850ca7fca375ecb
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2349293Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#69332}
parent 5ec483c3
......@@ -1326,30 +1326,29 @@ RUNTIME_FUNCTION(Runtime_SerializeDeserializeNow) {
return ReadOnlyRoots(isolate).undefined_value();
}
// Take a compiled wasm module and serialize it into an array buffer, which is
// then returned.
// Wait until the given module is fully tiered up, then serialize it into an
// array buffer.
RUNTIME_FUNCTION(Runtime_SerializeWasmModule) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(WasmModuleObject, module_obj, 0);
wasm::NativeModule* native_module = module_obj->native_module();
native_module->compilation_state()->WaitForTopTierFinished();
DCHECK(!native_module->compilation_state()->failed());
wasm::WasmSerializer wasm_serializer(native_module);
size_t byte_length = wasm_serializer.GetSerializedNativeModuleSize();
MaybeHandle<JSArrayBuffer> result =
isolate->factory()->NewJSArrayBufferAndBackingStore(
byte_length, InitializedFlag::kUninitialized);
Handle<JSArrayBuffer> array_buffer =
isolate->factory()
->NewJSArrayBufferAndBackingStore(byte_length,
InitializedFlag::kUninitialized)
.ToHandleChecked();
Handle<JSArrayBuffer> array_buffer;
if (result.ToHandle(&array_buffer) &&
wasm_serializer.SerializeNativeModule(
{reinterpret_cast<uint8_t*>(array_buffer->backing_store()),
byte_length})) {
CHECK(wasm_serializer.SerializeNativeModule(
{static_cast<uint8_t*>(array_buffer->backing_store()), byte_length}));
return *array_buffer;
}
UNREACHABLE();
}
// Take an array buffer and attempt to reconstruct a compiled wasm module.
......
......@@ -1035,6 +1035,8 @@ auto Module::serialize() const -> vec<byte_t> {
impl(this)->v8_object()->native_module();
i::Vector<const uint8_t> wire_bytes = native_module->wire_bytes();
size_t binary_size = wire_bytes.size();
// We can only serialize after top-tier compilation (TurboFan) finished.
native_module->compilation_state()->WaitForTopTierFinished();
i::wasm::WasmSerializer serializer(native_module);
size_t serial_size = serializer.GetSerializedNativeModuleSize();
size_t size_size = i::wasm::LEBHelper::sizeof_u64v(binary_size);
......
......@@ -101,7 +101,7 @@ enum class CompilationEvent : uint8_t {
// The implementation of {CompilationState} lives in module-compiler.cc.
// This is the PIMPL interface to that private class.
class CompilationState {
class V8_EXPORT_PRIVATE CompilationState {
public:
using callback_t = std::function<void(CompilationEvent)>;
......@@ -113,15 +113,17 @@ class CompilationState {
void SetWireBytesStorage(std::shared_ptr<WireBytesStorage>);
V8_EXPORT_PRIVATE std::shared_ptr<WireBytesStorage> GetWireBytesStorage()
const;
std::shared_ptr<WireBytesStorage> GetWireBytesStorage() const;
void AddCallback(callback_t);
// Wait until top tier finished, or compilation failed (to avoid deadlocks).
void WaitForTopTierFinished();
bool failed() const;
V8_EXPORT_PRIVATE bool baseline_compilation_finished() const;
V8_EXPORT_PRIVATE bool top_tier_compilation_finished() const;
V8_EXPORT_PRIVATE bool recompilation_finished() const;
bool baseline_compilation_finished() const;
bool top_tier_compilation_finished() const;
bool recompilation_finished() const;
// Override {operator delete} to avoid implicit instantiation of {operator
// delete} with {size_t} argument. The {size_t} argument would be incorrect.
......
......@@ -688,6 +688,17 @@ void CompilationState::AddCallback(CompilationState::callback_t callback) {
return Impl(this)->AddCallback(std::move(callback));
}
void CompilationState::WaitForTopTierFinished() {
auto top_tier_finished_semaphore = std::make_shared<base::Semaphore>(0);
AddCallback([top_tier_finished_semaphore](CompilationEvent event) {
if (event == CompilationEvent::kFailedCompilation ||
event == CompilationEvent::kFinishedTopTierCompilation) {
top_tier_finished_semaphore->Signal();
}
});
top_tier_finished_semaphore->Wait();
}
bool CompilationState::failed() const { return Impl(this)->failed(); }
bool CompilationState::baseline_compilation_finished() const {
......
......@@ -268,10 +268,11 @@ ZoneBuffer GetValidCompiledModuleBytes(Zone* zone, ZoneBuffer wire_bytes) {
// Serialize the NativeModule.
std::shared_ptr<NativeModule> native_module = tester.native_module();
CHECK(native_module);
native_module->compilation_state()->WaitForTopTierFinished();
i::wasm::WasmSerializer serializer(native_module.get());
size_t size = serializer.GetSerializedNativeModuleSize();
std::vector<byte> buffer(size);
CHECK(serializer.SerializeNativeModule({buffer.data(), size}));
CHECK(serializer.SerializeNativeModule(VectorOf(buffer)));
ZoneBuffer result(zone, size);
result.write(buffer.data(), size);
return result;
......
......@@ -148,6 +148,10 @@ class WasmSerializationTest {
// Check that the native module exists at this point.
CHECK(weak_native_module.lock());
auto* native_module = module_object->native_module();
native_module->compilation_state()->WaitForTopTierFinished();
DCHECK(!native_module->compilation_state()->failed());
v8::Local<v8::Object> v8_module_obj =
v8::Utils::ToLocal(Handle<JSObject>::cast(module_object));
CHECK(v8_module_obj->IsWasmModuleObject());
......@@ -163,6 +167,7 @@ class WasmSerializationTest {
wire_bytes_ = {bytes_copy, uncompiled_bytes.size()};
// keep alive data_ until the end
data_ = compiled_module.Serialize();
CHECK_LT(0, data_.size);
}
// Dispose of serialization isolate to destroy the reference to the
// NativeModule, which removes it from the module cache in the wasm engine
......
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