[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}
This commit is contained in:
mtrofin 2016-10-22 08:14:40 -07:00 committed by Commit bot
parent 3a7b389879
commit 91a5a219d4
8 changed files with 59 additions and 36 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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();

View File

@ -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) \

View File

@ -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;
}

View File

@ -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,

View File

@ -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);