Commit 79398ab0 authored by Clemens Backes's avatar Clemens Backes Committed by Commit Bot

[wasm] Further reduce the size of WasmCode

Also, save dynamic allocations (plus their memory overhead).
This is realized by storing the relocation information, source position
table, and protected instruction information together in one "metadata"
byte array.
For each of the three components, we just store their size, such that
the accessors can return the respecitive {Vector} views as before.

This makes each WasmCode object 24 bytes smaller on 64-bit
architectures. It also saves a few more bytes per code object because
less padding is needed for the individual allocations, and each dynamic
allocation comes with some constant memory overhead.

Since the protected instructions will just be stored in a byte array
now, some APIs are refactored to just return that byte array directly
(instead of an array of {ProtectedInstructionData}). This also
simplifies serialization and deserialization, and will allow for
switching to a more compact representation in the future.

Drive-by: Add some more checks to {Vector::cast} to protect against
  undefined behaviour.

R=ahaas@chromium.org

Bug: v8:10254
Change-Id: I81ca847023841110e3e52cc402fcb0349325d7af
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2078545Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66596}
parent cbbdb4df
...@@ -432,10 +432,9 @@ OwnedVector<byte> CodeGenerator::GetSourcePositionTable() { ...@@ -432,10 +432,9 @@ OwnedVector<byte> CodeGenerator::GetSourcePositionTable() {
return source_position_table_builder_.ToSourcePositionTableVector(); return source_position_table_builder_.ToSourcePositionTableVector();
} }
OwnedVector<trap_handler::ProtectedInstructionData> OwnedVector<byte> CodeGenerator::GetProtectedInstructionsData() {
CodeGenerator::GetProtectedInstructions() { return OwnedVector<byte>::Of(
return OwnedVector<trap_handler::ProtectedInstructionData>::Of( Vector<byte>::cast(VectorOf(protected_instructions_)));
protected_instructions_);
} }
MaybeHandle<Code> CodeGenerator::FinalizeCode() { MaybeHandle<Code> CodeGenerator::FinalizeCode() {
......
...@@ -125,8 +125,7 @@ class V8_EXPORT_PRIVATE CodeGenerator final : public GapResolver::Assembler { ...@@ -125,8 +125,7 @@ class V8_EXPORT_PRIVATE CodeGenerator final : public GapResolver::Assembler {
MaybeHandle<Code> FinalizeCode(); MaybeHandle<Code> FinalizeCode();
OwnedVector<byte> GetSourcePositionTable(); OwnedVector<byte> GetSourcePositionTable();
OwnedVector<trap_handler::ProtectedInstructionData> OwnedVector<byte> GetProtectedInstructionsData();
GetProtectedInstructions();
InstructionSequence* instructions() const { return instructions_; } InstructionSequence* instructions() const { return instructions_; }
FrameAccessState* frame_access_state() const { return frame_access_state_; } FrameAccessState* frame_access_state() const { return frame_access_state_; }
......
...@@ -2765,7 +2765,8 @@ wasm::WasmCompilationResult Pipeline::GenerateCodeForWasmNativeStub( ...@@ -2765,7 +2765,8 @@ wasm::WasmCompilationResult Pipeline::GenerateCodeForWasmNativeStub(
static_cast<int>(code_generator->GetHandlerTableOffset())); static_cast<int>(code_generator->GetHandlerTableOffset()));
result.instr_buffer = instruction_buffer->ReleaseBuffer(); result.instr_buffer = instruction_buffer->ReleaseBuffer();
result.source_positions = code_generator->GetSourcePositionTable(); result.source_positions = code_generator->GetSourcePositionTable();
result.protected_instructions = code_generator->GetProtectedInstructions(); result.protected_instructions_data =
code_generator->GetProtectedInstructionsData();
result.frame_slot_count = code_generator->frame()->GetTotalFrameSlotCount(); result.frame_slot_count = code_generator->frame()->GetTotalFrameSlotCount();
result.tagged_parameter_slots = call_descriptor->GetTaggedParameterSlots(); result.tagged_parameter_slots = call_descriptor->GetTaggedParameterSlots();
result.result_tier = wasm::ExecutionTier::kTurbofan; result.result_tier = wasm::ExecutionTier::kTurbofan;
...@@ -2972,7 +2973,8 @@ void Pipeline::GenerateCodeForWasmFunction( ...@@ -2972,7 +2973,8 @@ void Pipeline::GenerateCodeForWasmFunction(
result->frame_slot_count = code_generator->frame()->GetTotalFrameSlotCount(); result->frame_slot_count = code_generator->frame()->GetTotalFrameSlotCount();
result->tagged_parameter_slots = call_descriptor->GetTaggedParameterSlots(); result->tagged_parameter_slots = call_descriptor->GetTaggedParameterSlots();
result->source_positions = code_generator->GetSourcePositionTable(); result->source_positions = code_generator->GetSourcePositionTable();
result->protected_instructions = code_generator->GetProtectedInstructions(); result->protected_instructions_data =
code_generator->GetProtectedInstructionsData();
result->result_tier = wasm::ExecutionTier::kTurbofan; result->result_tier = wasm::ExecutionTier::kTurbofan;
if (data.info()->trace_turbo_json_enabled()) { if (data.info()->trace_turbo_json_enabled()) {
......
...@@ -6666,8 +6666,9 @@ wasm::WasmCode* CompileWasmCapiCallWrapper(wasm::WasmEngine* wasm_engine, ...@@ -6666,8 +6666,9 @@ wasm::WasmCode* CompileWasmCapiCallWrapper(wasm::WasmEngine* wasm_engine,
WasmStubAssemblerOptions(), source_positions); WasmStubAssemblerOptions(), source_positions);
std::unique_ptr<wasm::WasmCode> wasm_code = native_module->AddCode( std::unique_ptr<wasm::WasmCode> wasm_code = native_module->AddCode(
wasm::kAnonymousFuncIndex, result.code_desc, result.frame_slot_count, wasm::kAnonymousFuncIndex, result.code_desc, result.frame_slot_count,
result.tagged_parameter_slots, std::move(result.protected_instructions), result.tagged_parameter_slots,
std::move(result.source_positions), wasm::WasmCode::kWasmToCapiWrapper, result.protected_instructions_data.as_vector(),
result.source_positions.as_vector(), wasm::WasmCode::kWasmToCapiWrapper,
wasm::ExecutionTier::kNone); wasm::ExecutionTier::kNone);
return native_module->PublishCode(std::move(wasm_code)); return native_module->PublishCode(std::move(wasm_code));
} }
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <cstring> #include <cstring>
#include <iterator> #include <iterator>
#include <memory> #include <memory>
#include <type_traits>
#include "src/common/checks.h" #include "src/common/checks.h"
#include "src/common/globals.h" #include "src/common/globals.h"
...@@ -116,6 +117,14 @@ class Vector { ...@@ -116,6 +117,14 @@ class Vector {
template <typename S> template <typename S>
static constexpr Vector<T> cast(Vector<S> input) { static constexpr Vector<T> cast(Vector<S> input) {
// Casting is potentially dangerous, so be really restrictive here. This
// might be lifted once we have use cases for that.
STATIC_ASSERT(std::is_pod<S>::value);
STATIC_ASSERT(std::is_pod<T>::value);
#if V8_HAS_CXX14_CONSTEXPR
DCHECK_EQ(0, (input.length() * sizeof(S)) % sizeof(T));
DCHECK_EQ(0, reinterpret_cast<uintptr_t>(input.begin()) % alignof(T));
#endif
return Vector<T>(reinterpret_cast<T*>(input.begin()), return Vector<T>(reinterpret_cast<T*>(input.begin()),
input.length() * sizeof(S) / sizeof(T)); input.length() * sizeof(S) / sizeof(T));
} }
......
...@@ -321,10 +321,9 @@ class LiftoffCompiler { ...@@ -321,10 +321,9 @@ class LiftoffCompiler {
return source_position_table_builder_.ToSourcePositionTableVector(); return source_position_table_builder_.ToSourcePositionTableVector();
} }
OwnedVector<trap_handler::ProtectedInstructionData> GetProtectedInstructions() OwnedVector<uint8_t> GetProtectedInstructionsData() const {
const { return OwnedVector<uint8_t>::Of(
return OwnedVector<trap_handler::ProtectedInstructionData>::Of( Vector<const uint8_t>::cast(VectorOf(protected_instructions_)));
protected_instructions_);
} }
uint32_t GetTotalFrameSlotCount() const { uint32_t GetTotalFrameSlotCount() const {
...@@ -2796,7 +2795,7 @@ WasmCompilationResult ExecuteLiftoffCompilation( ...@@ -2796,7 +2795,7 @@ WasmCompilationResult ExecuteLiftoffCompilation(
compiler->GetCode(&result.code_desc); compiler->GetCode(&result.code_desc);
result.instr_buffer = instruction_buffer->ReleaseBuffer(); result.instr_buffer = instruction_buffer->ReleaseBuffer();
result.source_positions = compiler->GetSourcePositionTable(); result.source_positions = compiler->GetSourcePositionTable();
result.protected_instructions = compiler->GetProtectedInstructions(); result.protected_instructions_data = compiler->GetProtectedInstructionsData();
result.frame_slot_count = compiler->GetTotalFrameSlotCount(); result.frame_slot_count = compiler->GetTotalFrameSlotCount();
result.tagged_parameter_slots = call_descriptor->GetTaggedParameterSlots(); result.tagged_parameter_slots = call_descriptor->GetTaggedParameterSlots();
result.func_index = func_index; result.func_index = func_index;
......
...@@ -67,7 +67,7 @@ struct WasmCompilationResult { ...@@ -67,7 +67,7 @@ struct WasmCompilationResult {
uint32_t frame_slot_count = 0; uint32_t frame_slot_count = 0;
uint32_t tagged_parameter_slots = 0; uint32_t tagged_parameter_slots = 0;
OwnedVector<byte> source_positions; OwnedVector<byte> source_positions;
OwnedVector<trap_handler::ProtectedInstructionData> protected_instructions; OwnedVector<byte> protected_instructions_data;
int func_index = kAnonymousFuncIndex; int func_index = kAnonymousFuncIndex;
ExecutionTier requested_tier; ExecutionTier requested_tier;
ExecutionTier result_tier; ExecutionTier result_tier;
......
...@@ -2972,8 +2972,9 @@ WasmCode* CompileImportWrapper( ...@@ -2972,8 +2972,9 @@ WasmCode* CompileImportWrapper(
wasm_engine, &env, kind, sig, source_positions); wasm_engine, &env, kind, sig, source_positions);
std::unique_ptr<WasmCode> wasm_code = native_module->AddCode( std::unique_ptr<WasmCode> wasm_code = native_module->AddCode(
result.func_index, result.code_desc, result.frame_slot_count, result.func_index, result.code_desc, result.frame_slot_count,
result.tagged_parameter_slots, std::move(result.protected_instructions), result.tagged_parameter_slots,
std::move(result.source_positions), GetCodeKind(result), result.protected_instructions_data.as_vector(),
result.source_positions.as_vector(), GetCodeKind(result),
ExecutionTier::kNone); ExecutionTier::kNone);
WasmCode* published_code = native_module->PublishCode(std::move(wasm_code)); WasmCode* published_code = native_module->PublishCode(std::move(wasm_code));
(*cache_scope)[key] = published_code; (*cache_scope)[key] = published_code;
......
...@@ -147,17 +147,32 @@ int WasmCode::code_comments_size() const { ...@@ -147,17 +147,32 @@ int WasmCode::code_comments_size() const {
return static_cast<int>(unpadded_binary_size_ - code_comments_offset_); return static_cast<int>(unpadded_binary_size_ - code_comments_offset_);
} }
std::unique_ptr<const byte[]> WasmCode::ConcatenateBytes(
std::initializer_list<Vector<const byte>> vectors) {
size_t total_size = 0;
for (auto& vec : vectors) total_size += vec.size();
// Use default-initialization (== no initialization).
std::unique_ptr<byte[]> result{new byte[total_size]};
byte* ptr = result.get();
for (auto& vec : vectors) {
memcpy(ptr, vec.begin(), vec.size());
ptr += vec.size();
}
return result;
}
void WasmCode::RegisterTrapHandlerData() { void WasmCode::RegisterTrapHandlerData() {
DCHECK(!has_trap_handler_index()); DCHECK(!has_trap_handler_index());
if (kind() != WasmCode::kFunction) return; if (kind() != WasmCode::kFunction) return;
if (protected_instructions_.empty()) return; if (protected_instructions_size_ == 0) return;
Address base = instruction_start(); Address base = instruction_start();
size_t size = instructions().size(); size_t size = instructions().size();
auto protected_instruction_data = this->protected_instructions();
const int index = const int index =
RegisterHandlerData(base, size, protected_instructions().size(), RegisterHandlerData(base, size, protected_instruction_data.size(),
protected_instructions().begin()); protected_instruction_data.begin());
// TODO(eholk): if index is negative, fail. // TODO(eholk): if index is negative, fail.
CHECK_LE(0, index); CHECK_LE(0, index);
...@@ -322,7 +337,7 @@ void WasmCode::Disassemble(const char* name, std::ostream& os, ...@@ -322,7 +337,7 @@ void WasmCode::Disassemble(const char* name, std::ostream& os,
os << "\n"; os << "\n";
} }
if (!protected_instructions_.empty()) { if (protected_instructions_size_ > 0) {
os << "Protected instructions:\n pc offset land pad\n"; os << "Protected instructions:\n pc offset land pad\n";
for (auto& data : protected_instructions()) { for (auto& data : protected_instructions()) {
os << std::setw(10) << std::hex << data.instr_offset << std::setw(10) os << std::setw(10) << std::hex << data.instr_offset << std::setw(10)
...@@ -364,7 +379,7 @@ void WasmCode::Disassemble(const char* name, std::ostream& os, ...@@ -364,7 +379,7 @@ void WasmCode::Disassemble(const char* name, std::ostream& os,
os << "\n"; os << "\n";
} }
os << "RelocInfo (size = " << reloc_info_.size() << ")\n"; os << "RelocInfo (size = " << reloc_info().size() << ")\n";
for (RelocIterator it(instructions(), reloc_info(), constant_pool()); for (RelocIterator it(instructions(), reloc_info(), constant_pool());
!it.done(); it.next()) { !it.done(); it.next()) {
it.rinfo()->Print(nullptr, os); it.rinfo()->Print(nullptr, os);
...@@ -855,22 +870,22 @@ WasmCode* NativeModule::AddCodeForTesting(Handle<Code> code) { ...@@ -855,22 +870,22 @@ WasmCode* NativeModule::AddCodeForTesting(Handle<Code> code) {
// Flush the i-cache after relocation. // Flush the i-cache after relocation.
FlushInstructionCache(dst_code_bytes.begin(), dst_code_bytes.size()); FlushInstructionCache(dst_code_bytes.begin(), dst_code_bytes.size());
std::unique_ptr<WasmCode> new_code{new WasmCode{ std::unique_ptr<WasmCode> new_code{
this, // native_module new WasmCode{this, // native_module
kAnonymousFuncIndex, // index kAnonymousFuncIndex, // index
dst_code_bytes, // instructions dst_code_bytes, // instructions
stack_slots, // stack_slots stack_slots, // stack_slots
0, // tagged_parameter_slots 0, // tagged_parameter_slots
safepoint_table_offset, // safepoint_table_offset safepoint_table_offset, // safepoint_table_offset
handler_table_offset, // handler_table_offset handler_table_offset, // handler_table_offset
constant_pool_offset, // constant_pool_offset constant_pool_offset, // constant_pool_offset
code_comments_offset, // code_comments_offset code_comments_offset, // code_comments_offset
instructions.length(), // unpadded_binary_size instructions.length(), // unpadded_binary_size
OwnedVector<ProtectedInstructionData>{}, // protected_instructions {}, // protected_instructions
std::move(reloc_info), // reloc_info reloc_info.as_vector(), // reloc_info
std::move(source_pos), // source positions source_pos.as_vector(), // source positions
WasmCode::kFunction, // kind WasmCode::kFunction, // kind
ExecutionTier::kNone}}; // tier ExecutionTier::kNone}}; // tier
new_code->MaybePrint(nullptr); new_code->MaybePrint(nullptr);
new_code->Validate(); new_code->Validate();
...@@ -914,33 +929,27 @@ void NativeModule::UseLazyStub(uint32_t func_index) { ...@@ -914,33 +929,27 @@ void NativeModule::UseLazyStub(uint32_t func_index) {
std::unique_ptr<WasmCode> NativeModule::AddCode( std::unique_ptr<WasmCode> NativeModule::AddCode(
int index, const CodeDesc& desc, int stack_slots, int index, const CodeDesc& desc, int stack_slots,
int tagged_parameter_slots, int tagged_parameter_slots, Vector<const byte> protected_instructions_data,
OwnedVector<trap_handler::ProtectedInstructionData> protected_instructions, Vector<const byte> source_position_table, WasmCode::Kind kind,
OwnedVector<const byte> source_position_table, WasmCode::Kind kind,
ExecutionTier tier) { ExecutionTier tier) {
Vector<byte> code_space = Vector<byte> code_space =
code_allocator_.AllocateForCode(this, desc.instr_size); code_allocator_.AllocateForCode(this, desc.instr_size);
auto jump_table_ref = auto jump_table_ref =
FindJumpTablesForRegion(base::AddressRegionOf(code_space)); FindJumpTablesForRegion(base::AddressRegionOf(code_space));
return AddCodeWithCodeSpace(index, desc, stack_slots, tagged_parameter_slots, return AddCodeWithCodeSpace(index, desc, stack_slots, tagged_parameter_slots,
std::move(protected_instructions), protected_instructions_data,
std::move(source_position_table), kind, tier, source_position_table, kind, tier, code_space,
code_space, jump_table_ref); jump_table_ref);
} }
std::unique_ptr<WasmCode> NativeModule::AddCodeWithCodeSpace( std::unique_ptr<WasmCode> NativeModule::AddCodeWithCodeSpace(
int index, const CodeDesc& desc, int stack_slots, int index, const CodeDesc& desc, int stack_slots,
int tagged_parameter_slots, int tagged_parameter_slots, Vector<const byte> protected_instructions_data,
OwnedVector<ProtectedInstructionData> protected_instructions, Vector<const byte> source_position_table, WasmCode::Kind kind,
OwnedVector<const byte> source_position_table, WasmCode::Kind kind,
ExecutionTier tier, Vector<uint8_t> dst_code_bytes, ExecutionTier tier, Vector<uint8_t> dst_code_bytes,
const JumpTablesRef& jump_tables) { const JumpTablesRef& jump_tables) {
OwnedVector<byte> reloc_info; Vector<byte> reloc_info{desc.buffer + desc.buffer_size - desc.reloc_size,
if (desc.reloc_size > 0) { static_cast<size_t>(desc.reloc_size)};
reloc_info = OwnedVector<byte>::New(desc.reloc_size);
memcpy(reloc_info.start(), desc.buffer + desc.buffer_size - desc.reloc_size,
desc.reloc_size);
}
// TODO(jgruber,v8:8758): Remove this translation. It exists only because // TODO(jgruber,v8:8758): Remove this translation. It exists only because
// CodeDesc contains real offsets but WasmCode expects an offset of 0 to mean // CodeDesc contains real offsets but WasmCode expects an offset of 0 to mean
...@@ -962,8 +971,8 @@ std::unique_ptr<WasmCode> NativeModule::AddCodeWithCodeSpace( ...@@ -962,8 +971,8 @@ std::unique_ptr<WasmCode> NativeModule::AddCodeWithCodeSpace(
RelocInfo::ModeMask(RelocInfo::WASM_STUB_CALL); RelocInfo::ModeMask(RelocInfo::WASM_STUB_CALL);
Address code_start = reinterpret_cast<Address>(dst_code_bytes.begin()); Address code_start = reinterpret_cast<Address>(dst_code_bytes.begin());
Address constant_pool_start = code_start + constant_pool_offset; Address constant_pool_start = code_start + constant_pool_offset;
for (RelocIterator it(dst_code_bytes, reloc_info.as_vector(), for (RelocIterator it(dst_code_bytes, reloc_info, constant_pool_start,
constant_pool_start, mode_mask); mode_mask);
!it.done(); it.next()) { !it.done(); it.next()) {
RelocInfo::Mode mode = it.rinfo()->rmode(); RelocInfo::Mode mode = it.rinfo()->rmode();
if (RelocInfo::IsWasmCall(mode)) { if (RelocInfo::IsWasmCall(mode)) {
...@@ -987,8 +996,8 @@ std::unique_ptr<WasmCode> NativeModule::AddCodeWithCodeSpace( ...@@ -987,8 +996,8 @@ std::unique_ptr<WasmCode> NativeModule::AddCodeWithCodeSpace(
std::unique_ptr<WasmCode> code{new WasmCode{ std::unique_ptr<WasmCode> code{new WasmCode{
this, index, dst_code_bytes, stack_slots, tagged_parameter_slots, this, index, dst_code_bytes, stack_slots, tagged_parameter_slots,
safepoint_table_offset, handler_table_offset, constant_pool_offset, safepoint_table_offset, handler_table_offset, constant_pool_offset,
code_comments_offset, instr_size, std::move(protected_instructions), code_comments_offset, instr_size, protected_instructions_data, reloc_info,
std::move(reloc_info), std::move(source_position_table), kind, tier}}; source_position_table, kind, tier}};
code->MaybePrint(); code->MaybePrint();
code->Validate(); code->Validate();
...@@ -1077,10 +1086,9 @@ WasmCode* NativeModule::AddDeserializedCode( ...@@ -1077,10 +1086,9 @@ WasmCode* NativeModule::AddDeserializedCode(
int tagged_parameter_slots, int safepoint_table_offset, int tagged_parameter_slots, int safepoint_table_offset,
int handler_table_offset, int constant_pool_offset, int handler_table_offset, int constant_pool_offset,
int code_comments_offset, int unpadded_binary_size, int code_comments_offset, int unpadded_binary_size,
OwnedVector<ProtectedInstructionData> protected_instructions, Vector<const byte> protected_instructions_data,
OwnedVector<const byte> reloc_info, Vector<const byte> reloc_info, Vector<const byte> source_position_table,
OwnedVector<const byte> source_position_table, WasmCode::Kind kind, WasmCode::Kind kind, ExecutionTier tier) {
ExecutionTier tier) {
Vector<uint8_t> dst_code_bytes = Vector<uint8_t> dst_code_bytes =
code_allocator_.AllocateForCode(this, instructions.size()); code_allocator_.AllocateForCode(this, instructions.size());
memcpy(dst_code_bytes.begin(), instructions.begin(), instructions.size()); memcpy(dst_code_bytes.begin(), instructions.begin(), instructions.size());
...@@ -1088,9 +1096,8 @@ WasmCode* NativeModule::AddDeserializedCode( ...@@ -1088,9 +1096,8 @@ WasmCode* NativeModule::AddDeserializedCode(
std::unique_ptr<WasmCode> code{new WasmCode{ std::unique_ptr<WasmCode> code{new WasmCode{
this, index, dst_code_bytes, stack_slots, tagged_parameter_slots, this, index, dst_code_bytes, stack_slots, tagged_parameter_slots,
safepoint_table_offset, handler_table_offset, constant_pool_offset, safepoint_table_offset, handler_table_offset, constant_pool_offset,
code_comments_offset, unpadded_binary_size, code_comments_offset, unpadded_binary_size, protected_instructions_data,
std::move(protected_instructions), std::move(reloc_info), reloc_info, source_position_table, kind, tier}};
std::move(source_position_table), kind, tier}};
// Note: we do not flush the i-cache here, since the code needs to be // Note: we do not flush the i-cache here, since the code needs to be
// relocated anyway. The caller is responsible for flushing the i-cache later. // relocated anyway. The caller is responsible for flushing the i-cache later.
...@@ -1141,22 +1148,22 @@ WasmCode* NativeModule::CreateEmptyJumpTableInRegion( ...@@ -1141,22 +1148,22 @@ WasmCode* NativeModule::CreateEmptyJumpTableInRegion(
this, jump_table_size, region, allocator_lock); this, jump_table_size, region, allocator_lock);
DCHECK(!code_space.empty()); DCHECK(!code_space.empty());
ZapCode(reinterpret_cast<Address>(code_space.begin()), code_space.size()); ZapCode(reinterpret_cast<Address>(code_space.begin()), code_space.size());
std::unique_ptr<WasmCode> code{new WasmCode{ std::unique_ptr<WasmCode> code{
this, // native_module new WasmCode{this, // native_module
kAnonymousFuncIndex, // index kAnonymousFuncIndex, // index
code_space, // instructions code_space, // instructions
0, // stack_slots 0, // stack_slots
0, // tagged_parameter_slots 0, // tagged_parameter_slots
0, // safepoint_table_offset 0, // safepoint_table_offset
jump_table_size, // handler_table_offset jump_table_size, // handler_table_offset
jump_table_size, // constant_pool_offset jump_table_size, // constant_pool_offset
jump_table_size, // code_comments_offset jump_table_size, // code_comments_offset
jump_table_size, // unpadded_binary_size jump_table_size, // unpadded_binary_size
OwnedVector<ProtectedInstructionData>{}, // protected_instructions {}, // protected_instructions
OwnedVector<const uint8_t>{}, // reloc_info {}, // reloc_info
OwnedVector<const uint8_t>{}, // source_pos {}, // source_pos
WasmCode::kJumpTable, // kind WasmCode::kJumpTable, // kind
ExecutionTier::kNone}}; // tier ExecutionTier::kNone}}; // tier
return PublishCode(std::move(code)); return PublishCode(std::move(code));
} }
...@@ -1782,8 +1789,9 @@ std::vector<WasmCode*> NativeModule::AddCompiledCode( ...@@ -1782,8 +1789,9 @@ std::vector<WasmCode*> NativeModule::AddCompiledCode(
code_space += code_size; code_space += code_size;
generated_code.emplace_back(AddCodeWithCodeSpace( generated_code.emplace_back(AddCodeWithCodeSpace(
result.func_index, result.code_desc, result.frame_slot_count, result.func_index, result.code_desc, result.frame_slot_count,
result.tagged_parameter_slots, std::move(result.protected_instructions), result.tagged_parameter_slots,
std::move(result.source_positions), GetCodeKind(result), result.protected_instructions_data.as_vector(),
result.source_positions.as_vector(), GetCodeKind(result),
result.result_tier, this_code_space, jump_tables)); result.result_tier, this_code_space, jump_tables));
} }
DCHECK_EQ(0, code_space.size()); DCHECK_EQ(0, code_space.size());
......
...@@ -127,9 +127,12 @@ class V8_EXPORT_PRIVATE WasmCode final { ...@@ -127,9 +127,12 @@ class V8_EXPORT_PRIVATE WasmCode final {
Address instruction_start() const { Address instruction_start() const {
return reinterpret_cast<Address>(instructions_.begin()); return reinterpret_cast<Address>(instructions_.begin());
} }
Vector<const byte> reloc_info() const { return reloc_info_.as_vector(); } Vector<const byte> reloc_info() const {
return {protected_instructions_data().end(),
static_cast<size_t>(reloc_info_size_)};
}
Vector<const byte> source_positions() const { Vector<const byte> source_positions() const {
return source_position_table_.as_vector(); return {reloc_info().end(), static_cast<size_t>(source_positions_size_)};
} }
// TODO(clemensb): Make this return int. // TODO(clemensb): Make this return int.
...@@ -160,9 +163,15 @@ class V8_EXPORT_PRIVATE WasmCode final { ...@@ -160,9 +163,15 @@ class V8_EXPORT_PRIVATE WasmCode final {
pc < reinterpret_cast<Address>(instructions_.end()); pc < reinterpret_cast<Address>(instructions_.end());
} }
Vector<trap_handler::ProtectedInstructionData> protected_instructions() Vector<const uint8_t> protected_instructions_data() const {
return {meta_data_.get(),
static_cast<size_t>(protected_instructions_size_)};
}
Vector<const trap_handler::ProtectedInstructionData> protected_instructions()
const { const {
return protected_instructions_.as_vector(); return Vector<const trap_handler::ProtectedInstructionData>::cast(
protected_instructions_data());
} }
void Validate() const; void Validate() const;
...@@ -218,15 +227,17 @@ class V8_EXPORT_PRIVATE WasmCode final { ...@@ -218,15 +227,17 @@ class V8_EXPORT_PRIVATE WasmCode final {
int safepoint_table_offset, int handler_table_offset, int safepoint_table_offset, int handler_table_offset,
int constant_pool_offset, int code_comments_offset, int constant_pool_offset, int code_comments_offset,
int unpadded_binary_size, int unpadded_binary_size,
OwnedVector<trap_handler::ProtectedInstructionData> Vector<const byte> protected_instructions_data,
protected_instructions, Vector<const byte> reloc_info,
OwnedVector<const byte> reloc_info, Vector<const byte> source_position_table, Kind kind,
OwnedVector<const byte> source_position_table, Kind kind,
ExecutionTier tier) ExecutionTier tier)
: instructions_(instructions), : instructions_(instructions),
reloc_info_(std::move(reloc_info)),
source_position_table_(std::move(source_position_table)),
native_module_(native_module), native_module_(native_module),
meta_data_(ConcatenateBytes(
{protected_instructions_data, reloc_info, source_position_table})),
reloc_info_size_(reloc_info.length()),
source_positions_size_(source_position_table.length()),
protected_instructions_size_(protected_instructions_data.length()),
index_(index), index_(index),
kind_(kind), kind_(kind),
constant_pool_offset_(constant_pool_offset), constant_pool_offset_(constant_pool_offset),
...@@ -236,7 +247,6 @@ class V8_EXPORT_PRIVATE WasmCode final { ...@@ -236,7 +247,6 @@ class V8_EXPORT_PRIVATE WasmCode final {
handler_table_offset_(handler_table_offset), handler_table_offset_(handler_table_offset),
code_comments_offset_(code_comments_offset), code_comments_offset_(code_comments_offset),
unpadded_binary_size_(unpadded_binary_size), unpadded_binary_size_(unpadded_binary_size),
protected_instructions_(std::move(protected_instructions)),
tier_(tier) { tier_(tier) {
DCHECK_LE(safepoint_table_offset, unpadded_binary_size); DCHECK_LE(safepoint_table_offset, unpadded_binary_size);
DCHECK_LE(handler_table_offset, unpadded_binary_size); DCHECK_LE(handler_table_offset, unpadded_binary_size);
...@@ -244,6 +254,9 @@ class V8_EXPORT_PRIVATE WasmCode final { ...@@ -244,6 +254,9 @@ class V8_EXPORT_PRIVATE WasmCode final {
DCHECK_LE(constant_pool_offset, unpadded_binary_size); DCHECK_LE(constant_pool_offset, unpadded_binary_size);
} }
std::unique_ptr<const byte[]> ConcatenateBytes(
std::initializer_list<Vector<const byte>>);
// Code objects that have been registered with the global trap handler within // Code objects that have been registered with the global trap handler within
// this process, will have a {trap_handler_index} associated with them. // this process, will have a {trap_handler_index} associated with them.
int trap_handler_index() const { int trap_handler_index() const {
...@@ -265,9 +278,16 @@ class V8_EXPORT_PRIVATE WasmCode final { ...@@ -265,9 +278,16 @@ class V8_EXPORT_PRIVATE WasmCode final {
V8_NOINLINE bool DecRefOnPotentiallyDeadCode(); V8_NOINLINE bool DecRefOnPotentiallyDeadCode();
Vector<byte> instructions_; Vector<byte> instructions_;
OwnedVector<const byte> reloc_info_;
OwnedVector<const byte> source_position_table_;
NativeModule* native_module_ = nullptr; NativeModule* native_module_ = nullptr;
// {meta_data_} contains several byte vectors concatenated into one:
// - protected instructions data of size {protected_instructions_size_}
// - relocation info of size {reloc_info_size_}
// - source positions of size {source_positions_size_}
// Note that the protected instructions come first to ensure alignment.
std::unique_ptr<const byte[]> meta_data_;
const int reloc_info_size_;
const int source_positions_size_;
const int protected_instructions_size_;
int index_; int index_;
Kind kind_; Kind kind_;
int constant_pool_offset_ = 0; int constant_pool_offset_ = 0;
...@@ -282,7 +302,6 @@ class V8_EXPORT_PRIVATE WasmCode final { ...@@ -282,7 +302,6 @@ class V8_EXPORT_PRIVATE WasmCode final {
int code_comments_offset_ = 0; int code_comments_offset_ = 0;
int unpadded_binary_size_ = 0; int unpadded_binary_size_ = 0;
int trap_handler_index_ = -1; int trap_handler_index_ = -1;
OwnedVector<trap_handler::ProtectedInstructionData> protected_instructions_;
ExecutionTier tier_; ExecutionTier tier_;
// WasmCode is ref counted. Counters are held by: // WasmCode is ref counted. Counters are held by:
...@@ -304,7 +323,7 @@ class V8_EXPORT_PRIVATE WasmCode final { ...@@ -304,7 +323,7 @@ class V8_EXPORT_PRIVATE WasmCode final {
// often for rather small functions. // often for rather small functions.
// Increase the limit if needed, but first check if the size increase is // Increase the limit if needed, but first check if the size increase is
// justified. // justified.
STATIC_ASSERT(sizeof(WasmCode) <= 120); STATIC_ASSERT(sizeof(WasmCode) <= 96);
WasmCode::Kind GetCodeKind(const WasmCompilationResult& result); WasmCode::Kind GetCodeKind(const WasmCompilationResult& result);
...@@ -411,13 +430,11 @@ class V8_EXPORT_PRIVATE NativeModule final { ...@@ -411,13 +430,11 @@ class V8_EXPORT_PRIVATE NativeModule final {
// {AddCode} is thread safe w.r.t. other calls to {AddCode} or methods adding // {AddCode} is thread safe w.r.t. other calls to {AddCode} or methods adding
// code below, i.e. it can be called concurrently from background threads. // code below, i.e. it can be called concurrently from background threads.
// The returned code still needs to be published via {PublishCode}. // The returned code still needs to be published via {PublishCode}.
std::unique_ptr<WasmCode> AddCode( std::unique_ptr<WasmCode> AddCode(int index, const CodeDesc& desc,
int index, const CodeDesc& desc, int stack_slots, int stack_slots, int tagged_parameter_slots,
int tagged_parameter_slots, Vector<const byte> protected_instructions,
OwnedVector<trap_handler::ProtectedInstructionData> Vector<const byte> source_position_table,
protected_instructions, WasmCode::Kind kind, ExecutionTier tier);
OwnedVector<const byte> source_position_table, WasmCode::Kind kind,
ExecutionTier tier);
// {PublishCode} makes the code available to the system by entering it into // {PublishCode} makes the code available to the system by entering it into
// the code table and patching the jump table. It returns a raw pointer to the // the code table and patching the jump table. It returns a raw pointer to the
...@@ -431,11 +448,9 @@ class V8_EXPORT_PRIVATE NativeModule final { ...@@ -431,11 +448,9 @@ class V8_EXPORT_PRIVATE NativeModule final {
int tagged_parameter_slots, int safepoint_table_offset, int tagged_parameter_slots, int safepoint_table_offset,
int handler_table_offset, int constant_pool_offset, int handler_table_offset, int constant_pool_offset,
int code_comments_offset, int unpadded_binary_size, int code_comments_offset, int unpadded_binary_size,
OwnedVector<trap_handler::ProtectedInstructionData> Vector<const byte> protected_instructions_data,
protected_instructions, Vector<const byte> reloc_info, Vector<const byte> source_position_table,
OwnedVector<const byte> reloc_info, WasmCode::Kind kind, ExecutionTier tier);
OwnedVector<const byte> source_position_table, WasmCode::Kind kind,
ExecutionTier tier);
// Adds anonymous code for testing purposes. // Adds anonymous code for testing purposes.
WasmCode* AddCodeForTesting(Handle<Code> code); WasmCode* AddCodeForTesting(Handle<Code> code);
...@@ -601,9 +616,8 @@ class V8_EXPORT_PRIVATE NativeModule final { ...@@ -601,9 +616,8 @@ class V8_EXPORT_PRIVATE NativeModule final {
std::unique_ptr<WasmCode> AddCodeWithCodeSpace( std::unique_ptr<WasmCode> AddCodeWithCodeSpace(
int index, const CodeDesc& desc, int stack_slots, int index, const CodeDesc& desc, int stack_slots,
int tagged_parameter_slots, int tagged_parameter_slots,
OwnedVector<trap_handler::ProtectedInstructionData> Vector<const byte> protected_instructions_data,
protected_instructions, Vector<const byte> source_position_table, WasmCode::Kind kind,
OwnedVector<const byte> source_position_table, WasmCode::Kind kind,
ExecutionTier tier, Vector<uint8_t> code_space, ExecutionTier tier, Vector<uint8_t> code_space,
const JumpTablesRef& jump_tables_ref); const JumpTablesRef& jump_tables_ref);
......
...@@ -900,8 +900,9 @@ void WasmDebugInfo::RedirectToInterpreter(Handle<WasmDebugInfo> debug_info, ...@@ -900,8 +900,9 @@ void WasmDebugInfo::RedirectToInterpreter(Handle<WasmDebugInfo> debug_info,
module->functions[func_index].sig); module->functions[func_index].sig);
std::unique_ptr<wasm::WasmCode> wasm_code = native_module->AddCode( std::unique_ptr<wasm::WasmCode> wasm_code = native_module->AddCode(
func_index, result.code_desc, result.frame_slot_count, func_index, result.code_desc, result.frame_slot_count,
result.tagged_parameter_slots, std::move(result.protected_instructions), result.tagged_parameter_slots,
std::move(result.source_positions), wasm::WasmCode::kInterpreterEntry, result.protected_instructions_data.as_vector(),
result.source_positions.as_vector(), wasm::WasmCode::kInterpreterEntry,
wasm::ExecutionTier::kInterpreter); wasm::ExecutionTier::kInterpreter);
native_module->PublishCode(std::move(wasm_code)); native_module->PublishCode(std::move(wasm_code));
DCHECK(native_module->IsRedirectedToInterpreter(func_index)); DCHECK(native_module->IsRedirectedToInterpreter(func_index));
......
...@@ -1460,8 +1460,9 @@ void WasmInstanceObject::ImportWasmJSFunctionIntoTable( ...@@ -1460,8 +1460,9 @@ void WasmInstanceObject::ImportWasmJSFunctionIntoTable(
isolate->wasm_engine(), &env, kind, sig, false); isolate->wasm_engine(), &env, kind, sig, false);
std::unique_ptr<wasm::WasmCode> wasm_code = native_module->AddCode( std::unique_ptr<wasm::WasmCode> wasm_code = native_module->AddCode(
result.func_index, result.code_desc, result.frame_slot_count, result.func_index, result.code_desc, result.frame_slot_count,
result.tagged_parameter_slots, std::move(result.protected_instructions), result.tagged_parameter_slots,
std::move(result.source_positions), GetCodeKind(result), result.protected_instructions_data.as_vector(),
result.source_positions.as_vector(), GetCodeKind(result),
wasm::ExecutionTier::kNone); wasm::ExecutionTier::kNone);
wasm::WasmCode* published_code = wasm::WasmCode* published_code =
native_module->PublishCode(std::move(wasm_code)); native_module->PublishCode(std::move(wasm_code));
......
...@@ -99,16 +99,17 @@ class Reader { ...@@ -99,16 +99,17 @@ class Reader {
return value; return value;
} }
void ReadVector(Vector<byte> v) { template <typename T>
if (v.size() > 0) { Vector<const T> ReadVector(size_t size) {
DCHECK_GE(current_size(), v.size()); DCHECK_GE(current_size(), size);
memcpy(v.begin(), current_location(), v.size()); Vector<const byte> bytes{pos_, size * sizeof(T)};
pos_ += v.size(); pos_ += size * sizeof(T);
}
if (FLAG_trace_wasm_serialization) { if (FLAG_trace_wasm_serialization) {
StdoutStream{} << "read vector of " << v.size() << " elements" StdoutStream{} << "read vector of " << size << " elements of size "
<< sizeof(T) << " (total size " << size * sizeof(T) << ")"
<< std::endl; << std::endl;
} }
return Vector<const T>::cast(bytes);
} }
void Skip(size_t size) { pos_ += size; } void Skip(size_t size) { pos_ += size; }
...@@ -304,8 +305,7 @@ size_t NativeModuleSerializer::MeasureCode(const WasmCode* code) const { ...@@ -304,8 +305,7 @@ size_t NativeModuleSerializer::MeasureCode(const WasmCode* code) const {
code->kind() == WasmCode::kInterpreterEntry); code->kind() == WasmCode::kInterpreterEntry);
return kCodeHeaderSize + code->instructions().size() + return kCodeHeaderSize + code->instructions().size() +
code->reloc_info().size() + code->source_positions().size() + code->reloc_info().size() + code->source_positions().size() +
code->protected_instructions().size() * code->protected_instructions_data().size();
sizeof(trap_handler::ProtectedInstructionData);
} }
size_t NativeModuleSerializer::Measure() const { size_t NativeModuleSerializer::Measure() const {
...@@ -343,7 +343,7 @@ void NativeModuleSerializer::WriteCode(const WasmCode* code, Writer* writer) { ...@@ -343,7 +343,7 @@ void NativeModuleSerializer::WriteCode(const WasmCode* code, Writer* writer) {
writer->Write(code->instructions().length()); writer->Write(code->instructions().length());
writer->Write(code->reloc_info().length()); writer->Write(code->reloc_info().length());
writer->Write(code->source_positions().length()); writer->Write(code->source_positions().length());
writer->Write(code->protected_instructions().length()); writer->Write(code->protected_instructions_data().length());
writer->Write(code->kind()); writer->Write(code->kind());
writer->Write(code->tier()); writer->Write(code->tier());
...@@ -355,7 +355,7 @@ void NativeModuleSerializer::WriteCode(const WasmCode* code, Writer* writer) { ...@@ -355,7 +355,7 @@ void NativeModuleSerializer::WriteCode(const WasmCode* code, Writer* writer) {
// Write the reloc info, source positions, and protected code. // Write the reloc info, source positions, and protected code.
writer->WriteVector(code->reloc_info()); writer->WriteVector(code->reloc_info());
writer->WriteVector(code->source_positions()); writer->WriteVector(code->source_positions());
writer->WriteVector(Vector<byte>::cast(code->protected_instructions())); writer->WriteVector(code->protected_instructions_data());
#if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_ARM || \ #if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_ARM || \
V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64 || V8_TARGET_ARCH_S390X V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64 || V8_TARGET_ARCH_S390X
// On platforms that don't support misaligned word stores, copy to an aligned // On platforms that don't support misaligned word stores, copy to an aligned
...@@ -516,25 +516,17 @@ bool NativeModuleDeserializer::ReadCode(int fn_index, Reader* reader) { ...@@ -516,25 +516,17 @@ bool NativeModuleDeserializer::ReadCode(int fn_index, Reader* reader) {
WasmCode::Kind kind = reader->Read<WasmCode::Kind>(); WasmCode::Kind kind = reader->Read<WasmCode::Kind>();
ExecutionTier tier = reader->Read<ExecutionTier>(); ExecutionTier tier = reader->Read<ExecutionTier>();
Vector<const byte> code_buffer{reader->current_location(), auto code_buffer = reader->ReadVector<byte>(code_size);
static_cast<size_t>(code_size)}; auto reloc_info = reader->ReadVector<byte>(reloc_size);
reader->Skip(code_size); auto source_pos = reader->ReadVector<byte>(source_position_size);
OwnedVector<byte> reloc_info = OwnedVector<byte>::New(reloc_size);
reader->ReadVector(reloc_info.as_vector());
OwnedVector<byte> source_pos = OwnedVector<byte>::New(source_position_size);
reader->ReadVector(source_pos.as_vector());
auto protected_instructions = auto protected_instructions =
OwnedVector<trap_handler::ProtectedInstructionData>::New( reader->ReadVector<byte>(protected_instructions_size);
protected_instructions_size);
reader->ReadVector(Vector<byte>::cast(protected_instructions.as_vector()));
WasmCode* code = native_module_->AddDeserializedCode( WasmCode* code = native_module_->AddDeserializedCode(
fn_index, code_buffer, stack_slot_count, tagged_parameter_slots, fn_index, code_buffer, stack_slot_count, tagged_parameter_slots,
safepoint_table_offset, handler_table_offset, constant_pool_offset, safepoint_table_offset, handler_table_offset, constant_pool_offset,
code_comment_offset, unpadded_binary_size, code_comment_offset, unpadded_binary_size, protected_instructions,
std::move(protected_instructions), std::move(reloc_info), std::move(reloc_info), std::move(source_pos), kind, tier);
std::move(source_pos), kind, tier);
// Relocate the code. // Relocate the code.
int mask = RelocInfo::ModeMask(RelocInfo::WASM_CALL) | int mask = RelocInfo::ModeMask(RelocInfo::WASM_CALL) |
......
...@@ -3753,9 +3753,9 @@ TEST(Liftoff_tier_up) { ...@@ -3753,9 +3753,9 @@ TEST(Liftoff_tier_up) {
memcpy(buffer.get(), sub_code->instructions().begin(), sub_size); memcpy(buffer.get(), sub_code->instructions().begin(), sub_size);
desc.buffer = buffer.get(); desc.buffer = buffer.get();
desc.instr_size = static_cast<int>(sub_size); desc.instr_size = static_cast<int>(sub_size);
std::unique_ptr<WasmCode> new_code = native_module->AddCode( std::unique_ptr<WasmCode> new_code =
add.function_index(), desc, 0, 0, {}, OwnedVector<byte>(), native_module->AddCode(add.function_index(), desc, 0, 0, {}, {},
WasmCode::kFunction, ExecutionTier::kTurbofan); WasmCode::kFunction, ExecutionTier::kTurbofan);
native_module->PublishCode(std::move(new_code)); native_module->PublishCode(std::move(new_code));
// Second run should now execute {sub}. // Second run should now execute {sub}.
......
...@@ -144,8 +144,9 @@ uint32_t TestingModuleBuilder::AddFunction(const FunctionSig* sig, ...@@ -144,8 +144,9 @@ uint32_t TestingModuleBuilder::AddFunction(const FunctionSig* sig,
sig); sig);
std::unique_ptr<wasm::WasmCode> code = native_module_->AddCode( std::unique_ptr<wasm::WasmCode> code = native_module_->AddCode(
index, result.code_desc, result.frame_slot_count, index, result.code_desc, result.frame_slot_count,
result.tagged_parameter_slots, std::move(result.protected_instructions), result.tagged_parameter_slots,
std::move(result.source_positions), wasm::WasmCode::kInterpreterEntry, result.protected_instructions_data.as_vector(),
result.source_positions.as_vector(), wasm::WasmCode::kInterpreterEntry,
wasm::ExecutionTier::kInterpreter); wasm::ExecutionTier::kInterpreter);
native_module_->PublishCode(std::move(code)); native_module_->PublishCode(std::move(code));
} }
......
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