summaryrefslogtreecommitdiff
path: root/deps/v8/src/wasm/wasm-serialization.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/wasm/wasm-serialization.cc')
-rw-r--r--deps/v8/src/wasm/wasm-serialization.cc183
1 files changed, 125 insertions, 58 deletions
diff --git a/deps/v8/src/wasm/wasm-serialization.cc b/deps/v8/src/wasm/wasm-serialization.cc
index 337692b595..4466672f37 100644
--- a/deps/v8/src/wasm/wasm-serialization.cc
+++ b/deps/v8/src/wasm/wasm-serialization.cc
@@ -9,10 +9,12 @@
#include "src/external-reference-table.h"
#include "src/objects-inl.h"
#include "src/objects.h"
+#include "src/snapshot/code-serializer.h"
#include "src/snapshot/serializer-common.h"
#include "src/version.h"
#include "src/wasm/module-compiler.h"
#include "src/wasm/module-decoder.h"
+#include "src/wasm/wasm-code-manager.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects-inl.h"
#include "src/wasm/wasm-objects.h"
@@ -21,20 +23,7 @@
namespace v8 {
namespace internal {
namespace wasm {
-
namespace {
-void SetRawTargetData(RelocInfo* rinfo, uint32_t value) {
- if (rinfo->target_address_size() == sizeof(uint32_t)) {
- *(reinterpret_cast<uint32_t*>(rinfo->target_address_address())) = value;
- return;
- } else {
- DCHECK_EQ(rinfo->target_address_size(), sizeof(intptr_t));
- DCHECK_EQ(rinfo->target_address_size(), 8);
- *(reinterpret_cast<intptr_t*>(rinfo->target_address_address())) =
- static_cast<intptr_t>(value);
- return;
- }
-}
class Writer {
public:
@@ -108,31 +97,91 @@ class Reader {
Vector<const byte> buffer_;
};
-} // namespace
+constexpr size_t kVersionSize = 4 * sizeof(uint32_t);
-size_t WasmSerializedFormatVersion::GetVersionSize() { return kVersionSize; }
-
-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) {
@@ -164,8 +213,8 @@ size_t NativeModuleSerializer::MeasureHeader() const {
sizeof(
uint32_t) + // imported fcts - i.e. index of first wasm function
sizeof(uint32_t) + // table count
- native_module_->specialization_data_.function_tables.size() *
- 2 // 2 same-sized tables, containing pointers
+ native_module_->specialization_data_.function_tables.size()
+ // function table, containing pointers
* sizeof(GlobalHandleAddress);
}
@@ -182,7 +231,6 @@ void NativeModuleSerializer::BufferHeader() {
e = native_module_->specialization_data_.function_tables.size();
i < e; ++i) {
writer.Write(native_module_->specialization_data_.function_tables[i]);
- writer.Write(native_module_->specialization_data_.signature_tables[i]);
}
}
@@ -279,7 +327,7 @@ void NativeModuleSerializer::BufferCopiedStubs() {
FixedArray* NativeModuleSerializer::GetHandlerTable(
const WasmCode* code) const {
- if (code->kind() != WasmCode::Function) return nullptr;
+ if (code->kind() != WasmCode::kFunction) return nullptr;
uint32_t index = code->index();
// We write the address, the size, and then copy the code as-is, followed
// by reloc info, followed by handler table and source positions.
@@ -294,7 +342,7 @@ FixedArray* NativeModuleSerializer::GetHandlerTable(
ByteArray* NativeModuleSerializer::GetSourcePositions(
const WasmCode* code) const {
- if (code->kind() != WasmCode::Function) return nullptr;
+ if (code->kind() != WasmCode::kFunction) return nullptr;
uint32_t index = code->index();
Object* source_positions_entry =
native_module_->compiled_module()->source_positions()->get(
@@ -372,17 +420,17 @@ void NativeModuleSerializer::BufferCodeInAllocatedScratch(
case RelocInfo::CODE_TARGET: {
Address orig_target = orig_iter.rinfo()->target_address();
uint32_t tag = EncodeBuiltinOrStub(orig_target);
- SetRawTargetData(iter.rinfo(), tag);
+ SetWasmCalleeTag(iter.rinfo(), tag);
} break;
case RelocInfo::WASM_CALL: {
Address orig_target = orig_iter.rinfo()->wasm_call_address();
uint32_t tag = wasm_targets_lookup_[orig_target];
- SetRawTargetData(iter.rinfo(), tag);
+ SetWasmCalleeTag(iter.rinfo(), tag);
} break;
case RelocInfo::RUNTIME_ENTRY: {
Address orig_target = orig_iter.rinfo()->target_address();
uint32_t tag = reference_table_lookup_[orig_target];
- SetRawTargetData(iter.rinfo(), tag);
+ SetWasmCalleeTag(iter.rinfo(), tag);
} break;
default:
UNREACHABLE();
@@ -402,7 +450,7 @@ uint32_t NativeModuleSerializer::EncodeBuiltinOrStub(Address address) {
DCHECK(stub_iter != stub_lookup_.end());
uint32_t id = stub_iter->second;
DCHECK_LT(id, std::numeric_limits<uint16_t>::max());
- tag = id & 0x0000ffff;
+ tag = id & 0x0000FFFF;
}
return tag;
}
@@ -423,15 +471,20 @@ size_t NativeModuleSerializer::Write(Vector<byte> dest) {
dest = dest + DrainBuffer(dest);
if (remaining_.size() == 0) {
index_ = native_module_->num_imported_functions();
- BufferCurrentWasmCode();
- state_ = CodeSection;
+ if (index_ < native_module_->FunctionCount()) {
+ BufferCurrentWasmCode();
+ state_ = CodeSection;
+ } else {
+ state_ = Done;
+ }
}
break;
}
case CodeSection: {
dest = dest + DrainBuffer(dest);
if (remaining_.size() == 0) {
- if (++index_ < native_module_->FunctionCount()) {
+ ++index_; // Move to next code object.
+ if (index_ < native_module_->FunctionCount()) {
BufferCurrentWasmCode();
} else {
state_ = Done;
@@ -448,18 +501,22 @@ size_t NativeModuleSerializer::Write(Vector<byte> dest) {
}
// static
-std::pair<std::unique_ptr<byte[]>, size_t>
-NativeModuleSerializer::SerializeWholeModule(
+std::pair<std::unique_ptr<const byte[]>, size_t> SerializeNativeModule(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
+ if (!FLAG_wasm_jit_to_native) {
+ std::unique_ptr<ScriptData> script_data =
+ WasmCompiledModuleSerializer::SerializeWasmModule(isolate,
+ compiled_module);
+ script_data->ReleaseDataOwnership();
+ size_t size = static_cast<size_t>(script_data->length());
+ return {std::unique_ptr<const byte[]>(script_data->data()), size};
+ }
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});
@@ -500,18 +557,14 @@ bool NativeModuleDeserializer::ReadHeader() {
if (!ok) return false;
size_t table_count = reader.Read<uint32_t>();
- std::vector<GlobalHandleAddress> sigs(table_count);
std::vector<GlobalHandleAddress> funcs(table_count);
for (size_t i = 0; i < table_count; ++i) {
funcs[i] = reader.Read<GlobalHandleAddress>();
- sigs[i] = reader.Read<GlobalHandleAddress>();
}
- native_module_->signature_tables() = sigs;
native_module_->function_tables() = funcs;
// resize, so that from here on the native module can be
// asked about num_function_tables().
native_module_->empty_function_tables().resize(table_count);
- native_module_->empty_signature_tables().resize(table_count);
unread_ = unread_ + (start_size - reader.current_buffer().size());
return true;
@@ -558,7 +611,7 @@ bool NativeModuleDeserializer::ReadCode() {
}
WasmCode* ret = native_module_->AddOwnedCode(
code_buffer, std::move(reloc_info), reloc_size, Just(index_),
- WasmCode::Function, constant_pool_offset, stack_slot_count,
+ WasmCode::kFunction, constant_pool_offset, stack_slot_count,
safepoint_table_offset, protected_instructions, is_liftoff);
if (ret == nullptr) return false;
native_module_->SetCodeTable(index_, ret);
@@ -576,14 +629,15 @@ bool NativeModuleDeserializer::ReadCode() {
// We only expect {undefined}. We check for that when we add code.
iter.rinfo()->set_target_object(isolate_->heap()->undefined_value(),
SKIP_WRITE_BARRIER);
+ break;
}
case RelocInfo::CODE_TARGET: {
- uint32_t tag = *(reinterpret_cast<uint32_t*>(
- iter.rinfo()->target_address_address()));
+ uint32_t tag = GetWasmCalleeTag(iter.rinfo());
Address target = GetTrampolineOrStubFromTag(tag);
iter.rinfo()->set_target_address(nullptr, target, SKIP_WRITE_BARRIER,
SKIP_ICACHE_FLUSH);
- } break;
+ break;
+ }
case RelocInfo::RUNTIME_ENTRY: {
uint32_t orig_target = static_cast<uint32_t>(
reinterpret_cast<intptr_t>(iter.rinfo()->target_address()));
@@ -591,7 +645,8 @@ bool NativeModuleDeserializer::ReadCode() {
ExternalReferenceTable::instance(isolate_)->address(orig_target);
iter.rinfo()->set_target_runtime_entry(
nullptr, address, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
- } break;
+ break;
+ }
default:
break;
}
@@ -624,25 +679,35 @@ bool NativeModuleDeserializer::ReadCode() {
}
Address NativeModuleDeserializer::GetTrampolineOrStubFromTag(uint32_t tag) {
- if ((tag & 0x0000ffff) == 0) {
+ if ((tag & 0x0000FFFF) == 0) {
int builtin_id = static_cast<int>(tag >> 16);
v8::internal::Code* builtin = isolate_->builtins()->builtin(builtin_id);
return native_module_->GetLocalAddressFor(handle(builtin));
} else {
- DCHECK_EQ(tag & 0xffff0000, 0);
+ DCHECK_EQ(tag & 0xFFFF0000, 0);
return stubs_[tag];
}
}
-MaybeHandle<WasmCompiledModule> NativeModuleDeserializer::DeserializeFullBuffer(
+MaybeHandle<WasmCompiledModule> DeserializeNativeModule(
Isolate* isolate, Vector<const byte> data, Vector<const byte> wire_bytes) {
+ if (!FLAG_wasm_jit_to_native) {
+ ScriptData script_data(data.start(), data.length());
+ Handle<FixedArray> compiled_module;
+ if (!WasmCompiledModuleSerializer::DeserializeWasmModule(
+ isolate, &script_data, wire_bytes)
+ .ToHandle(&compiled_module)) {
+ return {};
+ }
+ return Handle<WasmCompiledModule>::cast(compiled_module);
+ }
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);
@@ -669,9 +734,11 @@ MaybeHandle<WasmCompiledModule> NativeModuleDeserializer::DeserializeFullBuffer(
static_cast<int>(export_wrappers_size), TENURED);
Handle<WasmCompiledModule> compiled_module = WasmCompiledModule::New(
- isolate, shared->module(), isolate->factory()->NewFixedArray(0, TENURED),
- export_wrappers, {}, {});
+ isolate, shared->module(), isolate->factory()->empty_fixed_array(),
+ export_wrappers, std::vector<wasm::GlobalHandleAddress>(),
+ trap_handler::IsTrapHandlerEnabled());
compiled_module->OnWasmModuleDecodingComplete(shared);
+ script->set_wasm_compiled_module(*compiled_module);
NativeModuleDeserializer deserializer(isolate,
compiled_module->GetNativeModule());
if (!deserializer.Read(data)) return {};