Commit 41870350 authored by mbrandy's avatar mbrandy Committed by Commit bot

PPC: [turbofan] Unify referencing of stack slots

Port cbbaf9ea

Note that the above commit breaks embedded constant pools and will need to
be revised in a future CL.

Original commit message:
    Previously, it was not possible to specify StackSlotOperands for all
    slots in both the caller and callee stacks. Specifically, the region
    of the callee's stack including the saved return address, frame
    pointer, function pointer and context pointer could not be addressed
    by the register allocator/gap resolver.

    In preparation for better tail call support, which will use the gap
    resolver to reconcile outgoing parameters, this change makes it
    possible to address all slots on the stack, because slots in the
    previously inaccessible dead zone may become parameter slots for
    outgoing tail calls. All caller stack slots are accessible as they
    were before, with slot -1 corresponding to the last stack
    parameter. Stack slot indices >= 0 access the callee stack, with slot
    0 corresponding to the callee's saved return address, 1 corresponding
    to the saved frame pointer, 2 corresponding to the current function
    context, 3 corresponding to the frame marker/JSFunction, and slots 4
    and above corresponding to spill slots.

    The following changes were specifically     needed:

    * Frame     has been changed to explicitly manage three areas of the
      callee frame, the fixed header, the spill slot area, and the
      callee-saved register area.
    * Conversions from stack slot indices to fp offsets all now go through
      a common bottleneck: OptimizedFrame::StackSlotOffsetRelativeToFp
    * The generation of deoptimization translation tables has been changed
      to support the new stack slot indexing scheme. Crankshaft, which
      doesn't support the new slot numbering in its register allocator,
      must adapt the indexes when creating translation tables.
    * Callee-saved parameters are now kept below spill slots, not above,
      to support saving only the optimal set of used registers, which is
      only known after register allocation is finished and spill slots
      have been allocated.

R=danno@chromium.org, titzer@chromium.org, jyan@ca.ibm.com, dstence@us.ibm.com, joransiu@ca.ibm.com
BUG=

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

Cr-Commit-Position: refs/heads/master@{#30396}
parent 1fe4c1e7
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "src/compiler/code-generator-impl.h" #include "src/compiler/code-generator-impl.h"
#include "src/compiler/gap-resolver.h" #include "src/compiler/gap-resolver.h"
#include "src/compiler/node-matchers.h" #include "src/compiler/node-matchers.h"
#include "src/compiler/osr.h"
#include "src/ppc/macro-assembler-ppc.h" #include "src/ppc/macro-assembler-ppc.h"
#include "src/scopes.h" #include "src/scopes.h"
...@@ -1304,50 +1305,28 @@ void CodeGenerator::AssembleDeoptimizerCall( ...@@ -1304,50 +1305,28 @@ void CodeGenerator::AssembleDeoptimizerCall(
void CodeGenerator::AssemblePrologue() { void CodeGenerator::AssemblePrologue() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
int stack_slots = frame()->GetSpillSlotCount();
if (descriptor->kind() == CallDescriptor::kCallAddress) { if (descriptor->kind() == CallDescriptor::kCallAddress) {
__ function_descriptor(); __ function_descriptor();
RegList frame_saves = 0;
__ mflr(r0); __ mflr(r0);
if (FLAG_enable_embedded_constant_pool) { if (FLAG_enable_embedded_constant_pool) {
__ Push(r0, fp, kConstantPoolRegister); __ Push(r0, fp, kConstantPoolRegister);
// Adjust FP to point to saved FP. // Adjust FP to point to saved FP.
__ subi(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset)); __ subi(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset));
frame_saves |= kConstantPoolRegister.bit();
} else { } else {
__ Push(r0, fp); __ Push(r0, fp);
__ mr(fp, sp); __ mr(fp, sp);
} }
// Save callee-saved registers.
const RegList saves = descriptor->CalleeSavedRegisters() & ~frame_saves;
__ MultiPush(saves);
// register save area does not include the fp.
DCHECK(kNumCalleeSaved - 1 ==
base::bits::CountPopulation32(saves | frame_saves));
int register_save_area_size = (kNumCalleeSaved - 1) * kPointerSize;
// Save callee-saved Double registers.
const RegList double_saves = descriptor->CalleeSavedFPRegisters();
__ MultiPushDoubles(double_saves);
DCHECK(kNumCalleeSavedDoubles ==
base::bits::CountPopulation32(double_saves));
register_save_area_size += kNumCalleeSavedDoubles * kDoubleSize;
frame()->SetRegisterSaveAreaSize(register_save_area_size);
} else if (descriptor->IsJSFunctionCall()) { } else if (descriptor->IsJSFunctionCall()) {
CompilationInfo* info = this->info(); CompilationInfo* info = this->info();
__ Prologue(info->IsCodePreAgingActive()); __ Prologue(info->IsCodePreAgingActive());
frame()->SetRegisterSaveAreaSize(
StandardFrameConstants::kFixedFrameSizeFromFp);
} else if (needs_frame_) { } else if (needs_frame_) {
__ StubPrologue(); __ StubPrologue();
frame()->SetRegisterSaveAreaSize(
StandardFrameConstants::kFixedFrameSizeFromFp);
} else { } else {
frame()->SetPCOnStack(false); frame()->SetElidedFrameSizeInSlots(0);
} }
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.
__ Abort(kShouldNotDirectlyEnterOsrFunction); __ Abort(kShouldNotDirectlyEnterOsrFunction);
...@@ -1360,38 +1339,62 @@ void CodeGenerator::AssemblePrologue() { ...@@ -1360,38 +1339,62 @@ void CodeGenerator::AssemblePrologue() {
osr_pc_offset_ = __ pc_offset(); osr_pc_offset_ = __ pc_offset();
// TODO(titzer): cannot address target function == local #-1 // TODO(titzer): cannot address target function == local #-1
__ LoadP(r4, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); __ LoadP(r4, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
DCHECK(stack_slots >= frame()->GetOsrStackSlotCount()); stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
stack_slots -= frame()->GetOsrStackSlotCount();
} }
if (stack_slots > 0) { const RegList double_saves = descriptor->CalleeSavedFPRegisters();
__ Add(sp, sp, -stack_slots * kPointerSize, r0); if (double_saves != 0) {
stack_shrink_slots += frame()->AlignSavedCalleeRegisterSlots();
}
if (stack_shrink_slots > 0) {
__ Add(sp, sp, -stack_shrink_slots * kPointerSize, r0);
}
// Save callee-saved Double registers.
if (double_saves != 0) {
__ MultiPushDoubles(double_saves);
DCHECK(kNumCalleeSavedDoubles ==
base::bits::CountPopulation32(double_saves));
frame()->AllocateSavedCalleeRegisterSlots(kNumCalleeSavedDoubles *
(kDoubleSize / kPointerSize));
}
// Save callee-saved registers.
const RegList saves =
FLAG_enable_embedded_constant_pool
? descriptor->CalleeSavedRegisters() & ~kConstantPoolRegister.bit()
: descriptor->CalleeSavedRegisters();
if (saves != 0) {
__ MultiPush(saves);
// register save area does not include the fp or constant pool pointer.
const int num_saves =
kNumCalleeSaved - 1 - (FLAG_enable_embedded_constant_pool ? 1 : 0);
DCHECK(num_saves == base::bits::CountPopulation32(saves));
frame()->AllocateSavedCalleeRegisterSlots(num_saves);
} }
} }
void CodeGenerator::AssembleReturn() { void CodeGenerator::AssembleReturn() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
int stack_slots = frame()->GetSpillSlotCount();
int pop_count = static_cast<int>(descriptor->StackParameterCount()); int pop_count = static_cast<int>(descriptor->StackParameterCount());
// Restore registers.
const RegList saves =
FLAG_enable_embedded_constant_pool
? descriptor->CalleeSavedRegisters() & ~kConstantPoolRegister.bit()
: descriptor->CalleeSavedRegisters();
if (saves != 0) {
__ MultiPop(saves);
}
// Restore double registers.
const RegList double_saves = descriptor->CalleeSavedFPRegisters();
if (double_saves != 0) {
__ MultiPopDoubles(double_saves);
}
if (descriptor->kind() == CallDescriptor::kCallAddress) { if (descriptor->kind() == CallDescriptor::kCallAddress) {
if (frame()->GetRegisterSaveAreaSize() > 0) {
// Remove this frame's spill slots first.
if (stack_slots > 0) {
__ Add(sp, sp, stack_slots * kPointerSize, r0);
}
// Restore double registers.
const RegList double_saves = descriptor->CalleeSavedFPRegisters();
__ MultiPopDoubles(double_saves);
// Restore registers.
RegList frame_saves = 0;
if (FLAG_enable_embedded_constant_pool) {
frame_saves |= kConstantPoolRegister.bit();
}
const RegList saves = descriptor->CalleeSavedRegisters() & ~frame_saves;
__ MultiPop(saves);
}
__ LeaveFrame(StackFrame::MANUAL, pop_count * kPointerSize); __ LeaveFrame(StackFrame::MANUAL, pop_count * kPointerSize);
} else if (descriptor->IsJSFunctionCall() || needs_frame_) { } else if (descriptor->IsJSFunctionCall() || needs_frame_) {
// Canonicalize JSFunction return sites for now. // Canonicalize JSFunction return sites for now.
......
...@@ -612,15 +612,23 @@ void LCodeGen::AddToTranslation(LEnvironment* environment, ...@@ -612,15 +612,23 @@ void LCodeGen::AddToTranslation(LEnvironment* environment,
} }
if (op->IsStackSlot()) { if (op->IsStackSlot()) {
int index = op->index();
if (index >= 0) {
index += StandardFrameConstants::kFixedFrameSize / kPointerSize;
}
if (is_tagged) { if (is_tagged) {
translation->StoreStackSlot(op->index()); translation->StoreStackSlot(index);
} else if (is_uint32) { } else if (is_uint32) {
translation->StoreUint32StackSlot(op->index()); translation->StoreUint32StackSlot(index);
} else { } else {
translation->StoreInt32StackSlot(op->index()); translation->StoreInt32StackSlot(index);
} }
} else if (op->IsDoubleStackSlot()) { } else if (op->IsDoubleStackSlot()) {
translation->StoreDoubleStackSlot(op->index()); int index = op->index();
if (index >= 0) {
index += StandardFrameConstants::kFixedFrameSize / kPointerSize;
}
translation->StoreDoubleStackSlot(index);
} else if (op->IsRegister()) { } else if (op->IsRegister()) {
Register reg = ToRegister(op); Register reg = ToRegister(op);
if (is_tagged) { if (is_tagged) {
......
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