Commit 244a05fb authored by Ben L. Titzer's avatar Ben L. Titzer Committed by Commit Bot

[wasm] Encapsulate WASM native module serialization in CC file.

This CL simply moves the implementation classes for WASM native
module serialization into the CC file and simplifies them a bit.

R=mstarzinger@chromium.org

Bug: 
Cq-Include-Trybots: master.tryserver.chromium.linux:linux_chromium_rel_ng
Change-Id: Id560d2c35eb12bdd461f5d80cb5211a2f4f51684
Reviewed-on: https://chromium-review.googlesource.com/856677Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Commit-Queue: Ben Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50434}
parent 11e80a35
......@@ -7544,8 +7544,7 @@ WasmCompiledModule::SerializedModule WasmCompiledModule::Serialize() {
if (i::FLAG_wasm_jit_to_native) {
i::Isolate* isolate = obj->GetIsolate();
return i::wasm::NativeModuleSerializer::SerializeWholeModule(isolate,
compiled_part);
return i::wasm::SerializeNativeModule(isolate, compiled_part);
} else {
std::unique_ptr<i::ScriptData> script_data =
i::WasmCompiledModuleSerializer::SerializeWasmModule(obj->GetIsolate(),
......@@ -7564,10 +7563,9 @@ MaybeLocal<WasmCompiledModule> WasmCompiledModule::Deserialize(
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
i::MaybeHandle<i::FixedArray> maybe_compiled_part;
if (i::FLAG_wasm_jit_to_native) {
maybe_compiled_part =
i::wasm::NativeModuleDeserializer::DeserializeFullBuffer(
i_isolate, {serialized_module.first, serialized_module.second},
{wire_bytes.first, wire_bytes.second});
maybe_compiled_part = i::wasm::DeserializeNativeModule(
i_isolate, {serialized_module.first, serialized_module.second},
{wire_bytes.first, wire_bytes.second});
} else {
int size = static_cast<int>(serialized_module.second);
i::ScriptData sc(serialized_module.first, size);
......
......@@ -997,7 +997,7 @@ RUNTIME_FUNCTION(Runtime_SerializeWasmModule) {
Handle<WasmCompiledModule> orig(module_obj->compiled_module());
if (FLAG_wasm_jit_to_native) {
std::pair<std::unique_ptr<byte[]>, size_t> serialized_module =
wasm::NativeModuleSerializer::SerializeWholeModule(isolate, orig);
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();
......@@ -1035,12 +1035,11 @@ RUNTIME_FUNCTION(Runtime_DeserializeWasmModule) {
}
MaybeHandle<FixedArray> maybe_compiled_module;
if (FLAG_wasm_jit_to_native) {
maybe_compiled_module =
wasm::NativeModuleDeserializer::DeserializeFullBuffer(
isolate, {mem_start, mem_size},
Vector<const uint8_t>(
reinterpret_cast<uint8_t*>(wire_bytes->backing_store()),
static_cast<int>(wire_bytes->byte_length()->Number())));
maybe_compiled_module = wasm::DeserializeNativeModule(
isolate, {mem_start, mem_size},
Vector<const uint8_t>(
reinterpret_cast<uint8_t*>(wire_bytes->backing_store()),
static_cast<int>(wire_bytes->byte_length()->Number())));
} else {
ScriptData sc(mem_start, static_cast<int>(mem_size));
maybe_compiled_module = WasmCompiledModuleSerializer::DeserializeWasmModule(
......
......@@ -858,8 +858,7 @@ Maybe<bool> ValueSerializer::WriteWasmModule(Handle<WasmModuleObject> object) {
if (FLAG_wasm_jit_to_native) {
std::pair<std::unique_ptr<byte[]>, size_t> serialized_module =
wasm::NativeModuleSerializer::SerializeWholeModule(isolate_,
compiled_part);
wasm::SerializeNativeModule(isolate_, compiled_part);
WriteVarint<uint32_t>(static_cast<uint32_t>(serialized_module.second));
WriteRawBytes(serialized_module.first.get(), serialized_module.second);
} else {
......@@ -1719,8 +1718,7 @@ MaybeHandle<JSObject> ValueDeserializer::ReadWasmModule() {
Handle<FixedArray> compiled_part;
MaybeHandle<JSObject> result;
if (FLAG_wasm_jit_to_native) {
if (wasm::NativeModuleDeserializer::DeserializeFullBuffer(
isolate_, compiled_bytes, wire_bytes)
if (wasm::DeserializeNativeModule(isolate_, compiled_bytes, wire_bytes)
.ToHandle(&compiled_part)) {
result = WasmModuleObject::New(
isolate_, Handle<WasmCompiledModule>::cast(compiled_part));
......
......@@ -22,7 +22,6 @@
namespace v8 {
namespace internal {
namespace wasm {
namespace {
class Writer {
......@@ -97,31 +96,91 @@ class Reader {
Vector<const byte> buffer_;
};
} // namespace
size_t WasmSerializedFormatVersion::GetVersionSize() { return kVersionSize; }
constexpr size_t kVersionSize = 4 * sizeof(uint32_t);
bool WasmSerializedFormatVersion::WriteVersion(Isolate* isolate,
Vector<byte> buffer) {
if (buffer.size() < GetVersionSize()) return false;
void WriteVersion(Isolate* isolate, Vector<byte> buffer) {
DCHECK_GE(buffer.size(), kVersionSize);
Writer writer(buffer);
writer.Write(SerializedData::ComputeMagicNumber(
ExternalReferenceTable::instance(isolate)));
writer.Write(Version::Hash());
writer.Write(static_cast<uint32_t>(CpuFeatures::SupportedFeatures()));
writer.Write(FlagList::Hash());
return true;
}
bool WasmSerializedFormatVersion::IsSupportedVersion(
Isolate* isolate, const Vector<const byte> buffer) {
bool IsSupportedVersion(Isolate* isolate, const Vector<const byte> buffer) {
if (buffer.size() < kVersionSize) return false;
byte version[kVersionSize];
CHECK(WriteVersion(isolate, {version, kVersionSize}));
WriteVersion(isolate, {version, kVersionSize});
if (memcmp(buffer.start(), version, kVersionSize) == 0) return true;
return false;
}
} // namespace
enum SerializationSection { Init, Metadata, Stubs, CodeSection, Done };
class V8_EXPORT_PRIVATE NativeModuleSerializer {
public:
explicit NativeModuleSerializer(Isolate*, const NativeModule*);
size_t Measure() const;
size_t Write(Vector<byte>);
bool IsDone() const { return state_ == Done; }
private:
size_t MeasureHeader() const;
static size_t GetCodeHeaderSize();
size_t MeasureCode(const WasmCode*) const;
size_t MeasureCopiedStubs() const;
FixedArray* GetHandlerTable(const WasmCode*) const;
ByteArray* GetSourcePositions(const WasmCode*) const;
void BufferHeader();
// we buffer all the stubs because they are small
void BufferCopiedStubs();
void BufferCodeInAllocatedScratch(const WasmCode*);
void BufferCurrentWasmCode();
size_t DrainBuffer(Vector<byte> dest);
uint32_t EncodeBuiltinOrStub(Address);
Isolate* const isolate_ = nullptr;
const NativeModule* const native_module_ = nullptr;
SerializationSection state_ = Init;
uint32_t index_ = 0;
std::vector<byte> scratch_;
Vector<byte> remaining_;
// wasm and copied stubs reverse lookup
std::map<Address, uint32_t> wasm_targets_lookup_;
// immovable builtins and runtime entries lookup
std::map<Address, uint32_t> reference_table_lookup_;
std::map<Address, uint32_t> stub_lookup_;
std::map<Address, uint32_t> builtin_lookup_;
};
class V8_EXPORT_PRIVATE NativeModuleDeserializer {
public:
explicit NativeModuleDeserializer(Isolate*, NativeModule*);
// Currently, we don't support streamed reading, yet albeit the
// API suggests that.
bool Read(Vector<const byte>);
private:
void ExpectHeader();
void Expect(size_t size);
bool ReadHeader();
bool ReadCode();
bool ReadStubs();
Address GetTrampolineOrStubFromTag(uint32_t);
Isolate* const isolate_ = nullptr;
NativeModule* const native_module_ = nullptr;
std::vector<byte> scratch_;
std::vector<Address> stubs_;
Vector<const byte> unread_;
size_t current_expectation_ = 0;
uint32_t index_ = 0;
};
NativeModuleSerializer::NativeModuleSerializer(Isolate* isolate,
const NativeModule* module)
: isolate_(isolate), native_module_(module) {
......@@ -437,18 +496,14 @@ size_t NativeModuleSerializer::Write(Vector<byte> dest) {
}
// static
std::pair<std::unique_ptr<byte[]>, size_t>
NativeModuleSerializer::SerializeWholeModule(
std::pair<std::unique_ptr<byte[]>, size_t> SerializeNativeModule(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
NativeModule* native_module = compiled_module->GetNativeModule();
NativeModuleSerializer serializer(isolate, native_module);
size_t version_size = WasmSerializedFormatVersion::GetVersionSize();
size_t version_size = kVersionSize;
size_t buff_size = serializer.Measure() + version_size;
std::unique_ptr<byte[]> ret(new byte[buff_size]);
if (!WasmSerializedFormatVersion::WriteVersion(isolate,
{ret.get(), buff_size})) {
return {};
}
WriteVersion(isolate, {ret.get(), buff_size});
size_t written =
serializer.Write({ret.get() + version_size, buff_size - version_size});
......@@ -622,15 +677,15 @@ Address NativeModuleDeserializer::GetTrampolineOrStubFromTag(uint32_t tag) {
}
}
MaybeHandle<WasmCompiledModule> NativeModuleDeserializer::DeserializeFullBuffer(
MaybeHandle<WasmCompiledModule> DeserializeNativeModule(
Isolate* isolate, Vector<const byte> data, Vector<const byte> wire_bytes) {
if (!IsWasmCodegenAllowed(isolate, isolate->native_context())) {
return {};
}
if (!WasmSerializedFormatVersion::IsSupportedVersion(isolate, data)) {
if (!IsSupportedVersion(isolate, data)) {
return {};
}
data = data + WasmSerializedFormatVersion::GetVersionSize();
data = data + kVersionSize;
ModuleResult decode_result =
SyncDecodeWasmModule(isolate, wire_bytes.start(), wire_bytes.end(), false,
i::wasm::kWasmOrigin);
......
......@@ -11,82 +11,11 @@ namespace v8 {
namespace internal {
namespace wasm {
class WasmSerializedFormatVersion {
public:
static size_t GetVersionSize();
static bool WriteVersion(Isolate* isolate, Vector<byte>);
static bool IsSupportedVersion(Isolate* isolate, const Vector<const byte>);
std::pair<std::unique_ptr<byte[]>, size_t> SerializeNativeModule(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module);
private:
static constexpr size_t kVersionSize = 4 * sizeof(uint32_t);
};
enum SerializationSection { Init, Metadata, Stubs, CodeSection, Done };
class V8_EXPORT_PRIVATE NativeModuleSerializer {
public:
explicit NativeModuleSerializer(Isolate*, const NativeModule*);
size_t Measure() const;
size_t Write(Vector<byte>);
bool IsDone() const { return state_ == Done; }
static std::pair<std::unique_ptr<byte[]>, size_t> SerializeWholeModule(
Isolate*, Handle<WasmCompiledModule>);
private:
size_t MeasureHeader() const;
static size_t GetCodeHeaderSize();
size_t MeasureCode(const WasmCode*) const;
size_t MeasureCopiedStubs() const;
FixedArray* GetHandlerTable(const WasmCode*) const;
ByteArray* GetSourcePositions(const WasmCode*) const;
void BufferHeader();
// we buffer all the stubs because they are small
void BufferCopiedStubs();
void BufferCodeInAllocatedScratch(const WasmCode*);
void BufferCurrentWasmCode();
size_t DrainBuffer(Vector<byte> dest);
uint32_t EncodeBuiltinOrStub(Address);
Isolate* const isolate_ = nullptr;
const NativeModule* const native_module_ = nullptr;
SerializationSection state_ = Init;
uint32_t index_ = 0;
std::vector<byte> scratch_;
Vector<byte> remaining_;
// wasm and copied stubs reverse lookup
std::map<Address, uint32_t> wasm_targets_lookup_;
// immovable builtins and runtime entries lookup
std::map<Address, uint32_t> reference_table_lookup_;
std::map<Address, uint32_t> stub_lookup_;
std::map<Address, uint32_t> builtin_lookup_;
};
class V8_EXPORT_PRIVATE NativeModuleDeserializer {
public:
explicit NativeModuleDeserializer(Isolate*, NativeModule*);
// Currently, we don't support streamed reading, yet albeit the
// API suggests that.
bool Read(Vector<const byte>);
static MaybeHandle<WasmCompiledModule> DeserializeFullBuffer(
Isolate*, Vector<const byte> data, Vector<const byte> wire_bytes);
private:
void ExpectHeader();
void Expect(size_t size);
bool ReadHeader();
bool ReadCode();
bool ReadStubs();
Address GetTrampolineOrStubFromTag(uint32_t);
Isolate* const isolate_ = nullptr;
NativeModule* const native_module_ = nullptr;
std::vector<byte> scratch_;
std::vector<Address> stubs_;
Vector<const byte> unread_;
size_t current_expectation_ = 0;
uint32_t index_ = 0;
};
MaybeHandle<WasmCompiledModule> DeserializeNativeModule(
Isolate* isolate, Vector<const byte> data, Vector<const byte> wire_bytes);
} // namespace wasm
} // namespace internal
......
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