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.cc174
1 files changed, 105 insertions, 69 deletions
diff --git a/deps/v8/src/wasm/wasm-serialization.cc b/deps/v8/src/wasm/wasm-serialization.cc
index b676a5b61b..a167b81cbd 100644
--- a/deps/v8/src/wasm/wasm-serialization.cc
+++ b/deps/v8/src/wasm/wasm-serialization.cc
@@ -8,6 +8,7 @@
#include "src/external-reference-table.h"
#include "src/objects-inl.h"
#include "src/objects.h"
+#include "src/ostreams.h"
#include "src/snapshot/code-serializer.h"
#include "src/snapshot/serializer-common.h"
#include "src/utils.h"
@@ -119,9 +120,8 @@ class Reader {
constexpr size_t kVersionSize = 4 * sizeof(uint32_t);
-void WriteVersion(Isolate* isolate, Writer* writer) {
- writer->Write(SerializedData::ComputeMagicNumber(
- isolate->heap()->external_reference_table()));
+void WriteVersion(Writer* writer) {
+ writer->Write(SerializedData::kMagicNumber);
writer->Write(Version::Hash());
writer->Write(static_cast<uint32_t>(CpuFeatures::SupportedFeatures()));
writer->Write(FlagList::Hash());
@@ -134,6 +134,7 @@ void WriteVersion(Isolate* isolate, Writer* writer) {
// Other platforms simply require accessing the target address.
void SetWasmCalleeTag(RelocInfo* rinfo, uint32_t tag) {
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
+ DCHECK(rinfo->HasTargetAddressAddress());
*(reinterpret_cast<uint32_t*>(rinfo->target_address_address())) = tag;
#elif V8_TARGET_ARCH_ARM64
Instruction* instr = reinterpret_cast<Instruction*>(rinfo->pc());
@@ -191,6 +192,8 @@ constexpr size_t kCodeHeaderSize =
sizeof(size_t) + // offset of constant pool
sizeof(size_t) + // offset of safepoint table
sizeof(size_t) + // offset of handler table
+ sizeof(size_t) + // offset of code comments
+ sizeof(size_t) + // unpadded binary size
sizeof(uint32_t) + // stack slots
sizeof(size_t) + // code size
sizeof(size_t) + // reloc size
@@ -198,13 +201,68 @@ constexpr size_t kCodeHeaderSize =
sizeof(size_t) + // protected instructions size
sizeof(WasmCode::Tier); // tier
+// A List of all isolate-independent external references. This is used to create
+// a tag from the Address of an external reference and vice versa.
+class ExternalReferenceList {
+ public:
+ uint32_t tag_from_address(Address ext_ref_address) const {
+ auto tag_addr_less_than = [this](uint32_t tag, Address searched_addr) {
+ return external_reference_by_tag_[tag] < searched_addr;
+ };
+ auto it = std::lower_bound(std::begin(tags_ordered_by_address_),
+ std::end(tags_ordered_by_address_),
+ ext_ref_address, tag_addr_less_than);
+ DCHECK_NE(std::end(tags_ordered_by_address_), it);
+ uint32_t tag = *it;
+ DCHECK_EQ(address_from_tag(tag), ext_ref_address);
+ return tag;
+ }
+
+ Address address_from_tag(uint32_t tag) const {
+ DCHECK_GT(kNumExternalReferences, tag);
+ return external_reference_by_tag_[tag];
+ }
+
+ static const ExternalReferenceList& Get() {
+ static ExternalReferenceList list; // Lazily initialized.
+ return list;
+ }
+
+ private:
+ // Private constructor. There will only be a single instance of this object.
+ ExternalReferenceList() {
+ for (uint32_t i = 0; i < kNumExternalReferences; ++i) {
+ tags_ordered_by_address_[i] = i;
+ }
+ auto addr_by_tag_less_than = [this](uint32_t a, uint32_t b) {
+ return external_reference_by_tag_[a] < external_reference_by_tag_[b];
+ };
+ std::sort(std::begin(tags_ordered_by_address_),
+ std::end(tags_ordered_by_address_), addr_by_tag_less_than);
+ }
+
+#define COUNT_EXTERNAL_REFERENCE(name, desc) +1
+ static constexpr uint32_t kNumExternalReferences =
+ EXTERNAL_REFERENCE_LIST(COUNT_EXTERNAL_REFERENCE);
+#undef COUNT_EXTERNAL_REFERENCE
+
+#define EXT_REF_ADDR(name, desc) ExternalReference::name().address(),
+ Address external_reference_by_tag_[kNumExternalReferences] = {
+ EXTERNAL_REFERENCE_LIST(EXT_REF_ADDR)};
+#undef EXT_REF_ADDR
+ uint32_t tags_ordered_by_address_[kNumExternalReferences];
+ DISALLOW_COPY_AND_ASSIGN(ExternalReferenceList);
+};
+
+static_assert(std::is_trivially_destructible<ExternalReferenceList>::value,
+ "static destructors not allowed");
+
} // namespace
class V8_EXPORT_PRIVATE NativeModuleSerializer {
public:
NativeModuleSerializer() = delete;
- NativeModuleSerializer(Isolate*, const NativeModule*,
- Vector<WasmCode* const>);
+ NativeModuleSerializer(const NativeModule*, Vector<WasmCode* const>);
size_t Measure() const;
bool Write(Writer* writer);
@@ -214,26 +272,19 @@ class V8_EXPORT_PRIVATE NativeModuleSerializer {
void WriteHeader(Writer* writer);
void WriteCode(const WasmCode*, Writer* writer);
- Isolate* const isolate_;
const NativeModule* const native_module_;
Vector<WasmCode* const> code_table_;
bool write_called_;
// Reverse lookup tables for embedded addresses.
std::map<Address, uint32_t> wasm_stub_targets_lookup_;
- std::map<Address, uint32_t> reference_table_lookup_;
DISALLOW_COPY_AND_ASSIGN(NativeModuleSerializer);
};
NativeModuleSerializer::NativeModuleSerializer(
- Isolate* isolate, const NativeModule* module,
- Vector<WasmCode* const> code_table)
- : isolate_(isolate),
- native_module_(module),
- code_table_(code_table),
- write_called_(false) {
- DCHECK_NOT_NULL(isolate_);
+ const NativeModule* module, Vector<WasmCode* const> code_table)
+ : native_module_(module), code_table_(code_table), write_called_(false) {
DCHECK_NOT_NULL(native_module_);
// TODO(mtrofin): persist the export wrappers. Ideally, we'd only persist
// the unique ones, i.e. the cache.
@@ -243,11 +294,6 @@ NativeModuleSerializer::NativeModuleSerializer(
->instruction_start();
wasm_stub_targets_lookup_.insert(std::make_pair(addr, i));
}
- ExternalReferenceTable* table = isolate_->heap()->external_reference_table();
- for (uint32_t i = 0; i < table->size(); ++i) {
- Address addr = table->address(i);
- reference_table_lookup_.insert(std::make_pair(addr, i));
- }
}
size_t NativeModuleSerializer::MeasureCode(const WasmCode* code) const {
@@ -268,6 +314,9 @@ size_t NativeModuleSerializer::Measure() const {
}
void NativeModuleSerializer::WriteHeader(Writer* writer) {
+ // TODO(eholk): We need to properly preserve the flag whether the trap
+ // handler was used or not when serializing.
+
writer->Write(native_module_->num_functions());
writer->Write(native_module_->num_imported_functions());
}
@@ -283,6 +332,8 @@ void NativeModuleSerializer::WriteCode(const WasmCode* code, Writer* writer) {
writer->Write(code->constant_pool_offset());
writer->Write(code->safepoint_table_offset());
writer->Write(code->handler_table_offset());
+ writer->Write(code->code_comments_offset());
+ writer->Write(code->unpadded_binary_size());
writer->Write(code->stack_slots());
writer->Write(code->instructions().size());
writer->Write(code->reloc_info().size());
@@ -340,10 +391,9 @@ void NativeModuleSerializer::WriteCode(const WasmCode* code, Writer* writer) {
} break;
case RelocInfo::EXTERNAL_REFERENCE: {
Address orig_target = orig_iter.rinfo()->target_external_reference();
- auto ref_iter = reference_table_lookup_.find(orig_target);
- DCHECK(ref_iter != reference_table_lookup_.end());
- uint32_t tag = ref_iter->second;
- SetWasmCalleeTag(iter.rinfo(), tag);
+ uint32_t ext_ref_tag =
+ ExternalReferenceList::Get().tag_from_address(orig_target);
+ SetWasmCalleeTag(iter.rinfo(), ext_ref_tag);
} break;
case RelocInfo::INTERNAL_REFERENCE:
case RelocInfo::INTERNAL_REFERENCE_ENCODED: {
@@ -374,25 +424,22 @@ bool NativeModuleSerializer::Write(Writer* writer) {
return true;
}
-WasmSerializer::WasmSerializer(Isolate* isolate, NativeModule* native_module)
- : isolate_(isolate),
- native_module_(native_module),
+WasmSerializer::WasmSerializer(NativeModule* native_module)
+ : native_module_(native_module),
code_table_(native_module->SnapshotCodeTable()) {}
size_t WasmSerializer::GetSerializedNativeModuleSize() const {
- Vector<WasmCode* const> code_table(code_table_.data(), code_table_.size());
- NativeModuleSerializer serializer(isolate_, native_module_, code_table);
+ NativeModuleSerializer serializer(native_module_, VectorOf(code_table_));
return kVersionSize + serializer.Measure();
}
bool WasmSerializer::SerializeNativeModule(Vector<byte> buffer) const {
- Vector<WasmCode* const> code_table(code_table_.data(), code_table_.size());
- NativeModuleSerializer serializer(isolate_, native_module_, code_table);
+ NativeModuleSerializer serializer(native_module_, VectorOf(code_table_));
size_t measured_size = kVersionSize + serializer.Measure();
if (buffer.size() < measured_size) return false;
Writer writer(buffer);
- WriteVersion(isolate_, &writer);
+ WriteVersion(&writer);
if (!serializer.Write(&writer)) return false;
DCHECK_EQ(measured_size, writer.bytes_written());
@@ -402,7 +449,7 @@ bool WasmSerializer::SerializeNativeModule(Vector<byte> buffer) const {
class V8_EXPORT_PRIVATE NativeModuleDeserializer {
public:
NativeModuleDeserializer() = delete;
- NativeModuleDeserializer(Isolate*, NativeModule*);
+ explicit NativeModuleDeserializer(NativeModule*);
bool Read(Reader* reader);
@@ -410,16 +457,14 @@ class V8_EXPORT_PRIVATE NativeModuleDeserializer {
bool ReadHeader(Reader* reader);
bool ReadCode(uint32_t fn_index, Reader* reader);
- Isolate* const isolate_;
NativeModule* const native_module_;
bool read_called_;
DISALLOW_COPY_AND_ASSIGN(NativeModuleDeserializer);
};
-NativeModuleDeserializer::NativeModuleDeserializer(Isolate* isolate,
- NativeModule* native_module)
- : isolate_(isolate), native_module_(native_module), read_called_(false) {}
+NativeModuleDeserializer::NativeModuleDeserializer(NativeModule* native_module)
+ : native_module_(native_module), read_called_(false) {}
bool NativeModuleDeserializer::Read(Reader* reader) {
DCHECK(!read_called_);
@@ -447,6 +492,8 @@ bool NativeModuleDeserializer::ReadCode(uint32_t fn_index, Reader* reader) {
size_t constant_pool_offset = reader->Read<size_t>();
size_t safepoint_table_offset = reader->Read<size_t>();
size_t handler_table_offset = reader->Read<size_t>();
+ size_t code_comment_offset = reader->Read<size_t>();
+ size_t unpadded_binary_size = reader->Read<size_t>();
uint32_t stack_slot_count = reader->Read<uint32_t>();
size_t code_size = reader->Read<size_t>();
size_t reloc_size = reader->Read<size_t>();
@@ -468,9 +515,9 @@ bool NativeModuleDeserializer::ReadCode(uint32_t fn_index, Reader* reader) {
WasmCode* code = native_module_->AddDeserializedCode(
fn_index, code_buffer, stack_slot_count, safepoint_table_offset,
- handler_table_offset, constant_pool_offset,
- std::move(protected_instructions), std::move(reloc_info),
- std::move(source_pos), tier);
+ handler_table_offset, constant_pool_offset, code_comment_offset,
+ unpadded_binary_size, std::move(protected_instructions),
+ std::move(reloc_info), std::move(source_pos), tier);
// Relocate the code.
int mask = RelocInfo::ModeMask(RelocInfo::WASM_CALL) |
@@ -501,8 +548,7 @@ bool NativeModuleDeserializer::ReadCode(uint32_t fn_index, Reader* reader) {
}
case RelocInfo::EXTERNAL_REFERENCE: {
uint32_t tag = GetWasmCalleeTag(iter.rinfo());
- Address address =
- isolate_->heap()->external_reference_table()->address(tag);
+ Address address = ExternalReferenceList::Get().address_from_tag(tag);
iter.rinfo()->set_target_external_reference(address, SKIP_ICACHE_FLUSH);
break;
}
@@ -519,7 +565,7 @@ bool NativeModuleDeserializer::ReadCode(uint32_t fn_index, Reader* reader) {
}
}
- if (FLAG_print_code || FLAG_print_wasm_code) code->Print();
+ code->MaybePrint();
code->Validate();
// Finally, flush the icache for that code.
@@ -529,60 +575,50 @@ bool NativeModuleDeserializer::ReadCode(uint32_t fn_index, Reader* reader) {
return true;
}
-bool IsSupportedVersion(Isolate* isolate, Vector<const byte> version) {
+bool IsSupportedVersion(Vector<const byte> version) {
if (version.size() < kVersionSize) return false;
byte current_version[kVersionSize];
Writer writer({current_version, kVersionSize});
- WriteVersion(isolate, &writer);
+ WriteVersion(&writer);
return memcmp(version.start(), current_version, kVersionSize) == 0;
}
MaybeHandle<WasmModuleObject> DeserializeNativeModule(
- Isolate* isolate, Vector<const byte> data, Vector<const byte> wire_bytes) {
- if (!IsWasmCodegenAllowed(isolate, isolate->native_context())) {
- return {};
- }
- if (!IsSupportedVersion(isolate, data)) {
- return {};
- }
+ Isolate* isolate, Vector<const byte> data,
+ Vector<const byte> wire_bytes_vec) {
+ if (!IsWasmCodegenAllowed(isolate, isolate->native_context())) return {};
+ if (!IsSupportedVersion(data)) return {};
+
+ ModuleWireBytes wire_bytes(wire_bytes_vec);
// TODO(titzer): module features should be part of the serialization format.
WasmFeatures enabled_features = WasmFeaturesFromIsolate(isolate);
ModuleResult decode_result = DecodeWasmModule(
enabled_features, wire_bytes.start(), wire_bytes.end(), false,
i::wasm::kWasmOrigin, isolate->counters(), isolate->allocator());
- if (!decode_result.ok()) return {};
- CHECK_NOT_NULL(decode_result.val);
- WasmModule* module = decode_result.val.get();
+ if (decode_result.failed()) return {};
+ CHECK_NOT_NULL(decode_result.value());
+ WasmModule* module = decode_result.value().get();
Handle<Script> script =
CreateWasmScript(isolate, wire_bytes, module->source_map_url);
- // TODO(eholk): We need to properly preserve the flag whether the trap
- // handler was used or not when serializing.
- UseTrapHandler use_trap_handler =
- trap_handler::IsTrapHandlerEnabled() ? kUseTrapHandler : kNoTrapHandler;
- ModuleEnv env(module, use_trap_handler,
- RuntimeExceptionSupport::kRuntimeExceptionSupport);
-
- OwnedVector<uint8_t> wire_bytes_copy = OwnedVector<uint8_t>::Of(wire_bytes);
+ OwnedVector<uint8_t> wire_bytes_copy =
+ OwnedVector<uint8_t>::Of(wire_bytes_vec);
Handle<WasmModuleObject> module_object = WasmModuleObject::New(
- isolate, enabled_features, std::move(decode_result.val), env,
+ isolate, enabled_features, std::move(decode_result).value(),
std::move(wire_bytes_copy), script, Handle<ByteArray>::null());
NativeModule* native_module = module_object->native_module();
if (FLAG_wasm_lazy_compilation) {
native_module->SetLazyBuiltin(BUILTIN_CODE(isolate, WasmCompileLazy));
}
- NativeModuleDeserializer deserializer(isolate, native_module);
+ NativeModuleDeserializer deserializer(native_module);
Reader reader(data + kVersionSize);
if (!deserializer.Read(&reader)) return {};
- // TODO(6792): Wrappers below might be cloned using {Factory::CopyCode}. This
- // requires unlocking the code space here. This should eventually be moved
- // into the allocator.
- CodeSpaceMemoryModificationScope modification_scope(isolate->heap());
- CompileJsToWasmWrappers(isolate, module_object);
+ CompileJsToWasmWrappers(isolate, native_module->module(),
+ handle(module_object->export_wrappers(), isolate));
// Log the code within the generated module for profiling.
native_module->LogWasmCodes(isolate);