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 @@
#error Unknown target architecture endianness
#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
// gives 1Mb bytes per page.
#if V8_HOST_ARCH_PPC && V8_TARGET_ARCH_PPC && V8_OS_LINUX
......
......@@ -359,13 +359,6 @@ void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
if (sp_slot_delta > 0) {
__ 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();
}
......@@ -376,6 +369,13 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
__ sub(sp, sp, Operand(-sp_slot_delta * kPointerSize));
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();
}
......
......@@ -464,9 +464,6 @@ void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
if (sp_slot_delta > 0) {
__ Add(jssp, jssp, Operand(sp_slot_delta * kPointerSize));
}
if (frame()->needs_frame()) {
__ Pop(fp, lr);
}
frame_access_state()->SetFrameAccessToDefault();
}
......@@ -477,6 +474,10 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
__ Sub(jssp, jssp, Operand(-sp_slot_delta * kPointerSize));
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();
}
......
......@@ -675,12 +675,10 @@ 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 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 =
has_frame
? (frame()->GetTotalFrameSlotCount() -
(StandardFrameConstants::kFixedFrameSizeFromFp / kPointerSize))
: 0;
has_frame ? (frame()->GetTotalFrameSlotCount() - pc_slots) : 0;
// Discard only slots that won't be used by new parameters.
sp_slot_delta += stack_param_delta;
return sp_slot_delta;
......
......@@ -337,9 +337,6 @@ void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
if (sp_slot_delta > 0) {
__ add(esp, Immediate(sp_slot_delta * kPointerSize));
}
if (frame()->needs_frame()) {
__ pop(ebp);
}
frame_access_state()->SetFrameAccessToDefault();
}
......@@ -350,6 +347,9 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
__ sub(esp, Immediate(-sp_slot_delta * kPointerSize));
frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
}
if (frame()->needs_frame()) {
__ mov(ebp, MemOperand(ebp, 0));
}
frame_access_state()->SetFrameAccessToSP();
}
......
......@@ -507,12 +507,11 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
}
DCHECK_EQ(input_count, buffer->instruction_args.size() + pushed_count -
buffer->frame_state_value_count());
if (call_tail && stack_param_delta != 0) {
// For tail calls that change the size of their parameter list, move the
// saved caller return address, parent frame pointer and parent constant
// pool pointer to just above the parameters.
// Return address
if (V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK && call_tail &&
stack_param_delta != 0) {
// For tail calls that change the size of their parameter list and keep
// their return address on the stack, move the return address to just above
// the parameters.
LinkageLocation saved_return_location =
LinkageLocation::ForSavedCallerReturnAddress();
InstructionOperand return_address =
......@@ -520,26 +519,6 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
saved_return_location, stack_param_delta),
saved_return_location);
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) {
if (sp_slot_delta > 0) {
__ addiu(sp, sp, sp_slot_delta * kPointerSize);
}
if (frame()->needs_frame()) {
__ Pop(ra, fp);
}
frame_access_state()->SetFrameAccessToDefault();
}
......@@ -480,6 +477,10 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
__ Subu(sp, sp, Operand(-sp_slot_delta * kPointerSize));
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();
}
......
......@@ -466,9 +466,6 @@ void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
if (sp_slot_delta > 0) {
__ daddiu(sp, sp, sp_slot_delta * kPointerSize);
}
if (frame()->needs_frame()) {
__ Pop(ra, fp);
}
frame_access_state()->SetFrameAccessToDefault();
}
......@@ -479,6 +476,10 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
__ Dsubu(sp, sp, Operand(-sp_slot_delta * kPointerSize));
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();
}
......
......@@ -578,9 +578,6 @@ void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
if (sp_slot_delta > 0) {
__ addq(rsp, Immediate(sp_slot_delta * kPointerSize));
}
if (frame()->needs_frame()) {
__ popq(rbp);
}
frame_access_state()->SetFrameAccessToDefault();
}
......@@ -591,6 +588,9 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
__ subq(rsp, Immediate(-sp_slot_delta * kPointerSize));
frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
}
if (frame()->needs_frame()) {
__ movq(rbp, MemOperand(rbp, 0));
}
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