[arm64] Remove deopt tables.

We can instead pass the deopt id in a register, where before we were passing the
deopt entry address. This removes the need for the deopt tables altogether,
saving 192kB.

Change-Id: I479d4de1a0245de328720b6b03a1955c8c63f696
Reviewed-on: https://chromium-review.googlesource.com/1076472
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Georgia Kouveli <georgia.kouveli@arm.com>
Cr-Commit-Position: refs/heads/master@{#53863}
This commit is contained in:
Georgia Kouveli 2018-06-19 12:39:25 +01:00 committed by Commit Bot
parent 8c4a30acab
commit cdb2ef01f5
24 changed files with 148 additions and 86 deletions

View File

@ -43,6 +43,7 @@
#include "src/base/bits.h"
#include "src/base/cpu.h"
#include "src/code-stubs.h"
#include "src/deoptimizer.h"
#include "src/macro-assembler.h"
#include "src/objects-inl.h"
@ -338,6 +339,11 @@ bool RelocInfo::IsInConstantPool() {
return Assembler::is_constant_pool_load(pc_);
}
int RelocInfo::GetDeoptimizationId(Isolate* isolate, DeoptimizeKind kind) {
DCHECK(IsRuntimeEntry(rmode_));
return Deoptimizer::GetDeoptimizationId(isolate, target_address(), kind);
}
void RelocInfo::set_js_to_wasm_address(Address address,
ICacheFlushMode icache_flush_mode) {
DCHECK_EQ(rmode_, JS_TO_WASM_CALL);

View File

@ -358,7 +358,9 @@ class TurboAssembler : public TurboAssemblerBase {
// This should only be used when assembling a deoptimizer call because of
// the CheckConstPool invocation, which is only needed for deoptimization.
void CallForDeoptimization(Address target, RelocInfo::Mode rmode) {
void CallForDeoptimization(Address target, int deopt_id,
RelocInfo::Mode rmode) {
USE(deopt_id);
Call(target, rmode);
CheckConstPool(false, false);
}

View File

@ -180,6 +180,17 @@ bool RelocInfo::IsInConstantPool() {
return instr->IsLdrLiteralX();
}
int RelocInfo::GetDeoptimizationId(Isolate* isolate, DeoptimizeKind kind) {
DCHECK(IsRuntimeEntry(rmode_));
Instruction* movz_instr = reinterpret_cast<Instruction*>(pc_)->preceding();
DCHECK(movz_instr->IsMovz());
uint64_t imm = static_cast<uint64_t>(movz_instr->ImmMoveWide())
<< (16 * movz_instr->ShiftMoveWide());
DCHECK_LE(imm, INT_MAX);
return static_cast<int>(imm);
}
void RelocInfo::set_js_to_wasm_address(Address address,
ICacheFlushMode icache_flush_mode) {
DCHECK_EQ(rmode_, JS_TO_WASM_CALL);

View File

@ -275,50 +275,18 @@ void Deoptimizer::TableEntryGenerator::Generate() {
__ Br(continuation);
}
// Size of an entry of the second level deopt table.
// This is the code size generated by GeneratePrologue for one entry.
const int Deoptimizer::table_entry_size_ = kInstructionSize;
// Size of an entry of the second level deopt table. Since we do not generate
// a table for ARM64, the size is zero.
const int Deoptimizer::table_entry_size_ = 0 * kInstructionSize;
void Deoptimizer::TableEntryGenerator::GeneratePrologue() {
UseScratchRegisterScope temps(masm());
// The address at which the deopt table is entered should be in x16, the first
// temp register allocated. We can't assert that the address is in there, but
// we can check that it's the first allocated temp. Later, we'll also check
// the computed entry_id is in the expected range.
Register entry_addr = temps.AcquireX();
// The MacroAssembler will have put the deoptimization id in x16, the first
// temp register allocated. We can't assert that the id is in there, but we
// can check that x16 the first allocated temp and that the value it contains
// is in the expected range.
Register entry_id = temps.AcquireX();
DCHECK(entry_addr.Is(x16));
DCHECK(entry_id.Is(x17));
// Create a sequence of deoptimization entries.
// Note that registers are still live when jumping to an entry.
{
InstructionAccurateScope scope(masm());
Label start_of_table, end_of_table;
__ bind(&start_of_table);
for (int i = 0; i < count(); i++) {
int start = masm()->pc_offset();
USE(start);
__ b(&end_of_table);
DCHECK(masm()->pc_offset() - start == table_entry_size_);
}
__ bind(&end_of_table);
// Get the address of the start of the table.
DCHECK(is_int21(table_entry_size_ * count()));
__ adr(entry_id, &start_of_table);
// Compute the gap in bytes between the entry address, which should have
// been left in entry_addr (x16) by CallForDeoptimization, and the start of
// the table.
__ sub(entry_id, entry_addr, entry_id);
// Shift down to obtain the entry_id.
DCHECK_EQ(table_entry_size_, kInstructionSize);
__ lsr(entry_id, entry_id, kInstructionSizeLog2);
}
DCHECK(entry_id.Is(x16));
__ Push(padreg, entry_id);
if (__ emit_debug_code()) {

View File

@ -2091,7 +2091,7 @@ bool TurboAssembler::IsNearCallOffset(int64_t offset) {
return is_int26(offset);
}
void TurboAssembler::CallForDeoptimization(Address target,
void TurboAssembler::CallForDeoptimization(Address target, int deopt_id,
RelocInfo::Mode rmode) {
DCHECK_EQ(rmode, RelocInfo::RUNTIME_ENTRY);
@ -2100,22 +2100,20 @@ void TurboAssembler::CallForDeoptimization(Address target,
Label start_call;
Bind(&start_call);
#endif
// The deoptimizer requires the deoptimization id to be in x16.
UseScratchRegisterScope temps(this);
Register temp = temps.AcquireX();
// Deoptimisation table entries require the call address to be in x16, in
// order to compute the entry id.
// TODO(all): Put the entry id back in the table now that we are using
// a direct branch for the call and do not need to set up x16.
DCHECK(temp.Is(x16));
Mov(temp, Immediate(target, rmode));
// Make sure that the deopt id can be encoded in 16 bits, so can be encoded
// in a single movz instruction with a zero shift.
DCHECK(is_uint16(deopt_id));
movz(temp, deopt_id);
int64_t offset = static_cast<int64_t>(target) -
static_cast<int64_t>(isolate_data().code_range_start);
DCHECK_EQ(offset % kInstructionSize, 0);
offset = offset / static_cast<int>(kInstructionSize);
DCHECK(IsNearCallOffset(offset));
near_call(static_cast<int>(offset), rmode);
near_call(static_cast<int>(offset), RelocInfo::RUNTIME_ENTRY);
#ifdef DEBUG
AssertSizeOfCodeGeneratedSince(&start_call, kNearCallSize + kInstructionSize);

View File

@ -902,7 +902,8 @@ class TurboAssembler : public TurboAssemblerBase {
// Generate an indirect call (for when a direct call's range is not adequate).
void IndirectCall(Address target, RelocInfo::Mode rmode);
void CallForDeoptimization(Address target, RelocInfo::Mode rmode);
void CallForDeoptimization(Address target, int deopt_id,
RelocInfo::Mode rmode);
// For every Call variant, there is a matching CallSize function that returns
// the size (in bytes) of the call sequence.

View File

@ -595,11 +595,12 @@ void RelocInfo::Print(Isolate* isolate, std::ostream& os) { // NOLINT
os << ") ";
os << " (" << reinterpret_cast<const void*>(target_address()) << ")";
} else if (IsRuntimeEntry(rmode_) && isolate->deoptimizer_data() != nullptr) {
// Depotimization bailouts are stored as runtime entries.
int id = Deoptimizer::GetDeoptimizationId(isolate, target_address(),
DeoptimizeKind::kEager);
if (id != Deoptimizer::kNotDeoptimizationEntry) {
os << " (deoptimization bailout " << id << ")";
// Deoptimization bailouts are stored as runtime entries.
DeoptimizeKind type;
if (Deoptimizer::IsDeoptimizationEntry(isolate, target_address(), &type)) {
int id = GetDeoptimizationId(isolate, type);
os << " (" << Deoptimizer::MessageFor(type) << " deoptimization bailout "
<< id << ")";
}
} else if (IsConstPool(rmode_)) {
os << " (size " << static_cast<int>(data_) << ")";

View File

@ -571,6 +571,11 @@ class RelocInfo {
// constant pool, otherwise the pointer is embedded in the instruction stream.
bool IsInConstantPool();
// Returns the deoptimization id for the entry associated with the reloc info
// where {kind} is the deoptimization kind.
// This is only used for printing RUNTIME_ENTRY relocation info.
int GetDeoptimizationId(Isolate* isolate, DeoptimizeKind kind);
Address wasm_call_address() const;
Address wasm_stub_call_address() const;
Address js_to_wasm_address() const;

View File

@ -126,7 +126,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
if (info()->is_source_positions_enabled()) {
tasm()->RecordDeoptReason(deoptimization_reason, pos, deoptimization_id);
}
tasm()->CallForDeoptimization(deopt_entry, RelocInfo::RUNTIME_ENTRY);
tasm()->CallForDeoptimization(deopt_entry, deoptimization_id,
RelocInfo::RUNTIME_ENTRY);
return kSuccess;
}

View File

@ -600,18 +600,43 @@ int Deoptimizer::GetDeoptimizationId(Isolate* isolate, Address addr,
DeoptimizeKind kind) {
DeoptimizerData* data = isolate->deoptimizer_data();
CHECK_LE(kind, DeoptimizerData::kLastDeoptimizeKind);
DCHECK(IsInDeoptimizationTable(isolate, addr, kind));
Code* code = data->deopt_entry_code(kind);
if (code == nullptr) return kNotDeoptimizationEntry;
Address start = code->raw_instruction_start();
if (addr < start ||
addr >= start + (kMaxNumberOfEntries * table_entry_size_)) {
return kNotDeoptimizationEntry;
}
DCHECK_EQ(0,
static_cast<int>(addr - start) % table_entry_size_);
return static_cast<int>(addr - start) / table_entry_size_;
}
bool Deoptimizer::IsInDeoptimizationTable(Isolate* isolate, Address addr,
DeoptimizeKind type) {
DeoptimizerData* data = isolate->deoptimizer_data();
CHECK_LE(type, DeoptimizerData::kLastDeoptimizeKind);
Code* code = data->deopt_entry_code(type);
if (code == nullptr) return false;
Address start = code->raw_instruction_start();
return ((table_entry_size_ == 0 && addr == start) ||
(addr >= start &&
addr < start + (kMaxNumberOfEntries * table_entry_size_)));
}
bool Deoptimizer::IsDeoptimizationEntry(Isolate* isolate, Address addr,
DeoptimizeKind* type) {
if (IsInDeoptimizationTable(isolate, addr, DeoptimizeKind::kEager)) {
*type = DeoptimizeKind::kEager;
return true;
}
if (IsInDeoptimizationTable(isolate, addr, DeoptimizeKind::kSoft)) {
*type = DeoptimizeKind::kSoft;
return true;
}
if (IsInDeoptimizationTable(isolate, addr, DeoptimizeKind::kLazy)) {
*type = DeoptimizeKind::kLazy;
return true;
}
return false;
}
int Deoptimizer::GetDeoptimizedCodeCount(Isolate* isolate) {
int length = 0;
// Count all entries in the deoptimizing code list of every context.

View File

@ -478,6 +478,11 @@ class Deoptimizer : public Malloced {
static int GetDeoptimizationId(Isolate* isolate, Address addr,
DeoptimizeKind kind);
// Returns true if {addr} is a deoptimization entry and stores its type in
// {type}. Returns false if {addr} is not a deoptimization entry.
static bool IsDeoptimizationEntry(Isolate* isolate, Address addr,
DeoptimizeKind* type);
// Code generation support.
static int input_offset() { return OFFSET_OF(Deoptimizer, input_); }
static int output_count_offset() {
@ -536,6 +541,9 @@ class Deoptimizer : public Malloced {
void PrintFunctionName();
void DeleteFrameDescriptions();
static bool IsInDeoptimizationTable(Isolate* isolate, Address addr,
DeoptimizeKind type);
void DoComputeOutputFrames();
void DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
int frame_index, bool goto_catch_handler);

View File

@ -152,26 +152,15 @@ static void PrintRelocInfo(StringBuilder* out, Isolate* isolate,
}
} else if (RelocInfo::IsRuntimeEntry(rmode) && isolate &&
isolate->deoptimizer_data() != nullptr) {
// A runtime entry reloinfo might be a deoptimization bailout->
// A runtime entry relocinfo might be a deoptimization bailout.
Address addr = relocinfo->target_address();
int id =
Deoptimizer::GetDeoptimizationId(isolate, addr, DeoptimizeKind::kEager);
if (id == Deoptimizer::kNotDeoptimizationEntry) {
id = Deoptimizer::GetDeoptimizationId(isolate, addr,
DeoptimizeKind::kLazy);
if (id == Deoptimizer::kNotDeoptimizationEntry) {
id = Deoptimizer::GetDeoptimizationId(isolate, addr,
DeoptimizeKind::kSoft);
if (id == Deoptimizer::kNotDeoptimizationEntry) {
out->AddFormatted(" ;; %s", RelocInfo::RelocModeName(rmode));
} else {
out->AddFormatted(" ;; soft deoptimization bailout %d", id);
}
} else {
out->AddFormatted(" ;; lazy deoptimization bailout %d", id);
}
DeoptimizeKind type;
if (Deoptimizer::IsDeoptimizationEntry(isolate, addr, &type)) {
int id = relocinfo->GetDeoptimizationId(isolate, type);
out->AddFormatted(" ;; %s deoptimization bailout %d",
Deoptimizer::MessageFor(type), id);
} else {
out->AddFormatted(" ;; deoptimization bailout %d", id);
out->AddFormatted(" ;; %s", RelocInfo::RelocModeName(rmode));
}
} else {
out->AddFormatted(" ;; %s", RelocInfo::RelocModeName(rmode));

View File

@ -52,6 +52,7 @@
#include "src/base/cpu.h"
#include "src/code-stubs.h"
#include "src/conversions-inl.h"
#include "src/deoptimizer.h"
#include "src/disassembler.h"
#include "src/macro-assembler.h"
#include "src/v8.h"
@ -205,6 +206,11 @@ bool RelocInfo::IsInConstantPool() {
return false;
}
int RelocInfo::GetDeoptimizationId(Isolate* isolate, DeoptimizeKind kind) {
DCHECK(IsRuntimeEntry(rmode_));
return Deoptimizer::GetDeoptimizationId(isolate, target_address(), kind);
}
void RelocInfo::set_js_to_wasm_address(Address address,
ICacheFlushMode icache_flush_mode) {
DCHECK_EQ(rmode_, JS_TO_WASM_CALL);

View File

@ -122,7 +122,9 @@ class TurboAssembler : public TurboAssemblerBase {
void RetpolineJump(Register reg);
void CallForDeoptimization(Address target, RelocInfo::Mode rmode) {
void CallForDeoptimization(Address target, int deopt_id,
RelocInfo::Mode rmode) {
USE(deopt_id);
call(target, rmode);
}

View File

@ -39,6 +39,7 @@
#include "src/base/bits.h"
#include "src/base/cpu.h"
#include "src/code-stubs.h"
#include "src/deoptimizer.h"
#include "src/mips/assembler-mips-inl.h"
namespace v8 {
@ -198,6 +199,11 @@ bool RelocInfo::IsInConstantPool() {
return false;
}
int RelocInfo::GetDeoptimizationId(Isolate* isolate, DeoptimizeKind kind) {
DCHECK(IsRuntimeEntry(rmode_));
return Deoptimizer::GetDeoptimizationId(isolate, target_address(), kind);
}
void RelocInfo::set_js_to_wasm_address(Address address,
ICacheFlushMode icache_flush_mode) {
DCHECK_EQ(rmode_, JS_TO_WASM_CALL);

View File

@ -281,7 +281,9 @@ class TurboAssembler : public TurboAssemblerBase {
COND_ARGS);
void Call(Label* target);
void CallForDeoptimization(Address target, RelocInfo::Mode rmode) {
void CallForDeoptimization(Address target, int deopt_id,
RelocInfo::Mode rmode) {
USE(deopt_id);
Call(target, rmode);
}

View File

@ -38,6 +38,7 @@
#include "src/base/cpu.h"
#include "src/code-stubs.h"
#include "src/deoptimizer.h"
#include "src/mips64/assembler-mips64-inl.h"
namespace v8 {
@ -176,6 +177,11 @@ bool RelocInfo::IsInConstantPool() {
return false;
}
int RelocInfo::GetDeoptimizationId(Isolate* isolate, DeoptimizeKind kind) {
DCHECK(IsRuntimeEntry(rmode_));
return Deoptimizer::GetDeoptimizationId(isolate, target_address(), kind);
}
void RelocInfo::set_js_to_wasm_address(Address address,
ICacheFlushMode icache_flush_mode) {
DCHECK_EQ(rmode_, JS_TO_WASM_CALL);

View File

@ -298,7 +298,9 @@ class TurboAssembler : public TurboAssemblerBase {
COND_ARGS);
void Call(Label* target);
void CallForDeoptimization(Address target, RelocInfo::Mode rmode) {
void CallForDeoptimization(Address target, int deopt_id,
RelocInfo::Mode rmode) {
USE(deopt_id);
Call(target, rmode);
}

View File

@ -41,6 +41,7 @@
#include "src/base/bits.h"
#include "src/base/cpu.h"
#include "src/code-stubs.h"
#include "src/deoptimizer.h"
#include "src/macro-assembler.h"
#include "src/ppc/assembler-ppc-inl.h"
@ -161,6 +162,11 @@ bool RelocInfo::IsInConstantPool() {
return false;
}
int RelocInfo::GetDeoptimizationId(Isolate* isolate, DeoptimizeKind kind) {
DCHECK(IsRuntimeEntry(rmode_));
return Deoptimizer::GetDeoptimizationId(isolate, target_address(), kind);
}
void RelocInfo::set_js_to_wasm_address(Address address,
ICacheFlushMode icache_flush_mode) {
DCHECK_EQ(rmode_, JS_TO_WASM_CALL);

View File

@ -471,7 +471,9 @@ class TurboAssembler : public TurboAssemblerBase {
Condition cond = al);
void Call(Label* target);
void CallForDeoptimization(Address target, RelocInfo::Mode rmode) {
void CallForDeoptimization(Address target, int deopt_id,
RelocInfo::Mode rmode) {
USE(deopt_id);
Call(target, rmode);
}

View File

@ -48,6 +48,7 @@
#include "src/base/bits.h"
#include "src/base/cpu.h"
#include "src/code-stubs.h"
#include "src/deoptimizer.h"
#include "src/macro-assembler.h"
#include "src/s390/assembler-s390-inl.h"
@ -271,6 +272,11 @@ bool RelocInfo::IsCodedSpecially() {
bool RelocInfo::IsInConstantPool() { return false; }
int RelocInfo::GetDeoptimizationId(Isolate* isolate, DeoptimizeKind kind) {
DCHECK(IsRuntimeEntry(rmode_));
return Deoptimizer::GetDeoptimizationId(isolate, target_address(), kind);
}
void RelocInfo::set_js_to_wasm_address(Address address,
ICacheFlushMode icache_flush_mode) {
DCHECK_EQ(rmode_, JS_TO_WASM_CALL);

View File

@ -215,7 +215,9 @@ class TurboAssembler : public TurboAssemblerBase {
void Ret() { b(r14); }
void Ret(Condition cond) { b(cond, r14); }
void CallForDeoptimization(Address target, RelocInfo::Mode rmode) {
void CallForDeoptimization(Address target, int deopt_id,
RelocInfo::Mode rmode) {
USE(deopt_id);
Call(target, rmode);
}

View File

@ -19,6 +19,7 @@
#include "src/base/bits.h"
#include "src/base/cpu.h"
#include "src/code-stubs.h"
#include "src/deoptimizer.h"
#include "src/macro-assembler.h"
#include "src/v8.h"
@ -4857,6 +4858,10 @@ bool RelocInfo::IsInConstantPool() {
return false;
}
int RelocInfo::GetDeoptimizationId(Isolate* isolate, DeoptimizeKind kind) {
DCHECK(IsRuntimeEntry(rmode_));
return Deoptimizer::GetDeoptimizationId(isolate, target_address(), kind);
}
} // namespace internal
} // namespace v8

View File

@ -410,7 +410,9 @@ class TurboAssembler : public TurboAssemblerBase {
void RetpolineJump(Register reg);
void CallForDeoptimization(Address target, RelocInfo::Mode rmode) {
void CallForDeoptimization(Address target, int deopt_id,
RelocInfo::Mode rmode) {
USE(deopt_id);
call(target, rmode);
}