Commit 53d51c52 authored by mtrofin's avatar mtrofin Committed by Commit bot

[turbofan] Frame elision for code stubs.

Removed Frame::needs_frame and the function-wide logic using it in
favor of FrameAccessState::has_frame, which can be set on a more
granular level, and driving it block by block.

BUG= v8:4533
LOG=N

Review URL: https://codereview.chromium.org/1775323002

Cr-Commit-Position: refs/heads/master@{#35139}
parent a549d4a7
...@@ -230,7 +230,8 @@ class OutOfLineRecordWrite final : public OutOfLineCode { ...@@ -230,7 +230,8 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
value_(value), value_(value),
scratch0_(scratch0), scratch0_(scratch0),
scratch1_(scratch1), scratch1_(scratch1),
mode_(mode) {} mode_(mode),
must_save_lr_(!gen->frame_access_state()->has_frame()) {}
void Generate() final { void Generate() final {
if (mode_ > RecordWriteMode::kValueIsPointer) { if (mode_ > RecordWriteMode::kValueIsPointer) {
...@@ -244,7 +245,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode { ...@@ -244,7 +245,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
: OMIT_REMEMBERED_SET; : OMIT_REMEMBERED_SET;
SaveFPRegsMode const save_fp_mode = SaveFPRegsMode const save_fp_mode =
frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
if (!frame()->needs_frame()) { if (must_save_lr_) {
// We need to save and restore lr if the frame was elided. // We need to save and restore lr if the frame was elided.
__ Push(lr); __ Push(lr);
} }
...@@ -257,7 +258,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode { ...@@ -257,7 +258,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
__ add(scratch1_, object_, Operand(index_)); __ add(scratch1_, object_, Operand(index_));
} }
__ CallStub(&stub); __ CallStub(&stub);
if (!frame()->needs_frame()) { if (must_save_lr_) {
__ Pop(lr); __ Pop(lr);
} }
} }
...@@ -270,6 +271,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode { ...@@ -270,6 +271,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
Register const scratch0_; Register const scratch0_;
Register const scratch1_; Register const scratch1_;
RecordWriteMode const mode_; RecordWriteMode const mode_;
bool must_save_lr_;
}; };
...@@ -386,6 +388,11 @@ Condition FlagsConditionToCondition(FlagsCondition condition) { ...@@ -386,6 +388,11 @@ Condition FlagsConditionToCondition(FlagsCondition condition) {
DCHECK_EQ(LeaveCC, i.OutputSBit()); \ DCHECK_EQ(LeaveCC, i.OutputSBit()); \
} while (0) } while (0)
void CodeGenerator::AssembleDeconstructFrame() {
__ LeaveFrame(StackFrame::MANUAL);
}
void CodeGenerator::AssembleSetupStackPointer() {}
void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
...@@ -402,7 +409,7 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { ...@@ -402,7 +409,7 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
__ sub(sp, sp, Operand(-sp_slot_delta * kPointerSize)); __ sub(sp, sp, Operand(-sp_slot_delta * kPointerSize));
frame_access_state()->IncreaseSPDelta(-sp_slot_delta); frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
} }
if (frame()->needs_frame()) { if (frame_access_state()->has_frame()) {
if (FLAG_enable_embedded_constant_pool) { if (FLAG_enable_embedded_constant_pool) {
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kConstantPoolOffset)); __ ldr(cp, MemOperand(fp, StandardFrameConstants::kConstantPoolOffset));
} }
...@@ -580,7 +587,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -580,7 +587,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
DCHECK_EQ(LeaveCC, i.OutputSBit()); DCHECK_EQ(LeaveCC, i.OutputSBit());
break; break;
case kArchParentFramePointer: case kArchParentFramePointer:
if (frame_access_state()->frame()->needs_frame()) { if (frame_access_state()->has_frame()) {
__ ldr(i.OutputRegister(), MemOperand(fp, 0)); __ ldr(i.OutputRegister(), MemOperand(fp, 0));
} else { } else {
__ mov(i.OutputRegister(), fp); __ mov(i.OutputRegister(), fp);
...@@ -1271,7 +1278,7 @@ void CodeGenerator::AssembleDeoptimizerCall( ...@@ -1271,7 +1278,7 @@ void CodeGenerator::AssembleDeoptimizerCall(
void CodeGenerator::AssemblePrologue() { void CodeGenerator::AssemblePrologue() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
if (frame()->needs_frame()) { if (frame_access_state()->has_frame()) {
if (descriptor->IsCFunctionCall()) { if (descriptor->IsCFunctionCall()) {
if (FLAG_enable_embedded_constant_pool) { if (FLAG_enable_embedded_constant_pool) {
__ Push(lr, fp, pp); __ Push(lr, fp, pp);
...@@ -1286,10 +1293,7 @@ void CodeGenerator::AssemblePrologue() { ...@@ -1286,10 +1293,7 @@ void CodeGenerator::AssemblePrologue() {
} else { } else {
__ StubPrologue(info()->GetOutputStackFrameType()); __ StubPrologue(info()->GetOutputStackFrameType());
} }
} else {
frame()->SetElidedFrameSizeInSlots(0);
} }
frame_access_state()->SetFrameAccessToDefault();
int stack_shrink_slots = frame()->GetSpillSlotCount(); int stack_shrink_slots = frame()->GetSpillSlotCount();
if (info()->is_osr()) { if (info()->is_osr()) {
...@@ -1359,15 +1363,15 @@ void CodeGenerator::AssembleReturn() { ...@@ -1359,15 +1363,15 @@ void CodeGenerator::AssembleReturn() {
} }
if (descriptor->IsCFunctionCall()) { if (descriptor->IsCFunctionCall()) {
__ LeaveFrame(StackFrame::MANUAL); AssembleDeconstructFrame();
} else if (frame()->needs_frame()) { } else if (frame_access_state()->has_frame()) {
// Canonicalize JSFunction return sites for now. // Canonicalize JSFunction return sites for now.
if (return_label_.is_bound()) { if (return_label_.is_bound()) {
__ b(&return_label_); __ b(&return_label_);
return; return;
} else { } else {
__ bind(&return_label_); __ bind(&return_label_);
__ LeaveFrame(StackFrame::MANUAL); AssembleDeconstructFrame();
} }
} }
__ Ret(pop_count); __ Ret(pop_count);
......
...@@ -279,7 +279,8 @@ class OutOfLineRecordWrite final : public OutOfLineCode { ...@@ -279,7 +279,8 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
value_(value), value_(value),
scratch0_(scratch0), scratch0_(scratch0),
scratch1_(scratch1), scratch1_(scratch1),
mode_(mode) {} mode_(mode),
must_save_lr_(!gen->frame_access_state()->has_frame()) {}
void Generate() final { void Generate() final {
if (mode_ > RecordWriteMode::kValueIsPointer) { if (mode_ > RecordWriteMode::kValueIsPointer) {
...@@ -293,7 +294,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode { ...@@ -293,7 +294,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
: OMIT_REMEMBERED_SET; : OMIT_REMEMBERED_SET;
SaveFPRegsMode const save_fp_mode = SaveFPRegsMode const save_fp_mode =
frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
if (!frame()->needs_frame()) { if (must_save_lr_) {
// We need to save and restore lr if the frame was elided. // We need to save and restore lr if the frame was elided.
__ Push(lr); __ Push(lr);
} }
...@@ -301,7 +302,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode { ...@@ -301,7 +302,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
remembered_set_action, save_fp_mode); remembered_set_action, save_fp_mode);
__ Add(scratch1_, object_, index_); __ Add(scratch1_, object_, index_);
__ CallStub(&stub); __ CallStub(&stub);
if (!frame()->needs_frame()) { if (must_save_lr_) {
__ Pop(lr); __ Pop(lr);
} }
} }
...@@ -313,6 +314,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode { ...@@ -313,6 +314,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
Register const scratch0_; Register const scratch0_;
Register const scratch1_; Register const scratch1_;
RecordWriteMode const mode_; RecordWriteMode const mode_;
bool must_save_lr_;
}; };
...@@ -466,6 +468,15 @@ Condition FlagsConditionToCondition(FlagsCondition condition) { ...@@ -466,6 +468,15 @@ Condition FlagsConditionToCondition(FlagsCondition condition) {
} \ } \
} while (0) } while (0)
void CodeGenerator::AssembleDeconstructFrame() {
const CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
if (descriptor->IsCFunctionCall() || descriptor->UseNativeStack()) {
__ Mov(csp, fp);
} else {
__ Mov(jssp, fp);
}
__ Pop(fp, lr);
}
void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
...@@ -482,7 +493,7 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { ...@@ -482,7 +493,7 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
__ Claim(-sp_slot_delta); __ Claim(-sp_slot_delta);
frame_access_state()->IncreaseSPDelta(-sp_slot_delta); frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
} }
if (frame()->needs_frame()) { if (frame_access_state()->has_frame()) {
__ Ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); __ Ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
__ Ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); __ Ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
} }
...@@ -672,7 +683,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -672,7 +683,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ mov(i.OutputRegister(), fp); __ mov(i.OutputRegister(), fp);
break; break;
case kArchParentFramePointer: case kArchParentFramePointer:
if (frame_access_state()->frame()->needs_frame()) { if (frame_access_state()->has_frame()) {
__ ldr(i.OutputRegister(), MemOperand(fp, 0)); __ ldr(i.OutputRegister(), MemOperand(fp, 0));
} else { } else {
__ mov(i.OutputRegister(), fp); __ mov(i.OutputRegister(), fp);
...@@ -1492,6 +1503,14 @@ void CodeGenerator::AssembleDeoptimizerCall( ...@@ -1492,6 +1503,14 @@ void CodeGenerator::AssembleDeoptimizerCall(
__ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
} }
void CodeGenerator::AssembleSetupStackPointer() {
const CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
if (descriptor->UseNativeStack() || descriptor->IsCFunctionCall()) {
__ SetStackPointer(csp);
} else {
__ SetStackPointer(jssp);
}
}
void CodeGenerator::AssemblePrologue() { void CodeGenerator::AssemblePrologue() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
...@@ -1499,19 +1518,12 @@ void CodeGenerator::AssemblePrologue() { ...@@ -1499,19 +1518,12 @@ void CodeGenerator::AssemblePrologue() {
__ AssertCspAligned(); __ AssertCspAligned();
} }
frame()->AlignFrame(16);
int stack_shrink_slots = frame()->GetSpillSlotCount(); int stack_shrink_slots = frame()->GetSpillSlotCount();
if (frame()->needs_frame()) { if (frame_access_state()->has_frame()) {
if (descriptor->IsJSFunctionCall()) { if (descriptor->IsJSFunctionCall()) {
DCHECK(!descriptor->UseNativeStack()); DCHECK(!descriptor->UseNativeStack());
__ SetStackPointer(jssp);
__ Prologue(this->info()->GeneratePreagedPrologue()); __ Prologue(this->info()->GeneratePreagedPrologue());
} else { } else {
if (descriptor->UseNativeStack() || descriptor->IsCFunctionCall()) {
__ SetStackPointer(csp);
} else {
__ SetStackPointer(jssp);
}
if (descriptor->IsCFunctionCall()) { if (descriptor->IsCFunctionCall()) {
__ Push(lr, fp); __ Push(lr, fp);
__ Mov(fp, masm_.StackPointer()); __ Mov(fp, masm_.StackPointer());
...@@ -1521,15 +1533,8 @@ void CodeGenerator::AssemblePrologue() { ...@@ -1521,15 +1533,8 @@ void CodeGenerator::AssemblePrologue() {
frame()->GetTotalFrameSlotCount()); frame()->GetTotalFrameSlotCount());
} }
} }
} else {
if (descriptor->UseNativeStack()) {
__ SetStackPointer(csp);
} else {
__ SetStackPointer(jssp);
}
frame()->SetElidedFrameSizeInSlots(0);
} }
frame_access_state()->SetFrameAccessToDefault();
if (info()->is_osr()) { if (info()->is_osr()) {
// TurboFan OSR-compiled functions cannot be entered directly. // TurboFan OSR-compiled functions cannot be entered directly.
__ Abort(kShouldNotDirectlyEnterOsrFunction); __ Abort(kShouldNotDirectlyEnterOsrFunction);
...@@ -1590,22 +1595,18 @@ void CodeGenerator::AssembleReturn() { ...@@ -1590,22 +1595,18 @@ void CodeGenerator::AssembleReturn() {
int pop_count = static_cast<int>(descriptor->StackParameterCount()); int pop_count = static_cast<int>(descriptor->StackParameterCount());
if (descriptor->IsCFunctionCall()) { if (descriptor->IsCFunctionCall()) {
__ Mov(csp, fp); AssembleDeconstructFrame();
__ Pop(fp, lr); } else if (frame_access_state()->has_frame()) {
} else if (frame()->needs_frame()) {
// Canonicalize JSFunction return sites for now. // Canonicalize JSFunction return sites for now.
if (return_label_.is_bound()) { if (return_label_.is_bound()) {
__ B(&return_label_); __ B(&return_label_);
return; return;
} else { } else {
__ Bind(&return_label_); __ Bind(&return_label_);
AssembleDeconstructFrame();
if (descriptor->UseNativeStack()) { if (descriptor->UseNativeStack()) {
__ Mov(csp, fp);
pop_count += (pop_count & 1); // align pop_count += (pop_count & 1); // align
} else {
__ Mov(jssp, fp);
} }
__ Pop(fp, lr);
} }
} else if (descriptor->UseNativeStack()) { } else if (descriptor->UseNativeStack()) {
pop_count += (pop_count & 1); // align pop_count += (pop_count & 1); // align
......
...@@ -56,12 +56,8 @@ CodeGenerator::CodeGenerator(Frame* frame, Linkage* linkage, ...@@ -56,12 +56,8 @@ CodeGenerator::CodeGenerator(Frame* frame, Linkage* linkage,
for (int i = 0; i < code->InstructionBlockCount(); ++i) { for (int i = 0; i < code->InstructionBlockCount(); ++i) {
new (&labels_[i]) Label; new (&labels_[i]) Label;
} }
if (code->ContainsCall()) {
frame->MarkNeedsFrame();
}
} }
Handle<Code> CodeGenerator::GenerateCode() { Handle<Code> CodeGenerator::GenerateCode() {
CompilationInfo* info = this->info(); CompilationInfo* info = this->info();
...@@ -80,10 +76,6 @@ Handle<Code> CodeGenerator::GenerateCode() { ...@@ -80,10 +76,6 @@ Handle<Code> CodeGenerator::GenerateCode() {
} }
// Architecture-specific, linkage-specific prologue. // Architecture-specific, linkage-specific prologue.
info->set_prologue_offset(masm()->pc_offset()); info->set_prologue_offset(masm()->pc_offset());
AssemblePrologue();
if (linkage()->GetIncomingDescriptor()->InitializeRootRegister()) {
masm()->InitializeRootRegister();
}
// Define deoptimization literals for all inlined functions. // Define deoptimization literals for all inlined functions.
DCHECK_EQ(0u, deoptimization_literals_.size()); DCHECK_EQ(0u, deoptimization_literals_.size());
...@@ -104,6 +96,9 @@ Handle<Code> CodeGenerator::GenerateCode() { ...@@ -104,6 +96,9 @@ Handle<Code> CodeGenerator::GenerateCode() {
} }
} }
// Finish the Frame
frame()->AlignFrame(kFrameAlignmentInBytes);
AssembleSetupStackPointer();
// Assemble all non-deferred blocks, followed by deferred ones. // Assemble all non-deferred blocks, followed by deferred ones.
for (int deferred = 0; deferred < 2; ++deferred) { for (int deferred = 0; deferred < 2; ++deferred) {
for (const InstructionBlock* block : code()->instruction_blocks()) { for (const InstructionBlock* block : code()->instruction_blocks()) {
...@@ -143,9 +138,24 @@ Handle<Code> CodeGenerator::GenerateCode() { ...@@ -143,9 +138,24 @@ Handle<Code> CodeGenerator::GenerateCode() {
SNPrintF(buffer, " --"); SNPrintF(buffer, " --");
masm()->RecordComment(buffer_start); masm()->RecordComment(buffer_start);
} }
frame_access_state()->MarkHasFrame(block->needs_frame());
masm()->bind(GetLabel(current_block_)); masm()->bind(GetLabel(current_block_));
if (block->must_construct_frame()) {
AssemblePrologue();
// We need to setup the root register after we assemble the prologue, to
// avoid clobbering callee saved registers in case of C linkage and
// using the roots.
// TODO(mtrofin): investigate how we can avoid doing this repeatedly.
if (linkage()->GetIncomingDescriptor()->InitializeRootRegister()) {
masm()->InitializeRootRegister();
}
}
for (int i = block->code_start(); i < block->code_end(); ++i) { for (int i = block->code_start(); i < block->code_end(); ++i) {
AssembleInstruction(code()->InstructionAt(i)); Instruction* instr = code()->InstructionAt(i);
AssembleInstruction(instr, block);
} }
} }
} }
...@@ -290,9 +300,12 @@ bool CodeGenerator::IsMaterializableFromRoot( ...@@ -290,9 +300,12 @@ bool CodeGenerator::IsMaterializableFromRoot(
return false; return false;
} }
void CodeGenerator::AssembleInstruction(Instruction* instr,
void CodeGenerator::AssembleInstruction(Instruction* instr) { const InstructionBlock* block) {
AssembleGaps(instr); AssembleGaps(instr);
if (instr->IsJump() && block->must_deconstruct_frame()) {
AssembleDeconstructFrame();
}
AssembleSourcePosition(instr); AssembleSourcePosition(instr);
// Assemble architecture-specific code for the instruction. // Assemble architecture-specific code for the instruction.
AssembleArchInstruction(instr); AssembleArchInstruction(instr);
...@@ -761,13 +774,11 @@ DeoptimizationExit* CodeGenerator::AddDeoptimizationExit( ...@@ -761,13 +774,11 @@ DeoptimizationExit* CodeGenerator::AddDeoptimizationExit(
} }
int CodeGenerator::TailCallFrameStackSlotDelta(int stack_param_delta) { int CodeGenerator::TailCallFrameStackSlotDelta(int stack_param_delta) {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
int spill_slots = frame()->GetSpillSlotCount();
bool has_frame = descriptor->IsJSFunctionCall() || spill_slots > 0;
// Leave the PC on the stack on platforms that have that as part of their ABI // Leave the PC on the stack on platforms that have that as part of their ABI
int pc_slots = V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK ? 1 : 0; int pc_slots = V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK ? 1 : 0;
int sp_slot_delta = int sp_slot_delta = frame_access_state()->has_frame()
has_frame ? (frame()->GetTotalFrameSlotCount() - pc_slots) : 0; ? (frame()->GetTotalFrameSlotCount() - pc_slots)
: 0;
// Discard only slots that won't be used by new parameters. // Discard only slots that won't be used by new parameters.
sp_slot_delta += stack_param_delta; sp_slot_delta += stack_param_delta;
return sp_slot_delta; return sp_slot_delta;
......
...@@ -85,7 +85,7 @@ class CodeGenerator final : public GapResolver::Assembler { ...@@ -85,7 +85,7 @@ class CodeGenerator final : public GapResolver::Assembler {
Heap::RootListIndex* index_return); Heap::RootListIndex* index_return);
// Assemble code for the specified instruction. // Assemble code for the specified instruction.
void AssembleInstruction(Instruction* instr); void AssembleInstruction(Instruction* instr, const InstructionBlock* block);
void AssembleSourcePosition(Instruction* instr); void AssembleSourcePosition(Instruction* instr);
void AssembleGaps(Instruction* instr); void AssembleGaps(Instruction* instr);
...@@ -106,6 +106,9 @@ class CodeGenerator final : public GapResolver::Assembler { ...@@ -106,6 +106,9 @@ class CodeGenerator final : public GapResolver::Assembler {
// Generates an architecture-specific, descriptor-specific prologue // Generates an architecture-specific, descriptor-specific prologue
// to set up a stack frame. // to set up a stack frame.
void AssemblePrologue(); void AssemblePrologue();
void AssembleSetupStackPointer();
// Generates an architecture-specific, descriptor-specific return sequence // Generates an architecture-specific, descriptor-specific return sequence
// to tear down a stack frame. // to tear down a stack frame.
void AssembleReturn(); void AssembleReturn();
...@@ -113,6 +116,8 @@ class CodeGenerator final : public GapResolver::Assembler { ...@@ -113,6 +116,8 @@ class CodeGenerator final : public GapResolver::Assembler {
// Generates code to deconstruct a the caller's frame, including arguments. // Generates code to deconstruct a the caller's frame, including arguments.
void AssembleDeconstructActivationRecord(int stack_param_delta); void AssembleDeconstructActivationRecord(int stack_param_delta);
void AssembleDeconstructFrame();
// Generates code to manipulate the stack in preparation for a tail call. // Generates code to manipulate the stack in preparation for a tail call.
void AssemblePrepareTailCall(int stack_param_delta); void AssemblePrepareTailCall(int stack_param_delta);
......
...@@ -734,7 +734,8 @@ Node* CodeStubAssembler::ChangeFloat64ToTagged(Node* value) { ...@@ -734,7 +734,8 @@ Node* CodeStubAssembler::ChangeFloat64ToTagged(Node* value) {
} else { } else {
Node* pair = Int32AddWithOverflow(value32, value32); Node* pair = Int32AddWithOverflow(value32, value32);
Node* overflow = Projection(1, pair); Node* overflow = Projection(1, pair);
Label if_overflow(this, Label::kDeferred), if_notoverflow(this); Label if_overflow(this, Label::kDeferred), if_notoverflow(this),
if_join(this);
Branch(overflow, &if_overflow, &if_notoverflow); Branch(overflow, &if_overflow, &if_notoverflow);
Bind(&if_overflow); Bind(&if_overflow);
Goto(&if_valueisheapnumber); Goto(&if_valueisheapnumber);
......
...@@ -22,8 +22,9 @@ void FrameElider::MarkBlocks() { ...@@ -22,8 +22,9 @@ void FrameElider::MarkBlocks() {
for (InstructionBlock* block : instruction_blocks()) { for (InstructionBlock* block : instruction_blocks()) {
if (block->needs_frame()) continue; if (block->needs_frame()) continue;
for (int i = block->code_start(); i < block->code_end(); ++i) { for (int i = block->code_start(); i < block->code_end(); ++i) {
if (InstructionAt(i)->IsCall() || const Instruction* instr = InstructionAt(i);
InstructionAt(i)->opcode() == ArchOpcode::kArchDeoptimize) { if (instr->IsCall() || instr->IsDeoptimizeCall() ||
instr->arch_opcode() == ArchOpcode::kArchStackPointer) {
block->mark_needs_frame(); block->mark_needs_frame();
break; break;
} }
...@@ -50,6 +51,16 @@ void FrameElider::MarkDeConstruction() { ...@@ -50,6 +51,16 @@ void FrameElider::MarkDeConstruction() {
for (RpoNumber& succ : block->successors()) { for (RpoNumber& succ : block->successors()) {
if (!InstructionBlockAt(succ)->needs_frame()) { if (!InstructionBlockAt(succ)->needs_frame()) {
DCHECK_EQ(1U, block->SuccessorCount()); DCHECK_EQ(1U, block->SuccessorCount());
const Instruction* last =
InstructionAt(block->last_instruction_index());
if (last->IsThrow() || last->IsTailCall() ||
last->IsDeoptimizeCall()) {
// We need to keep the frame if we exit the block through any
// of these.
continue;
}
// The only cases when we need to deconstruct are ret and jump.
DCHECK(last->IsRet() || last->IsJump());
block->mark_must_deconstruct_frame(); block->mark_must_deconstruct_frame();
} }
} }
......
...@@ -13,9 +13,7 @@ namespace internal { ...@@ -13,9 +13,7 @@ namespace internal {
namespace compiler { namespace compiler {
Frame::Frame(int fixed_frame_size_in_slots, const CallDescriptor* descriptor) Frame::Frame(int fixed_frame_size_in_slots, const CallDescriptor* descriptor)
: needs_frame_((descriptor != nullptr) && : frame_slot_count_(fixed_frame_size_in_slots),
descriptor->RequiresFrameAsIncoming()),
frame_slot_count_(fixed_frame_size_in_slots),
callee_saved_slot_count_(0), callee_saved_slot_count_(0),
spill_slot_count_(0), spill_slot_count_(0),
allocated_registers_(nullptr), allocated_registers_(nullptr),
...@@ -34,8 +32,13 @@ int Frame::AlignFrame(int alignment) { ...@@ -34,8 +32,13 @@ int Frame::AlignFrame(int alignment) {
return delta; return delta;
} }
void FrameAccessState::MarkHasFrame(bool state) {
has_frame_ = state;
SetFrameAccessToDefault();
}
void FrameAccessState::SetFrameAccessToDefault() { void FrameAccessState::SetFrameAccessToDefault() {
if (frame()->needs_frame() && !FLAG_turbo_sp_frame_access) { if (has_frame() && !FLAG_turbo_sp_frame_access) {
SetFrameAccessToFP(); SetFrameAccessToFP();
} else { } else {
SetFrameAccessToSP(); SetFrameAccessToSP();
...@@ -46,7 +49,6 @@ void FrameAccessState::SetFrameAccessToDefault() { ...@@ -46,7 +49,6 @@ void FrameAccessState::SetFrameAccessToDefault() {
FrameOffset FrameAccessState::GetFrameOffset(int spill_slot) const { FrameOffset FrameAccessState::GetFrameOffset(int spill_slot) const {
const int frame_offset = FrameSlotToFPOffset(spill_slot); const int frame_offset = FrameSlotToFPOffset(spill_slot);
if (access_frame_with_fp()) { if (access_frame_with_fp()) {
DCHECK(frame()->needs_frame());
return FrameOffset::FromFramePointer(frame_offset); return FrameOffset::FromFramePointer(frame_offset);
} else { } else {
// No frame. Retrieve all parameters relative to stack pointer. // No frame. Retrieve all parameters relative to stack pointer.
......
...@@ -81,26 +81,13 @@ class Frame : public ZoneObject { ...@@ -81,26 +81,13 @@ class Frame : public ZoneObject {
explicit Frame(int fixed_frame_size_in_slots, explicit Frame(int fixed_frame_size_in_slots,
const CallDescriptor* descriptor); const CallDescriptor* descriptor);
inline bool needs_frame() const { return needs_frame_; }
inline void MarkNeedsFrame() { needs_frame_ = true; }
inline int GetTotalFrameSlotCount() const { return frame_slot_count_; } inline int GetTotalFrameSlotCount() const { return frame_slot_count_; }
inline int GetSPToFPSlotCount() const {
return GetTotalFrameSlotCount() -
StandardFrameConstants::kFixedSlotCountAboveFp;
}
inline int GetSavedCalleeRegisterSlotCount() const { inline int GetSavedCalleeRegisterSlotCount() const {
return callee_saved_slot_count_; return callee_saved_slot_count_;
} }
inline int GetSpillSlotCount() const { return spill_slot_count_; } inline int GetSpillSlotCount() const { return spill_slot_count_; }
inline void SetElidedFrameSizeInSlots(int slots) {
DCHECK_EQ(0, callee_saved_slot_count_);
DCHECK_EQ(0, spill_slot_count_);
frame_slot_count_ = slots;
}
void SetAllocatedRegisters(BitVector* regs) { void SetAllocatedRegisters(BitVector* regs) {
DCHECK(allocated_registers_ == nullptr); DCHECK(allocated_registers_ == nullptr);
allocated_registers_ = regs; allocated_registers_ = regs;
...@@ -120,21 +107,18 @@ class Frame : public ZoneObject { ...@@ -120,21 +107,18 @@ class Frame : public ZoneObject {
int alignment_slots = alignment / kPointerSize; int alignment_slots = alignment / kPointerSize;
int delta = alignment_slots - (frame_slot_count_ & (alignment_slots - 1)); int delta = alignment_slots - (frame_slot_count_ & (alignment_slots - 1));
if (delta != alignment_slots) { if (delta != alignment_slots) {
DCHECK(needs_frame_);
frame_slot_count_ += delta; frame_slot_count_ += delta;
} }
return delta; return delta;
} }
void AllocateSavedCalleeRegisterSlots(int count) { void AllocateSavedCalleeRegisterSlots(int count) {
needs_frame_ = true;
frame_slot_count_ += count; frame_slot_count_ += count;
callee_saved_slot_count_ += count; callee_saved_slot_count_ += count;
} }
int AllocateSpillSlot(int width) { int AllocateSpillSlot(int width) {
DCHECK_EQ(0, callee_saved_slot_count_); DCHECK_EQ(0, callee_saved_slot_count_);
needs_frame_ = true;
int frame_slot_count_before = frame_slot_count_; int frame_slot_count_before = frame_slot_count_;
int slot = AllocateAlignedFrameSlot(width); int slot = AllocateAlignedFrameSlot(width);
spill_slot_count_ += (frame_slot_count_ - frame_slot_count_before); spill_slot_count_ += (frame_slot_count_ - frame_slot_count_before);
...@@ -146,7 +130,6 @@ class Frame : public ZoneObject { ...@@ -146,7 +130,6 @@ class Frame : public ZoneObject {
int ReserveSpillSlots(size_t slot_count) { int ReserveSpillSlots(size_t slot_count) {
DCHECK_EQ(0, callee_saved_slot_count_); DCHECK_EQ(0, callee_saved_slot_count_);
DCHECK_EQ(0, spill_slot_count_); DCHECK_EQ(0, spill_slot_count_);
needs_frame_ = true;
spill_slot_count_ += static_cast<int>(slot_count); spill_slot_count_ += static_cast<int>(slot_count);
frame_slot_count_ += static_cast<int>(slot_count); frame_slot_count_ += static_cast<int>(slot_count);
return frame_slot_count_ - 1; return frame_slot_count_ - 1;
...@@ -168,7 +151,6 @@ class Frame : public ZoneObject { ...@@ -168,7 +151,6 @@ class Frame : public ZoneObject {
} }
private: private:
bool needs_frame_;
int frame_slot_count_; int frame_slot_count_;
int callee_saved_slot_count_; int callee_saved_slot_count_;
int spill_slot_count_; int spill_slot_count_;
...@@ -210,23 +192,33 @@ class FrameOffset { ...@@ -210,23 +192,33 @@ class FrameOffset {
class FrameAccessState : public ZoneObject { class FrameAccessState : public ZoneObject {
public: public:
explicit FrameAccessState(Frame* const frame) explicit FrameAccessState(Frame* const frame)
: frame_(frame), access_frame_with_fp_(false), sp_delta_(0) { : frame_(frame),
SetFrameAccessToDefault(); access_frame_with_fp_(false),
} sp_delta_(0),
has_frame_(false) {}
Frame* frame() const { return frame_; } Frame* frame() const { return frame_; }
void MarkHasFrame(bool state);
int sp_delta() const { return sp_delta_; } int sp_delta() const { return sp_delta_; }
void ClearSPDelta() { sp_delta_ = 0; } void ClearSPDelta() { sp_delta_ = 0; }
void IncreaseSPDelta(int amount) { sp_delta_ += amount; } void IncreaseSPDelta(int amount) { sp_delta_ += amount; }
bool access_frame_with_fp() const { return access_frame_with_fp_; } bool access_frame_with_fp() const { return access_frame_with_fp_; }
// Regardless of how we access slots on the stack - using sp or fp - do we
// have a frame, at the current stage in code generation.
bool has_frame() const { return has_frame_; }
void SetFrameAccessToDefault(); void SetFrameAccessToDefault();
void SetFrameAccessToFP() { access_frame_with_fp_ = true; } void SetFrameAccessToFP() { access_frame_with_fp_ = true; }
void SetFrameAccessToSP() { access_frame_with_fp_ = false; } void SetFrameAccessToSP() { access_frame_with_fp_ = false; }
int GetSPToFPSlotCount() const { int GetSPToFPSlotCount() const {
return frame_->GetSPToFPSlotCount() + sp_delta(); int frame_slot_count =
(has_frame() ? frame()->GetTotalFrameSlotCount() : kElidedFrameSlots) -
StandardFrameConstants::kFixedSlotCountAboveFp;
return frame_slot_count + sp_delta();
} }
int GetSPToFPOffset() const { return GetSPToFPSlotCount() * kPointerSize; } int GetSPToFPOffset() const { return GetSPToFPSlotCount() * kPointerSize; }
...@@ -240,6 +232,7 @@ class FrameAccessState : public ZoneObject { ...@@ -240,6 +232,7 @@ class FrameAccessState : public ZoneObject {
Frame* const frame_; Frame* const frame_;
bool access_frame_with_fp_; bool access_frame_with_fp_;
int sp_delta_; int sp_delta_;
bool has_frame_;
}; };
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
......
...@@ -330,6 +330,12 @@ class OutOfLineRecordWrite final : public OutOfLineCode { ...@@ -330,6 +330,12 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
__ bind(&done); \ __ bind(&done); \
} while (false) } while (false)
void CodeGenerator::AssembleDeconstructFrame() {
__ mov(esp, ebp);
__ pop(ebp);
}
void CodeGenerator::AssembleSetupStackPointer() {}
void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
...@@ -346,7 +352,7 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { ...@@ -346,7 +352,7 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
__ sub(esp, Immediate(-sp_slot_delta * kPointerSize)); __ sub(esp, Immediate(-sp_slot_delta * kPointerSize));
frame_access_state()->IncreaseSPDelta(-sp_slot_delta); frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
} }
if (frame()->needs_frame()) { if (frame_access_state()->has_frame()) {
__ mov(ebp, MemOperand(ebp, 0)); __ mov(ebp, MemOperand(ebp, 0));
} }
frame_access_state()->SetFrameAccessToSP(); frame_access_state()->SetFrameAccessToSP();
...@@ -514,7 +520,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -514,7 +520,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ mov(i.OutputRegister(), ebp); __ mov(i.OutputRegister(), ebp);
break; break;
case kArchParentFramePointer: case kArchParentFramePointer:
if (frame_access_state()->frame()->needs_frame()) { if (frame_access_state()->has_frame()) {
__ mov(i.OutputRegister(), Operand(ebp, 0)); __ mov(i.OutputRegister(), Operand(ebp, 0));
} else { } else {
__ mov(i.OutputRegister(), ebp); __ mov(i.OutputRegister(), ebp);
...@@ -1607,7 +1613,7 @@ void CodeGenerator::AssembleDeoptimizerCall( ...@@ -1607,7 +1613,7 @@ void CodeGenerator::AssembleDeoptimizerCall(
void CodeGenerator::AssemblePrologue() { void CodeGenerator::AssemblePrologue() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
if (frame()->needs_frame()) { if (frame_access_state()->has_frame()) {
if (descriptor->IsCFunctionCall()) { if (descriptor->IsCFunctionCall()) {
__ push(ebp); __ push(ebp);
__ mov(ebp, esp); __ mov(ebp, esp);
...@@ -1616,11 +1622,7 @@ void CodeGenerator::AssemblePrologue() { ...@@ -1616,11 +1622,7 @@ void CodeGenerator::AssemblePrologue() {
} else { } else {
__ StubPrologue(info()->GetOutputStackFrameType()); __ StubPrologue(info()->GetOutputStackFrameType());
} }
} else {
frame()->SetElidedFrameSizeInSlots(kPCOnStackSize / kPointerSize);
} }
frame_access_state()->SetFrameAccessToDefault();
int stack_shrink_slots = frame()->GetSpillSlotCount(); int stack_shrink_slots = frame()->GetSpillSlotCount();
if (info()->is_osr()) { if (info()->is_osr()) {
// TurboFan OSR-compiled functions cannot be entered directly. // TurboFan OSR-compiled functions cannot be entered directly.
...@@ -1666,17 +1668,15 @@ void CodeGenerator::AssembleReturn() { ...@@ -1666,17 +1668,15 @@ void CodeGenerator::AssembleReturn() {
} }
if (descriptor->IsCFunctionCall()) { if (descriptor->IsCFunctionCall()) {
__ mov(esp, ebp); // Move stack pointer back to frame pointer. AssembleDeconstructFrame();
__ pop(ebp); // Pop caller's frame pointer. } else if (frame_access_state()->has_frame()) {
} else if (frame()->needs_frame()) {
// Canonicalize JSFunction return sites for now. // Canonicalize JSFunction return sites for now.
if (return_label_.is_bound()) { if (return_label_.is_bound()) {
__ jmp(&return_label_); __ jmp(&return_label_);
return; return;
} else { } else {
__ bind(&return_label_); __ bind(&return_label_);
__ mov(esp, ebp); // Move stack pointer back to frame pointer. AssembleDeconstructFrame();
__ pop(ebp); // Pop caller's frame pointer.
} }
} }
size_t pop_size = descriptor->StackParameterCount() * kPointerSize; size_t pop_size = descriptor->StackParameterCount() * kPointerSize;
......
...@@ -1190,7 +1190,6 @@ void InstructionSelector::VisitLoadStackPointer(Node* node) { ...@@ -1190,7 +1190,6 @@ void InstructionSelector::VisitLoadStackPointer(Node* node) {
void InstructionSelector::VisitLoadFramePointer(Node* node) { void InstructionSelector::VisitLoadFramePointer(Node* node) {
OperandGenerator g(this); OperandGenerator g(this);
frame_->MarkNeedsFrame();
Emit(kArchFramePointer, g.DefineAsRegister(node)); Emit(kArchFramePointer, g.DefineAsRegister(node));
} }
......
...@@ -812,6 +812,23 @@ class Instruction final { ...@@ -812,6 +812,23 @@ class Instruction final {
OutputCount() == 0 && TempCount() == 0; OutputCount() == 0 && TempCount() == 0;
} }
bool IsDeoptimizeCall() const {
return arch_opcode() == ArchOpcode::kArchDeoptimize ||
FlagsModeField::decode(opcode()) == kFlags_deoptimize;
}
bool IsJump() const { return arch_opcode() == ArchOpcode::kArchJmp; }
bool IsRet() const { return arch_opcode() == ArchOpcode::kArchRet; }
bool IsTailCall() const {
return arch_opcode() == ArchOpcode::kArchTailCallCodeObject ||
arch_opcode() == ArchOpcode::kArchTailCallCodeObjectFromJSFunction ||
arch_opcode() == ArchOpcode::kArchTailCallJSFunction ||
arch_opcode() == ArchOpcode::kArchTailCallJSFunctionFromJSFunction;
}
bool IsThrow() const {
return arch_opcode() == ArchOpcode::kArchThrowTerminator;
}
enum GapPosition { enum GapPosition {
START, START,
END, END,
......
...@@ -96,7 +96,9 @@ bool JumpThreading::ComputeForwarding(Zone* local_zone, ...@@ -96,7 +96,9 @@ bool JumpThreading::ComputeForwarding(Zone* local_zone,
// the frame at start. So we should move the decision of whether // the frame at start. So we should move the decision of whether
// to build a frame or not in the register allocator, and trickle it // to build a frame or not in the register allocator, and trickle it
// here and to the code generator. // here and to the code generator.
if (frame_at_start || !block->must_deconstruct_frame()) { if (frame_at_start ||
!(block->must_deconstruct_frame() ||
block->must_construct_frame())) {
fw = code->InputRpo(instr, 0); fw = code->InputRpo(instr, 0);
} }
fallthru = false; fallthru = false;
......
...@@ -224,7 +224,8 @@ class OutOfLineRecordWrite final : public OutOfLineCode { ...@@ -224,7 +224,8 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
value_(value), value_(value),
scratch0_(scratch0), scratch0_(scratch0),
scratch1_(scratch1), scratch1_(scratch1),
mode_(mode) {} mode_(mode),
must_save_lr_(!gen->frame_access_state()->has_frame()) {}
void Generate() final { void Generate() final {
if (mode_ > RecordWriteMode::kValueIsPointer) { if (mode_ > RecordWriteMode::kValueIsPointer) {
...@@ -238,7 +239,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode { ...@@ -238,7 +239,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
: OMIT_REMEMBERED_SET; : OMIT_REMEMBERED_SET;
SaveFPRegsMode const save_fp_mode = SaveFPRegsMode const save_fp_mode =
frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
if (!frame()->needs_frame()) { if (must_save_lr_) {
// We need to save and restore ra if the frame was elided. // We need to save and restore ra if the frame was elided.
__ Push(ra); __ Push(ra);
} }
...@@ -246,7 +247,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode { ...@@ -246,7 +247,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
remembered_set_action, save_fp_mode); remembered_set_action, save_fp_mode);
__ Addu(scratch1_, object_, index_); __ Addu(scratch1_, object_, index_);
__ CallStub(&stub); __ CallStub(&stub);
if (!frame()->needs_frame()) { if (must_save_lr_) {
__ Pop(ra); __ Pop(ra);
} }
} }
...@@ -258,6 +259,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode { ...@@ -258,6 +259,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
Register const scratch0_; Register const scratch0_;
Register const scratch1_; Register const scratch1_;
RecordWriteMode const mode_; RecordWriteMode const mode_;
bool must_save_lr_;
}; };
...@@ -470,6 +472,13 @@ FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate, ...@@ -470,6 +472,13 @@ FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate,
__ bind(&done); \ __ bind(&done); \
} }
void CodeGenerator::AssembleDeconstructFrame() {
__ mov(sp, fp);
__ Pop(ra, fp);
}
void CodeGenerator::AssembleSetupStackPointer() {}
void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
if (sp_slot_delta > 0) { if (sp_slot_delta > 0) {
...@@ -485,7 +494,7 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { ...@@ -485,7 +494,7 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
__ Subu(sp, sp, Operand(-sp_slot_delta * kPointerSize)); __ Subu(sp, sp, Operand(-sp_slot_delta * kPointerSize));
frame_access_state()->IncreaseSPDelta(-sp_slot_delta); frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
} }
if (frame()->needs_frame()) { if (frame_access_state()->has_frame()) {
__ lw(ra, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); __ lw(ra, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
__ lw(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); __ lw(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
} }
...@@ -645,7 +654,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -645,7 +654,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ mov(i.OutputRegister(), fp); __ mov(i.OutputRegister(), fp);
break; break;
case kArchParentFramePointer: case kArchParentFramePointer:
if (frame_access_state()->frame()->needs_frame()) { if (frame_access_state()->has_frame()) {
__ lw(i.OutputRegister(), MemOperand(fp, 0)); __ lw(i.OutputRegister(), MemOperand(fp, 0));
} else { } else {
__ mov(i.OutputRegister(), fp); __ mov(i.OutputRegister(), fp);
...@@ -1564,7 +1573,7 @@ void CodeGenerator::AssembleDeoptimizerCall( ...@@ -1564,7 +1573,7 @@ void CodeGenerator::AssembleDeoptimizerCall(
void CodeGenerator::AssemblePrologue() { void CodeGenerator::AssemblePrologue() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
int stack_shrink_slots = frame()->GetSpillSlotCount(); int stack_shrink_slots = frame()->GetSpillSlotCount();
if (frame()->needs_frame()) { if (frame_access_state()->has_frame()) {
if (descriptor->IsCFunctionCall()) { if (descriptor->IsCFunctionCall()) {
__ Push(ra, fp); __ Push(ra, fp);
__ mov(fp, sp); __ mov(fp, sp);
...@@ -1573,10 +1582,7 @@ void CodeGenerator::AssemblePrologue() { ...@@ -1573,10 +1582,7 @@ void CodeGenerator::AssemblePrologue() {
} else { } else {
__ StubPrologue(info()->GetOutputStackFrameType()); __ StubPrologue(info()->GetOutputStackFrameType());
} }
} else {
frame()->SetElidedFrameSizeInSlots(0);
} }
frame_access_state()->SetFrameAccessToDefault();
if (info()->is_osr()) { if (info()->is_osr()) {
// TurboFan OSR-compiled functions cannot be entered directly. // TurboFan OSR-compiled functions cannot be entered directly.
...@@ -1638,17 +1644,15 @@ void CodeGenerator::AssembleReturn() { ...@@ -1638,17 +1644,15 @@ void CodeGenerator::AssembleReturn() {
} }
if (descriptor->IsCFunctionCall()) { if (descriptor->IsCFunctionCall()) {
__ mov(sp, fp); AssembleDeconstructFrame();
__ Pop(ra, fp); } else if (frame_access_state()->has_frame()) {
} else if (frame()->needs_frame()) {
// Canonicalize JSFunction return sites for now. // Canonicalize JSFunction return sites for now.
if (return_label_.is_bound()) { if (return_label_.is_bound()) {
__ Branch(&return_label_); __ Branch(&return_label_);
return; return;
} else { } else {
__ bind(&return_label_); __ bind(&return_label_);
__ mov(sp, fp); AssembleDeconstructFrame();
__ Pop(ra, fp);
} }
} }
if (pop_count != 0) { if (pop_count != 0) {
......
...@@ -224,7 +224,8 @@ class OutOfLineRecordWrite final : public OutOfLineCode { ...@@ -224,7 +224,8 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
value_(value), value_(value),
scratch0_(scratch0), scratch0_(scratch0),
scratch1_(scratch1), scratch1_(scratch1),
mode_(mode) {} mode_(mode),
must_save_lr_(gen->frame_access_state()->has_frame()) {}
void Generate() final { void Generate() final {
if (mode_ > RecordWriteMode::kValueIsPointer) { if (mode_ > RecordWriteMode::kValueIsPointer) {
...@@ -238,7 +239,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode { ...@@ -238,7 +239,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
: OMIT_REMEMBERED_SET; : OMIT_REMEMBERED_SET;
SaveFPRegsMode const save_fp_mode = SaveFPRegsMode const save_fp_mode =
frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
if (!frame()->needs_frame()) { if (must_save_lr_) {
// We need to save and restore ra if the frame was elided. // We need to save and restore ra if the frame was elided.
__ Push(ra); __ Push(ra);
} }
...@@ -246,7 +247,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode { ...@@ -246,7 +247,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
remembered_set_action, save_fp_mode); remembered_set_action, save_fp_mode);
__ Daddu(scratch1_, object_, index_); __ Daddu(scratch1_, object_, index_);
__ CallStub(&stub); __ CallStub(&stub);
if (!frame()->needs_frame()) { if (must_save_lr_) {
__ Pop(ra); __ Pop(ra);
} }
} }
...@@ -258,6 +259,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode { ...@@ -258,6 +259,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
Register const scratch0_; Register const scratch0_;
Register const scratch1_; Register const scratch1_;
RecordWriteMode const mode_; RecordWriteMode const mode_;
bool must_save_lr_;
}; };
...@@ -482,6 +484,13 @@ FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate, ...@@ -482,6 +484,13 @@ FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate,
__ bind(&done); \ __ bind(&done); \
} }
void CodeGenerator::AssembleDeconstructFrame() {
__ mov(sp, fp);
__ Pop(ra, fp);
}
void CodeGenerator::AssembleSetupStackPointer() {}
void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
if (sp_slot_delta > 0) { if (sp_slot_delta > 0) {
...@@ -497,7 +506,7 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { ...@@ -497,7 +506,7 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
__ Dsubu(sp, sp, Operand(-sp_slot_delta * kPointerSize)); __ Dsubu(sp, sp, Operand(-sp_slot_delta * kPointerSize));
frame_access_state()->IncreaseSPDelta(-sp_slot_delta); frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
} }
if (frame()->needs_frame()) { if (frame_access_state()->has_frame()) {
__ ld(ra, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); __ ld(ra, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
__ ld(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); __ ld(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
} }
...@@ -655,7 +664,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -655,7 +664,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ mov(i.OutputRegister(), fp); __ mov(i.OutputRegister(), fp);
break; break;
case kArchParentFramePointer: case kArchParentFramePointer:
if (frame_access_state()->frame()->needs_frame()) { if (frame_access_state()->has_frame()) {
__ ld(i.OutputRegister(), MemOperand(fp, 0)); __ ld(i.OutputRegister(), MemOperand(fp, 0));
} else { } else {
__ mov(i.OutputRegister(), fp); __ mov(i.OutputRegister(), fp);
...@@ -1870,7 +1879,7 @@ void CodeGenerator::AssembleDeoptimizerCall( ...@@ -1870,7 +1879,7 @@ void CodeGenerator::AssembleDeoptimizerCall(
void CodeGenerator::AssemblePrologue() { void CodeGenerator::AssemblePrologue() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
if (frame()->needs_frame()) { if (frame_access_state()->has_frame()) {
if (descriptor->IsCFunctionCall()) { if (descriptor->IsCFunctionCall()) {
__ Push(ra, fp); __ Push(ra, fp);
__ mov(fp, sp); __ mov(fp, sp);
...@@ -1879,10 +1888,7 @@ void CodeGenerator::AssemblePrologue() { ...@@ -1879,10 +1888,7 @@ void CodeGenerator::AssemblePrologue() {
} else { } else {
__ StubPrologue(info()->GetOutputStackFrameType()); __ StubPrologue(info()->GetOutputStackFrameType());
} }
} else {
frame()->SetElidedFrameSizeInSlots(0);
} }
frame_access_state()->SetFrameAccessToDefault();
int stack_shrink_slots = frame()->GetSpillSlotCount(); int stack_shrink_slots = frame()->GetSpillSlotCount();
if (info()->is_osr()) { if (info()->is_osr()) {
...@@ -1941,17 +1947,15 @@ void CodeGenerator::AssembleReturn() { ...@@ -1941,17 +1947,15 @@ void CodeGenerator::AssembleReturn() {
} }
if (descriptor->IsCFunctionCall()) { if (descriptor->IsCFunctionCall()) {
__ mov(sp, fp); AssembleDeconstructFrame();
__ Pop(ra, fp); } else if (frame_access_state()->has_frame()) {
} else if (frame()->needs_frame()) {
// Canonicalize JSFunction return sites for now. // Canonicalize JSFunction return sites for now.
if (return_label_.is_bound()) { if (return_label_.is_bound()) {
__ Branch(&return_label_); __ Branch(&return_label_);
return; return;
} else { } else {
__ bind(&return_label_); __ bind(&return_label_);
__ mov(sp, fp); AssembleDeconstructFrame();
__ Pop(ra, fp);
} }
} }
int pop_count = static_cast<int>(descriptor->StackParameterCount()); int pop_count = static_cast<int>(descriptor->StackParameterCount());
......
...@@ -276,6 +276,9 @@ class PipelineData { ...@@ -276,6 +276,9 @@ class PipelineData {
info()->isolate(), instruction_zone(), instruction_blocks); info()->isolate(), instruction_zone(), instruction_blocks);
if (descriptor && descriptor->RequiresFrameAsIncoming()) { if (descriptor && descriptor->RequiresFrameAsIncoming()) {
sequence_->instruction_blocks()[0]->mark_needs_frame(); sequence_->instruction_blocks()[0]->mark_needs_frame();
} else {
DCHECK_EQ(0, descriptor->CalleeSavedFPRegisters());
DCHECK_EQ(0, descriptor->CalleeSavedRegisters());
} }
} }
...@@ -1370,6 +1373,7 @@ Handle<Code> Pipeline::ScheduleAndGenerateCode( ...@@ -1370,6 +1373,7 @@ Handle<Code> Pipeline::ScheduleAndGenerateCode(
AllocateRegisters( AllocateRegisters(
RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN), RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN),
call_descriptor, run_verifier); call_descriptor, run_verifier);
Run<FrameElisionPhase>();
if (data->compilation_failed()) { if (data->compilation_failed()) {
info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc); info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc);
return Handle<Code>(); return Handle<Code>();
...@@ -1378,11 +1382,7 @@ Handle<Code> Pipeline::ScheduleAndGenerateCode( ...@@ -1378,11 +1382,7 @@ Handle<Code> Pipeline::ScheduleAndGenerateCode(
BeginPhaseKind("code generation"); BeginPhaseKind("code generation");
// TODO(mtrofin): move this off to the register allocator. // TODO(mtrofin): move this off to the register allocator.
bool generate_frame_at_start = bool generate_frame_at_start =
!FLAG_turbo_frame_elision || !data_->info()->IsStub() || data_->sequence()->instruction_blocks().front()->must_construct_frame();
!data_->frame()->needs_frame() ||
data_->sequence()->instruction_blocks().front()->needs_frame() ||
linkage.GetIncomingDescriptor()->CalleeSavedFPRegisters() != 0 ||
linkage.GetIncomingDescriptor()->CalleeSavedRegisters() != 0;
// Optimimize jumps. // Optimimize jumps.
if (FLAG_turbo_jt) { if (FLAG_turbo_jt) {
Run<JumpThreadingPhase>(generate_frame_at_start); Run<JumpThreadingPhase>(generate_frame_at_start);
...@@ -1502,7 +1502,6 @@ void Pipeline::AllocateRegisters(const RegisterConfiguration* config, ...@@ -1502,7 +1502,6 @@ void Pipeline::AllocateRegisters(const RegisterConfiguration* config,
} }
Run<LocateSpillSlotsPhase>(); Run<LocateSpillSlotsPhase>();
Run<FrameElisionPhase>();
if (FLAG_trace_turbo_graph) { if (FLAG_trace_turbo_graph) {
OFStream os(stdout); OFStream os(stdout);
......
...@@ -602,6 +602,12 @@ class OutOfLineRecordWrite final : public OutOfLineCode { ...@@ -602,6 +602,12 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
} \ } \
} while (false) } while (false)
void CodeGenerator::AssembleDeconstructFrame() {
__ movq(rsp, rbp);
__ popq(rbp);
}
void CodeGenerator::AssembleSetupStackPointer() {}
void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
...@@ -618,7 +624,7 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { ...@@ -618,7 +624,7 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
__ subq(rsp, Immediate(-sp_slot_delta * kPointerSize)); __ subq(rsp, Immediate(-sp_slot_delta * kPointerSize));
frame_access_state()->IncreaseSPDelta(-sp_slot_delta); frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
} }
if (frame()->needs_frame()) { if (frame_access_state()->has_frame()) {
__ movq(rbp, MemOperand(rbp, 0)); __ movq(rbp, MemOperand(rbp, 0));
} }
frame_access_state()->SetFrameAccessToSP(); frame_access_state()->SetFrameAccessToSP();
...@@ -775,7 +781,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -775,7 +781,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ movq(i.OutputRegister(), rbp); __ movq(i.OutputRegister(), rbp);
break; break;
case kArchParentFramePointer: case kArchParentFramePointer:
if (frame_access_state()->frame()->needs_frame()) { if (frame_access_state()->has_frame()) {
__ movq(i.OutputRegister(), Operand(rbp, 0)); __ movq(i.OutputRegister(), Operand(rbp, 0));
} else { } else {
__ movq(i.OutputRegister(), rbp); __ movq(i.OutputRegister(), rbp);
...@@ -1929,7 +1935,7 @@ static const int kQuadWordSize = 16; ...@@ -1929,7 +1935,7 @@ static const int kQuadWordSize = 16;
void CodeGenerator::AssemblePrologue() { void CodeGenerator::AssemblePrologue() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
if (frame()->needs_frame()) { if (frame_access_state()->has_frame()) {
if (descriptor->IsCFunctionCall()) { if (descriptor->IsCFunctionCall()) {
__ pushq(rbp); __ pushq(rbp);
__ movq(rbp, rsp); __ movq(rbp, rsp);
...@@ -1938,11 +1944,7 @@ void CodeGenerator::AssemblePrologue() { ...@@ -1938,11 +1944,7 @@ void CodeGenerator::AssemblePrologue() {
} else { } else {
__ StubPrologue(info()->GetOutputStackFrameType()); __ StubPrologue(info()->GetOutputStackFrameType());
} }
} else {
frame()->SetElidedFrameSizeInSlots(kPCOnStackSize / kPointerSize);
} }
frame_access_state()->SetFrameAccessToDefault();
int stack_shrink_slots = frame()->GetSpillSlotCount(); int stack_shrink_slots = frame()->GetSpillSlotCount();
if (info()->is_osr()) { if (info()->is_osr()) {
// TurboFan OSR-compiled functions cannot be entered directly. // TurboFan OSR-compiled functions cannot be entered directly.
...@@ -2022,17 +2024,15 @@ void CodeGenerator::AssembleReturn() { ...@@ -2022,17 +2024,15 @@ void CodeGenerator::AssembleReturn() {
} }
if (descriptor->IsCFunctionCall()) { if (descriptor->IsCFunctionCall()) {
__ movq(rsp, rbp); // Move stack pointer back to frame pointer. AssembleDeconstructFrame();
__ popq(rbp); // Pop caller's frame pointer. } else if (frame_access_state()->has_frame()) {
} else if (frame()->needs_frame()) {
// Canonicalize JSFunction return sites for now. // Canonicalize JSFunction return sites for now.
if (return_label_.is_bound()) { if (return_label_.is_bound()) {
__ jmp(&return_label_); __ jmp(&return_label_);
return; return;
} else { } else {
__ bind(&return_label_); __ bind(&return_label_);
__ movq(rsp, rbp); // Move stack pointer back to frame pointer. AssembleDeconstructFrame();
__ popq(rbp); // Pop caller's frame pointer.
} }
} }
size_t pop_size = descriptor->StackParameterCount() * kPointerSize; size_t pop_size = descriptor->StackParameterCount() * kPointerSize;
......
...@@ -124,6 +124,11 @@ const int kFloatSize = sizeof(float); // NOLINT ...@@ -124,6 +124,11 @@ const int kFloatSize = sizeof(float); // NOLINT
const int kDoubleSize = sizeof(double); // NOLINT const int kDoubleSize = sizeof(double); // NOLINT
const int kIntptrSize = sizeof(intptr_t); // NOLINT const int kIntptrSize = sizeof(intptr_t); // NOLINT
const int kPointerSize = sizeof(void*); // NOLINT const int kPointerSize = sizeof(void*); // NOLINT
#if V8_TARGET_ARCH_ARM64
const int kFrameAlignmentInBytes = 2 * kPointerSize;
#else
const int kFrameAlignmentInBytes = kPointerSize;
#endif
#if V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT #if V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
const int kRegisterSize = kPointerSize + kPointerSize; const int kRegisterSize = kPointerSize + kPointerSize;
#else #else
...@@ -132,6 +137,12 @@ const int kRegisterSize = kPointerSize; ...@@ -132,6 +137,12 @@ const int kRegisterSize = kPointerSize;
const int kPCOnStackSize = kRegisterSize; const int kPCOnStackSize = kRegisterSize;
const int kFPOnStackSize = kRegisterSize; const int kFPOnStackSize = kRegisterSize;
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
const int kElidedFrameSlots = kPCOnStackSize / kPointerSize;
#else
const int kElidedFrameSlots = 0;
#endif
const int kDoubleSizeLog2 = 3; const int kDoubleSizeLog2 = 3;
#if V8_HOST_ARCH_64_BIT #if V8_HOST_ARCH_64_BIT
......
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