Commit 207d6b35 authored by Georgia Kouveli's avatar Georgia Kouveli Committed by Commit Bot

[arm64] Reduce code size of deoptimization exits

Do not pass the deoptimization index in a register, instead infer it
from the address we made the deoptimization call from. This makes the
deoptimization exit sequence one instruction long instead of two.

This requires emitting all deoptimization exits at the end of the
function in a contiguous block, making sure no constant or veneer
pools are emitted in between. This means that soft deoptimizations
require an additional branch to the end of the function, which
counteracts the removal of the move instruction, however soft
deoptimizations are rare compared to eager and lazy ones.

This reduces the code size of optimised functions for benchmarks like
Octane and ARES-6 by about 4%.

Change-Id: I771f9104a07de7931a4bb9c5836e25fb55b1a2a4
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1714876
Commit-Queue: Georgia Kouveli <georgia.kouveli@arm.com>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62991}
parent 20655a20
......@@ -13,6 +13,7 @@
#include "src/codegen/macro-assembler-inl.h"
#include "src/codegen/register-configuration.h"
#include "src/debug/debug.h"
#include "src/deoptimizer/deoptimizer.h"
#include "src/execution/frame-constants.h"
#include "src/execution/frames-inl.h"
#include "src/heap/heap-inl.h" // For MemoryChunk.
......@@ -2057,22 +2058,17 @@ bool TurboAssembler::IsNearCallOffset(int64_t offset) {
void TurboAssembler::CallForDeoptimization(Address target, int deopt_id) {
BlockPoolsScope scope(this);
NoRootArrayScope no_root_array(this);
#ifdef DEBUG
Label start;
Bind(&start);
bind(&start);
#endif
// 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(x26, deopt_id);
int64_t offset = static_cast<int64_t>(target) -
static_cast<int64_t>(options().code_range_start);
DCHECK_EQ(offset % kInstrSize, 0);
offset = offset / static_cast<int>(kInstrSize);
DCHECK(IsNearCallOffset(offset));
near_call(static_cast<int>(offset), RelocInfo::RUNTIME_ENTRY);
DCHECK_EQ(SizeOfCodeGeneratedSince(&start), Deoptimizer::kDeoptExitSize);
}
void TurboAssembler::PrepareForTailCall(const ParameterCount& callee_args_count,
......
......@@ -91,32 +91,24 @@ Safepoint SafepointTableBuilder::DefineSafepoint(
Assembler* assembler, Safepoint::DeoptMode deopt_mode) {
deoptimization_info_.push_back(
DeoptimizationInfo(zone_, assembler->pc_offset()));
if (deopt_mode == Safepoint::kNoLazyDeopt) {
last_lazy_safepoint_ = deoptimization_info_.size();
}
DeoptimizationInfo& new_info = deoptimization_info_.back();
return Safepoint(new_info.indexes);
}
void SafepointTableBuilder::RecordLazyDeoptimizationIndex(int index) {
for (auto it = deoptimization_info_.Find(last_lazy_safepoint_);
it != deoptimization_info_.end(); it++, last_lazy_safepoint_++) {
it->deopt_index = index;
}
}
unsigned SafepointTableBuilder::GetCodeOffset() const {
DCHECK(emitted_);
return offset_;
}
int SafepointTableBuilder::UpdateDeoptimizationInfo(int pc, int trampoline,
int start) {
int start,
unsigned deopt_index) {
int index = start;
for (auto it = deoptimization_info_.Find(start);
it != deoptimization_info_.end(); it++, index++) {
if (static_cast<int>(it->pc) == pc) {
it->trampoline = trampoline;
it->deopt_index = deopt_index;
return index;
}
}
......
......@@ -164,7 +164,6 @@ class SafepointTableBuilder {
explicit SafepointTableBuilder(Zone* zone)
: deoptimization_info_(zone),
emitted_(false),
last_lazy_safepoint_(0),
zone_(zone) {}
// Get the offset of the emitted safepoint table in the code.
......@@ -173,13 +172,6 @@ class SafepointTableBuilder {
// Define a new safepoint for the current position in the body.
Safepoint DefineSafepoint(Assembler* assembler, Safepoint::DeoptMode mode);
// Record deoptimization index for lazy deoptimization for the last
// outstanding safepoints.
void RecordLazyDeoptimizationIndex(int index);
void BumpLastLazySafepointIndex() {
last_lazy_safepoint_ = deoptimization_info_.size();
}
// Emit the safepoint table after the body. The number of bits per
// entry must be enough to hold all the pointer indexes.
V8_EXPORT_PRIVATE void Emit(Assembler* assembler, int bits_per_entry);
......@@ -188,7 +180,8 @@ class SafepointTableBuilder {
// trampoline field. Calling this function ensures that the safepoint
// table contains the trampoline PC {trampoline} that replaced the
// return PC {pc} on the stack.
int UpdateDeoptimizationInfo(int pc, int trampoline, int start);
int UpdateDeoptimizationInfo(int pc, int trampoline, int start,
unsigned deopt_index);
private:
struct DeoptimizationInfo {
......@@ -215,7 +208,6 @@ class SafepointTableBuilder {
unsigned offset_;
bool emitted_;
size_t last_lazy_safepoint_;
Zone* zone_;
......
......@@ -909,10 +909,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
DCHECK_EQ(LeaveCC, i.OutputSBit());
break;
case kArchDeoptimize: {
int deopt_state_id =
DeoptimizationExit* exit =
BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
CodeGenResult result =
AssembleDeoptimizerCall(deopt_state_id, current_source_position_);
CodeGenResult result = AssembleDeoptimizerCall(exit);
if (result != kSuccess) return result;
unwinding_info_writer_.MarkBlockWillExit();
break;
......@@ -3192,6 +3191,8 @@ void CodeGenerator::AssembleReturn(InstructionOperand* pop) {
void CodeGenerator::FinishCode() { __ CheckConstPool(true, false); }
void CodeGenerator::PrepareForDeoptimizationExits(int deopt_count) {}
void CodeGenerator::AssembleMove(InstructionOperand* source,
InstructionOperand* destination) {
ArmOperandConverter g(this, nullptr);
......
......@@ -820,12 +820,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
// don't emit code for nops.
break;
case kArchDeoptimize: {
int deopt_state_id =
DeoptimizationExit* exit =
BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
CodeGenResult result =
AssembleDeoptimizerCall(deopt_state_id, current_source_position_);
if (result != kSuccess) return result;
unwinding_info_writer_.MarkBlockWillExit();
__ B(exit->label());
break;
}
case kArchRet:
......@@ -2729,6 +2726,11 @@ void CodeGenerator::AssembleReturn(InstructionOperand* pop) {
void CodeGenerator::FinishCode() { __ ForceConstantPoolEmissionWithoutJump(); }
void CodeGenerator::PrepareForDeoptimizationExits(int deopt_count) {
__ ForceConstantPoolEmissionWithoutJump();
__ CheckVeneerPool(false, false, deopt_count * Deoptimizer::kDeoptExitSize);
}
void CodeGenerator::AssembleMove(InstructionOperand* source,
InstructionOperand* destination) {
Arm64OperandConverter g(this, nullptr);
......
......@@ -176,20 +176,55 @@ class InstructionOperandConverter {
Instruction* instr_;
};
// Eager deoptimization exit.
// Deoptimization exit.
class DeoptimizationExit : public ZoneObject {
public:
explicit DeoptimizationExit(int deoptimization_id, SourcePosition pos)
: deoptimization_id_(deoptimization_id), pos_(pos) {}
int deoptimization_id() const { return deoptimization_id_; }
Label* label() { return &label_; }
explicit DeoptimizationExit(SourcePosition pos, BailoutId bailout_id,
int translation_id, int pc_offset,
DeoptimizeKind kind, DeoptimizeReason reason)
: deoptimization_id_(kNoDeoptIndex),
pos_(pos),
bailout_id_(bailout_id),
translation_id_(translation_id),
pc_offset_(pc_offset),
kind_(kind),
reason_(reason),
emitted_(false) {}
bool has_deoptimization_id() const {
return deoptimization_id_ != kNoDeoptIndex;
}
int deoptimization_id() const {
DCHECK(has_deoptimization_id());
return deoptimization_id_;
}
void set_deoptimization_id(int deoptimization_id) {
deoptimization_id_ = deoptimization_id;
}
SourcePosition pos() const { return pos_; }
Label* label() { return &label_; }
BailoutId bailout_id() const { return bailout_id_; }
int translation_id() const { return translation_id_; }
int pc_offset() const { return pc_offset_; }
DeoptimizeKind kind() const { return kind_; }
DeoptimizeReason reason() const { return reason_; }
// Returns whether the deopt exit has already been emitted. Most deopt exits
// are emitted contiguously at the end of the code, but unconditional deopt
// exits (kArchDeoptimize) may be inlined where they are encountered.
bool emitted() const { return emitted_; }
void set_emitted() { emitted_ = true; }
private:
int const deoptimization_id_;
static const int kNoDeoptIndex = kMaxInt16 + 1;
int deoptimization_id_;
const SourcePosition pos_;
Label label_;
SourcePosition const pos_;
const BailoutId bailout_id_;
const int translation_id_;
const int pc_offset_;
const DeoptimizeKind kind_;
const DeoptimizeReason reason_;
bool emitted_;
};
// Generator for out-of-line code that is emitted after the main code is done.
......
......@@ -64,7 +64,6 @@ CodeGenerator::CodeGenerator(
safepoints_(zone()),
handlers_(zone()),
deoptimization_exits_(zone()),
deoptimization_states_(zone()),
deoptimization_literals_(zone()),
translations_(zone()),
caller_registers_saved_(false),
......@@ -115,20 +114,22 @@ void CodeGenerator::CreateFrameAccessState(Frame* frame) {
}
CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
int deoptimization_id, SourcePosition pos) {
DeoptimizationExit* exit) {
int deoptimization_id = exit->deoptimization_id();
if (deoptimization_id > Deoptimizer::kMaxNumberOfEntries) {
return kTooManyDeoptimizationBailouts;
}
DeoptimizeKind deopt_kind = GetDeoptimizationKind(deoptimization_id);
DeoptimizeReason deoptimization_reason =
GetDeoptimizationReason(deoptimization_id);
DeoptimizeKind deopt_kind = exit->kind();
DeoptimizeReason deoptimization_reason = exit->reason();
Address deopt_entry =
Deoptimizer::GetDeoptimizationEntry(tasm()->isolate(), deopt_kind);
if (info()->is_source_positions_enabled()) {
tasm()->RecordDeoptReason(deoptimization_reason, pos, deoptimization_id);
tasm()->RecordDeoptReason(deoptimization_reason, exit->pos(),
deoptimization_id);
}
tasm()->CallForDeoptimization(deopt_entry, deoptimization_id);
exit->set_emitted();
return kSuccess;
}
......@@ -267,19 +268,33 @@ void CodeGenerator::AssembleCode() {
// The test regress/regress-259 is an example of where we need it.
tasm()->nop();
// For some targets, we must make sure that constant and veneer pools are
// emitted before emitting the deoptimization exits.
PrepareForDeoptimizationExits(static_cast<int>(deoptimization_exits_.size()));
if (Deoptimizer::kSupportsFixedDeoptExitSize) {
deopt_exit_start_offset_ = tasm()->pc_offset();
}
// Assemble deoptimization exits.
int last_updated = 0;
for (DeoptimizationExit* exit : deoptimization_exits_) {
if (exit->emitted()) continue;
if (Deoptimizer::kSupportsFixedDeoptExitSize) {
exit->set_deoptimization_id(next_deoptimization_id_++);
}
tasm()->bind(exit->label());
int trampoline_pc = tasm()->pc_offset();
int deoptimization_id = exit->deoptimization_id();
DeoptimizationState* ds = deoptimization_states_[deoptimization_id];
if (ds->kind() == DeoptimizeKind::kLazy) {
// UpdateDeoptimizationInfo expects lazy deopts to be visited in pc_offset
// order, which is always the case since they are added to
// deoptimization_exits_ in that order.
if (exit->kind() == DeoptimizeKind::kLazy) {
int trampoline_pc = tasm()->pc_offset();
last_updated = safepoints()->UpdateDeoptimizationInfo(
ds->pc_offset(), trampoline_pc, last_updated);
exit->pc_offset(), trampoline_pc, last_updated,
exit->deoptimization_id());
}
result_ = AssembleDeoptimizerCall(deoptimization_id, exit->pos());
result_ = AssembleDeoptimizerCall(exit);
if (result_ != kSuccess) return;
}
......@@ -802,7 +817,7 @@ Handle<PodArray<InliningPosition>> CreateInliningPositions(
Handle<DeoptimizationData> CodeGenerator::GenerateDeoptimizationData() {
OptimizedCompilationInfo* info = this->info();
int deopt_count = static_cast<int>(deoptimization_states_.size());
int deopt_count = static_cast<int>(deoptimization_exits_.size());
if (deopt_count == 0 && !info->is_osr()) {
return DeoptimizationData::Empty(isolate());
}
......@@ -817,6 +832,8 @@ Handle<DeoptimizationData> CodeGenerator::GenerateDeoptimizationData() {
Smi::FromInt(static_cast<int>(inlined_function_count_)));
data->SetOptimizationId(Smi::FromInt(info->optimization_id()));
data->SetDeoptExitStart(Smi::FromInt(deopt_exit_start_offset_));
if (info->has_shared_info()) {
data->SetSharedFunctionInfo(*info->shared_info());
} else {
......@@ -847,12 +864,13 @@ Handle<DeoptimizationData> CodeGenerator::GenerateDeoptimizationData() {
// Populate deoptimization entries.
for (int i = 0; i < deopt_count; i++) {
DeoptimizationState* deoptimization_state = deoptimization_states_[i];
data->SetBytecodeOffset(i, deoptimization_state->bailout_id());
CHECK(deoptimization_state);
DeoptimizationExit* deoptimization_exit = deoptimization_exits_[i];
CHECK_NOT_NULL(deoptimization_exit);
DCHECK_EQ(i, deoptimization_exit->deoptimization_id());
data->SetBytecodeOffset(i, deoptimization_exit->bailout_id());
data->SetTranslationIndex(
i, Smi::FromInt(deoptimization_state->translation_id()));
data->SetPc(i, Smi::FromInt(deoptimization_state->pc_offset()));
i, Smi::FromInt(deoptimization_exit->translation_id()));
data->SetPc(i, Smi::FromInt(deoptimization_exit->pc_offset()));
}
return data;
......@@ -886,13 +904,8 @@ void CodeGenerator::RecordCallPosition(Instruction* instr) {
FrameStateDescriptor* descriptor =
GetDeoptimizationEntry(instr, frame_state_offset).descriptor();
int pc_offset = tasm()->pc_offset();
int deopt_state_id = BuildTranslation(instr, pc_offset, frame_state_offset,
descriptor->state_combine());
DeoptimizationExit* const exit = new (zone())
DeoptimizationExit(deopt_state_id, current_source_position_);
deoptimization_exits_.push_back(exit);
safepoints()->RecordLazyDeoptimizationIndex(deopt_state_id);
BuildTranslation(instr, pc_offset, frame_state_offset,
descriptor->state_combine());
}
}
......@@ -912,20 +925,6 @@ DeoptimizationEntry const& CodeGenerator::GetDeoptimizationEntry(
return instructions()->GetDeoptimizationEntry(state_id);
}
DeoptimizeKind CodeGenerator::GetDeoptimizationKind(
int deoptimization_id) const {
size_t const index = static_cast<size_t>(deoptimization_id);
DCHECK_LT(index, deoptimization_states_.size());
return deoptimization_states_[index]->kind();
}
DeoptimizeReason CodeGenerator::GetDeoptimizationReason(
int deoptimization_id) const {
size_t const index = static_cast<size_t>(deoptimization_id);
DCHECK_LT(index, deoptimization_states_.size());
return deoptimization_states_[index]->reason();
}
void CodeGenerator::TranslateStateValueDescriptor(
StateValueDescriptor* desc, StateValueList* nested,
Translation* translation, InstructionOperandIterator* iter) {
......@@ -1054,9 +1053,9 @@ void CodeGenerator::BuildTranslationForFrameStateDescriptor(
TranslateFrameStateDescriptorOperands(descriptor, iter, translation);
}
int CodeGenerator::BuildTranslation(Instruction* instr, int pc_offset,
size_t frame_state_offset,
OutputFrameStateCombine state_combine) {
DeoptimizationExit* CodeGenerator::BuildTranslation(
Instruction* instr, int pc_offset, size_t frame_state_offset,
OutputFrameStateCombine state_combine) {
DeoptimizationEntry const& entry =
GetDeoptimizationEntry(instr, frame_state_offset);
FrameStateDescriptor* const descriptor = entry.descriptor();
......@@ -1077,13 +1076,16 @@ int CodeGenerator::BuildTranslation(Instruction* instr, int pc_offset,
BuildTranslationForFrameStateDescriptor(descriptor, &iter, &translation,
state_combine);
int deoptimization_id = static_cast<int>(deoptimization_states_.size());
DeoptimizationExit* const exit = new (zone()) DeoptimizationExit(
current_source_position_, descriptor->bailout_id(), translation.index(),
pc_offset, entry.kind(), entry.reason());
deoptimization_states_.push_back(new (zone()) DeoptimizationState(
descriptor->bailout_id(), translation.index(), pc_offset, entry.kind(),
entry.reason()));
if (!Deoptimizer::kSupportsFixedDeoptExitSize) {
exit->set_deoptimization_id(next_deoptimization_id_++);
}
return deoptimization_id;
deoptimization_exits_.push_back(exit);
return exit;
}
void CodeGenerator::AddTranslationForOperand(Translation* translation,
......@@ -1237,13 +1239,8 @@ void CodeGenerator::MarkLazyDeoptSite() {
DeoptimizationExit* CodeGenerator::AddDeoptimizationExit(
Instruction* instr, size_t frame_state_offset) {
int const deoptimization_id = BuildTranslation(
instr, -1, frame_state_offset, OutputFrameStateCombine::Ignore());
DeoptimizationExit* const exit = new (zone())
DeoptimizationExit(deoptimization_id, current_source_position_);
deoptimization_exits_.push_back(exit);
return exit;
return BuildTranslation(instr, -1, frame_state_offset,
OutputFrameStateCombine::Ignore());
}
void CodeGenerator::InitializeSpeculationPoison() {
......
......@@ -199,8 +199,7 @@ class V8_EXPORT_PRIVATE CodeGenerator final : public GapResolver::Assembler {
// Determines how to call helper stubs depending on the code kind.
StubCallMode DetermineStubCallMode() const;
CodeGenResult AssembleDeoptimizerCall(int deoptimization_id,
SourcePosition pos);
CodeGenResult AssembleDeoptimizerCall(DeoptimizationExit* exit);
// ===========================================================================
// ============= Architecture-specific code generation methods. ==============
......@@ -342,11 +341,9 @@ class V8_EXPORT_PRIVATE CodeGenerator final : public GapResolver::Assembler {
int DefineDeoptimizationLiteral(DeoptimizationLiteral literal);
DeoptimizationEntry const& GetDeoptimizationEntry(Instruction* instr,
size_t frame_state_offset);
DeoptimizeKind GetDeoptimizationKind(int deoptimization_id) const;
DeoptimizeReason GetDeoptimizationReason(int deoptimization_id) const;
int BuildTranslation(Instruction* instr, int pc_offset,
size_t frame_state_offset,
OutputFrameStateCombine state_combine);
DeoptimizationExit* BuildTranslation(Instruction* instr, int pc_offset,
size_t frame_state_offset,
OutputFrameStateCombine state_combine);
void BuildTranslationForFrameStateDescriptor(
FrameStateDescriptor* descriptor, InstructionOperandIterator* iter,
Translation* translation, OutputFrameStateCombine state_combine);
......@@ -361,35 +358,12 @@ class V8_EXPORT_PRIVATE CodeGenerator final : public GapResolver::Assembler {
InstructionOperand* op, MachineType type);
void MarkLazyDeoptSite();
void PrepareForDeoptimizationExits(int deopt_count);
DeoptimizationExit* AddDeoptimizationExit(Instruction* instr,
size_t frame_state_offset);
// ===========================================================================
class DeoptimizationState final : public ZoneObject {
public:
DeoptimizationState(BailoutId bailout_id, int translation_id, int pc_offset,
DeoptimizeKind kind, DeoptimizeReason reason)
: bailout_id_(bailout_id),
translation_id_(translation_id),
pc_offset_(pc_offset),
kind_(kind),
reason_(reason) {}
BailoutId bailout_id() const { return bailout_id_; }
int translation_id() const { return translation_id_; }
int pc_offset() const { return pc_offset_; }
DeoptimizeKind kind() const { return kind_; }
DeoptimizeReason reason() const { return reason_; }
private:
BailoutId bailout_id_;
int translation_id_;
int pc_offset_;
DeoptimizeKind kind_;
DeoptimizeReason reason_;
};
struct HandlerInfo {
Label* handler;
int pc_offset;
......@@ -414,8 +388,9 @@ class V8_EXPORT_PRIVATE CodeGenerator final : public GapResolver::Assembler {
GapResolver resolver_;
SafepointTableBuilder safepoints_;
ZoneVector<HandlerInfo> handlers_;
int next_deoptimization_id_ = 0;
int deopt_exit_start_offset_ = 0;
ZoneDeque<DeoptimizationExit*> deoptimization_exits_;
ZoneDeque<DeoptimizationState*> deoptimization_states_;
ZoneDeque<DeoptimizationLiteral> deoptimization_literals_;
size_t inlined_function_count_ = 0;
TranslationBuffer translations_;
......
......@@ -907,10 +907,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
// don't emit code for nops.
break;
case kArchDeoptimize: {
int deopt_state_id =
DeoptimizationExit* exit =
BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
CodeGenResult result =
AssembleDeoptimizerCall(deopt_state_id, current_source_position_);
CodeGenResult result = AssembleDeoptimizerCall(exit);
if (result != kSuccess) return result;
break;
}
......@@ -4404,6 +4403,8 @@ void CodeGenerator::AssembleReturn(InstructionOperand* pop) {
void CodeGenerator::FinishCode() {}
void CodeGenerator::PrepareForDeoptimizationExits(int deopt_count) {}
void CodeGenerator::AssembleMove(InstructionOperand* source,
InstructionOperand* destination) {
IA32OperandConverter g(this, nullptr);
......
......@@ -850,10 +850,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
// don't emit code for nops.
break;
case kArchDeoptimize: {
int deopt_state_id =
DeoptimizationExit* exit =
BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
CodeGenResult result =
AssembleDeoptimizerCall(deopt_state_id, current_source_position_);
CodeGenResult result = AssembleDeoptimizerCall(exit);
if (result != kSuccess) return result;
break;
}
......@@ -3527,6 +3526,8 @@ void CodeGenerator::AssembleReturn(InstructionOperand* pop) {
void CodeGenerator::FinishCode() {}
void CodeGenerator::PrepareForDeoptimizationExits(int deopt_count) {}
void CodeGenerator::AssembleMove(InstructionOperand* source,
InstructionOperand* destination) {
MipsOperandConverter g(this, nullptr);
......
......@@ -828,10 +828,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
// don't emit code for nops.
break;
case kArchDeoptimize: {
int deopt_state_id =
DeoptimizationExit* exit =
BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
CodeGenResult result =
AssembleDeoptimizerCall(deopt_state_id, current_source_position_);
CodeGenResult result = AssembleDeoptimizerCall(exit);
if (result != kSuccess) return result;
break;
}
......@@ -3686,6 +3685,8 @@ void CodeGenerator::AssembleReturn(InstructionOperand* pop) {
void CodeGenerator::FinishCode() {}
void CodeGenerator::PrepareForDeoptimizationExits(int deopt_count) {}
void CodeGenerator::AssembleMove(InstructionOperand* source,
InstructionOperand* destination) {
MipsOperandConverter g(this, nullptr);
......
......@@ -1104,10 +1104,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
DCHECK_EQ(LeaveRC, i.OutputRCBit());
break;
case kArchDeoptimize: {
int deopt_state_id =
DeoptimizationExit* exit =
BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
CodeGenResult result =
AssembleDeoptimizerCall(deopt_state_id, current_source_position_);
CodeGenResult result = AssembleDeoptimizerCall(exit);
if (result != kSuccess) return result;
break;
}
......@@ -2516,6 +2515,8 @@ void CodeGenerator::AssembleReturn(InstructionOperand* pop) {
void CodeGenerator::FinishCode() {}
void CodeGenerator::PrepareForDeoptimizationExits(int deopt_count) {}
void CodeGenerator::AssembleMove(InstructionOperand* source,
InstructionOperand* destination) {
PPCOperandConverter g(this, nullptr);
......
......@@ -1578,10 +1578,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
// don't emit code for nops.
break;
case kArchDeoptimize: {
int deopt_state_id =
DeoptimizationExit* exit =
BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
CodeGenResult result =
AssembleDeoptimizerCall(deopt_state_id, current_source_position_);
CodeGenResult result = AssembleDeoptimizerCall(exit);
if (result != kSuccess) return result;
break;
}
......@@ -3193,6 +3192,8 @@ void CodeGenerator::AssembleReturn(InstructionOperand* pop) {
void CodeGenerator::FinishCode() {}
void CodeGenerator::PrepareForDeoptimizationExits(int deopt_count) {}
void CodeGenerator::AssembleMove(InstructionOperand* source,
InstructionOperand* destination) {
S390OperandConverter g(this, nullptr);
......
......@@ -993,10 +993,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
// don't emit code for nops.
break;
case kArchDeoptimize: {
int deopt_state_id =
DeoptimizationExit* exit =
BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
CodeGenResult result =
AssembleDeoptimizerCall(deopt_state_id, current_source_position_);
CodeGenResult result = AssembleDeoptimizerCall(exit);
if (result != kSuccess) return result;
unwinding_info_writer_.MarkBlockWillExit();
break;
......@@ -4259,6 +4258,8 @@ void CodeGenerator::AssembleReturn(InstructionOperand* pop) {
void CodeGenerator::FinishCode() { tasm()->PatchConstPool(); }
void CodeGenerator::PrepareForDeoptimizationExits(int deopt_count) {}
void CodeGenerator::AssembleMove(InstructionOperand* source,
InstructionOperand* destination) {
X64OperandConverter g(this, nullptr);
......
......@@ -12,6 +12,9 @@
namespace v8 {
namespace internal {
const bool Deoptimizer::kSupportsFixedDeoptExitSize = false;
const int Deoptimizer::kDeoptExitSize = 0;
#define __ masm->
// This code tries to be close to ia32 code so that any changes can be
......
......@@ -13,6 +13,9 @@
namespace v8 {
namespace internal {
const bool Deoptimizer::kSupportsFixedDeoptExitSize = true;
const int Deoptimizer::kDeoptExitSize = kInstrSize;
#define __ masm->
namespace {
......@@ -133,9 +136,10 @@ void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm,
// Floating point registers are saved on the stack above core registers.
const int kDoubleRegistersOffset = saved_registers.Count() * kXRegSize;
// The bailout id was passed by the caller in x26.
// We don't use a bailout id for arm64, because we can compute the id from the
// address. Pass kMaxUInt32 instead to signify this.
Register bailout_id = x2;
__ Mov(bailout_id, x26);
__ Mov(bailout_id, kMaxUInt32);
Register code_object = x3;
Register fp_to_sp = x4;
......
......@@ -505,6 +505,19 @@ Deoptimizer::Deoptimizer(Isolate* isolate, JSFunction function,
unsigned size = ComputeInputFrameSize();
int parameter_count = function.shared().internal_formal_parameter_count() + 1;
input_ = new (size) FrameDescription(size, parameter_count);
if (kSupportsFixedDeoptExitSize) {
DCHECK_EQ(bailout_id_, kMaxUInt32);
// Calculate bailout id from return address.
DCHECK_GT(kDeoptExitSize, 0);
DeoptimizationData deopt_data =
DeoptimizationData::cast(compiled_code_.deoptimization_data());
Address deopt_start = compiled_code_.raw_instruction_start() +
deopt_data.DeoptExitStart().value();
int offset = static_cast<int>(from_ - kDeoptExitSize - deopt_start);
DCHECK_EQ(0, offset % kDeoptExitSize);
bailout_id_ = offset / kDeoptExitSize;
}
}
Code Deoptimizer::FindOptimizedCode() {
......
......@@ -501,6 +501,15 @@ class Deoptimizer : public Malloced {
static const int kMaxNumberOfEntries = 16384;
// Set to true when the architecture supports deoptimization exit sequences
// of a fixed size, that can be sorted so that the deoptimization index is
// deduced from the address of the deoptimization exit.
static const bool kSupportsFixedDeoptExitSize;
// Size of deoptimization exit sequence. This is only meaningful when
// kSupportsFixedDeoptExitSize is true.
static const int kDeoptExitSize;
enum class BuiltinContinuationMode {
STUB,
JAVASCRIPT,
......
......@@ -13,6 +13,9 @@
namespace v8 {
namespace internal {
const bool Deoptimizer::kSupportsFixedDeoptExitSize = false;
const int Deoptimizer::kDeoptExitSize = 0;
#define __ masm->
void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm,
......
......@@ -10,6 +10,9 @@
namespace v8 {
namespace internal {
const bool Deoptimizer::kSupportsFixedDeoptExitSize = false;
const int Deoptimizer::kDeoptExitSize = 0;
#define __ masm->
// This code tries to be close to ia32 code so that any changes can be
......
......@@ -10,6 +10,9 @@
namespace v8 {
namespace internal {
const bool Deoptimizer::kSupportsFixedDeoptExitSize = false;
const int Deoptimizer::kDeoptExitSize = 0;
#define __ masm->
// This code tries to be close to ia32 code so that any changes can be
......
......@@ -11,6 +11,9 @@
namespace v8 {
namespace internal {
const bool Deoptimizer::kSupportsFixedDeoptExitSize = false;
const int Deoptimizer::kDeoptExitSize = 0;
#define __ masm->
// This code tries to be close to ia32 code so that any changes can be
......
......@@ -10,6 +10,9 @@
namespace v8 {
namespace internal {
const bool Deoptimizer::kSupportsFixedDeoptExitSize = false;
const int Deoptimizer::kDeoptExitSize = 0;
#define __ masm->
// This code tries to be close to ia32 code so that any changes can be
......
......@@ -13,6 +13,9 @@
namespace v8 {
namespace internal {
const bool Deoptimizer::kSupportsFixedDeoptExitSize = false;
const int Deoptimizer::kDeoptExitSize = 0;
#define __ masm->
void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm,
......
......@@ -768,6 +768,7 @@ DEFINE_DEOPT_ELEMENT_ACCESSORS(OsrBytecodeOffset, Smi)
DEFINE_DEOPT_ELEMENT_ACCESSORS(OsrPcOffset, Smi)
DEFINE_DEOPT_ELEMENT_ACCESSORS(OptimizationId, Smi)
DEFINE_DEOPT_ELEMENT_ACCESSORS(InliningPositions, PodArray<InliningPosition>)
DEFINE_DEOPT_ELEMENT_ACCESSORS(DeoptExitStart, Smi)
DEFINE_DEOPT_ENTRY_ACCESSORS(BytecodeOffsetRaw, Smi)
DEFINE_DEOPT_ENTRY_ACCESSORS(TranslationIndex, Smi)
......
......@@ -866,7 +866,8 @@ class DeoptimizationData : public FixedArray {
static const int kOptimizationIdIndex = 5;
static const int kSharedFunctionInfoIndex = 6;
static const int kInliningPositionsIndex = 7;
static const int kFirstDeoptEntryIndex = 8;
static const int kDeoptExitStartIndex = 8;
static const int kFirstDeoptEntryIndex = 9;
// Offsets of deopt entry elements relative to the start of the entry.
static const int kBytecodeOffsetRawOffset = 0;
......@@ -887,6 +888,7 @@ class DeoptimizationData : public FixedArray {
DECL_ELEMENT_ACCESSORS(OptimizationId, Smi)
DECL_ELEMENT_ACCESSORS(SharedFunctionInfo, Object)
DECL_ELEMENT_ACCESSORS(InliningPositions, PodArray<InliningPosition>)
DECL_ELEMENT_ACCESSORS(DeoptExitStart, Smi)
#undef DECL_ELEMENT_ACCESSORS
......
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