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.cc197
1 files changed, 102 insertions, 95 deletions
diff --git a/deps/v8/src/wasm/wasm-serialization.cc b/deps/v8/src/wasm/wasm-serialization.cc
index 240ffbca3d..a069823194 100644
--- a/deps/v8/src/wasm/wasm-serialization.cc
+++ b/deps/v8/src/wasm/wasm-serialization.cc
@@ -11,6 +11,7 @@
#include "src/objects.h"
#include "src/snapshot/code-serializer.h"
#include "src/snapshot/serializer-common.h"
+#include "src/utils.h"
#include "src/version.h"
#include "src/wasm/module-compiler.h"
#include "src/wasm/module-decoder.h"
@@ -23,6 +24,7 @@
namespace v8 {
namespace internal {
namespace wasm {
+
namespace {
class Writer {
@@ -35,7 +37,7 @@ class Writer {
os << "wrote: " << (size_t)value << " sized: " << sizeof(T) << std::endl;
}
DCHECK_GE(buffer_.size(), sizeof(T));
- memcpy(buffer_.start(), reinterpret_cast<const byte*>(&value), sizeof(T));
+ WriteUnalignedValue(buffer_.start(), value);
buffer_ = buffer_ + sizeof(T);
}
@@ -63,8 +65,7 @@ class Reader {
template <typename T>
T Read() {
DCHECK_GE(buffer_.size(), sizeof(T));
- T ret;
- memcpy(reinterpret_cast<byte*>(&ret), buffer_.start(), sizeof(T));
+ T ret = ReadUnalignedValue<T>(buffer_.start());
buffer_ = buffer_ + sizeof(T);
if (FLAG_wasm_trace_serialization) {
OFStream os(stdout);
@@ -99,11 +100,14 @@ class Reader {
constexpr size_t kVersionSize = 4 * sizeof(uint32_t);
+// Start from 1 so an encoded stub id is not confused with an encoded builtin.
+constexpr int kFirstStubId = 1;
+
void WriteVersion(Isolate* isolate, Vector<byte> buffer) {
DCHECK_GE(buffer.size(), kVersionSize);
Writer writer(buffer);
writer.Write(SerializedData::ComputeMagicNumber(
- ExternalReferenceTable::instance(isolate)));
+ isolate->heap()->external_reference_table()));
writer.Write(Version::Hash());
writer.Write(static_cast<uint32_t>(CpuFeatures::SupportedFeatures()));
writer.Write(FlagList::Hash());
@@ -117,6 +121,35 @@ bool IsSupportedVersion(Isolate* isolate, const Vector<const byte> buffer) {
return false;
}
+// On Intel, call sites are encoded as a displacement. For linking
+// and for serialization/deserialization, we want to store/retrieve
+// a tag (the function index). On Intel, that means accessing the
+// raw displacement. Everywhere else, that simply means accessing
+// the target address.
+void SetWasmCalleeTag(RelocInfo* rinfo, uint32_t tag) {
+#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
+ *(reinterpret_cast<uint32_t*>(rinfo->target_address_address())) = tag;
+#else
+ Address addr = reinterpret_cast<Address>(tag);
+ if (rinfo->rmode() == RelocInfo::EXTERNAL_REFERENCE) {
+ rinfo->set_target_external_reference(addr, SKIP_ICACHE_FLUSH);
+ } else {
+ rinfo->set_target_address(addr, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
+ }
+#endif
+}
+
+uint32_t GetWasmCalleeTag(RelocInfo* rinfo) {
+#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
+ return *(reinterpret_cast<uint32_t*>(rinfo->target_address_address()));
+#else
+ Address addr = rinfo->rmode() == RelocInfo::EXTERNAL_REFERENCE
+ ? rinfo->target_external_reference()
+ : rinfo->target_address();
+ return static_cast<uint32_t>(reinterpret_cast<size_t>(addr));
+#endif
+}
+
} // namespace
enum SerializationSection { Init, Metadata, Stubs, CodeSection, Done };
@@ -133,7 +166,6 @@ class V8_EXPORT_PRIVATE NativeModuleSerializer {
static size_t GetCodeHeaderSize();
size_t MeasureCode(const WasmCode*) const;
size_t MeasureCopiedStubs() const;
- ByteArray* GetSourcePositions(const WasmCode*) const;
void BufferHeader();
// we buffer all the stubs because they are small
@@ -188,7 +220,7 @@ NativeModuleSerializer::NativeModuleSerializer(Isolate* isolate,
DCHECK_NOT_NULL(native_module_);
// TODO(mtrofin): persist the export wrappers. Ideally, we'd only persist
// the unique ones, i.e. the cache.
- ExternalReferenceTable* table = ExternalReferenceTable::instance(isolate_);
+ 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));
@@ -221,27 +253,23 @@ void NativeModuleSerializer::BufferHeader() {
}
size_t NativeModuleSerializer::GetCodeHeaderSize() {
- return sizeof(size_t) + // size of this section
- sizeof(size_t) + // offset of constant pool
- sizeof(size_t) + // offset of safepoint table
- sizeof(size_t) + // offset of handler table
- sizeof(uint32_t) + // stack slots
- sizeof(size_t) + // code size
- sizeof(size_t) + // reloc size
- sizeof(uint32_t) + // source positions size
- sizeof(size_t) + // protected instructions size
- sizeof(bool); // is_liftoff
+ return sizeof(size_t) + // size of this section
+ sizeof(size_t) + // offset of constant pool
+ sizeof(size_t) + // offset of safepoint table
+ sizeof(size_t) + // offset of handler table
+ sizeof(uint32_t) + // stack slots
+ sizeof(size_t) + // code size
+ sizeof(size_t) + // reloc size
+ sizeof(size_t) + // source positions size
+ sizeof(size_t) + // protected instructions size
+ sizeof(WasmCode::Tier); // tier
}
size_t NativeModuleSerializer::MeasureCode(const WasmCode* code) const {
- ByteArray* source_positions = GetSourcePositions(code);
return GetCodeHeaderSize() + code->instructions().size() + // code
code->reloc_info().size() + // reloc info
- (source_positions == nullptr
- ? 0
- : static_cast<uint32_t>(
- source_positions->length())) + // source positions
- code->protected_instructions().size() *
+ code->source_positions().size() + // source pos.
+ code->protected_instructions().size() * // protected inst.
sizeof(trap_handler::ProtectedInstructionData);
}
@@ -285,7 +313,7 @@ void NativeModuleSerializer::BufferCopiedStubs() {
Writer writer(remaining_);
writer.Write(
static_cast<uint32_t>((buff_size - sizeof(uint32_t)) / sizeof(uint32_t)));
- uint32_t stub_id = 0;
+ uint32_t stub_id = kFirstStubId;
for (auto pair : native_module_->stubs_) {
uint32_t key = pair.first;
@@ -306,19 +334,6 @@ void NativeModuleSerializer::BufferCopiedStubs() {
}
}
-ByteArray* NativeModuleSerializer::GetSourcePositions(
- const WasmCode* code) const {
- if (code->kind() != WasmCode::kFunction) return nullptr;
- uint32_t index = code->index();
- Object* source_positions_entry =
- native_module_->compiled_module()->source_positions()->get(
- static_cast<int>(index));
- if (source_positions_entry->IsByteArray()) {
- return ByteArray::cast(source_positions_entry);
- }
- return nullptr;
-}
-
void NativeModuleSerializer::BufferCurrentWasmCode() {
const WasmCode* code = native_module_->GetCode(index_);
size_t size = MeasureCode(code);
@@ -331,14 +346,6 @@ void NativeModuleSerializer::BufferCodeInAllocatedScratch(
const WasmCode* code) {
// We write the address, the size, and then copy the code as-is, followed
// by reloc info, followed by source positions.
- ByteArray* source_positions_entry = GetSourcePositions(code);
- Address source_positions = nullptr;
- uint32_t source_positions_size = 0;
- if (source_positions_entry != nullptr) {
- source_positions = source_positions_entry->GetDataStartAddress();
- source_positions_size =
- static_cast<uint32_t>(source_positions_entry->length());
- }
Writer writer(remaining_);
// write the header
writer.Write(MeasureCode(code));
@@ -348,15 +355,15 @@ void NativeModuleSerializer::BufferCodeInAllocatedScratch(
writer.Write(code->stack_slots());
writer.Write(code->instructions().size());
writer.Write(code->reloc_info().size());
- writer.Write(source_positions_size);
+ writer.Write(code->source_positions().size());
writer.Write(code->protected_instructions().size());
- writer.Write(code->is_liftoff());
+ writer.Write(code->tier());
// next is the code, which we have to reloc.
Address serialized_code_start = writer.current_buffer().start();
// write the code and everything else
writer.WriteVector(code->instructions());
writer.WriteVector(code->reloc_info());
- writer.WriteVector({source_positions, source_positions_size});
+ writer.WriteVector(code->source_positions());
writer.WriteVector(
{reinterpret_cast<const byte*>(code->protected_instructions().data()),
sizeof(trap_handler::ProtectedInstructionData) *
@@ -364,7 +371,8 @@ void NativeModuleSerializer::BufferCodeInAllocatedScratch(
// now relocate the code
int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
RelocInfo::ModeMask(RelocInfo::WASM_CALL) |
- RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
+ RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
+ RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE);
RelocIterator orig_iter(code->instructions(), code->reloc_info(),
code->constant_pool(), mask);
for (RelocIterator
@@ -386,7 +394,16 @@ void NativeModuleSerializer::BufferCodeInAllocatedScratch(
} break;
case RelocInfo::RUNTIME_ENTRY: {
Address orig_target = orig_iter.rinfo()->target_address();
- uint32_t tag = reference_table_lookup_[orig_target];
+ 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);
+ } 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);
} break;
default:
@@ -460,14 +477,6 @@ size_t NativeModuleSerializer::Write(Vector<byte> dest) {
// static
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 = kVersionSize;
@@ -500,7 +509,6 @@ bool NativeModuleDeserializer::Read(Vector<const byte> data) {
for (; index_ < native_module_->FunctionCount(); ++index_) {
if (!ReadCode()) return false;
}
- native_module_->LinkAll();
return data.size() - unread_.size();
}
@@ -543,9 +551,10 @@ bool NativeModuleDeserializer::ReadCode() {
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>();
- uint32_t source_position_size = reader.Read<uint32_t>();
+ size_t source_position_size = reader.Read<size_t>();
size_t protected_instructions_size = reader.Read<size_t>();
- bool is_liftoff = reader.Read<bool>();
+ WasmCode::Tier tier = reader.Read<WasmCode::Tier>();
+
std::shared_ptr<ProtectedInstructions> protected_instructions(
new ProtectedInstructions(protected_instructions_size));
DCHECK_EQ(protected_instructions_size, protected_instructions->size());
@@ -556,18 +565,24 @@ bool NativeModuleDeserializer::ReadCode() {
reloc_info.reset(new byte[reloc_size]);
reader.ReadIntoVector({reloc_info.get(), reloc_size});
}
+ std::unique_ptr<byte[]> source_pos;
+ if (source_position_size > 0) {
+ source_pos.reset(new byte[source_position_size]);
+ reader.ReadIntoVector({source_pos.get(), source_position_size});
+ }
WasmCode* ret = native_module_->AddOwnedCode(
- code_buffer, std::move(reloc_info), reloc_size, Just(index_),
- WasmCode::kFunction, constant_pool_offset, stack_slot_count,
- safepoint_table_offset, handler_table_offset, protected_instructions,
- is_liftoff);
- if (ret == nullptr) return false;
+ code_buffer, std::move(reloc_info), reloc_size, std::move(source_pos),
+ source_position_size, Just(index_), WasmCode::kFunction,
+ constant_pool_offset, stack_slot_count, safepoint_table_offset,
+ handler_table_offset, protected_instructions, tier,
+ WasmCode::kNoFlushICache);
native_module_->code_table_[index_] = ret;
// now relocate the code
int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
- RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
+ RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
+ RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE);
for (RelocIterator iter(ret->instructions(), ret->reloc_info(),
ret->constant_pool(), mask);
!iter.done(); iter.next()) {
@@ -576,7 +591,7 @@ bool NativeModuleDeserializer::ReadCode() {
case RelocInfo::EMBEDDED_OBJECT: {
// We only expect {undefined}. We check for that when we add code.
iter.rinfo()->set_target_object(isolate_->heap()->undefined_value(),
- SKIP_WRITE_BARRIER);
+ SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
break;
}
case RelocInfo::CODE_TARGET: {
@@ -587,26 +602,29 @@ bool NativeModuleDeserializer::ReadCode() {
break;
}
case RelocInfo::RUNTIME_ENTRY: {
- uint32_t orig_target = static_cast<uint32_t>(
- reinterpret_cast<intptr_t>(iter.rinfo()->target_address()));
+ uint32_t tag = GetWasmCalleeTag(iter.rinfo());
Address address =
- ExternalReferenceTable::instance(isolate_)->address(orig_target);
+ isolate_->heap()->external_reference_table()->address(tag);
iter.rinfo()->set_target_runtime_entry(address, SKIP_WRITE_BARRIER,
SKIP_ICACHE_FLUSH);
break;
}
- default:
+ case RelocInfo::EXTERNAL_REFERENCE: {
+ uint32_t tag = GetWasmCalleeTag(iter.rinfo());
+ Address address =
+ isolate_->heap()->external_reference_table()->address(tag);
+ iter.rinfo()->set_target_external_reference(address, SKIP_ICACHE_FLUSH);
break;
+ }
+ default:
+ UNREACHABLE();
}
}
- if (source_position_size > 0) {
- Handle<ByteArray> source_positions = isolate_->factory()->NewByteArray(
- static_cast<int>(source_position_size), TENURED);
- reader.ReadIntoVector(
- {source_positions->GetDataStartAddress(), source_position_size});
- native_module_->compiled_module()->source_positions()->set(
- static_cast<int>(index_), *source_positions);
- }
+ // Flush the i-cache here instead of in AddOwnedCode, to include the changes
+ // made while iterating over the RelocInfo above.
+ Assembler::FlushICache(ret->instructions().start(),
+ ret->instructions().size());
+
if (protected_instructions_size > 0) {
reader.ReadIntoVector(
{reinterpret_cast<byte*>(protected_instructions->data()),
@@ -624,22 +642,12 @@ Address NativeModuleDeserializer::GetTrampolineOrStubFromTag(uint32_t tag) {
return native_module_->GetLocalAddressFor(handle(builtin));
} else {
DCHECK_EQ(tag & 0xFFFF0000, 0);
- return stubs_[tag];
+ return stubs_[tag - kFirstStubId];
}
}
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 {};
}
@@ -672,11 +680,10 @@ MaybeHandle<WasmCompiledModule> DeserializeNativeModule(
Handle<FixedArray> export_wrappers = isolate->factory()->NewFixedArray(
static_cast<int>(export_wrappers_size), TENURED);
- Handle<WasmCompiledModule> compiled_module = WasmCompiledModule::New(
- isolate, shared->module(), isolate->factory()->empty_fixed_array(),
- export_wrappers, std::vector<wasm::GlobalHandleAddress>(),
- trap_handler::IsTrapHandlerEnabled());
- compiled_module->OnWasmModuleDecodingComplete(shared);
+ Handle<WasmCompiledModule> compiled_module =
+ WasmCompiledModule::New(isolate, shared->module(), export_wrappers,
+ trap_handler::IsTrapHandlerEnabled());
+ compiled_module->set_shared(*shared);
script->set_wasm_compiled_module(*compiled_module);
NativeModuleDeserializer deserializer(isolate,
compiled_module->GetNativeModule());