Commit 91a5a219 authored by mtrofin's avatar mtrofin Committed by Commit bot

[wasm] Avoid double-serializing the wire bytes

Since the public API for deserialization is now just DeserializeOrCompile,
we can trickle down the wire bytes to the deserialization logic, and
avoid the need for duplicating the wire bytes when serializing.

BUG=chromium:657316

Review-Url: https://chromiumcodereview.appspot.com/2433273002
Cr-Commit-Position: refs/heads/master@{#40516}
parent 3a7b3898
......@@ -3915,7 +3915,8 @@ class V8_EXPORT WasmCompiledModule : public Object {
private:
static MaybeLocal<WasmCompiledModule> Deserialize(
Isolate* isolate, const CallerOwnedBuffer& serialized_module);
Isolate* isolate, const CallerOwnedBuffer& serialized_module,
const CallerOwnedBuffer& wire_bytes);
static MaybeLocal<WasmCompiledModule> Compile(Isolate* isolate,
const uint8_t* start,
size_t length);
......
......@@ -7224,12 +7224,15 @@ WasmCompiledModule::SerializedModule WasmCompiledModule::Serialize() {
MaybeLocal<WasmCompiledModule> WasmCompiledModule::Deserialize(
Isolate* isolate,
const WasmCompiledModule::CallerOwnedBuffer& serialized_module) {
const WasmCompiledModule::CallerOwnedBuffer& serialized_module,
const WasmCompiledModule::CallerOwnedBuffer& wire_bytes) {
int size = static_cast<int>(serialized_module.second);
i::ScriptData sc(serialized_module.first, size);
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
i::MaybeHandle<i::FixedArray> maybe_compiled_part =
i::WasmCompiledModuleSerializer::DeserializeWasmModule(i_isolate, &sc);
i::WasmCompiledModuleSerializer::DeserializeWasmModule(
i_isolate, &sc,
{wire_bytes.first, static_cast<int>(wire_bytes.second)});
i::Handle<i::FixedArray> compiled_part;
if (!maybe_compiled_part.ToHandle(&compiled_part)) {
return MaybeLocal<WasmCompiledModule>();
......@@ -7245,24 +7248,9 @@ MaybeLocal<WasmCompiledModule> WasmCompiledModule::DeserializeOrCompile(
Isolate* isolate,
const WasmCompiledModule::CallerOwnedBuffer& serialized_module,
const WasmCompiledModule::CallerOwnedBuffer& wire_bytes) {
MaybeLocal<WasmCompiledModule> ret = Deserialize(isolate, serialized_module);
MaybeLocal<WasmCompiledModule> ret =
Deserialize(isolate, serialized_module, wire_bytes);
if (!ret.IsEmpty()) {
// TODO(mtrofin): once we stop taking a dependency on Deserialize,
// clean this up to avoid the back and forth between internal
// and external representations.
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
i::Vector<const uint8_t> str(wire_bytes.first,
static_cast<int>(wire_bytes.second));
i::Handle<i::SeqOneByteString> wire_bytes_as_string(
i::SeqOneByteString::cast(
*i_isolate->factory()->NewStringFromOneByte(str).ToHandleChecked()),
i_isolate);
i::Handle<i::JSObject> obj =
i::Handle<i::JSObject>::cast(Utils::OpenHandle(*ret.ToLocalChecked()));
i::Handle<i::wasm::WasmCompiledModule> compiled_part =
i::handle(i::wasm::WasmCompiledModule::cast(obj->GetInternalField(0)));
compiled_part->set_module_bytes(wire_bytes_as_string);
return ret;
}
return Compile(isolate, wire_bytes.first, wire_bytes.second);
......
......@@ -1442,6 +1442,10 @@ class Heap {
// ArrayBuffer tracking. =====================================================
// ===========================================================================
// TODO(gc): API usability: encapsulate mutation of JSArrayBuffer::is_external
// in the registration/unregistration APIs. Consider dropping the "New" from
// "RegisterNewArrayBuffer" because one can re-register a previously
// unregistered buffer, too, and the name is confusing.
void RegisterNewArrayBuffer(JSArrayBuffer* buffer);
void UnregisterArrayBuffer(JSArrayBuffer* buffer);
......
......@@ -754,15 +754,31 @@ RUNTIME_FUNCTION(Runtime_SerializeWasmModule) {
// Return undefined if unsuccessful.
RUNTIME_FUNCTION(Runtime_DeserializeWasmModule) {
HandleScope shs(isolate);
DCHECK(args.length() == 1);
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 0);
CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, wire_bytes, 1);
Address mem_start = static_cast<Address>(buffer->backing_store());
int mem_size = static_cast<int>(buffer->byte_length()->Number());
// DeserializeWasmModule will allocate. We assume JSArrayBuffer doesn't
// get relocated.
ScriptData sc(mem_start, mem_size);
bool already_external = wire_bytes->is_external();
if (!already_external) {
wire_bytes->set_is_external(true);
isolate->heap()->UnregisterArrayBuffer(*wire_bytes);
}
MaybeHandle<FixedArray> maybe_compiled_module =
WasmCompiledModuleSerializer::DeserializeWasmModule(isolate, &sc);
WasmCompiledModuleSerializer::DeserializeWasmModule(
isolate, &sc,
Vector<const uint8_t>(
reinterpret_cast<uint8_t*>(wire_bytes->backing_store()),
static_cast<int>(wire_bytes->byte_length()->Number())));
if (!already_external) {
wire_bytes->set_is_external(false);
isolate->heap()->RegisterNewArrayBuffer(*wire_bytes);
}
Handle<FixedArray> compiled_module;
if (!maybe_compiled_module.ToHandle(&compiled_module)) {
return isolate->heap()->undefined_value();
......
......@@ -897,7 +897,7 @@ namespace internal {
F(HasFixedUint8ClampedElements, 1, 1) \
F(SpeciesProtector, 0, 1) \
F(SerializeWasmModule, 1, 1) \
F(DeserializeWasmModule, 1, 1) \
F(DeserializeWasmModule, 2, 1) \
F(IsAsmWasmCode, 1, 1) \
F(IsNotAsmWasmCode, 1, 1) \
F(ValidateWasmInstancesChain, 2, 1) \
......
......@@ -223,12 +223,14 @@ std::unique_ptr<ScriptData> WasmCompiledModuleSerializer::SerializeWasmModule(
Handle<wasm::WasmCompiledModule>::cast(input);
WasmCompiledModuleSerializer wasm_cs(isolate, 0);
wasm_cs.reference_map()->AddAttachedReference(*isolate->native_context());
wasm_cs.reference_map()->AddAttachedReference(
*compiled_module->module_bytes());
ScriptData* data = wasm_cs.Serialize(compiled_module);
return std::unique_ptr<ScriptData>(data);
}
MaybeHandle<FixedArray> WasmCompiledModuleSerializer::DeserializeWasmModule(
Isolate* isolate, ScriptData* data) {
Isolate* isolate, ScriptData* data, Vector<const byte> wire_bytes) {
SerializedCodeData::SanityCheckResult sanity_check_result =
SerializedCodeData::CHECK_SUCCESS;
MaybeHandle<FixedArray> nothing;
......@@ -242,6 +244,15 @@ MaybeHandle<FixedArray> WasmCompiledModuleSerializer::DeserializeWasmModule(
Deserializer deserializer(&scd, true);
deserializer.AddAttachedObject(isolate->native_context());
MaybeHandle<String> maybe_wire_bytes_as_string =
isolate->factory()->NewStringFromOneByte(wire_bytes, TENURED);
Handle<String> wire_bytes_as_string;
if (!maybe_wire_bytes_as_string.ToHandle(&wire_bytes_as_string)) {
return nothing;
}
deserializer.AddAttachedObject(
handle(SeqOneByteString::cast(*wire_bytes_as_string)));
Vector<const uint32_t> stub_keys = scd.CodeStubKeys();
for (int i = 0; i < stub_keys.length(); ++i) {
deserializer.AddAttachedObject(
......@@ -250,8 +261,9 @@ MaybeHandle<FixedArray> WasmCompiledModuleSerializer::DeserializeWasmModule(
MaybeHandle<HeapObject> obj = deserializer.DeserializeObject(isolate);
if (obj.is_null() || !obj.ToHandleChecked()->IsFixedArray()) return nothing;
Handle<FixedArray> compiled_module =
Handle<FixedArray>::cast(obj.ToHandleChecked());
Handle<wasm::WasmCompiledModule> compiled_module =
Handle<wasm::WasmCompiledModule>::cast(obj.ToHandleChecked());
wasm::WasmCompiledModule::RecreateModuleWrapper(isolate, compiled_module);
return compiled_module;
}
......
......@@ -59,8 +59,8 @@ class WasmCompiledModuleSerializer : public CodeSerializer {
public:
static std::unique_ptr<ScriptData> SerializeWasmModule(
Isolate* isolate, Handle<FixedArray> compiled_module);
static MaybeHandle<FixedArray> DeserializeWasmModule(Isolate* isolate,
ScriptData* data);
static MaybeHandle<FixedArray> DeserializeWasmModule(
Isolate* isolate, ScriptData* data, Vector<const byte> wire_bytes);
protected:
void SerializeCodeObject(Code* code_object, HowToCode how_to_code,
......
......@@ -35,12 +35,12 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
kExprCallFunction, 1]);
builder.appendToTable([2, 3]);
var module = new WebAssembly.Module(builder.toBuffer());
var wire_bytes = builder.toBuffer();
var module = new WebAssembly.Module(wire_bytes);
var buff = %SerializeWasmModule(module);
module = null;
gc();
module = %DeserializeWasmModule(buff);
module = %DeserializeWasmModule(buff, wire_bytes);
var mem_1 = new ArrayBuffer(4);
var view_1 = new Int32Array(mem_1);
......@@ -59,7 +59,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
(function DeserializeInvalidObject() {
var invalid_buffer = new ArrayBuffer(10);
module = %DeserializeWasmModule(invalid_buffer);
module = %DeserializeWasmModule(invalid_buffer, invalid_buffer);
assertEquals(module, undefined);
})();
......@@ -69,9 +69,10 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
.addBody([kExprI8Const, 42])
.exportFunc();
var compiled_module = new WebAssembly.Module(builder.toBuffer());
var wire_bytes = builder.toBuffer();
var compiled_module = new WebAssembly.Module(wire_bytes);
var serialized = %SerializeWasmModule(compiled_module);
var clone = %DeserializeWasmModule(serialized);
var clone = %DeserializeWasmModule(serialized, wire_bytes);
assertNotNull(clone);
assertFalse(clone == undefined);
......@@ -85,11 +86,12 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
.addBody([kExprI8Const, 42])
.exportFunc();
var compiled_module = new WebAssembly.Module(builder.toBuffer());
var wire_bytes = builder.toBuffer()
var compiled_module = new WebAssembly.Module(wire_bytes);
var instance1 = new WebAssembly.Instance(compiled_module);
var instance2 = new WebAssembly.Instance(compiled_module);
var serialized = %SerializeWasmModule(compiled_module);
var clone = %DeserializeWasmModule(serialized);
var clone = %DeserializeWasmModule(serialized, wire_bytes);
assertNotNull(clone);
assertFalse(clone == undefined);
......
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