[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:
parent
3a7b389879
commit
91a5a219d4
@ -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);
|
||||
|
26
src/api.cc
26
src/api.cc
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user