[turbofan] Unify referencing of stack slots

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.

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

Cr-Commit-Position: refs/heads/master@{#30224}
This commit is contained in:
danno 2015-08-18 07:47:56 -07:00 committed by Commit bot
parent 54f18db864
commit cbbaf9ea6a
26 changed files with 550 additions and 422 deletions

View File

@ -687,6 +687,7 @@ source_set("v8_base") {
"src/compiler/dead-code-elimination.cc",
"src/compiler/dead-code-elimination.h",
"src/compiler/diamond.h",
"src/compiler/frame.cc",
"src/compiler/frame.h",
"src/compiler/frame-elider.cc",
"src/compiler/frame-elider.h",

View File

@ -647,15 +647,23 @@ void LCodeGen::AddToTranslation(LEnvironment* environment,
}
if (op->IsStackSlot()) {
int index = op->index();
if (index >= 0) {
index += StandardFrameConstants::kFixedFrameSize / kPointerSize;
}
if (is_tagged) {
translation->StoreStackSlot(op->index());
translation->StoreStackSlot(index);
} else if (is_uint32) {
translation->StoreUint32StackSlot(op->index());
translation->StoreUint32StackSlot(index);
} else {
translation->StoreInt32StackSlot(op->index());
translation->StoreInt32StackSlot(index);
}
} 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()) {
Register reg = ToRegister(op);
if (is_tagged) {

View File

@ -275,15 +275,23 @@ void LCodeGen::AddToTranslation(LEnvironment* environment,
}
if (op->IsStackSlot()) {
int index = op->index();
if (index >= 0) {
index += StandardFrameConstants::kFixedFrameSize / kPointerSize;
}
if (is_tagged) {
translation->StoreStackSlot(op->index());
translation->StoreStackSlot(index);
} else if (is_uint32) {
translation->StoreUint32StackSlot(op->index());
translation->StoreUint32StackSlot(index);
} else {
translation->StoreInt32StackSlot(op->index());
translation->StoreInt32StackSlot(index);
}
} 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()) {
Register reg = ToRegister(op);
if (is_tagged) {

View File

@ -8,6 +8,7 @@
#include "src/compiler/code-generator-impl.h"
#include "src/compiler/gap-resolver.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/osr.h"
#include "src/scopes.h"
namespace v8 {
@ -949,55 +950,25 @@ void CodeGenerator::AssembleDeoptimizerCall(
void CodeGenerator::AssemblePrologue() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
int stack_slots = frame()->GetSpillSlotCount();
if (descriptor->kind() == CallDescriptor::kCallAddress) {
bool saved_pp;
if (FLAG_enable_embedded_constant_pool) {
__ Push(lr, fp, pp);
// Adjust FP to point to saved FP.
__ sub(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset));
saved_pp = true;
} else {
__ Push(lr, fp);
__ mov(fp, sp);
saved_pp = false;
}
int register_save_area_size = saved_pp ? kPointerSize : 0;
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0 || saved_pp) {
// Save callee-saved registers.
__ stm(db_w, sp, saves);
register_save_area_size +=
kPointerSize * base::bits::CountPopulation32(saves);
}
const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
if (saves_fp != 0) {
// Save callee-saved FP registers.
STATIC_ASSERT(DwVfpRegister::kMaxNumRegisters == 32);
uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1;
uint32_t first = base::bits::CountTrailingZeros32(saves_fp);
DCHECK_EQ((last - first + 1), base::bits::CountPopulation32(saves_fp));
__ vstm(db_w, sp, DwVfpRegister::from_code(first),
DwVfpRegister::from_code(last));
register_save_area_size += 2 * kPointerSize * (last - first + 1);
}
if (register_save_area_size > 0) {
frame()->SetRegisterSaveAreaSize(register_save_area_size);
}
} else if (descriptor->IsJSFunctionCall()) {
CompilationInfo* info = this->info();
__ Prologue(info->IsCodePreAgingActive());
frame()->SetRegisterSaveAreaSize(
StandardFrameConstants::kFixedFrameSizeFromFp);
} else if (needs_frame_) {
__ StubPrologue();
frame()->SetRegisterSaveAreaSize(
StandardFrameConstants::kFixedFrameSizeFromFp);
} else {
frame()->SetPCOnStack(false);
frame()->SetElidedFrameSizeInSlots(0);
}
int stack_shrink_slots = frame()->GetSpillSlotCount();
if (info()->is_osr()) {
// TurboFan OSR-compiled functions cannot be entered directly.
__ Abort(kShouldNotDirectlyEnterOsrFunction);
@ -1010,41 +981,63 @@ void CodeGenerator::AssemblePrologue() {
osr_pc_offset_ = __ pc_offset();
// TODO(titzer): cannot address target function == local #-1
__ ldr(r1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
DCHECK(stack_slots >= frame()->GetOsrStackSlotCount());
stack_slots -= frame()->GetOsrStackSlotCount();
stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
}
if (stack_slots > 0) {
__ sub(sp, sp, Operand(stack_slots * kPointerSize));
const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
if (saves_fp != 0) {
stack_shrink_slots += frame()->AlignSavedCalleeRegisterSlots();
}
if (stack_shrink_slots > 0) {
__ sub(sp, sp, Operand(stack_shrink_slots * kPointerSize));
}
if (saves_fp != 0) {
// Save callee-saved FP registers.
STATIC_ASSERT(DwVfpRegister::kMaxNumRegisters == 32);
uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1;
uint32_t first = base::bits::CountTrailingZeros32(saves_fp);
DCHECK_EQ((last - first + 1), base::bits::CountPopulation32(saves_fp));
__ vstm(db_w, sp, DwVfpRegister::from_code(first),
DwVfpRegister::from_code(last));
frame()->AllocateSavedCalleeRegisterSlots((last - first + 1) *
(kDoubleSize / kPointerSize));
}
const RegList saves = FLAG_enable_embedded_constant_pool
? (descriptor->CalleeSavedRegisters() & ~pp.bit())
: descriptor->CalleeSavedRegisters();
if (saves != 0) {
// Save callee-saved registers.
__ stm(db_w, sp, saves);
frame()->AllocateSavedCalleeRegisterSlots(
base::bits::CountPopulation32(saves));
}
}
void CodeGenerator::AssembleReturn() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
int stack_slots = frame()->GetSpillSlotCount();
int pop_count = static_cast<int>(descriptor->StackParameterCount());
// Restore registers.
const RegList saves = FLAG_enable_embedded_constant_pool
? (descriptor->CalleeSavedRegisters() & ~pp.bit())
: descriptor->CalleeSavedRegisters();
if (saves != 0) {
__ ldm(ia_w, sp, saves);
}
// Restore FP registers.
const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
if (saves_fp != 0) {
STATIC_ASSERT(DwVfpRegister::kMaxNumRegisters == 32);
uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1;
uint32_t first = base::bits::CountTrailingZeros32(saves_fp);
__ vldm(ia_w, sp, DwVfpRegister::from_code(first),
DwVfpRegister::from_code(last));
}
if (descriptor->kind() == CallDescriptor::kCallAddress) {
if (frame()->GetRegisterSaveAreaSize() > 0) {
// Remove this frame's spill slots first.
if (stack_slots > 0) {
__ add(sp, sp, Operand(stack_slots * kPointerSize));
}
// Restore FP registers.
const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
if (saves_fp != 0) {
STATIC_ASSERT(DwVfpRegister::kMaxNumRegisters == 32);
uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1;
uint32_t first = base::bits::CountTrailingZeros32(saves_fp);
__ vldm(ia_w, sp, DwVfpRegister::from_code(first),
DwVfpRegister::from_code(last));
}
// Restore registers.
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0) {
__ ldm(ia_w, sp, saves);
}
}
__ LeaveFrame(StackFrame::MANUAL);
} else if (descriptor->IsJSFunctionCall() || needs_frame_) {
// Canonicalize JSFunction return sites for now.

View File

@ -9,6 +9,7 @@
#include "src/compiler/code-generator-impl.h"
#include "src/compiler/gap-resolver.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/osr.h"
#include "src/scopes.h"
namespace v8 {
@ -1083,43 +1084,22 @@ static int AlignedStackSlots(int stack_slots) {
void CodeGenerator::AssemblePrologue() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
int stack_slots = frame()->GetSpillSlotCount();
if (descriptor->kind() == CallDescriptor::kCallAddress) {
__ SetStackPointer(csp);
__ Push(lr, fp);
__ Mov(fp, csp);
// Save FP registers.
CPURegList saves_fp = CPURegList(CPURegister::kFPRegister, kDRegSizeInBits,
descriptor->CalleeSavedFPRegisters());
DCHECK(saves_fp.list() == CPURegList::GetCalleeSavedFP().list());
int saved_count = saves_fp.Count();
__ PushCPURegList(saves_fp);
// Save registers.
CPURegList saves = CPURegList(CPURegister::kRegister, kXRegSizeInBits,
descriptor->CalleeSavedRegisters());
// TODO(palfia): TF save list is not in sync with
// CPURegList::GetCalleeSaved(): x30 is missing.
// DCHECK(saves.list() == CPURegList::GetCalleeSaved().list());
saved_count += saves.Count();
__ PushCPURegList(saves);
frame()->SetRegisterSaveAreaSize(saved_count * kPointerSize);
} else if (descriptor->IsJSFunctionCall()) {
CompilationInfo* info = this->info();
__ SetStackPointer(jssp);
__ Prologue(info->IsCodePreAgingActive());
frame()->SetRegisterSaveAreaSize(
StandardFrameConstants::kFixedFrameSizeFromFp);
} else if (needs_frame_) {
__ SetStackPointer(jssp);
__ StubPrologue();
frame()->SetRegisterSaveAreaSize(
StandardFrameConstants::kFixedFrameSizeFromFp);
} else {
frame()->SetPCOnStack(false);
frame()->SetElidedFrameSizeInSlots(0);
}
int stack_shrink_slots = frame()->GetSpillSlotCount();
if (info()->is_osr()) {
// TurboFan OSR-compiled functions cannot be entered directly.
__ Abort(kShouldNotDirectlyEnterOsrFunction);
@ -1132,42 +1112,60 @@ void CodeGenerator::AssemblePrologue() {
osr_pc_offset_ = __ pc_offset();
// TODO(titzer): cannot address target function == local #-1
__ ldr(x1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
DCHECK(stack_slots >= frame()->GetOsrStackSlotCount());
stack_slots -= frame()->GetOsrStackSlotCount();
stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
}
if (stack_slots > 0) {
if (stack_shrink_slots > 0) {
Register sp = __ StackPointer();
if (!sp.Is(csp)) {
__ Sub(sp, sp, stack_slots * kPointerSize);
__ Sub(sp, sp, stack_shrink_slots * kPointerSize);
}
__ Sub(csp, csp, AlignedStackSlots(stack_slots) * kPointerSize);
__ Sub(csp, csp, AlignedStackSlots(stack_shrink_slots) * kPointerSize);
}
// Save FP registers.
CPURegList saves_fp = CPURegList(CPURegister::kFPRegister, kDRegSizeInBits,
descriptor->CalleeSavedFPRegisters());
int saved_count = saves_fp.Count();
if (saved_count != 0) {
DCHECK(saves_fp.list() == CPURegList::GetCalleeSavedFP().list());
__ PushCPURegList(saves_fp);
frame()->AllocateSavedCalleeRegisterSlots(saved_count *
(kDoubleSize / kPointerSize));
}
// Save registers.
// TODO(palfia): TF save list is not in sync with
// CPURegList::GetCalleeSaved(): x30 is missing.
// DCHECK(saves.list() == CPURegList::GetCalleeSaved().list());
CPURegList saves = CPURegList(CPURegister::kRegister, kXRegSizeInBits,
descriptor->CalleeSavedRegisters());
saved_count = saves.Count();
if (saved_count != 0) {
__ PushCPURegList(saves);
frame()->AllocateSavedCalleeRegisterSlots(saved_count);
}
}
void CodeGenerator::AssembleReturn() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
int stack_slots = frame()->GetSpillSlotCount();
// Restore registers.
CPURegList saves = CPURegList(CPURegister::kRegister, kXRegSizeInBits,
descriptor->CalleeSavedRegisters());
if (saves.Count() != 0) {
__ PopCPURegList(saves);
}
// Restore fp registers.
CPURegList saves_fp = CPURegList(CPURegister::kFPRegister, kDRegSizeInBits,
descriptor->CalleeSavedFPRegisters());
if (saves_fp.Count() != 0) {
__ PopCPURegList(saves_fp);
}
int pop_count = static_cast<int>(descriptor->StackParameterCount());
if (descriptor->kind() == CallDescriptor::kCallAddress) {
if (frame()->GetRegisterSaveAreaSize() > 0) {
// Remove this frame's spill slots first.
if (stack_slots > 0) {
__ Add(csp, csp, AlignedStackSlots(stack_slots) * kPointerSize);
}
// Restore registers.
CPURegList saves = CPURegList(CPURegister::kRegister, kXRegSizeInBits,
descriptor->CalleeSavedRegisters());
__ PopCPURegList(saves);
CPURegList saves_fp =
CPURegList(CPURegister::kFPRegister, kDRegSizeInBits,
descriptor->CalleeSavedFPRegisters());
__ PopCPURegList(saves_fp);
}
__ Mov(csp, fp);
__ Pop(fp, lr);
} else if (descriptor->IsJSFunctionCall() || needs_frame_) {

View File

@ -216,10 +216,16 @@ void CodeGenerator::RecordSafepoint(ReferenceMap* references,
Safepoint::DeoptMode deopt_mode) {
Safepoint safepoint =
safepoints()->DefineSafepoint(masm(), kind, arguments, deopt_mode);
int stackSlotToSpillSlotDelta =
frame()->GetTotalFrameSlotCount() - frame()->GetSpillSlotCount();
for (auto& operand : references->reference_operands()) {
if (operand.IsStackSlot()) {
safepoint.DefinePointerSlot(StackSlotOperand::cast(operand).index(),
zone());
int index = StackSlotOperand::cast(operand).index();
DCHECK(index >= 0);
// Safepoint table indices are 0-based from the beginning of the spill
// slot area, adjust appropriately.
index -= stackSlotToSpillSlotDelta;
safepoint.DefinePointerSlot(index, zone());
} else if (operand.IsRegister() && (kind & Safepoint::kWithRegisters)) {
Register reg =
Register::FromAllocationIndex(RegisterOperand::cast(operand).index());

24
src/compiler/frame.cc Normal file
View File

@ -0,0 +1,24 @@
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/compiler/frame.h"
#include "src/compiler/linkage.h"
#include "src/compiler/register-allocator.h"
#include "src/macro-assembler.h"
namespace v8 {
namespace internal {
namespace compiler {
Frame::Frame(int fixed_frame_size_in_slots)
: frame_slot_count_(fixed_frame_size_in_slots),
spilled_callee_register_slot_count_(0),
stack_slot_count_(0),
allocated_registers_(NULL),
allocated_double_registers_(NULL) {}
} // namespace compiler
} // namespace internal
} // namespace v8

View File

@ -6,26 +6,93 @@
#define V8_COMPILER_FRAME_H_
#include "src/bit-vector.h"
#include "src/frames.h"
namespace v8 {
namespace internal {
namespace compiler {
// Collects the spill slot requirements and the allocated general and double
// registers for a compiled function. Frames are usually populated by the
// register allocator and are used by Linkage to generate code for the prologue
// and epilogue to compiled code.
// Collects the spill slot and other frame slot requirements for a compiled
// function. Frames are usually populated by the register allocator and are used
// by Linkage to generate code for the prologue and epilogue to compiled code.
//
// Frames are divided up into three regions. The first is the fixed header,
// which always has a constant size and can be predicted before code generation
// begins depending on the type of code being generated. The second is the
// region for spill slots, which is immediately below the fixed header and grows
// as the register allocator needs to spill to the stack and asks the frame for
// more space. The third region, which contains the callee-saved registers must
// be reserved after register allocation, since its size can only be precisely
// determined after register allocation once the number of used callee-saved
// register is certain.
//
// Every pointer in a frame has a slot id. On 32-bit platforms, doubles consume
// two slots.
//
// Stack slot indices >= 0 access the callee stack with slot 0 corresponding to
// the callee's saved return address and 1 corresponding to the saved frame
// pointer. Some frames have additional information stored in the fixed header,
// for example JSFunctions store the function context and marker in the fixed
// header, with slot index 2 corresponding to the current function context and 3
// corresponding to the frame marker/JSFunction. The frame region immediately
// below the fixed header contains spill slots starting a 4 for JsFunctions. The
// callee-saved frame region below that starts at 4+spilled_slot_count. Callee
// stack slots corresponding to parameters are accessible through negative slot
// ids.
//
// Every slot of a caller or callee frame is accessible by the register
// allocator and gap resolver with a SpillSlotOperand containing its
// corresponding slot id.
//
// Below an example JSFunction Frame with slot ids, frame regions and contents:
//
// slot JS frame
// +-----------------+----------------------------
// -n-1 | parameter 0 | ^
// |- - - - - - - - -| |
// -n | | Caller
// ... | ... | frame slots
// -2 | parameter n-1 | (slot < 0)
// |- - - - - - - - -| |
// -1 | parameter n | v
// -----+-----------------+----------------------------
// 0 | return addr | ^ ^
// |- - - - - - - - -| | |
// 1 | saved frame ptr | Fixed |
// |- - - - - - - - -| Header <-- frame ptr |
// 2 | Context | | |
// |- - - - - - - - -| | |
// 3 |JSFunction/Marker| v |
// +-----------------+---- |
// 4 | spill 1 | ^ Callee
// |- - - - - - - - -| | frame slots
// ... | ... | Spill slots (slot >= 0)
// |- - - - - - - - -| | |
// m+4 | spill m | v |
// +-----------------+---- |
// m+5 | callee-saved 1 | ^ |
// |- - - - - - - - -| | |
// | ... | Callee-saved |
// |- - - - - - - - -| | |
// m+r+4 | callee-saved r | v v
// -----+-----------------+----- <-- stack ptr ---------
//
class Frame : public ZoneObject {
public:
Frame()
: register_save_area_size_(0),
spill_slot_count_(0),
osr_stack_slot_count_(0),
allocated_registers_(NULL),
allocated_double_registers_(NULL),
pc_on_stack_(true) {}
explicit Frame(int fixed_frame_size_in_slots);
inline int GetSpillSlotCount() { return spill_slot_count_; }
inline int GetTotalFrameSlotCount() { return frame_slot_count_; }
inline int GetSavedCalleeRegisterSlotCount() {
return spilled_callee_register_slot_count_;
}
inline int GetSpillSlotCount() { return stack_slot_count_; }
inline void SetElidedFrameSizeInSlots(int slots) {
DCHECK_EQ(0, spilled_callee_register_slot_count_);
DCHECK_EQ(0, stack_slot_count_);
frame_slot_count_ = slots;
}
void SetAllocatedRegisters(BitVector* regs) {
DCHECK(allocated_registers_ == NULL);
@ -41,48 +108,52 @@ class Frame : public ZoneObject {
return !allocated_double_registers_->IsEmpty();
}
void SetRegisterSaveAreaSize(int size) {
DCHECK(IsAligned(size, kPointerSize));
register_save_area_size_ = size;
int AlignSavedCalleeRegisterSlots() {
DCHECK_EQ(0, spilled_callee_register_slot_count_);
int frame_slot_count_before = frame_slot_count_;
frame_slot_count_ = RoundUp(frame_slot_count_, 2);
return frame_slot_count_before - frame_slot_count_;
}
int GetRegisterSaveAreaSize() { return register_save_area_size_; }
// OSR stack slots, including locals and expression stack slots.
void SetOsrStackSlotCount(int slots) {
DCHECK(slots >= 0);
osr_stack_slot_count_ = slots;
void AllocateSavedCalleeRegisterSlots(int count) {
frame_slot_count_ += count;
spilled_callee_register_slot_count_ += count;
}
int GetOsrStackSlotCount() { return osr_stack_slot_count_; }
int AllocateSpillSlot(int width) {
DCHECK_EQ(0, spilled_callee_register_slot_count_);
int frame_slot_count_before = frame_slot_count_;
int slot = AllocateAlignedFrameSlot(width);
stack_slot_count_ += (frame_slot_count_ - frame_slot_count_before);
return slot;
}
int ReserveSpillSlots(size_t slot_count) {
DCHECK_EQ(0, spilled_callee_register_slot_count_);
DCHECK_EQ(0, stack_slot_count_);
stack_slot_count_ += static_cast<int>(slot_count);
frame_slot_count_ += static_cast<int>(slot_count);
return frame_slot_count_ - 1;
}
private:
int AllocateAlignedFrameSlot(int width) {
DCHECK(width == 4 || width == 8);
// Skip one slot if necessary.
if (width > kPointerSize) {
DCHECK(width == kPointerSize * 2);
spill_slot_count_++;
spill_slot_count_ |= 1;
frame_slot_count_++;
frame_slot_count_ |= 1;
}
return spill_slot_count_++;
return frame_slot_count_++;
}
void ReserveSpillSlots(size_t slot_count) {
DCHECK_EQ(0, spill_slot_count_); // can only reserve before allocation.
spill_slot_count_ = static_cast<int>(slot_count);
}
void SetPCOnStack(bool val) { pc_on_stack_ = val; }
int PCOnStackSize() { return pc_on_stack_ ? kRegisterSize : 0; }
private:
int register_save_area_size_;
int spill_slot_count_;
int osr_stack_slot_count_;
int frame_slot_count_;
int spilled_callee_register_slot_count_;
int stack_slot_count_;
BitVector* allocated_registers_;
BitVector* allocated_double_registers_;
bool pc_on_stack_;
DISALLOW_COPY_AND_ASSIGN(Frame);
};

View File

@ -7,6 +7,7 @@
#include "src/compiler/code-generator-impl.h"
#include "src/compiler/gap-resolver.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/osr.h"
#include "src/ia32/assembler-ia32.h"
#include "src/ia32/frames-ia32.h"
#include "src/ia32/macro-assembler-ia32.h"
@ -1260,34 +1261,22 @@ void CodeGenerator::AssembleDeoptimizerCall(
void CodeGenerator::AssemblePrologue() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
int stack_slots = frame()->GetSpillSlotCount();
if (descriptor->kind() == CallDescriptor::kCallAddress) {
// Assemble a prologue similar the to cdecl calling convention.
__ push(ebp);
__ mov(ebp, esp);
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0) { // Save callee-saved registers.
int register_save_area_size = 0;
for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
if (!((1 << i) & saves)) continue;
__ push(Register::from_code(i));
register_save_area_size += kPointerSize;
}
frame()->SetRegisterSaveAreaSize(register_save_area_size);
}
} else if (descriptor->IsJSFunctionCall()) {
// TODO(turbofan): this prologue is redundant with OSR, but needed for
// code aging.
CompilationInfo* info = this->info();
__ Prologue(info->IsCodePreAgingActive());
frame()->SetRegisterSaveAreaSize(
StandardFrameConstants::kFixedFrameSizeFromFp);
} else if (needs_frame_) {
__ StubPrologue();
frame()->SetRegisterSaveAreaSize(
StandardFrameConstants::kFixedFrameSizeFromFp);
} else {
frame()->SetElidedFrameSizeInSlots(kPCOnStackSize / kPointerSize);
}
int stack_shrink_slots = frame()->GetSpillSlotCount();
if (info()->is_osr()) {
// TurboFan OSR-compiled functions cannot be entered directly.
__ Abort(kShouldNotDirectlyEnterOsrFunction);
@ -1300,40 +1289,42 @@ void CodeGenerator::AssemblePrologue() {
osr_pc_offset_ = __ pc_offset();
// TODO(titzer): cannot address target function == local #-1
__ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
DCHECK(stack_slots >= frame()->GetOsrStackSlotCount());
stack_slots -= frame()->GetOsrStackSlotCount();
stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
}
if (stack_slots > 0) {
// Allocate the stack slots used by this frame.
__ sub(esp, Immediate(stack_slots * kPointerSize));
const RegList saves = descriptor->CalleeSavedRegisters();
if (stack_shrink_slots > 0) {
__ sub(esp, Immediate(stack_shrink_slots * kPointerSize));
}
if (saves != 0) { // Save callee-saved registers.
DCHECK(!info()->is_osr());
int pushed = 0;
for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
if (!((1 << i) & saves)) continue;
__ push(Register::from_code(i));
++pushed;
}
frame()->AllocateSavedCalleeRegisterSlots(pushed);
}
}
void CodeGenerator::AssembleReturn() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
int stack_slots = frame()->GetSpillSlotCount();
if (descriptor->kind() == CallDescriptor::kCallAddress) {
const RegList saves = descriptor->CalleeSavedRegisters();
if (frame()->GetRegisterSaveAreaSize() > 0) {
// Remove this frame's spill slots first.
if (stack_slots > 0) {
__ add(esp, Immediate(stack_slots * kPointerSize));
}
// Restore registers.
if (saves != 0) {
for (int i = 0; i < Register::kNumRegisters; i++) {
if (!((1 << i) & saves)) continue;
__ pop(Register::from_code(i));
}
}
__ pop(ebp); // Pop caller's frame pointer.
} else {
// No saved registers.
__ mov(esp, ebp); // Move stack pointer back to frame pointer.
__ pop(ebp); // Pop caller's frame pointer.
const RegList saves = descriptor->CalleeSavedRegisters();
// Restore registers.
if (saves != 0) {
for (int i = 0; i < Register::kNumRegisters; i++) {
if (!((1 << i) & saves)) continue;
__ pop(Register::from_code(i));
}
}
if (descriptor->kind() == CallDescriptor::kCallAddress) {
__ mov(esp, ebp); // Move stack pointer back to frame pointer.
__ pop(ebp); // Pop caller's frame pointer.
} else if (descriptor->IsJSFunctionCall() || needs_frame_) {
// Canonicalize JSFunction return sites for now.
if (return_label_.is_bound()) {

View File

@ -5,6 +5,7 @@
#include "src/code-stubs.h"
#include "src/compiler.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/frame.h"
#include "src/compiler/linkage.h"
#include "src/compiler/node.h"
#include "src/compiler/osr.h"
@ -190,27 +191,21 @@ CallDescriptor* Linkage::ComputeIncoming(Zone* zone, CompilationInfo* info) {
FrameOffset Linkage::GetFrameOffset(int spill_slot, Frame* frame) const {
if (frame->GetSpillSlotCount() > 0 || incoming_->IsJSFunctionCall() ||
incoming_->kind() == CallDescriptor::kCallAddress) {
int offset;
int register_save_area_size = frame->GetRegisterSaveAreaSize();
if (spill_slot >= 0) {
// Local or spill slot. Skip the frame pointer, function, and
// context in the fixed part of the frame.
offset = -(spill_slot + 1) * kPointerSize - register_save_area_size;
} else {
// Incoming parameter. Skip the return address.
offset = -(spill_slot + 1) * kPointerSize + kFPOnStackSize +
frame->PCOnStackSize();
}
bool has_frame = frame->GetSpillSlotCount() > 0 ||
incoming_->IsJSFunctionCall() ||
incoming_->kind() == CallDescriptor::kCallAddress;
const int offset =
(StandardFrameConstants::kFixedSlotCountAboveFp - spill_slot - 1) *
kPointerSize;
if (has_frame) {
return FrameOffset::FromFramePointer(offset);
} else {
// No frame. Retrieve all parameters relative to stack pointer.
DCHECK(spill_slot < 0); // Must be a parameter.
int register_save_area_size = frame->GetRegisterSaveAreaSize();
int offset = register_save_area_size - (spill_slot + 1) * kPointerSize +
frame->PCOnStackSize();
return FrameOffset::FromStackPointer(offset);
int offsetSpToFp =
kPointerSize * (StandardFrameConstants::kFixedSlotCountAboveFp -
frame->GetTotalFrameSlotCount());
return FrameOffset::FromStackPointer(offset - offsetSpToFp);
}
}
@ -505,7 +500,8 @@ LinkageLocation Linkage::GetOsrValueLocation(int index) const {
return incoming_->GetInputLocation(context_index);
} else if (index >= first_stack_slot) {
// Local variable stored in this (callee) stack.
int spill_index = index - first_stack_slot;
int spill_index =
index - first_stack_slot + StandardFrameConstants::kFixedSlotCount;
return LinkageLocation::ForCalleeFrameSlot(spill_index);
} else {
// Parameter. Use the assigned location from the incoming call descriptor.

View File

@ -6,6 +6,7 @@
#include "src/compiler/code-generator-impl.h"
#include "src/compiler/gap-resolver.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/osr.h"
#include "src/mips/macro-assembler-mips.h"
#include "src/scopes.h"
@ -1077,38 +1078,17 @@ void CodeGenerator::AssembleDeoptimizerCall(
void CodeGenerator::AssemblePrologue() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
int stack_slots = frame()->GetSpillSlotCount();
int stack_shrink_slots = frame()->GetSpillSlotCount();
if (descriptor->kind() == CallDescriptor::kCallAddress) {
__ Push(ra, fp);
__ mov(fp, sp);
const RegList saves = descriptor->CalleeSavedRegisters();
// Save callee-saved registers.
__ MultiPush(saves);
// kNumCalleeSaved includes the fp register, but the fp register
// is saved separately in TF.
DCHECK(kNumCalleeSaved == base::bits::CountPopulation32(saves) + 1);
int register_save_area_size =
base::bits::CountPopulation32(saves) * kPointerSize;
const RegList saves_fpu = descriptor->CalleeSavedFPRegisters();
// Save callee-saved FPU registers.
__ MultiPushFPU(saves_fpu);
DCHECK(kNumCalleeSavedFPU == base::bits::CountPopulation32(saves_fpu));
register_save_area_size += kNumCalleeSavedFPU * kDoubleSize;
frame()->SetRegisterSaveAreaSize(register_save_area_size);
} else if (descriptor->IsJSFunctionCall()) {
CompilationInfo* info = this->info();
__ Prologue(info->IsCodePreAgingActive());
frame()->SetRegisterSaveAreaSize(
StandardFrameConstants::kFixedFrameSizeFromFp);
} else if (needs_frame_) {
__ StubPrologue();
frame()->SetRegisterSaveAreaSize(
StandardFrameConstants::kFixedFrameSizeFromFp);
} else {
frame()->SetPCOnStack(false);
frame()->SetElidedFrameSizeInSlots(0);
}
if (info()->is_osr()) {
@ -1123,34 +1103,56 @@ void CodeGenerator::AssemblePrologue() {
osr_pc_offset_ = __ pc_offset();
// TODO(titzer): cannot address target function == local #-1
__ lw(a1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
DCHECK(stack_slots >= frame()->GetOsrStackSlotCount());
stack_slots -= frame()->GetOsrStackSlotCount();
stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
}
if (stack_slots > 0) {
__ Subu(sp, sp, Operand(stack_slots * kPointerSize));
const RegList saves_fpu = descriptor->CalleeSavedFPRegisters();
if (saves_fpu != 0) {
stack_shrink_slots += frame()->AlignSavedCalleeRegisterSlots();
}
if (stack_shrink_slots > 0) {
__ Subu(sp, sp, Operand(stack_shrink_slots * kPointerSize));
}
// Save callee-saved FPU registers.
if (saves_fpu != 0) {
__ MultiPushFPU(saves_fpu);
int count = base::bits::CountPopulation32(saves_fpu);
DCHECK(kNumCalleeSavedFPU == count);
frame()->AllocateSavedCalleeRegisterSlots(count *
(kDoubleSize / kPointerSize));
}
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0) {
// Save callee-saved registers.
__ MultiPush(saves);
// kNumCalleeSaved includes the fp register, but the fp register
// is saved separately in TF.
int count = base::bits::CountPopulation32(saves);
DCHECK(kNumCalleeSaved == count + 1);
frame()->AllocateSavedCalleeRegisterSlots(count);
}
}
void CodeGenerator::AssembleReturn() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
int stack_slots = frame()->GetSpillSlotCount();
int pop_count = static_cast<int>(descriptor->StackParameterCount());
if (descriptor->kind() == CallDescriptor::kCallAddress) {
if (frame()->GetRegisterSaveAreaSize() > 0) {
// Remove this frame's spill slots first.
if (stack_slots > 0) {
__ Addu(sp, sp, Operand(stack_slots * kPointerSize));
}
// Restore FPU registers.
const RegList saves_fpu = descriptor->CalleeSavedFPRegisters();
__ MultiPopFPU(saves_fpu);
// Restore GP registers.
const RegList saves = descriptor->CalleeSavedRegisters();
__ MultiPop(saves);
}
// Restore GP registers.
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0) {
__ MultiPop(saves);
}
// Restore FPU registers.
const RegList saves_fpu = descriptor->CalleeSavedFPRegisters();
if (saves_fpu != 0) {
__ MultiPopFPU(saves_fpu);
}
if (descriptor->kind() == CallDescriptor::kCallAddress) {
__ mov(sp, fp);
__ Pop(ra, fp);
} else if (descriptor->IsJSFunctionCall() || needs_frame_) {

View File

@ -6,6 +6,7 @@
#include "src/compiler/code-generator-impl.h"
#include "src/compiler/gap-resolver.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/osr.h"
#include "src/mips/macro-assembler-mips.h"
#include "src/scopes.h"
@ -1147,40 +1148,19 @@ void CodeGenerator::AssembleDeoptimizerCall(
void CodeGenerator::AssemblePrologue() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
int stack_slots = frame()->GetSpillSlotCount();
if (descriptor->kind() == CallDescriptor::kCallAddress) {
__ Push(ra, fp);
__ mov(fp, sp);
const RegList saves = descriptor->CalleeSavedRegisters();
// Save callee-saved registers.
__ MultiPush(saves);
// kNumCalleeSaved includes the fp register, but the fp register
// is saved separately in TF.
DCHECK(kNumCalleeSaved == base::bits::CountPopulation32(saves) + 1);
int register_save_area_size =
base::bits::CountPopulation32(saves) * kPointerSize;
const RegList saves_fpu = descriptor->CalleeSavedFPRegisters();
// Save callee-saved FPU registers.
__ MultiPushFPU(saves_fpu);
DCHECK(kNumCalleeSavedFPU == base::bits::CountPopulation32(saves_fpu));
register_save_area_size += kNumCalleeSavedFPU * kDoubleSize;
frame()->SetRegisterSaveAreaSize(register_save_area_size);
} else if (descriptor->IsJSFunctionCall()) {
CompilationInfo* info = this->info();
__ Prologue(info->IsCodePreAgingActive());
frame()->SetRegisterSaveAreaSize(
StandardFrameConstants::kFixedFrameSizeFromFp);
} else if (needs_frame_) {
__ StubPrologue();
frame()->SetRegisterSaveAreaSize(
StandardFrameConstants::kFixedFrameSizeFromFp);
} else {
frame()->SetPCOnStack(false);
frame()->SetElidedFrameSizeInSlots(0);
}
int stack_shrink_slots = frame()->GetSpillSlotCount();
if (info()->is_osr()) {
// TurboFan OSR-compiled functions cannot be entered directly.
__ Abort(kShouldNotDirectlyEnterOsrFunction);
@ -1193,34 +1173,52 @@ void CodeGenerator::AssemblePrologue() {
osr_pc_offset_ = __ pc_offset();
// TODO(titzer): cannot address target function == local #-1
__ ld(a1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
DCHECK(stack_slots >= frame()->GetOsrStackSlotCount());
stack_slots -= frame()->GetOsrStackSlotCount();
stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
}
if (stack_slots > 0) {
__ Dsubu(sp, sp, Operand(stack_slots * kPointerSize));
if (stack_shrink_slots > 0) {
__ Dsubu(sp, sp, Operand(stack_shrink_slots * kPointerSize));
}
const RegList saves_fpu = descriptor->CalleeSavedFPRegisters();
if (saves_fpu != 0) {
// Save callee-saved FPU registers.
__ MultiPushFPU(saves_fpu);
int count = base::bits::CountPopulation32(saves_fpu);
DCHECK(kNumCalleeSavedFPU == count);
frame()->AllocateSavedCalleeRegisterSlots(count *
(kDoubleSize / kPointerSize));
}
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0) {
// Save callee-saved registers.
__ MultiPush(saves);
// kNumCalleeSaved includes the fp register, but the fp register
// is saved separately in TF.
int count = base::bits::CountPopulation32(saves);
DCHECK(kNumCalleeSaved == count + 1);
frame()->AllocateSavedCalleeRegisterSlots(count);
}
}
void CodeGenerator::AssembleReturn() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
int stack_slots = frame()->GetSpillSlotCount();
int pop_count = static_cast<int>(descriptor->StackParameterCount());
if (descriptor->kind() == CallDescriptor::kCallAddress) {
if (frame()->GetRegisterSaveAreaSize() > 0) {
// Remove this frame's spill slots first.
if (stack_slots > 0) {
__ Daddu(sp, sp, Operand(stack_slots * kPointerSize));
}
// Restore FPU registers.
const RegList saves_fpu = descriptor->CalleeSavedFPRegisters();
__ MultiPopFPU(saves_fpu);
// Restore GP registers.
const RegList saves = descriptor->CalleeSavedRegisters();
__ MultiPop(saves);
}
// Restore GP registers.
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0) {
__ MultiPop(saves);
}
// Restore FPU registers.
const RegList saves_fpu = descriptor->CalleeSavedFPRegisters();
if (saves_fpu != 0) {
__ MultiPopFPU(saves_fpu);
}
if (descriptor->kind() == CallDescriptor::kCallAddress) {
__ mov(sp, fp);
__ Pop(ra, fp);
} else if (descriptor->IsJSFunctionCall() || needs_frame_) {
@ -1234,6 +1232,7 @@ void CodeGenerator::AssembleReturn() {
__ Pop(ra, fp);
}
}
int pop_count = static_cast<int>(descriptor->StackParameterCount());
if (pop_count != 0) {
__ DropAndRet(pop_count);
} else {

View File

@ -328,8 +328,6 @@ void OsrHelper::SetupFrame(Frame* frame) {
// The optimized frame will subsume the unoptimized frame. Do so by reserving
// the first spill slots.
frame->ReserveSpillSlots(UnoptimizedFrameSlots());
// The frame needs to be adjusted by the number of unoptimized frame slots.
frame->SetOsrStackSlotCount(static_cast<int>(UnoptimizedFrameSlots()));
}
} // namespace compiler

View File

@ -259,10 +259,17 @@ class PipelineData {
}
void InitializeRegisterAllocationData(const RegisterConfiguration* config,
CallDescriptor* descriptor,
const char* debug_name) {
DCHECK(frame_ == nullptr);
DCHECK(register_allocation_data_ == nullptr);
frame_ = new (instruction_zone()) Frame();
int fixed_frame_size = 0;
if (descriptor != nullptr) {
fixed_frame_size = (descriptor->kind() == CallDescriptor::kCallAddress)
? StandardFrameConstants::kFixedSlotCountAboveFp
: StandardFrameConstants::kFixedSlotCount;
}
frame_ = new (instruction_zone()) Frame(fixed_frame_size);
register_allocation_data_ = new (register_allocation_zone())
RegisterAllocationData(config, register_allocation_zone(), frame(),
sequence(), debug_name);
@ -1190,7 +1197,7 @@ bool Pipeline::AllocateRegistersForTesting(const RegisterConfiguration* config,
PipelineData data(&zone_pool, &info, sequence);
Pipeline pipeline(&info);
pipeline.data_ = &data;
pipeline.AllocateRegisters(config, run_verifier);
pipeline.AllocateRegisters(config, nullptr, run_verifier);
return !data.compilation_failed();
}
@ -1234,7 +1241,8 @@ Handle<Code> Pipeline::ScheduleAndGenerateCode(
bool run_verifier = FLAG_turbo_verify_allocation;
// Allocate registers.
AllocateRegisters(RegisterConfiguration::ArchDefault(), run_verifier);
AllocateRegisters(RegisterConfiguration::ArchDefault(), call_descriptor,
run_verifier);
if (data->compilation_failed()) {
info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc);
return Handle<Code>();
@ -1293,6 +1301,7 @@ Handle<Code> Pipeline::ScheduleAndGenerateCode(
void Pipeline::AllocateRegisters(const RegisterConfiguration* config,
CallDescriptor* descriptor,
bool run_verifier) {
PipelineData* data = this->data_;
@ -1310,7 +1319,7 @@ void Pipeline::AllocateRegisters(const RegisterConfiguration* config,
debug_name = GetDebugName(data->info());
#endif
data->InitializeRegisterAllocationData(config, debug_name.get());
data->InitializeRegisterAllocationData(config, descriptor, debug_name.get());
if (info()->is_osr()) {
OsrHelper osr_helper(info());
osr_helper.SetupFrame(data->frame());

View File

@ -67,7 +67,7 @@ class Pipeline {
void RunPrintAndVerify(const char* phase, bool untyped = false);
Handle<Code> ScheduleAndGenerateCode(CallDescriptor* call_descriptor);
void AllocateRegisters(const RegisterConfiguration* config,
bool run_verifier);
CallDescriptor* descriptor, bool run_verifier);
};
} // namespace compiler

View File

@ -1367,7 +1367,7 @@ void ConstraintBuilder::MeetConstraintsAfter(int instr_index) {
// This value is produced on the stack, we never need to spill it.
if (first_output->IsStackSlot()) {
DCHECK(StackSlotOperand::cast(first_output)->index() <
data()->frame()->GetSpillSlotCount());
data()->frame()->GetTotalFrameSlotCount());
range->SetSpillOperand(StackSlotOperand::cast(first_output));
range->SetSpillStartIndex(instr_index + 1);
assigned = true;

View File

@ -7,6 +7,7 @@
#include "src/compiler/code-generator-impl.h"
#include "src/compiler/gap-resolver.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/osr.h"
#include "src/scopes.h"
#include "src/x64/assembler-x64.h"
#include "src/x64/macro-assembler-x64.h"
@ -1460,50 +1461,28 @@ void CodeGenerator::AssembleDeoptimizerCall(
}
namespace {
static const int kQuadWordSize = 16;
} // namespace
void CodeGenerator::AssemblePrologue() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
int stack_slots = frame()->GetSpillSlotCount();
if (descriptor->kind() == CallDescriptor::kCallAddress) {
__ pushq(rbp);
__ movq(rbp, rsp);
int register_save_area_size = 0;
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0) { // Save callee-saved registers.
for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
if (!((1 << i) & saves)) continue;
__ pushq(Register::from_code(i));
register_save_area_size += kPointerSize;
}
}
const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
if (saves_fp != 0) { // Save callee-saved XMM registers.
const uint32_t saves_fp_count = base::bits::CountPopulation32(saves_fp);
const int stack_size = saves_fp_count * 16;
// Adjust the stack pointer.
__ subp(rsp, Immediate(stack_size));
// Store the registers on the stack.
int slot_idx = 0;
for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
if (!((1 << i) & saves_fp)) continue;
__ movdqu(Operand(rsp, 16 * slot_idx), XMMRegister::from_code(i));
slot_idx++;
}
register_save_area_size += stack_size;
}
if (register_save_area_size > 0) {
frame()->SetRegisterSaveAreaSize(register_save_area_size);
}
} else if (descriptor->IsJSFunctionCall()) {
CompilationInfo* info = this->info();
__ Prologue(info->IsCodePreAgingActive());
frame()->SetRegisterSaveAreaSize(
StandardFrameConstants::kFixedFrameSizeFromFp);
} else if (needs_frame_) {
__ StubPrologue();
frame()->SetRegisterSaveAreaSize(
StandardFrameConstants::kFixedFrameSizeFromFp);
} else {
frame()->SetElidedFrameSizeInSlots(kPCOnStackSize / kPointerSize);
}
int stack_shrink_slots = frame()->GetSpillSlotCount();
if (info()->is_osr()) {
// TurboFan OSR-compiled functions cannot be entered directly.
__ Abort(kShouldNotDirectlyEnterOsrFunction);
@ -1516,53 +1495,76 @@ void CodeGenerator::AssemblePrologue() {
osr_pc_offset_ = __ pc_offset();
// TODO(titzer): cannot address target function == local #-1
__ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
DCHECK(stack_slots >= frame()->GetOsrStackSlotCount());
stack_slots -= frame()->GetOsrStackSlotCount();
stack_shrink_slots -=
static_cast<int>(OsrHelper(info()).UnoptimizedFrameSlots());
}
if (stack_slots > 0) {
__ subq(rsp, Immediate(stack_slots * kPointerSize));
const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
if (saves_fp != 0) {
stack_shrink_slots += frame()->AlignSavedCalleeRegisterSlots();
}
if (stack_shrink_slots > 0) {
__ subq(rsp, Immediate(stack_shrink_slots * kPointerSize));
}
if (saves_fp != 0) { // Save callee-saved XMM registers.
const uint32_t saves_fp_count = base::bits::CountPopulation32(saves_fp);
const int stack_size = saves_fp_count * kQuadWordSize;
// Adjust the stack pointer.
__ subp(rsp, Immediate(stack_size));
// Store the registers on the stack.
int slot_idx = 0;
for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
if (!((1 << i) & saves_fp)) continue;
__ movdqu(Operand(rsp, kQuadWordSize * slot_idx),
XMMRegister::from_code(i));
slot_idx++;
}
frame()->AllocateSavedCalleeRegisterSlots(saves_fp_count *
(kQuadWordSize / kPointerSize));
}
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0) { // Save callee-saved registers.
for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
if (!((1 << i) & saves)) continue;
__ pushq(Register::from_code(i));
frame()->AllocateSavedCalleeRegisterSlots(1);
}
}
}
void CodeGenerator::AssembleReturn() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
int stack_slots = frame()->GetSpillSlotCount();
if (descriptor->kind() == CallDescriptor::kCallAddress) {
if (frame()->GetRegisterSaveAreaSize() > 0) {
// Remove this frame's spill slots first.
if (stack_slots > 0) {
__ addq(rsp, Immediate(stack_slots * kPointerSize));
}
// Restore registers.
const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
if (saves_fp != 0) {
const uint32_t saves_fp_count = base::bits::CountPopulation32(saves_fp);
const int stack_size = saves_fp_count * 16;
// Load the registers from the stack.
int slot_idx = 0;
for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
if (!((1 << i) & saves_fp)) continue;
__ movdqu(XMMRegister::from_code(i), Operand(rsp, 16 * slot_idx));
slot_idx++;
}
// Adjust the stack pointer.
__ addp(rsp, Immediate(stack_size));
}
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0) {
for (int i = 0; i < Register::kNumRegisters; i++) {
if (!((1 << i) & saves)) continue;
__ popq(Register::from_code(i));
}
}
__ popq(rbp); // Pop caller's frame pointer.
} else {
// No saved registers.
__ movq(rsp, rbp); // Move stack pointer back to frame pointer.
__ popq(rbp); // Pop caller's frame pointer.
// Restore registers.
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0) {
for (int i = 0; i < Register::kNumRegisters; i++) {
if (!((1 << i) & saves)) continue;
__ popq(Register::from_code(i));
}
}
const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
if (saves_fp != 0) {
const uint32_t saves_fp_count = base::bits::CountPopulation32(saves_fp);
const int stack_size = saves_fp_count * kQuadWordSize;
// Load the registers from the stack.
int slot_idx = 0;
for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
if (!((1 << i) & saves_fp)) continue;
__ movdqu(XMMRegister::from_code(i),
Operand(rsp, kQuadWordSize * slot_idx));
slot_idx++;
}
// Adjust the stack pointer.
__ addp(rsp, Immediate(stack_size));
}
if (descriptor->kind() == CallDescriptor::kCallAddress) {
__ movq(rsp, rbp); // Move stack pointer back to frame pointer.
__ popq(rbp); // Pop caller's frame pointer.
} else if (descriptor->IsJSFunctionCall() || needs_frame_) {
// Canonicalize JSFunction return sites for now.
if (return_label_.is_bound()) {

View File

@ -2609,22 +2609,6 @@ int TranslatedValue::GetChildrenCount() const {
}
int TranslatedState::SlotOffsetFp(int slot_index) {
if (slot_index >= 0) {
const int offset = StandardFrameConstants::kExpressionsOffset;
return offset - (slot_index * kPointerSize);
} else {
const int offset = StandardFrameConstants::kCallerSPOffset;
return offset - ((slot_index + 1) * kPointerSize);
}
}
Address TranslatedState::SlotAddress(Address fp, int slot_index) {
return fp + SlotOffsetFp(slot_index);
}
uint32_t TranslatedState::GetUInt32Slot(Address fp, int slot_offset) {
Address address = fp + slot_offset;
#if V8_TARGET_BIG_ENDIAN && V8_HOST_ARCH_64_BIT
@ -2947,7 +2931,8 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue(
}
case Translation::STACK_SLOT: {
int slot_offset = SlotOffsetFp(iterator->Next());
int slot_offset =
OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
intptr_t value = *(reinterpret_cast<intptr_t*>(fp + slot_offset));
if (trace_file != nullptr) {
PrintF(trace_file, "0x%08" V8PRIxPTR " ; [fp %c %d] ", value,
@ -2958,7 +2943,8 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue(
}
case Translation::INT32_STACK_SLOT: {
int slot_offset = SlotOffsetFp(iterator->Next());
int slot_offset =
OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
uint32_t value = GetUInt32Slot(fp, slot_offset);
if (trace_file != nullptr) {
PrintF(trace_file, "%d ; (int) [fp %c %d] ",
@ -2969,7 +2955,8 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue(
}
case Translation::UINT32_STACK_SLOT: {
int slot_offset = SlotOffsetFp(iterator->Next());
int slot_offset =
OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
uint32_t value = GetUInt32Slot(fp, slot_offset);
if (trace_file != nullptr) {
PrintF(trace_file, "%u ; (uint) [fp %c %d] ", value,
@ -2979,7 +2966,8 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue(
}
case Translation::BOOL_STACK_SLOT: {
int slot_offset = SlotOffsetFp(iterator->Next());
int slot_offset =
OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
uint32_t value = GetUInt32Slot(fp, slot_offset);
if (trace_file != nullptr) {
PrintF(trace_file, "%u ; (bool) [fp %c %d] ", value,
@ -2989,7 +2977,8 @@ TranslatedValue TranslatedState::CreateNextTranslatedValue(
}
case Translation::DOUBLE_STACK_SLOT: {
int slot_offset = SlotOffsetFp(iterator->Next());
int slot_offset =
OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
double value = ReadDoubleValue(fp + slot_offset);
if (trace_file != nullptr) {
PrintF(trace_file, "%e ; (double) [fp %c %d] ", value,

View File

@ -276,8 +276,6 @@ class TranslatedState {
Handle<Object> MaterializeObjectAt(int object_index);
bool GetAdaptedArguments(Handle<JSObject>* result, int frame_index);
static int SlotOffsetFp(int slot_index);
static Address SlotAddress(Address fp, int slot_index);
static uint32_t GetUInt32Slot(Address fp, int slot_index);
std::vector<TranslatedFrame> frames_;

View File

@ -1079,18 +1079,14 @@ void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) {
}
Object* OptimizedFrame::StackSlotAt(int index) const {
// Positive index means the value is spilled to the locals
// area. Negative means it is stored in the incoming parameter
// area.
if (index >= 0) return GetExpression(index);
int OptimizedFrame::StackSlotOffsetRelativeToFp(int slot_index) {
return StandardFrameConstants::kCallerSPOffset -
((slot_index + 1) * kPointerSize);
}
// Index -1 overlaps with last parameter, -n with the first parameter,
// (-n - 1) with the receiver with n being the number of parameters
// of the outermost, optimized frame.
int const parameter_count = ComputeParametersCount();
int const parameter_index = index + parameter_count;
return (parameter_index == -1) ? receiver() : GetParameter(parameter_index);
Object* OptimizedFrame::StackSlotAt(int index) const {
return Memory::Object_at(fp() + StackSlotOffsetRelativeToFp(index));
}

View File

@ -120,8 +120,12 @@ class StandardFrameConstants : public AllStatic {
static const int kCPSlotSize =
FLAG_enable_embedded_constant_pool ? kPointerSize : 0;
static const int kFixedFrameSizeFromFp = 2 * kPointerSize + kCPSlotSize;
static const int kFixedFrameSizeAboveFp = kPCOnStackSize + kFPOnStackSize;
static const int kFixedFrameSize =
kPCOnStackSize + kFPOnStackSize + kFixedFrameSizeFromFp;
kFixedFrameSizeAboveFp + kFixedFrameSizeFromFp;
static const int kFixedSlotCountAboveFp =
kFixedFrameSizeAboveFp / kPointerSize;
static const int kFixedSlotCount = kFixedFrameSize / kPointerSize;
static const int kExpressionsOffset = -3 * kPointerSize - kCPSlotSize;
static const int kMarkerOffset = -2 * kPointerSize - kCPSlotSize;
static const int kContextOffset = -1 * kPointerSize - kCPSlotSize;
@ -678,6 +682,8 @@ class OptimizedFrame : public JavaScriptFrame {
DeoptimizationInputData* GetDeoptimizationData(int* deopt_index);
static int StackSlotOffsetRelativeToFp(int slot_index);
protected:
inline explicit OptimizedFrame(StackFrameIteratorBase* iterator);

View File

@ -673,15 +673,23 @@ void LCodeGen::AddToTranslation(LEnvironment* environment,
}
if (op->IsStackSlot()) {
int index = op->index();
if (index >= 0) {
index += StandardFrameConstants::kFixedFrameSize / kPointerSize;
}
if (is_tagged) {
translation->StoreStackSlot(op->index());
translation->StoreStackSlot(index);
} else if (is_uint32) {
translation->StoreUint32StackSlot(op->index());
translation->StoreUint32StackSlot(index);
} else {
translation->StoreInt32StackSlot(op->index());
translation->StoreInt32StackSlot(index);
}
} 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()) {
Register reg = ToRegister(op);
if (is_tagged) {

View File

@ -645,15 +645,23 @@ void LCodeGen::AddToTranslation(LEnvironment* environment,
}
if (op->IsStackSlot()) {
int index = op->index();
if (index >= 0) {
index += StandardFrameConstants::kFixedFrameSize / kPointerSize;
}
if (is_tagged) {
translation->StoreStackSlot(op->index());
translation->StoreStackSlot(index);
} else if (is_uint32) {
translation->StoreUint32StackSlot(op->index());
translation->StoreUint32StackSlot(index);
} else {
translation->StoreInt32StackSlot(op->index());
translation->StoreInt32StackSlot(index);
}
} 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()) {
Register reg = ToRegister(op);
if (is_tagged) {

View File

@ -633,15 +633,23 @@ void LCodeGen::AddToTranslation(LEnvironment* environment,
}
if (op->IsStackSlot()) {
int index = op->index();
if (index >= 0) {
index += StandardFrameConstants::kFixedFrameSize / kPointerSize;
}
if (is_tagged) {
translation->StoreStackSlot(op->index());
translation->StoreStackSlot(index);
} else if (is_uint32) {
translation->StoreUint32StackSlot(op->index());
translation->StoreUint32StackSlot(index);
} else {
translation->StoreInt32StackSlot(op->index());
translation->StoreInt32StackSlot(index);
}
} 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()) {
Register reg = ToRegister(op);
if (is_tagged) {

View File

@ -592,15 +592,23 @@ void LCodeGen::AddToTranslation(LEnvironment* environment,
}
if (op->IsStackSlot()) {
int index = op->index();
if (index >= 0) {
index += StandardFrameConstants::kFixedFrameSize / kPointerSize;
}
if (is_tagged) {
translation->StoreStackSlot(op->index());
translation->StoreStackSlot(index);
} else if (is_uint32) {
translation->StoreUint32StackSlot(op->index());
translation->StoreUint32StackSlot(index);
} else {
translation->StoreInt32StackSlot(op->index());
translation->StoreInt32StackSlot(index);
}
} 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()) {
Register reg = ToRegister(op);
if (is_tagged) {

View File

@ -478,6 +478,7 @@
'../../src/compiler/dead-code-elimination.cc',
'../../src/compiler/dead-code-elimination.h',
'../../src/compiler/diamond.h',
'../../src/compiler/frame.cc',
'../../src/compiler/frame.h',
'../../src/compiler/frame-elider.cc',
'../../src/compiler/frame-elider.h',