"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",
}
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) {
}
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) {
#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 {
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);
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.
#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 {
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);
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();
- 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);
+ // Restore registers.
+ CPURegList saves = CPURegList(CPURegister::kRegister, kXRegSizeInBits,
+ descriptor->CalleeSavedRegisters());
+ if (saves.Count() != 0) {
+ __ PopCPURegList(saves);
+ }
- CPURegList saves_fp =
- CPURegList(CPURegister::kFPRegister, kDRegSizeInBits,
- descriptor->CalleeSavedFPRegisters());
- __ PopCPURegList(saves_fp);
- }
+ // 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) {
__ Mov(csp, fp);
__ Pop(fp, lr);
} else if (descriptor->IsJSFunctionCall() || needs_frame_) {
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());
--- /dev/null
+// 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
#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);
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_; }
+ void AllocateSavedCalleeRegisterSlots(int count) {
+ frame_slot_count_ += count;
+ spilled_callee_register_slot_count_ += count;
+ }
- // OSR stack slots, including locals and expression stack slots.
- void SetOsrStackSlotCount(int slots) {
- DCHECK(slots >= 0);
- osr_stack_slot_count_ = slots;
+ 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 GetOsrStackSlotCount() { return osr_stack_slot_count_; }
+ 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;
+ }
- int AllocateSpillSlot(int width) {
+ 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_++;
- }
-
- 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);
+ return frame_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);
};
#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"
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);
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();
+ }
+
+ const RegList saves = descriptor->CalleeSavedRegisters();
+ if (stack_shrink_slots > 0) {
+ __ sub(esp, Immediate(stack_shrink_slots * kPointerSize));
}
- if (stack_slots > 0) {
- // Allocate the stack slots used by this frame.
- __ sub(esp, Immediate(stack_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()) {
#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"
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);
}
}
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.
#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"
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()) {
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();
+ }
+
+ 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));
}
- if (stack_slots > 0) {
- __ Subu(sp, sp, Operand(stack_slots * 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_) {
#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"
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);
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_shrink_slots > 0) {
+ __ Dsubu(sp, sp, Operand(stack_shrink_slots * kPointerSize));
}
- if (stack_slots > 0) {
- __ Dsubu(sp, sp, Operand(stack_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_) {
__ Pop(ra, fp);
}
}
+ int pop_count = static_cast<int>(descriptor->StackParameterCount());
if (pop_count != 0) {
__ DropAndRet(pop_count);
} else {
// 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
}
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);
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();
}
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>();
void Pipeline::AllocateRegisters(const RegisterConfiguration* config,
+ CallDescriptor* descriptor,
bool run_verifier) {
PipelineData* data = this->data_;
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());
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
// 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;
#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"
}
+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);
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());
+ }
+
+ 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));
}
- if (stack_slots > 0) {
- __ subq(rsp, Immediate(stack_slots * 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()) {
}
-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
}
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,
}
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] ",
}
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,
}
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,
}
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,
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_;
}
+int OptimizedFrame::StackSlotOffsetRelativeToFp(int slot_index) {
+ return StandardFrameConstants::kCallerSPOffset -
+ ((slot_index + 1) * kPointerSize);
+}
+
+
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);
-
- // 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);
+ return Memory::Object_at(fp() + StackSlotOffsetRelativeToFp(index));
}
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;
DeoptimizationInputData* GetDeoptimizationData(int* deopt_index);
+ static int StackSlotOffsetRelativeToFp(int slot_index);
+
protected:
inline explicit OptimizedFrame(StackFrameIteratorBase* iterator);
}
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) {
}
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) {
}
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) {
}
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) {
'../../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',