Commit 0a1b8f96 authored by Bill Budge's avatar Bill Budge Committed by Commit Bot

[wasm] Avoid extra copies when serializing the native module

- Separates measuring from wasm::SerializeNativeModule so caller
  can allocate or reserve the buffer memory. Call site thus avoid
  one unnecessary copy.

Bug: chromium:719007
Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng
Change-Id: I50412c0c0279114dcdc1aead810ad39e7c4e2a6e
Reviewed-on: https://chromium-review.googlesource.com/1039183
Commit-Queue: Bill Budge <bbudge@chromium.org>
Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52965}
parent 72f9d380
......@@ -7407,7 +7407,13 @@ WasmCompiledModule::SerializedModule WasmCompiledModule::Serialize() {
i::Handle<i::WasmModuleObject>::cast(Utils::OpenHandle(this));
i::Handle<i::WasmCompiledModule> compiled_part =
i::handle(i::WasmCompiledModule::cast(obj->compiled_module()));
return i::wasm::SerializeNativeModule(obj->GetIsolate(), compiled_part);
size_t buffer_size =
i::wasm::GetSerializedNativeModuleSize(obj->GetIsolate(), compiled_part);
std::unique_ptr<uint8_t[]> buffer(new uint8_t[buffer_size]);
if (i::wasm::SerializeNativeModule(obj->GetIsolate(), compiled_part,
{buffer.get(), buffer_size}))
return {std::move(buffer), buffer_size};
return {};
}
MaybeLocal<WasmCompiledModule> WasmCompiledModule::Deserialize(
......
......@@ -861,22 +861,27 @@ RUNTIME_FUNCTION(Runtime_PromiseSpeciesProtector) {
isolate->IsPromiseSpeciesLookupChainIntact());
}
// Take a compiled wasm module, serialize it and copy the buffer into an array
// buffer, which is then returned.
// Take a compiled wasm module and serialize it into an array buffer, which is
// then returned.
RUNTIME_FUNCTION(Runtime_SerializeWasmModule) {
HandleScope shs(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(WasmModuleObject, module_obj, 0);
Handle<WasmCompiledModule> orig(module_obj->compiled_module());
std::pair<std::unique_ptr<const byte[]>, size_t> serialized_module =
wasm::SerializeNativeModule(isolate, orig);
int data_size = static_cast<int>(serialized_module.second);
void* buff = isolate->array_buffer_allocator()->Allocate(data_size);
Handle<JSArrayBuffer> ret = isolate->factory()->NewJSArrayBuffer();
JSArrayBuffer::Setup(ret, isolate, false, buff, data_size);
memcpy(buff, serialized_module.first.get(), data_size);
return *ret;
Handle<WasmCompiledModule> compiled_module(module_obj->compiled_module(),
isolate);
size_t compiled_size =
wasm::GetSerializedNativeModuleSize(isolate, compiled_module);
void* array_data = isolate->array_buffer_allocator()->Allocate(compiled_size);
Handle<JSArrayBuffer> array_buffer = isolate->factory()->NewJSArrayBuffer();
JSArrayBuffer::Setup(array_buffer, isolate, false, array_data, compiled_size);
if (!array_data ||
!wasm::SerializeNativeModule(
isolate, compiled_module,
{reinterpret_cast<uint8_t*>(array_data), compiled_size})) {
return isolate->heap()->undefined_value();
}
return *array_buffer;
}
// Take an array buffer and attempt to reconstruct a compiled wasm module.
......
......@@ -885,10 +885,17 @@ Maybe<bool> ValueSerializer::WriteWasmModule(Handle<WasmModuleObject> object) {
String::WriteToFlat(*wire_bytes, destination, 0, wire_bytes_length);
}
std::pair<std::unique_ptr<const byte[]>, size_t> serialized_module =
wasm::SerializeNativeModule(isolate_, compiled_part);
WriteVarint<uint32_t>(static_cast<uint32_t>(serialized_module.second));
WriteRawBytes(serialized_module.first.get(), serialized_module.second);
size_t module_size =
wasm::GetSerializedNativeModuleSize(isolate_, compiled_part);
CHECK_GE(std::numeric_limits<uint32_t>::max(), module_size);
WriteVarint<uint32_t>(static_cast<uint32_t>(module_size));
uint8_t* module_buffer;
if (ReserveRawBytes(module_size).To(&module_buffer)) {
if (!wasm::SerializeNativeModule(isolate_, compiled_part,
{module_buffer, module_size})) {
return Nothing<bool>();
}
}
return ThrowIfOutOfMemory();
}
......
......@@ -391,21 +391,25 @@ bool NativeModuleSerializer::Write(Writer* writer) {
return true;
}
// static
std::pair<std::unique_ptr<const byte[]>, size_t> SerializeNativeModule(
size_t GetSerializedNativeModuleSize(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
NativeModule* native_module = compiled_module->GetNativeModule();
NativeModuleSerializer serializer(isolate, native_module);
size_t buffer_size = kVersionSize + serializer.Measure();
std::unique_ptr<byte[]> buffer(new byte[buffer_size]);
return kVersionSize + serializer.Measure();
}
Writer writer({buffer.get(), buffer_size});
WriteVersion(isolate, &writer);
bool SerializeNativeModule(Isolate* isolate,
Handle<WasmCompiledModule> compiled_module,
Vector<byte> buffer) {
NativeModule* native_module = compiled_module->GetNativeModule();
NativeModuleSerializer serializer(isolate, native_module);
size_t measured_size = serializer.Measure();
if (buffer.size() < measured_size) return false;
if (!serializer.Write(&writer)) return {};
if (writer.bytes_written() != buffer_size) return {};
Writer writer(buffer);
WriteVersion(isolate, &writer);
return {std::move(buffer), buffer_size};
return serializer.Write(&writer);
}
class V8_EXPORT_PRIVATE NativeModuleDeserializer {
......
......@@ -11,9 +11,13 @@ namespace v8 {
namespace internal {
namespace wasm {
std::pair<std::unique_ptr<const byte[]>, size_t> SerializeNativeModule(
size_t GetSerializedNativeModuleSize(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module);
bool SerializeNativeModule(Isolate* isolate,
Handle<WasmCompiledModule> compiled_module,
Vector<byte> buffer);
MaybeHandle<WasmCompiledModule> DeserializeNativeModule(
Isolate* isolate, Vector<const byte> data, Vector<const byte> wire_bytes);
......
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