Commit ce2d01bc authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Store protected instructions in an OwnedVector

We currently store the protected instructions per code object in a
{std::unique_ptr<std::vector<ProtectedInstructionData>>}. This wastes
memory, because it requires two heap allocations, plus the vector might
over-allocate (and it currently does, because it is filled dynamically
during compilation).
This CL changes that to store the protected instructions in an
{OwnedVector}. This requires one copy after generating the list of
{ProtectedInstructionData} in an {std::vector} during compilation, but
saves memory afterwards.

R=mstarzinger@chromium.org

Bug: chromium:856938
Change-Id: Ie290a17dc32f27fbbfe0c000a52297181c954550
Reviewed-on: https://chromium-review.googlesource.com/1116701Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54052}
parent 9cd33e9e
...@@ -1051,7 +1051,7 @@ PipelineWasmCompilationJob::Status PipelineWasmCompilationJob::FinalizeJobImpl( ...@@ -1051,7 +1051,7 @@ PipelineWasmCompilationJob::Status PipelineWasmCompilationJob::FinalizeJobImpl(
code_desc, code_generator->frame()->GetTotalFrameSlotCount(), code_desc, code_generator->frame()->GetTotalFrameSlotCount(),
data_.wasm_function_index(), code_generator->GetSafepointTableOffset(), data_.wasm_function_index(), code_generator->GetSafepointTableOffset(),
code_generator->GetHandlerTableOffset(), code_generator->GetHandlerTableOffset(),
data_.wasm_compilation_data()->ReleaseProtectedInstructions(), data_.wasm_compilation_data()->GetProtectedInstructions(),
code_generator->GetSourcePositionTable(), wasm::WasmCode::kTurbofan); code_generator->GetSourcePositionTable(), wasm::WasmCode::kTurbofan);
if (!code) return FAILED; if (!code) return FAILED;
......
...@@ -4999,18 +4999,6 @@ MaybeHandle<Code> CompileCWasmEntry(Isolate* isolate, wasm::FunctionSig* sig) { ...@@ -4999,18 +4999,6 @@ MaybeHandle<Code> CompileCWasmEntry(Isolate* isolate, wasm::FunctionSig* sig) {
return code; return code;
} }
WasmCompilationData::WasmCompilationData(
wasm::RuntimeExceptionSupport runtime_exception_support)
: protected_instructions_(
new std::vector<trap_handler::ProtectedInstructionData>()),
runtime_exception_support_(runtime_exception_support) {}
void WasmCompilationData::AddProtectedInstruction(uint32_t instr_offset,
uint32_t landing_offset) {
protected_instructions_->emplace_back(
trap_handler::ProtectedInstructionData{instr_offset, landing_offset});
}
TurbofanWasmCompilationUnit::TurbofanWasmCompilationUnit( TurbofanWasmCompilationUnit::TurbofanWasmCompilationUnit(
wasm::WasmCompilationUnit* wasm_unit) wasm::WasmCompilationUnit* wasm_unit)
: wasm_unit_(wasm_unit), : wasm_unit_(wasm_unit),
......
...@@ -52,13 +52,17 @@ namespace compiler { ...@@ -52,13 +52,17 @@ namespace compiler {
class WasmCompilationData { class WasmCompilationData {
public: public:
explicit WasmCompilationData( explicit WasmCompilationData(
wasm::RuntimeExceptionSupport runtime_exception_support); wasm::RuntimeExceptionSupport runtime_exception_support)
: runtime_exception_support_(runtime_exception_support) {}
void AddProtectedInstruction(uint32_t instr_offset, uint32_t landing_offset); void AddProtectedInstruction(uint32_t instr_offset, uint32_t landing_offset) {
protected_instructions_.push_back({instr_offset, landing_offset});
}
std::unique_ptr<std::vector<trap_handler::ProtectedInstructionData>> OwnedVector<trap_handler::ProtectedInstructionData>
ReleaseProtectedInstructions() { GetProtectedInstructions() {
return std::move(protected_instructions_); return OwnedVector<trap_handler::ProtectedInstructionData>::Of(
protected_instructions_);
} }
wasm::RuntimeExceptionSupport runtime_exception_support() const { wasm::RuntimeExceptionSupport runtime_exception_support() const {
...@@ -66,8 +70,7 @@ class WasmCompilationData { ...@@ -66,8 +70,7 @@ class WasmCompilationData {
} }
private: private:
std::unique_ptr<std::vector<trap_handler::ProtectedInstructionData>> std::vector<trap_handler::ProtectedInstructionData> protected_instructions_;
protected_instructions_;
// See ModuleEnv::runtime_exception_support_. // See ModuleEnv::runtime_exception_support_.
wasm::RuntimeExceptionSupport runtime_exception_support_; wasm::RuntimeExceptionSupport runtime_exception_support_;
......
...@@ -176,8 +176,7 @@ OwnedVector<byte> SourcePositionTableBuilder::ToSourcePositionTableVector() { ...@@ -176,8 +176,7 @@ OwnedVector<byte> SourcePositionTableBuilder::ToSourcePositionTableVector() {
if (bytes_.empty()) return OwnedVector<byte>(); if (bytes_.empty()) return OwnedVector<byte>();
DCHECK(!Omit()); DCHECK(!Omit());
OwnedVector<byte> table = OwnedVector<byte>::New(bytes_.size()); OwnedVector<byte> table = OwnedVector<byte>::Of(bytes_);
MemCopy(table.start(), bytes_.data(), bytes_.size());
#ifdef ENABLE_SLOW_DCHECKS #ifdef ENABLE_SLOW_DCHECKS
// Brute force testing: Record all positions and decode // Brute force testing: Record all positions and decode
......
...@@ -5,8 +5,9 @@ ...@@ -5,8 +5,9 @@
#ifndef V8_VECTOR_H_ #ifndef V8_VECTOR_H_
#define V8_VECTOR_H_ #define V8_VECTOR_H_
#include <string.h>
#include <algorithm> #include <algorithm>
#include <cstring>
#include <iterator>
#include "src/allocation.h" #include "src/allocation.h"
#include "src/checks.h" #include "src/checks.h"
...@@ -210,9 +211,24 @@ class OwnedVector { ...@@ -210,9 +211,24 @@ class OwnedVector {
// Allocates a new vector of the specified size via the default allocator. // Allocates a new vector of the specified size via the default allocator.
static OwnedVector<T> New(size_t size) { static OwnedVector<T> New(size_t size) {
if (size == 0) return {};
return OwnedVector<T>(std::unique_ptr<T[]>(new T[size]), size); return OwnedVector<T>(std::unique_ptr<T[]>(new T[size]), size);
} }
// Allocates a new vector containing the specified collection of values.
// {Iterator} is the common type of {std::begin} and {std::end} called on a
// {const U&}. This function is only instantiable if that type exists.
template <typename U, typename Iterator = typename std::common_type<
decltype(std::begin(std::declval<const U&>())),
decltype(std::end(std::declval<const U&>()))>::type>
static OwnedVector<T> Of(const U& collection) {
Iterator begin = std::begin(collection);
Iterator end = std::end(collection);
OwnedVector<T> vec = New(std::distance(begin, end));
std::copy(begin, end, vec.start());
return vec;
}
private: private:
std::unique_ptr<T[]> data_; std::unique_ptr<T[]> data_;
size_t length_ = 0; size_t length_ = 0;
......
...@@ -1830,13 +1830,11 @@ bool LiftoffCompilationUnit::ExecuteCompilation() { ...@@ -1830,13 +1830,11 @@ bool LiftoffCompilationUnit::ExecuteCompilation() {
compiler::GetWasmCallDescriptor(&zone, wasm_unit_->func_body_.sig); compiler::GetWasmCallDescriptor(&zone, wasm_unit_->func_body_.sig);
base::Optional<TimedHistogramScope> liftoff_compile_time_scope( base::Optional<TimedHistogramScope> liftoff_compile_time_scope(
base::in_place, wasm_unit_->counters_->liftoff_compile_time()); base::in_place, wasm_unit_->counters_->liftoff_compile_time());
DCHECK(!protected_instructions_); DCHECK(protected_instructions_.empty());
protected_instructions_.reset(
new std::vector<trap_handler::ProtectedInstructionData>());
wasm::WasmFullDecoder<wasm::Decoder::kValidate, wasm::LiftoffCompiler> wasm::WasmFullDecoder<wasm::Decoder::kValidate, wasm::LiftoffCompiler>
decoder(&zone, module, wasm_unit_->func_body_, &asm_, call_descriptor, decoder(&zone, module, wasm_unit_->func_body_, &asm_, call_descriptor,
wasm_unit_->env_, &source_position_table_builder_, wasm_unit_->env_, &source_position_table_builder_,
protected_instructions_.get(), &zone); &protected_instructions_, &zone);
decoder.Decode(); decoder.Decode();
liftoff_compile_time_scope.reset(); liftoff_compile_time_scope.reset();
if (!decoder.interface().ok()) { if (!decoder.interface().ok()) {
...@@ -1861,7 +1859,7 @@ bool LiftoffCompilationUnit::ExecuteCompilation() { ...@@ -1861,7 +1859,7 @@ bool LiftoffCompilationUnit::ExecuteCompilation() {
// Record the memory cost this unit places on the system until // Record the memory cost this unit places on the system until
// it is finalized. // it is finalized.
wasm_unit_->memory_cost_ = wasm_unit_->memory_cost_ =
asm_.pc_offset() + protected_instructions_->size() * asm_.pc_offset() + protected_instructions_.size() *
sizeof(trap_handler::ProtectedInstructionData); sizeof(trap_handler::ProtectedInstructionData);
safepoint_table_offset_ = decoder.interface().GetSafepointTableOffset(); safepoint_table_offset_ = decoder.interface().GetSafepointTableOffset();
...@@ -1876,10 +1874,12 @@ wasm::WasmCode* LiftoffCompilationUnit::FinishCompilation( ...@@ -1876,10 +1874,12 @@ wasm::WasmCode* LiftoffCompilationUnit::FinishCompilation(
OwnedVector<byte> source_positions = OwnedVector<byte> source_positions =
source_position_table_builder_.ToSourcePositionTableVector(); source_position_table_builder_.ToSourcePositionTableVector();
auto protected_instructions_copy =
OwnedVector<trap_handler::ProtectedInstructionData>::Of(
protected_instructions_);
wasm::WasmCode* code = wasm_unit_->native_module_->AddCode( wasm::WasmCode* code = wasm_unit_->native_module_->AddCode(
desc, asm_.GetTotalFrameSlotCount(), wasm_unit_->func_index_, desc, asm_.GetTotalFrameSlotCount(), wasm_unit_->func_index_,
safepoint_table_offset_, 0, std::move(protected_instructions_), safepoint_table_offset_, 0, std::move(protected_instructions_copy),
std::move(source_positions), wasm::WasmCode::kLiftoff); std::move(source_positions), wasm::WasmCode::kLiftoff);
return code; return code;
......
...@@ -29,8 +29,7 @@ class LiftoffCompilationUnit final { ...@@ -29,8 +29,7 @@ class LiftoffCompilationUnit final {
wasm::LiftoffAssembler asm_; wasm::LiftoffAssembler asm_;
int safepoint_table_offset_; int safepoint_table_offset_;
SourcePositionTableBuilder source_position_table_builder_; SourcePositionTableBuilder source_position_table_builder_;
std::unique_ptr<std::vector<trap_handler::ProtectedInstructionData>> std::vector<trap_handler::ProtectedInstructionData> protected_instructions_;
protected_instructions_;
DISALLOW_COPY_AND_ASSIGN(LiftoffCompilationUnit); DISALLOW_COPY_AND_ASSIGN(LiftoffCompilationUnit);
}; };
......
...@@ -131,7 +131,7 @@ void WasmCode::RegisterTrapHandlerData() { ...@@ -131,7 +131,7 @@ void WasmCode::RegisterTrapHandlerData() {
size_t size = instructions().size(); size_t size = instructions().size();
const int index = const int index =
RegisterHandlerData(base, size, protected_instructions().size(), RegisterHandlerData(base, size, protected_instructions().size(),
protected_instructions().data()); protected_instructions().start());
// TODO(eholk): if index is negative, fail. // TODO(eholk): if index is negative, fail.
CHECK_LE(0, index); CHECK_LE(0, index);
...@@ -365,7 +365,7 @@ WasmCode* NativeModule::AddOwnedCode( ...@@ -365,7 +365,7 @@ WasmCode* NativeModule::AddOwnedCode(
Maybe<uint32_t> index, WasmCode::Kind kind, size_t constant_pool_offset, Maybe<uint32_t> index, WasmCode::Kind kind, size_t constant_pool_offset,
uint32_t stack_slots, size_t safepoint_table_offset, uint32_t stack_slots, size_t safepoint_table_offset,
size_t handler_table_offset, size_t handler_table_offset,
std::unique_ptr<ProtectedInstructions> protected_instructions, OwnedVector<trap_handler::ProtectedInstructionData> protected_instructions,
WasmCode::Tier tier, WasmCode::FlushICache flush_icache) { WasmCode::Tier tier, WasmCode::FlushICache flush_icache) {
// both allocation and insertion in owned_code_ happen in the same critical // both allocation and insertion in owned_code_ happen in the same critical
// section, thus ensuring owned_code_'s elements are rarely if ever moved. // section, thus ensuring owned_code_'s elements are rarely if ever moved.
...@@ -464,8 +464,6 @@ WasmCode* NativeModule::AddAnonymousCode(Handle<Code> code, ...@@ -464,8 +464,6 @@ WasmCode* NativeModule::AddAnonymousCode(Handle<Code> code,
source_pos.reset(new byte[source_pos_table->length()]); source_pos.reset(new byte[source_pos_table->length()]);
source_pos_table->copy_out(0, source_pos.get(), source_pos_table->length()); source_pos_table->copy_out(0, source_pos.get(), source_pos_table->length());
} }
std::unique_ptr<ProtectedInstructions> protected_instructions(
new ProtectedInstructions(0));
Vector<const byte> orig_instructions( Vector<const byte> orig_instructions(
reinterpret_cast<byte*>(code->InstructionStart()), reinterpret_cast<byte*>(code->InstructionStart()),
static_cast<size_t>(code->InstructionSize())); static_cast<size_t>(code->InstructionSize()));
...@@ -484,7 +482,7 @@ WasmCode* NativeModule::AddAnonymousCode(Handle<Code> code, ...@@ -484,7 +482,7 @@ WasmCode* NativeModule::AddAnonymousCode(Handle<Code> code,
stack_slots, // stack_slots stack_slots, // stack_slots
safepoint_table_offset, // safepoint_table_offset safepoint_table_offset, // safepoint_table_offset
code->handler_table_offset(), // handler_table_offset code->handler_table_offset(), // handler_table_offset
std::move(protected_instructions), // protected_instructions {}, // protected_instructions
WasmCode::kOther, // kind WasmCode::kOther, // kind
WasmCode::kNoFlushICache); // flush_icache WasmCode::kNoFlushICache); // flush_icache
...@@ -521,7 +519,7 @@ WasmCode* NativeModule::AddAnonymousCode(Handle<Code> code, ...@@ -521,7 +519,7 @@ WasmCode* NativeModule::AddAnonymousCode(Handle<Code> code,
WasmCode* NativeModule::AddCode( WasmCode* NativeModule::AddCode(
const CodeDesc& desc, uint32_t frame_slots, uint32_t index, const CodeDesc& desc, uint32_t frame_slots, uint32_t index,
size_t safepoint_table_offset, size_t handler_table_offset, size_t safepoint_table_offset, size_t handler_table_offset,
std::unique_ptr<ProtectedInstructions> protected_instructions, OwnedVector<trap_handler::ProtectedInstructionData> protected_instructions,
OwnedVector<byte> source_pos_table, WasmCode::Tier tier) { OwnedVector<byte> source_pos_table, WasmCode::Tier tier) {
std::unique_ptr<byte[]> reloc_info; std::unique_ptr<byte[]> reloc_info;
if (desc.reloc_size) { if (desc.reloc_size) {
......
...@@ -86,9 +86,6 @@ class V8_EXPORT_PRIVATE DisjointAllocationPool final { ...@@ -86,9 +86,6 @@ class V8_EXPORT_PRIVATE DisjointAllocationPool final {
DISALLOW_COPY_AND_ASSIGN(DisjointAllocationPool) DISALLOW_COPY_AND_ASSIGN(DisjointAllocationPool)
}; };
using ProtectedInstructions =
std::vector<trap_handler::ProtectedInstructionData>;
class V8_EXPORT_PRIVATE WasmCode final { class V8_EXPORT_PRIVATE WasmCode final {
public: public:
enum Kind { enum Kind {
...@@ -144,11 +141,9 @@ class V8_EXPORT_PRIVATE WasmCode final { ...@@ -144,11 +141,9 @@ class V8_EXPORT_PRIVATE WasmCode final {
pc < reinterpret_cast<Address>(instructions_.end()); pc < reinterpret_cast<Address>(instructions_.end());
} }
const ProtectedInstructions& protected_instructions() const { Vector<trap_handler::ProtectedInstructionData> protected_instructions()
// TODO(mstarzinger): Code that doesn't have trapping instruction should const {
// not be required to have this vector, make it possible to be null. return protected_instructions_.as_vector();
DCHECK_NOT_NULL(protected_instructions_);
return *protected_instructions_.get();
} }
void Validate() const; void Validate() const;
...@@ -177,7 +172,8 @@ class V8_EXPORT_PRIVATE WasmCode final { ...@@ -177,7 +172,8 @@ class V8_EXPORT_PRIVATE WasmCode final {
Maybe<uint32_t> index, Kind kind, size_t constant_pool_offset, Maybe<uint32_t> index, Kind kind, size_t constant_pool_offset,
uint32_t stack_slots, size_t safepoint_table_offset, uint32_t stack_slots, size_t safepoint_table_offset,
size_t handler_table_offset, size_t handler_table_offset,
std::unique_ptr<ProtectedInstructions> protected_instructions, OwnedVector<trap_handler::ProtectedInstructionData>
protected_instructions,
Tier tier) Tier tier)
: instructions_(instructions), : instructions_(instructions),
reloc_info_(std::move(reloc_info)), reloc_info_(std::move(reloc_info)),
...@@ -225,7 +221,7 @@ class V8_EXPORT_PRIVATE WasmCode final { ...@@ -225,7 +221,7 @@ class V8_EXPORT_PRIVATE WasmCode final {
size_t safepoint_table_offset_ = 0; size_t safepoint_table_offset_ = 0;
size_t handler_table_offset_ = 0; size_t handler_table_offset_ = 0;
intptr_t trap_handler_index_ = -1; intptr_t trap_handler_index_ = -1;
std::unique_ptr<ProtectedInstructions> protected_instructions_; OwnedVector<trap_handler::ProtectedInstructionData> protected_instructions_;
Tier tier_; Tier tier_;
DISALLOW_COPY_AND_ASSIGN(WasmCode); DISALLOW_COPY_AND_ASSIGN(WasmCode);
...@@ -238,7 +234,8 @@ class V8_EXPORT_PRIVATE NativeModule final { ...@@ -238,7 +234,8 @@ class V8_EXPORT_PRIVATE NativeModule final {
public: public:
WasmCode* AddCode(const CodeDesc& desc, uint32_t frame_count, uint32_t index, WasmCode* AddCode(const CodeDesc& desc, uint32_t frame_count, uint32_t index,
size_t safepoint_table_offset, size_t handler_table_offset, size_t safepoint_table_offset, size_t handler_table_offset,
std::unique_ptr<ProtectedInstructions>, OwnedVector<trap_handler::ProtectedInstructionData>
protected_instructions,
OwnedVector<byte> source_position_table, OwnedVector<byte> source_position_table,
WasmCode::Tier tier); WasmCode::Tier tier);
...@@ -361,8 +358,8 @@ class V8_EXPORT_PRIVATE NativeModule final { ...@@ -361,8 +358,8 @@ class V8_EXPORT_PRIVATE NativeModule final {
WasmCode::Kind kind, size_t constant_pool_offset, WasmCode::Kind kind, size_t constant_pool_offset,
uint32_t stack_slots, size_t safepoint_table_offset, uint32_t stack_slots, size_t safepoint_table_offset,
size_t handler_table_offset, size_t handler_table_offset,
std::unique_ptr<ProtectedInstructions>, WasmCode::Tier, OwnedVector<trap_handler::ProtectedInstructionData>,
WasmCode::FlushICache); WasmCode::Tier, WasmCode::FlushICache);
WasmCode* CreateEmptyJumpTable(uint32_t num_wasm_functions); WasmCode* CreateEmptyJumpTable(uint32_t num_wasm_functions);
......
...@@ -301,10 +301,7 @@ void NativeModuleSerializer::WriteCode(const WasmCode* code, Writer* writer) { ...@@ -301,10 +301,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( writer->WriteVector(Vector<byte>::cast(code->protected_instructions()));
{reinterpret_cast<const byte*>(code->protected_instructions().data()),
sizeof(trap_handler::ProtectedInstructionData) *
code->protected_instructions().size()});
#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
// 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
// buffer if necessary so we can relocate the serialized code. // buffer if necessary so we can relocate the serialized code.
...@@ -458,15 +455,10 @@ bool NativeModuleDeserializer::ReadCode(uint32_t fn_index, Reader* reader) { ...@@ -458,15 +455,10 @@ bool NativeModuleDeserializer::ReadCode(uint32_t fn_index, Reader* reader) {
source_pos.reset(new byte[source_position_size]); source_pos.reset(new byte[source_position_size]);
reader->ReadVector({source_pos.get(), source_position_size}); reader->ReadVector({source_pos.get(), source_position_size});
} }
std::unique_ptr<ProtectedInstructions> protected_instructions( auto protected_instructions =
new ProtectedInstructions(protected_instructions_size)); OwnedVector<trap_handler::ProtectedInstructionData>::New(
if (protected_instructions_size > 0) { protected_instructions_size);
size_t size = sizeof(trap_handler::ProtectedInstructionData) * reader->ReadVector(Vector<byte>::cast(protected_instructions.as_vector()));
protected_instructions->size();
Vector<byte> data(reinterpret_cast<byte*>(protected_instructions->data()),
size);
reader->ReadVector(data);
}
WasmCode* ret = native_module_->AddOwnedCode( WasmCode* ret = native_module_->AddOwnedCode(
code_buffer, std::move(reloc_info), reloc_size, std::move(source_pos), code_buffer, std::move(reloc_info), reloc_size, std::move(source_pos),
source_position_size, Just(fn_index), WasmCode::kFunction, source_position_size, Just(fn_index), WasmCode::kFunction,
......
...@@ -3438,10 +3438,7 @@ TEST(Liftoff_tier_up) { ...@@ -3438,10 +3438,7 @@ TEST(Liftoff_tier_up) {
memcpy(buffer.get(), sub_code->instructions().start(), sub_size); memcpy(buffer.get(), sub_code->instructions().start(), 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<ProtectedInstructions> protected_instructions( native_module->AddCode(desc, 0, add.function_index(), 0, 0, {},
new ProtectedInstructions(sub_code->protected_instructions()));
native_module->AddCode(desc, 0, add.function_index(), 0, 0,
std::move(protected_instructions),
OwnedVector<byte>(), WasmCode::kOther); OwnedVector<byte>(), WasmCode::kOther);
// Second run should now execute {sub}. // Second run should now execute {sub}.
......
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