Commit 51e992f1 authored by danno's avatar danno Committed by Commit bot

[turbofan] Fewer gap moves for tail calls

Restore frame pointer directly from stack rather than copying it and
restoring. Also restore return address register directly on platforms that
support it.

BUG=v8:4076
LOG=n

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

Cr-Commit-Position: refs/heads/master@{#32410}
parent 802c036a
...@@ -183,6 +183,13 @@ ...@@ -183,6 +183,13 @@
#error Unknown target architecture endianness #error Unknown target architecture endianness
#endif #endif
#if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64) || \
defined(V8_TARGET_ARCH_X87)
#define V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK 1
#else
#define V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK 0
#endif
// Number of bits to represent the page size for paged spaces. The value of 20 // Number of bits to represent the page size for paged spaces. The value of 20
// gives 1Mb bytes per page. // gives 1Mb bytes per page.
#if V8_HOST_ARCH_PPC && V8_TARGET_ARCH_PPC && V8_OS_LINUX #if V8_HOST_ARCH_PPC && V8_TARGET_ARCH_PPC && V8_OS_LINUX
......
...@@ -359,13 +359,6 @@ void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { ...@@ -359,13 +359,6 @@ void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
if (sp_slot_delta > 0) { if (sp_slot_delta > 0) {
__ add(sp, sp, Operand(sp_slot_delta * kPointerSize)); __ add(sp, sp, Operand(sp_slot_delta * kPointerSize));
} }
if (frame()->needs_frame()) {
if (FLAG_enable_embedded_constant_pool) {
__ ldm(ia_w, sp, pp.bit() | fp.bit() | lr.bit());
} else {
__ ldm(ia_w, sp, fp.bit() | lr.bit());
}
}
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();
} }
...@@ -376,6 +369,13 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { ...@@ -376,6 +369,13 @@ 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 (FLAG_enable_embedded_constant_pool) {
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kConstantPoolOffset));
}
__ ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
__ ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
}
frame_access_state()->SetFrameAccessToSP(); frame_access_state()->SetFrameAccessToSP();
} }
......
...@@ -464,9 +464,6 @@ void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { ...@@ -464,9 +464,6 @@ void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
if (sp_slot_delta > 0) { if (sp_slot_delta > 0) {
__ Add(jssp, jssp, Operand(sp_slot_delta * kPointerSize)); __ Add(jssp, jssp, Operand(sp_slot_delta * kPointerSize));
} }
if (frame()->needs_frame()) {
__ Pop(fp, lr);
}
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();
} }
...@@ -477,6 +474,10 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { ...@@ -477,6 +474,10 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
__ Sub(jssp, jssp, Operand(-sp_slot_delta * kPointerSize)); __ Sub(jssp, jssp, Operand(-sp_slot_delta * kPointerSize));
frame_access_state()->IncreaseSPDelta(-sp_slot_delta); frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
} }
if (frame()->needs_frame()) {
__ Ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
__ Ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
}
frame_access_state()->SetFrameAccessToSP(); frame_access_state()->SetFrameAccessToSP();
} }
......
...@@ -675,12 +675,10 @@ int CodeGenerator::TailCallFrameStackSlotDelta(int stack_param_delta) { ...@@ -675,12 +675,10 @@ int CodeGenerator::TailCallFrameStackSlotDelta(int stack_param_delta) {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
int spill_slots = frame()->GetSpillSlotCount(); int spill_slots = frame()->GetSpillSlotCount();
bool has_frame = descriptor->IsJSFunctionCall() || spill_slots > 0; bool has_frame = descriptor->IsJSFunctionCall() || spill_slots > 0;
// Leave the PC and saved frame pointer on the stack. // 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 sp_slot_delta = int sp_slot_delta =
has_frame has_frame ? (frame()->GetTotalFrameSlotCount() - pc_slots) : 0;
? (frame()->GetTotalFrameSlotCount() -
(StandardFrameConstants::kFixedFrameSizeFromFp / kPointerSize))
: 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;
......
...@@ -337,9 +337,6 @@ void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { ...@@ -337,9 +337,6 @@ void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
if (sp_slot_delta > 0) { if (sp_slot_delta > 0) {
__ add(esp, Immediate(sp_slot_delta * kPointerSize)); __ add(esp, Immediate(sp_slot_delta * kPointerSize));
} }
if (frame()->needs_frame()) {
__ pop(ebp);
}
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();
} }
...@@ -350,6 +347,9 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { ...@@ -350,6 +347,9 @@ 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()) {
__ mov(ebp, MemOperand(ebp, 0));
}
frame_access_state()->SetFrameAccessToSP(); frame_access_state()->SetFrameAccessToSP();
} }
......
...@@ -507,12 +507,11 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer, ...@@ -507,12 +507,11 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
} }
DCHECK_EQ(input_count, buffer->instruction_args.size() + pushed_count - DCHECK_EQ(input_count, buffer->instruction_args.size() + pushed_count -
buffer->frame_state_value_count()); buffer->frame_state_value_count());
if (call_tail && stack_param_delta != 0) { if (V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK && call_tail &&
// For tail calls that change the size of their parameter list, move the stack_param_delta != 0) {
// saved caller return address, parent frame pointer and parent constant // For tail calls that change the size of their parameter list and keep
// pool pointer to just above the parameters. // their return address on the stack, move the return address to just above
// the parameters.
// Return address
LinkageLocation saved_return_location = LinkageLocation saved_return_location =
LinkageLocation::ForSavedCallerReturnAddress(); LinkageLocation::ForSavedCallerReturnAddress();
InstructionOperand return_address = InstructionOperand return_address =
...@@ -520,26 +519,6 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer, ...@@ -520,26 +519,6 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
saved_return_location, stack_param_delta), saved_return_location, stack_param_delta),
saved_return_location); saved_return_location);
buffer->instruction_args.push_back(return_address); buffer->instruction_args.push_back(return_address);
// Parent frame pointer
LinkageLocation saved_frame_location =
LinkageLocation::ForSavedCallerFramePtr();
InstructionOperand saved_frame =
g.UsePointerLocation(LinkageLocation::ConvertToTailCallerLocation(
saved_frame_location, stack_param_delta),
saved_frame_location);
buffer->instruction_args.push_back(saved_frame);
if (V8_EMBEDDED_CONSTANT_POOL) {
// Constant pool pointer
LinkageLocation saved_cp_location =
LinkageLocation::ForSavedCallerConstantPool();
InstructionOperand saved_cp =
g.UsePointerLocation(LinkageLocation::ConvertToTailCallerLocation(
saved_cp_location, stack_param_delta),
saved_cp_location);
buffer->instruction_args.push_back(saved_cp);
}
} }
} }
......
...@@ -467,9 +467,6 @@ void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { ...@@ -467,9 +467,6 @@ void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
if (sp_slot_delta > 0) { if (sp_slot_delta > 0) {
__ addiu(sp, sp, sp_slot_delta * kPointerSize); __ addiu(sp, sp, sp_slot_delta * kPointerSize);
} }
if (frame()->needs_frame()) {
__ Pop(ra, fp);
}
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();
} }
...@@ -480,6 +477,10 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { ...@@ -480,6 +477,10 @@ 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()) {
__ lw(ra, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
__ lw(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
}
frame_access_state()->SetFrameAccessToSP(); frame_access_state()->SetFrameAccessToSP();
} }
......
...@@ -466,9 +466,6 @@ void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { ...@@ -466,9 +466,6 @@ void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
if (sp_slot_delta > 0) { if (sp_slot_delta > 0) {
__ daddiu(sp, sp, sp_slot_delta * kPointerSize); __ daddiu(sp, sp, sp_slot_delta * kPointerSize);
} }
if (frame()->needs_frame()) {
__ Pop(ra, fp);
}
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();
} }
...@@ -479,6 +476,10 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { ...@@ -479,6 +476,10 @@ 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()) {
__ ld(ra, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
__ ld(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
}
frame_access_state()->SetFrameAccessToSP(); frame_access_state()->SetFrameAccessToSP();
} }
......
...@@ -578,9 +578,6 @@ void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { ...@@ -578,9 +578,6 @@ void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
if (sp_slot_delta > 0) { if (sp_slot_delta > 0) {
__ addq(rsp, Immediate(sp_slot_delta * kPointerSize)); __ addq(rsp, Immediate(sp_slot_delta * kPointerSize));
} }
if (frame()->needs_frame()) {
__ popq(rbp);
}
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();
} }
...@@ -591,6 +588,9 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { ...@@ -591,6 +588,9 @@ 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()) {
__ movq(rbp, MemOperand(rbp, 0));
}
frame_access_state()->SetFrameAccessToSP(); frame_access_state()->SetFrameAccessToSP();
} }
......
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