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() { ...@@ -7407,7 +7407,13 @@ WasmCompiledModule::SerializedModule WasmCompiledModule::Serialize() {
i::Handle<i::WasmModuleObject>::cast(Utils::OpenHandle(this)); i::Handle<i::WasmModuleObject>::cast(Utils::OpenHandle(this));
i::Handle<i::WasmCompiledModule> compiled_part = i::Handle<i::WasmCompiledModule> compiled_part =
i::handle(i::WasmCompiledModule::cast(obj->compiled_module())); 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( MaybeLocal<WasmCompiledModule> WasmCompiledModule::Deserialize(
......
...@@ -861,22 +861,27 @@ RUNTIME_FUNCTION(Runtime_PromiseSpeciesProtector) { ...@@ -861,22 +861,27 @@ RUNTIME_FUNCTION(Runtime_PromiseSpeciesProtector) {
isolate->IsPromiseSpeciesLookupChainIntact()); isolate->IsPromiseSpeciesLookupChainIntact());
} }
// Take a compiled wasm module, serialize it and copy the buffer into an array // Take a compiled wasm module and serialize it into an array buffer, which is
// buffer, which is then returned. // then returned.
RUNTIME_FUNCTION(Runtime_SerializeWasmModule) { RUNTIME_FUNCTION(Runtime_SerializeWasmModule) {
HandleScope shs(isolate); HandleScope shs(isolate);
DCHECK_EQ(1, args.length()); DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(WasmModuleObject, module_obj, 0); CONVERT_ARG_HANDLE_CHECKED(WasmModuleObject, module_obj, 0);
Handle<WasmCompiledModule> orig(module_obj->compiled_module()); Handle<WasmCompiledModule> compiled_module(module_obj->compiled_module(),
std::pair<std::unique_ptr<const byte[]>, size_t> serialized_module = isolate);
wasm::SerializeNativeModule(isolate, orig); size_t compiled_size =
int data_size = static_cast<int>(serialized_module.second); wasm::GetSerializedNativeModuleSize(isolate, compiled_module);
void* buff = isolate->array_buffer_allocator()->Allocate(data_size); void* array_data = isolate->array_buffer_allocator()->Allocate(compiled_size);
Handle<JSArrayBuffer> ret = isolate->factory()->NewJSArrayBuffer(); Handle<JSArrayBuffer> array_buffer = isolate->factory()->NewJSArrayBuffer();
JSArrayBuffer::Setup(ret, isolate, false, buff, data_size); JSArrayBuffer::Setup(array_buffer, isolate, false, array_data, compiled_size);
memcpy(buff, serialized_module.first.get(), data_size); if (!array_data ||
return *ret; !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. // Take an array buffer and attempt to reconstruct a compiled wasm module.
......
...@@ -885,10 +885,17 @@ Maybe<bool> ValueSerializer::WriteWasmModule(Handle<WasmModuleObject> object) { ...@@ -885,10 +885,17 @@ Maybe<bool> ValueSerializer::WriteWasmModule(Handle<WasmModuleObject> object) {
String::WriteToFlat(*wire_bytes, destination, 0, wire_bytes_length); String::WriteToFlat(*wire_bytes, destination, 0, wire_bytes_length);
} }
std::pair<std::unique_ptr<const byte[]>, size_t> serialized_module = size_t module_size =
wasm::SerializeNativeModule(isolate_, compiled_part); wasm::GetSerializedNativeModuleSize(isolate_, compiled_part);
WriteVarint<uint32_t>(static_cast<uint32_t>(serialized_module.second)); CHECK_GE(std::numeric_limits<uint32_t>::max(), module_size);
WriteRawBytes(serialized_module.first.get(), serialized_module.second); 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(); return ThrowIfOutOfMemory();
} }
......
...@@ -391,21 +391,25 @@ bool NativeModuleSerializer::Write(Writer* writer) { ...@@ -391,21 +391,25 @@ bool NativeModuleSerializer::Write(Writer* writer) {
return true; return true;
} }
// static size_t GetSerializedNativeModuleSize(
std::pair<std::unique_ptr<const byte[]>, size_t> SerializeNativeModule(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module) { Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
NativeModule* native_module = compiled_module->GetNativeModule(); NativeModule* native_module = compiled_module->GetNativeModule();
NativeModuleSerializer serializer(isolate, native_module); NativeModuleSerializer serializer(isolate, native_module);
size_t buffer_size = kVersionSize + serializer.Measure(); return kVersionSize + serializer.Measure();
std::unique_ptr<byte[]> buffer(new byte[buffer_size]); }
Writer writer({buffer.get(), buffer_size}); bool SerializeNativeModule(Isolate* isolate,
WriteVersion(isolate, &writer); 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 {}; Writer writer(buffer);
if (writer.bytes_written() != buffer_size) return {}; WriteVersion(isolate, &writer);
return {std::move(buffer), buffer_size}; return serializer.Write(&writer);
} }
class V8_EXPORT_PRIVATE NativeModuleDeserializer { class V8_EXPORT_PRIVATE NativeModuleDeserializer {
......
...@@ -11,9 +11,13 @@ namespace v8 { ...@@ -11,9 +11,13 @@ namespace v8 {
namespace internal { namespace internal {
namespace wasm { namespace wasm {
std::pair<std::unique_ptr<const byte[]>, size_t> SerializeNativeModule( size_t GetSerializedNativeModuleSize(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module); Isolate* isolate, Handle<WasmCompiledModule> compiled_module);
bool SerializeNativeModule(Isolate* isolate,
Handle<WasmCompiledModule> compiled_module,
Vector<byte> buffer);
MaybeHandle<WasmCompiledModule> DeserializeNativeModule( MaybeHandle<WasmCompiledModule> DeserializeNativeModule(
Isolate* isolate, Vector<const byte> data, Vector<const byte> wire_bytes); 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