1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_COMPILER_FRAME_H_
6 #define V8_COMPILER_FRAME_H_
7 
8 #include "src/v8.h"
9 
10 #include "src/data-flow.h"
11 
12 namespace v8 {
13 namespace internal {
14 namespace compiler {
15 
16 // Collects the spill slot requirements and the allocated general and double
17 // registers for a compiled function. Frames are usually populated by the
18 // register allocator and are used by Linkage to generate code for the prologue
19 // and epilogue to compiled code.
20 class Frame {
21  public:
Frame()22   Frame()
23       : register_save_area_size_(0),
24         spill_slot_count_(0),
25         double_spill_slot_count_(0),
26         allocated_registers_(NULL),
27         allocated_double_registers_(NULL) {}
28 
GetSpillSlotCount()29   inline int GetSpillSlotCount() { return spill_slot_count_; }
GetDoubleSpillSlotCount()30   inline int GetDoubleSpillSlotCount() { return double_spill_slot_count_; }
31 
SetAllocatedRegisters(BitVector * regs)32   void SetAllocatedRegisters(BitVector* regs) {
33     DCHECK(allocated_registers_ == NULL);
34     allocated_registers_ = regs;
35   }
36 
SetAllocatedDoubleRegisters(BitVector * regs)37   void SetAllocatedDoubleRegisters(BitVector* regs) {
38     DCHECK(allocated_double_registers_ == NULL);
39     allocated_double_registers_ = regs;
40   }
41 
DidAllocateDoubleRegisters()42   bool DidAllocateDoubleRegisters() {
43     return !allocated_double_registers_->IsEmpty();
44   }
45 
SetRegisterSaveAreaSize(int size)46   void SetRegisterSaveAreaSize(int size) {
47     DCHECK(IsAligned(size, kPointerSize));
48     register_save_area_size_ = size;
49   }
50 
GetRegisterSaveAreaSize()51   int GetRegisterSaveAreaSize() { return register_save_area_size_; }
52 
AllocateSpillSlot(bool is_double)53   int AllocateSpillSlot(bool is_double) {
54     // If 32-bit, skip one if the new slot is a double.
55     if (is_double) {
56       if (kDoubleSize > kPointerSize) {
57         DCHECK(kDoubleSize == kPointerSize * 2);
58         spill_slot_count_++;
59         spill_slot_count_ |= 1;
60       }
61       double_spill_slot_count_++;
62     }
63     return spill_slot_count_++;
64   }
65 
66  private:
67   int register_save_area_size_;
68   int spill_slot_count_;
69   int double_spill_slot_count_;
70   BitVector* allocated_registers_;
71   BitVector* allocated_double_registers_;
72 };
73 
74 
75 // Represents an offset from either the stack pointer or frame pointer.
76 class FrameOffset {
77  public:
from_stack_pointer()78   inline bool from_stack_pointer() { return (offset_ & 1) == kFromSp; }
from_frame_pointer()79   inline bool from_frame_pointer() { return (offset_ & 1) == kFromFp; }
offset()80   inline int offset() { return offset_ & ~1; }
81 
FromStackPointer(int offset)82   inline static FrameOffset FromStackPointer(int offset) {
83     DCHECK((offset & 1) == 0);
84     return FrameOffset(offset | kFromSp);
85   }
86 
FromFramePointer(int offset)87   inline static FrameOffset FromFramePointer(int offset) {
88     DCHECK((offset & 1) == 0);
89     return FrameOffset(offset | kFromFp);
90   }
91 
92  private:
FrameOffset(int offset)93   explicit FrameOffset(int offset) : offset_(offset) {}
94 
95   int offset_;  // Encodes SP or FP in the low order bit.
96 
97   static const int kFromSp = 1;
98   static const int kFromFp = 0;
99 };
100 }
101 }
102 }  // namespace v8::internal::compiler
103 
104 #endif  // V8_COMPILER_FRAME_H_
105