Commit 6ed7edf6 authored by Kim-Anh Tran's avatar Kim-Anh Tran Committed by Commit Bot

[wasm] Add prologue to Liftoff-compiled code for tiering

The prologue checks if optimized code exists, and if not, continues
execution of the current function. Otherwise, it jumps to the address
specified in the native module's code_table.

Also-by: clemensh@chromium.org
Change-Id: If3e76de02115f44ab7758590a949c3f0965a11ca
Reviewed-on: https://chromium-review.googlesource.com/985837
Commit-Queue: Kim-Anh Tran <kimanh@google.com>
Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52471}
parent 9160b832
...@@ -144,6 +144,12 @@ Address RelocInfo::target_internal_reference_address() { ...@@ -144,6 +144,12 @@ Address RelocInfo::target_internal_reference_address() {
return reinterpret_cast<Address>(pc_); return reinterpret_cast<Address>(pc_);
} }
void RelocInfo::set_wasm_code_table_entry(Address target,
ICacheFlushMode icache_flush_mode) {
DCHECK(rmode_ == RelocInfo::WASM_CODE_TABLE_ENTRY);
Assembler::set_target_address_at(pc_, constant_pool_, target,
icache_flush_mode);
}
Address RelocInfo::target_runtime_entry(Assembler* origin) { Address RelocInfo::target_runtime_entry(Assembler* origin) {
DCHECK(IsRuntimeEntry(rmode_)); DCHECK(IsRuntimeEntry(rmode_));
......
...@@ -674,6 +674,12 @@ Address RelocInfo::target_internal_reference_address() { ...@@ -674,6 +674,12 @@ Address RelocInfo::target_internal_reference_address() {
return reinterpret_cast<Address>(pc_); return reinterpret_cast<Address>(pc_);
} }
void RelocInfo::set_wasm_code_table_entry(Address target,
ICacheFlushMode icache_flush_mode) {
DCHECK(rmode_ == RelocInfo::WASM_CODE_TABLE_ENTRY);
Assembler::set_target_address_at(pc_, constant_pool_, target,
icache_flush_mode);
}
Address RelocInfo::target_runtime_entry(Assembler* origin) { Address RelocInfo::target_runtime_entry(Assembler* origin) {
DCHECK(IsRuntimeEntry(rmode_)); DCHECK(IsRuntimeEntry(rmode_));
......
...@@ -539,6 +539,8 @@ const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) { ...@@ -539,6 +539,8 @@ const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
return "global handle"; return "global handle";
case WASM_CALL: case WASM_CALL:
return "internal wasm call"; return "internal wasm call";
case WASM_CODE_TABLE_ENTRY:
return "wasm code table entry";
case JS_TO_WASM_CALL: case JS_TO_WASM_CALL:
return "js to wasm call"; return "js to wasm call";
case NUMBER_OF_MODES: case NUMBER_OF_MODES:
...@@ -640,6 +642,7 @@ void RelocInfo::Verify(Isolate* isolate) { ...@@ -640,6 +642,7 @@ void RelocInfo::Verify(Isolate* isolate) {
case WASM_GLOBAL_HANDLE: case WASM_GLOBAL_HANDLE:
case WASM_CALL: case WASM_CALL:
case JS_TO_WASM_CALL: case JS_TO_WASM_CALL:
case WASM_CODE_TABLE_ENTRY:
case NONE: case NONE:
break; break;
case NUMBER_OF_MODES: case NUMBER_OF_MODES:
......
...@@ -396,6 +396,9 @@ class RelocInfo { ...@@ -396,6 +396,9 @@ class RelocInfo {
// cannot be encoded as part of another record. // cannot be encoded as part of another record.
PC_JUMP, PC_JUMP,
// Points to a wasm code table entry.
WASM_CODE_TABLE_ENTRY,
// Pseudo-types // Pseudo-types
NUMBER_OF_MODES, NUMBER_OF_MODES,
NONE, // never recorded value NONE, // never recorded value
...@@ -538,6 +541,8 @@ class RelocInfo { ...@@ -538,6 +541,8 @@ class RelocInfo {
INLINE(void set_target_cell( INLINE(void set_target_cell(
Cell* cell, WriteBarrierMode write_barrier_mode = UPDATE_WRITE_BARRIER, Cell* cell, WriteBarrierMode write_barrier_mode = UPDATE_WRITE_BARRIER,
ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)); ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
INLINE(void set_wasm_code_table_entry(
Address, ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
INLINE(void set_target_external_reference( INLINE(void set_target_external_reference(
Address, ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)); Address, ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
......
...@@ -543,6 +543,9 @@ DEFINE_UINT(wasm_max_mem_pages, v8::internal::wasm::kV8MaxWasmMemoryPages, ...@@ -543,6 +543,9 @@ DEFINE_UINT(wasm_max_mem_pages, v8::internal::wasm::kV8MaxWasmMemoryPages,
"maximum memory size of a wasm instance") "maximum memory size of a wasm instance")
DEFINE_UINT(wasm_max_table_size, v8::internal::wasm::kV8MaxWasmTableSize, DEFINE_UINT(wasm_max_table_size, v8::internal::wasm::kV8MaxWasmTableSize,
"maximum table size of a wasm instance") "maximum table size of a wasm instance")
DEFINE_BOOL(wasm_tier_up, false,
"enable basic tiering up to the optimizing compiler")
DEFINE_IMPLICATION(wasm_tier_up, liftoff)
DEFINE_DEBUG_BOOL(trace_wasm_decoder, false, "trace decoding of wasm code") DEFINE_DEBUG_BOOL(trace_wasm_decoder, false, "trace decoding of wasm code")
DEFINE_DEBUG_BOOL(trace_wasm_decode_time, false, DEFINE_DEBUG_BOOL(trace_wasm_decode_time, false,
"trace decoding time of wasm code") "trace decoding time of wasm code")
......
...@@ -138,6 +138,14 @@ Address RelocInfo::target_internal_reference_address() { ...@@ -138,6 +138,14 @@ Address RelocInfo::target_internal_reference_address() {
return reinterpret_cast<Address>(pc_); return reinterpret_cast<Address>(pc_);
} }
void RelocInfo::set_wasm_code_table_entry(Address target,
ICacheFlushMode icache_flush_mode) {
DCHECK(rmode_ == RelocInfo::WASM_CODE_TABLE_ENTRY);
Memory::Address_at(pc_) = target;
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
Assembler::FlushICache(pc_, sizeof(Address));
}
}
Address RelocInfo::target_runtime_entry(Assembler* origin) { Address RelocInfo::target_runtime_entry(Assembler* origin) {
DCHECK(IsRuntimeEntry(rmode_)); DCHECK(IsRuntimeEntry(rmode_));
......
...@@ -247,6 +247,12 @@ Address RelocInfo::target_internal_reference_address() { ...@@ -247,6 +247,12 @@ Address RelocInfo::target_internal_reference_address() {
return reinterpret_cast<Address>(pc_); return reinterpret_cast<Address>(pc_);
} }
void RelocInfo::set_wasm_code_table_entry(Address target,
ICacheFlushMode icache_flush_mode) {
DCHECK(rmode_ == RelocInfo::WASM_CODE_TABLE_ENTRY);
Assembler::set_target_address_at(pc_, constant_pool_, target,
icache_flush_mode);
}
Address RelocInfo::target_runtime_entry(Assembler* origin) { Address RelocInfo::target_runtime_entry(Assembler* origin) {
DCHECK(IsRuntimeEntry(rmode_)); DCHECK(IsRuntimeEntry(rmode_));
......
...@@ -213,6 +213,12 @@ Address RelocInfo::target_internal_reference_address() { ...@@ -213,6 +213,12 @@ Address RelocInfo::target_internal_reference_address() {
return reinterpret_cast<Address>(pc_); return reinterpret_cast<Address>(pc_);
} }
void RelocInfo::set_wasm_code_table_entry(Address target,
ICacheFlushMode icache_flush_mode) {
DCHECK(rmode_ == RelocInfo::WASM_CODE_TABLE_ENTRY);
Assembler::set_target_address_at(pc_, constant_pool_, target,
icache_flush_mode);
}
Address RelocInfo::target_runtime_entry(Assembler* origin) { Address RelocInfo::target_runtime_entry(Assembler* origin) {
DCHECK(IsRuntimeEntry(rmode_)); DCHECK(IsRuntimeEntry(rmode_));
......
...@@ -200,6 +200,13 @@ void RelocInfo::set_target_external_reference( ...@@ -200,6 +200,13 @@ void RelocInfo::set_target_external_reference(
icache_flush_mode); icache_flush_mode);
} }
void RelocInfo::set_wasm_code_table_entry(Address target,
ICacheFlushMode icache_flush_mode) {
DCHECK(rmode_ == RelocInfo::WASM_CODE_TABLE_ENTRY);
Assembler::set_target_address_at(pc_, constant_pool_, target,
icache_flush_mode);
}
Address RelocInfo::target_runtime_entry(Assembler* origin) { Address RelocInfo::target_runtime_entry(Assembler* origin) {
DCHECK(IsRuntimeEntry(rmode_)); DCHECK(IsRuntimeEntry(rmode_));
return target_address(); return target_address();
......
...@@ -182,6 +182,13 @@ void RelocInfo::set_target_external_reference( ...@@ -182,6 +182,13 @@ void RelocInfo::set_target_external_reference(
icache_flush_mode); icache_flush_mode);
} }
void RelocInfo::set_wasm_code_table_entry(Address target,
ICacheFlushMode icache_flush_mode) {
DCHECK(rmode_ == RelocInfo::WASM_CODE_TABLE_ENTRY);
Assembler::set_target_address_at(pc_, constant_pool_, target,
icache_flush_mode);
}
Address RelocInfo::target_runtime_entry(Assembler* origin) { Address RelocInfo::target_runtime_entry(Assembler* origin) {
DCHECK(IsRuntimeEntry(rmode_)); DCHECK(IsRuntimeEntry(rmode_));
return target_address(); return target_address();
......
...@@ -190,6 +190,8 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -190,6 +190,8 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
void LiftoffAssembler::emit_jump(Label* label) { BAILOUT("emit_jump"); } void LiftoffAssembler::emit_jump(Label* label) { BAILOUT("emit_jump"); }
void LiftoffAssembler::emit_jump(Register target) { BAILOUT("emit_jump"); }
void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label, void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label,
ValueType type, Register lhs, ValueType type, Register lhs,
Register rhs) { Register rhs) {
......
...@@ -193,6 +193,8 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -193,6 +193,8 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
void LiftoffAssembler::emit_jump(Label* label) { BAILOUT("emit_jump"); } void LiftoffAssembler::emit_jump(Label* label) { BAILOUT("emit_jump"); }
void LiftoffAssembler::emit_jump(Register target) { BAILOUT("emit_jump"); }
void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label, void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label,
ValueType type, Register lhs, ValueType type, Register lhs,
Register rhs) { Register rhs) {
......
...@@ -932,6 +932,8 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -932,6 +932,8 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
void LiftoffAssembler::emit_jump(Label* label) { jmp(label); } void LiftoffAssembler::emit_jump(Label* label) { jmp(label); }
void LiftoffAssembler::emit_jump(Register target) { jmp(target); }
void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label, void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label,
ValueType type, Register lhs, ValueType type, Register lhs,
Register rhs) { Register rhs) {
......
...@@ -465,6 +465,8 @@ class LiftoffAssembler : public TurboAssembler { ...@@ -465,6 +465,8 @@ class LiftoffAssembler : public TurboAssembler {
LiftoffRegister src); LiftoffRegister src);
inline void emit_jump(Label*); inline void emit_jump(Label*);
inline void emit_jump(Register);
inline void emit_cond_jump(Condition, Label*, ValueType value, Register lhs, inline void emit_cond_jump(Condition, Label*, ValueType value, Register lhs,
Register rhs = no_reg); Register rhs = no_reg);
// Set {dst} to 1 if condition holds, 0 otherwise. // Set {dst} to 1 if condition holds, 0 otherwise.
......
...@@ -135,7 +135,8 @@ class LiftoffCompiler { ...@@ -135,7 +135,8 @@ class LiftoffCompiler {
compiler::ModuleEnv* env, compiler::ModuleEnv* env,
SourcePositionTableBuilder* source_position_table_builder, SourcePositionTableBuilder* source_position_table_builder,
WasmCompilationData* wasm_compilation_data, WasmCompilationData* wasm_compilation_data,
Zone* compilation_zone, std::unique_ptr<Zone>* codegen_zone) Zone* compilation_zone, std::unique_ptr<Zone>* codegen_zone,
WasmCode* const* code_table_entry)
: asm_(liftoff_asm), : asm_(liftoff_asm),
descriptor_( descriptor_(
GetLoweredCallDescriptor(compilation_zone, call_descriptor)), GetLoweredCallDescriptor(compilation_zone, call_descriptor)),
...@@ -149,7 +150,8 @@ class LiftoffCompiler { ...@@ -149,7 +150,8 @@ class LiftoffCompiler {
wasm_compilation_data_(wasm_compilation_data), wasm_compilation_data_(wasm_compilation_data),
compilation_zone_(compilation_zone), compilation_zone_(compilation_zone),
codegen_zone_(codegen_zone), codegen_zone_(codegen_zone),
safepoint_table_builder_(compilation_zone_) {} safepoint_table_builder_(compilation_zone_),
code_table_entry_(code_table_entry) {}
~LiftoffCompiler() { BindUnboundLabels(nullptr); } ~LiftoffCompiler() { BindUnboundLabels(nullptr); }
...@@ -271,6 +273,49 @@ class LiftoffCompiler { ...@@ -271,6 +273,49 @@ class LiftoffCompiler {
if (ool.continuation) __ bind(ool.continuation.get()); if (ool.continuation) __ bind(ool.continuation.get());
} }
// Inserts a check whether the optimized version of this code already exists.
// If so, it redirects execution to the optimized code.
void JumpToOptimizedCodeIfExisting() {
// Check whether we have an optimized function before
// continuing to execute the Liftoff-compiled code.
// TODO(clemensh): Reduce number of temporary registers.
LiftoffRegList pinned;
LiftoffRegister wasm_code_addr =
pinned.set(__ GetUnusedRegister(kGpReg, pinned));
LiftoffRegister target_code_addr =
pinned.set(__ GetUnusedRegister(kGpReg, pinned));
LiftoffRegister code_start_address =
pinned.set(__ GetUnusedRegister(kGpReg, pinned));
// Get the current code's target address ({instructions_.start()}).
__ ComputeCodeStartAddress(code_start_address.gp());
static LoadType kPointerLoadType =
LoadType::ForValueType(LiftoffAssembler::kWasmIntPtr);
using int_t = std::conditional<kPointerSize == 8, uint64_t, uint32_t>::type;
static_assert(sizeof(int_t) == sizeof(uintptr_t), "weird uintptr_t");
// Get the address of the WasmCode* currently stored in the code table.
__ LoadConstant(target_code_addr,
WasmValue(reinterpret_cast<int_t>(code_table_entry_)),
RelocInfo::WASM_CODE_TABLE_ENTRY);
// Load the corresponding WasmCode*.
__ Load(wasm_code_addr, target_code_addr.gp(), Register::no_reg(), 0,
kPointerLoadType, pinned);
// Load its target address ({instuctions_.start()}).
__ Load(target_code_addr, wasm_code_addr.gp(), Register::no_reg(),
WasmCode::kInstructionStartOffset, kPointerLoadType, pinned);
// If the current code's target address is the same as the
// target address of the stored WasmCode, then continue executing, otherwise
// jump to the updated WasmCode.
Label cont;
__ emit_cond_jump(kEqual, &cont, LiftoffAssembler::kWasmIntPtr,
target_code_addr.gp(), code_start_address.gp());
__ LeaveFrame(StackFrame::WASM_COMPILED);
__ emit_jump(target_code_addr.gp());
__ bind(&cont);
}
void StartFunctionBody(Decoder* decoder, Control* block) { void StartFunctionBody(Decoder* decoder, Control* block) {
__ EnterFrame(StackFrame::WASM_COMPILED); __ EnterFrame(StackFrame::WASM_COMPILED);
__ set_has_frame(true); __ set_has_frame(true);
...@@ -339,6 +384,14 @@ class LiftoffCompiler { ...@@ -339,6 +384,14 @@ class LiftoffCompiler {
StackCheck(0); StackCheck(0);
DCHECK_EQ(__ num_locals(), __ cache_state()->stack_height()); DCHECK_EQ(__ num_locals(), __ cache_state()->stack_height());
// TODO(kimanh): if possible, we want to move this check further up,
// in order to avoid unnecessary overhead each time we enter
// a Liftoff-compiled function that will jump to a Turbofan-compiled
// function.
if (FLAG_wasm_tier_up) {
JumpToOptimizedCodeIfExisting();
}
} }
void GenerateOutOfLineCode(OutOfLineCode& ool) { void GenerateOutOfLineCode(OutOfLineCode& ool) {
...@@ -1519,6 +1572,10 @@ class LiftoffCompiler { ...@@ -1519,6 +1572,10 @@ class LiftoffCompiler {
// patch the actually needed stack size in the end. // patch the actually needed stack size in the end.
uint32_t pc_offset_stack_frame_construction_ = 0; uint32_t pc_offset_stack_frame_construction_ = 0;
// Points to the cell within the {code_table_} of the NativeModule,
// which corresponds to the currently compiled function
WasmCode* const* code_table_entry_ = nullptr;
void TraceCacheState(Decoder* decoder) const { void TraceCacheState(Decoder* decoder) const {
#ifdef DEBUG #ifdef DEBUG
if (!FLAG_trace_liftoff || !FLAG_trace_wasm_decoder) return; if (!FLAG_trace_liftoff || !FLAG_trace_wasm_decoder) return;
...@@ -1555,10 +1612,12 @@ bool compiler::WasmCompilationUnit::ExecuteLiftoffCompilation() { ...@@ -1555,10 +1612,12 @@ bool compiler::WasmCompilationUnit::ExecuteLiftoffCompilation() {
auto call_descriptor = compiler::GetWasmCallDescriptor(&zone, func_body_.sig); auto call_descriptor = compiler::GetWasmCallDescriptor(&zone, func_body_.sig);
base::Optional<TimedHistogramScope> liftoff_compile_time_scope( base::Optional<TimedHistogramScope> liftoff_compile_time_scope(
base::in_place, counters()->liftoff_compile_time()); base::in_place, counters()->liftoff_compile_time());
wasm::WasmCode* const* code_table_entry =
native_module_->code_table().data() + func_index_;
wasm::WasmFullDecoder<wasm::Decoder::kValidate, wasm::LiftoffCompiler> wasm::WasmFullDecoder<wasm::Decoder::kValidate, wasm::LiftoffCompiler>
decoder(&zone, module, func_body_, &liftoff_.asm_, call_descriptor, env_, decoder(&zone, module, func_body_, &liftoff_.asm_, call_descriptor, env_,
&liftoff_.source_position_table_builder_, &wasm_compilation_data_, &liftoff_.source_position_table_builder_, &wasm_compilation_data_,
&zone, &liftoff_.codegen_zone_); &zone, &liftoff_.codegen_zone_, code_table_entry);
decoder.Decode(); decoder.Decode();
liftoff_compile_time_scope.reset(); liftoff_compile_time_scope.reset();
if (!decoder.interface().ok()) { if (!decoder.interface().ok()) {
......
...@@ -620,6 +620,8 @@ void LiftoffAssembler::emit_jump(Label* label) { ...@@ -620,6 +620,8 @@ void LiftoffAssembler::emit_jump(Label* label) {
TurboAssembler::Branch(label); TurboAssembler::Branch(label);
} }
void LiftoffAssembler::emit_jump(Register target) { BAILOUT("emit_jump"); }
void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label, void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label,
ValueType type, Register lhs, ValueType type, Register lhs,
Register rhs) { Register rhs) {
......
...@@ -515,6 +515,8 @@ void LiftoffAssembler::emit_jump(Label* label) { ...@@ -515,6 +515,8 @@ void LiftoffAssembler::emit_jump(Label* label) {
TurboAssembler::Branch(label); TurboAssembler::Branch(label);
} }
void LiftoffAssembler::emit_jump(Register target) { BAILOUT("emit_jump"); }
void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label, void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label,
ValueType type, Register lhs, ValueType type, Register lhs,
Register rhs) { Register rhs) {
......
...@@ -190,6 +190,8 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -190,6 +190,8 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
void LiftoffAssembler::emit_jump(Label* label) { BAILOUT("emit_jump"); } void LiftoffAssembler::emit_jump(Label* label) { BAILOUT("emit_jump"); }
void LiftoffAssembler::emit_jump(Register target) { BAILOUT("emit_jump"); }
void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label, void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label,
ValueType type, Register lhs, ValueType type, Register lhs,
Register rhs) { Register rhs) {
......
...@@ -190,6 +190,8 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -190,6 +190,8 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
void LiftoffAssembler::emit_jump(Label* label) { BAILOUT("emit_jump"); } void LiftoffAssembler::emit_jump(Label* label) { BAILOUT("emit_jump"); }
void LiftoffAssembler::emit_jump(Register target) { BAILOUT("emit_jump"); }
void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label, void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label,
ValueType type, Register lhs, ValueType type, Register lhs,
Register rhs) { Register rhs) {
......
...@@ -842,6 +842,8 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -842,6 +842,8 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
void LiftoffAssembler::emit_jump(Label* label) { jmp(label); } void LiftoffAssembler::emit_jump(Label* label) { jmp(label); }
void LiftoffAssembler::emit_jump(Register target) { jmp(target); }
void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label, void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label,
ValueType type, Register lhs, ValueType type, Register lhs,
Register rhs) { Register rhs) {
......
...@@ -462,10 +462,24 @@ NativeModule::NativeModule(uint32_t num_functions, uint32_t num_imports, ...@@ -462,10 +462,24 @@ NativeModule::NativeModule(uint32_t num_functions, uint32_t num_imports,
owned_code_.reserve(num_functions); owned_code_.reserve(num_functions);
} }
void NativeModule::ResizeCodeTableForTest(size_t last_index) { void NativeModule::ResizeCodeTableForTesting(size_t num_functions,
size_t new_size = last_index + 1; size_t max_functions) {
if (new_size > FunctionCount()) { DCHECK_LE(num_functions, max_functions);
code_table_.resize(new_size); if (num_imported_functions_ == num_functions) {
// For some tests, the code table might have been initialized to store
// a number of imported functions on creation. If that is the case,
// we need to retroactively reserve the space.
DCHECK_EQ(code_table_.capacity(), num_imported_functions_);
DCHECK_EQ(code_table_.size(), num_imported_functions_);
DCHECK_EQ(num_functions, 1);
code_table_.reserve(max_functions);
} else {
DCHECK_GT(num_functions, FunctionCount());
if (code_table_.capacity() == 0) {
code_table_.reserve(max_functions);
}
DCHECK_EQ(code_table_.capacity(), max_functions);
code_table_.resize(num_functions);
} }
} }
......
...@@ -141,6 +141,11 @@ class V8_EXPORT_PRIVATE WasmCode final { ...@@ -141,6 +141,11 @@ class V8_EXPORT_PRIVATE WasmCode final {
enum FlushICache : bool { kFlushICache = true, kNoFlushICache = false }; enum FlushICache : bool { kFlushICache = true, kNoFlushICache = false };
// Offset of {instructions_.start()}. It is used for tiering, when
// we check if optimized code is available during the prologue
// of Liftoff-compiled code.
static constexpr int kInstructionStartOffset = 0;
private: private:
friend class NativeModule; friend class NativeModule;
...@@ -169,6 +174,7 @@ class V8_EXPORT_PRIVATE WasmCode final { ...@@ -169,6 +174,7 @@ class V8_EXPORT_PRIVATE WasmCode final {
DCHECK_LE(safepoint_table_offset, instructions.size()); DCHECK_LE(safepoint_table_offset, instructions.size());
DCHECK_LE(constant_pool_offset, instructions.size()); DCHECK_LE(constant_pool_offset, instructions.size());
DCHECK_LE(handler_table_offset, instructions.size()); DCHECK_LE(handler_table_offset, instructions.size());
DCHECK_EQ(kInstructionStartOffset, OFFSET_OF(WasmCode, instructions_));
} }
Vector<byte> instructions_; Vector<byte> instructions_;
...@@ -253,7 +259,7 @@ class V8_EXPORT_PRIVATE NativeModule final { ...@@ -253,7 +259,7 @@ class V8_EXPORT_PRIVATE NativeModule final {
// For cctests, where we build both WasmModule and the runtime objects // For cctests, where we build both WasmModule and the runtime objects
// on the fly, and bypass the instance builder pipeline. // on the fly, and bypass the instance builder pipeline.
void ResizeCodeTableForTest(size_t); void ResizeCodeTableForTesting(size_t num_functions, size_t max_functions);
CompilationState* compilation_state() { return compilation_state_.get(); } CompilationState* compilation_state() { return compilation_state_.get(); }
...@@ -264,6 +270,8 @@ class V8_EXPORT_PRIVATE NativeModule final { ...@@ -264,6 +270,8 @@ class V8_EXPORT_PRIVATE NativeModule final {
uint32_t num_imported_functions() const { return num_imported_functions_; } uint32_t num_imported_functions() const { return num_imported_functions_; }
const std::vector<WasmCode*>& code_table() const { return code_table_; }
size_t committed_memory() const { return committed_memory_; } size_t committed_memory() const { return committed_memory_; }
const size_t instance_id = 0; const size_t instance_id = 0;
~NativeModule(); ~NativeModule();
......
...@@ -166,6 +166,10 @@ bool CodeSpecialization::ApplyToWasmCode(wasm::WasmCode* code, ...@@ -166,6 +166,10 @@ bool CodeSpecialization::ApplyToWasmCode(wasm::WasmCode* code,
}; };
add_mode(reloc_direct_calls, RelocInfo::WASM_CALL); add_mode(reloc_direct_calls, RelocInfo::WASM_CALL);
// Always patch the code table entry address which is used in Liftoff
// prologue to jump to optimized code if existent.
reloc_mode |= RelocInfo::ModeMask(RelocInfo::WASM_CODE_TABLE_ENTRY);
base::Optional<PatchDirectCallsHelper> patch_direct_calls_helper; base::Optional<PatchDirectCallsHelper> patch_direct_calls_helper;
bool changed = false; bool changed = false;
...@@ -198,6 +202,16 @@ bool CodeSpecialization::ApplyToWasmCode(wasm::WasmCode* code, ...@@ -198,6 +202,16 @@ bool CodeSpecialization::ApplyToWasmCode(wasm::WasmCode* code,
icache_flush_mode); icache_flush_mode);
changed = true; changed = true;
} break; } break;
case RelocInfo::WASM_CODE_TABLE_ENTRY: {
DCHECK(FLAG_wasm_tier_up);
WasmCode* const* code_table_entry =
native_module->code_table().data() + code->index();
it.rinfo()->set_wasm_code_table_entry(
const_cast<Address>(
reinterpret_cast<byte const*>(code_table_entry)),
icache_flush_mode);
} break;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
......
...@@ -336,6 +336,14 @@ Handle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) { ...@@ -336,6 +336,14 @@ Handle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) {
} }
} }
void RelocInfo::set_wasm_code_table_entry(Address target,
ICacheFlushMode icache_flush_mode) {
DCHECK(rmode_ == RelocInfo::WASM_CODE_TABLE_ENTRY);
Memory::Address_at(pc_) = target;
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
Assembler::FlushICache(pc_, sizeof(Address));
}
}
Address RelocInfo::target_external_reference() { Address RelocInfo::target_external_reference() {
DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE); DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
......
...@@ -45,7 +45,8 @@ TestingModuleBuilder::TestingModuleBuilder( ...@@ -45,7 +45,8 @@ TestingModuleBuilder::TestingModuleBuilder(
isolate_, maybe_import->js_function, maybe_import->sig, isolate_, maybe_import->js_function, maybe_import->sig,
maybe_import_index, test_module_.origin(), maybe_import_index, test_module_.origin(),
trap_handler::IsTrapHandlerEnabled()); trap_handler::IsTrapHandlerEnabled());
native_module_->ResizeCodeTableForTest(maybe_import_index); native_module_->ResizeCodeTableForTesting(maybe_import_index + 1,
kMaxFunctions);
auto wasm_to_js_wrapper = native_module_->AddCodeCopy( auto wasm_to_js_wrapper = native_module_->AddCodeCopy(
code, wasm::WasmCode::kWasmToJsWrapper, maybe_import_index); code, wasm::WasmCode::kWasmToJsWrapper, maybe_import_index);
...@@ -99,7 +100,7 @@ uint32_t TestingModuleBuilder::AddFunction(FunctionSig* sig, const char* name) { ...@@ -99,7 +100,7 @@ uint32_t TestingModuleBuilder::AddFunction(FunctionSig* sig, const char* name) {
} }
uint32_t index = static_cast<uint32_t>(test_module_.functions.size()); uint32_t index = static_cast<uint32_t>(test_module_.functions.size());
if (native_module_) { if (native_module_) {
native_module_->ResizeCodeTableForTest(index); native_module_->ResizeCodeTableForTesting(index + 1, kMaxFunctions);
} }
test_module_.functions.push_back({sig, index, 0, {0, 0}, false, false}); test_module_.functions.push_back({sig, index, 0, {0, 0}, false, false});
if (name) { if (name) {
...@@ -420,7 +421,6 @@ void WasmFunctionCompiler::Build(const byte* start, const byte* end) { ...@@ -420,7 +421,6 @@ void WasmFunctionCompiler::Build(const byte* start, const byte* end) {
Handle<WasmCompiledModule> compiled_module( Handle<WasmCompiledModule> compiled_module(
builder_->instance_object()->compiled_module(), isolate()); builder_->instance_object()->compiled_module(), isolate());
NativeModule* native_module = compiled_module->GetNativeModule(); NativeModule* native_module = compiled_module->GetNativeModule();
native_module->ResizeCodeTableForTest(function_->func_index);
Handle<SeqOneByteString> wire_bytes(compiled_module->shared()->module_bytes(), Handle<SeqOneByteString> wire_bytes(compiled_module->shared()->module_bytes(),
isolate()); isolate());
......
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