• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 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_SAFEPOINT_TABLE_H_
6 #define V8_SAFEPOINT_TABLE_H_
7 
8 #include "src/allocation.h"
9 #include "src/heap.h"
10 #include "src/v8memory.h"
11 #include "src/zone.h"
12 
13 namespace v8 {
14 namespace internal {
15 
16 struct Register;
17 
18 class SafepointEntry BASE_EMBEDDED {
19  public:
SafepointEntry()20   SafepointEntry() : info_(0), bits_(NULL) {}
21 
SafepointEntry(unsigned info,uint8_t * bits)22   SafepointEntry(unsigned info, uint8_t* bits) : info_(info), bits_(bits) {
23     ASSERT(is_valid());
24   }
25 
is_valid()26   bool is_valid() const { return bits_ != NULL; }
27 
Equals(const SafepointEntry & other)28   bool Equals(const SafepointEntry& other) const {
29     return info_ == other.info_ && bits_ == other.bits_;
30   }
31 
Reset()32   void Reset() {
33     info_ = 0;
34     bits_ = NULL;
35   }
36 
deoptimization_index()37   int deoptimization_index() const {
38     ASSERT(is_valid());
39     return DeoptimizationIndexField::decode(info_);
40   }
41 
42   static const int kArgumentsFieldBits = 3;
43   static const int kSaveDoublesFieldBits = 1;
44   static const int kDeoptIndexBits =
45       32 - kArgumentsFieldBits - kSaveDoublesFieldBits;
46   class DeoptimizationIndexField:
47     public BitField<int, 0, kDeoptIndexBits> {};  // NOLINT
48   class ArgumentsField:
49     public BitField<unsigned,
50                     kDeoptIndexBits,
51                     kArgumentsFieldBits> {};  // NOLINT
52   class SaveDoublesField:
53     public BitField<bool,
54                     kDeoptIndexBits + kArgumentsFieldBits,
55                     kSaveDoublesFieldBits> { }; // NOLINT
56 
argument_count()57   int argument_count() const {
58     ASSERT(is_valid());
59     return ArgumentsField::decode(info_);
60   }
61 
has_doubles()62   bool has_doubles() const {
63     ASSERT(is_valid());
64     return SaveDoublesField::decode(info_);
65   }
66 
bits()67   uint8_t* bits() {
68     ASSERT(is_valid());
69     return bits_;
70   }
71 
72   bool HasRegisters() const;
73   bool HasRegisterAt(int reg_index) const;
74 
75  private:
76   unsigned info_;
77   uint8_t* bits_;
78 };
79 
80 
81 class SafepointTable BASE_EMBEDDED {
82  public:
83   explicit SafepointTable(Code* code);
84 
size()85   int size() const {
86     return kHeaderSize +
87            (length_ * (kPcAndDeoptimizationIndexSize + entry_size_)); }
length()88   unsigned length() const { return length_; }
entry_size()89   unsigned entry_size() const { return entry_size_; }
90 
GetPcOffset(unsigned index)91   unsigned GetPcOffset(unsigned index) const {
92     ASSERT(index < length_);
93     return Memory::uint32_at(GetPcOffsetLocation(index));
94   }
95 
GetEntry(unsigned index)96   SafepointEntry GetEntry(unsigned index) const {
97     ASSERT(index < length_);
98     unsigned info = Memory::uint32_at(GetInfoLocation(index));
99     uint8_t* bits = &Memory::uint8_at(entries_ + (index * entry_size_));
100     return SafepointEntry(info, bits);
101   }
102 
103   // Returns the entry for the given pc.
104   SafepointEntry FindEntry(Address pc) const;
105 
106   void PrintEntry(unsigned index, FILE* out = stdout) const;
107 
108  private:
109   static const uint8_t kNoRegisters = 0xFF;
110 
111   static const int kLengthOffset = 0;
112   static const int kEntrySizeOffset = kLengthOffset + kIntSize;
113   static const int kHeaderSize = kEntrySizeOffset + kIntSize;
114 
115   static const int kPcSize = kIntSize;
116   static const int kDeoptimizationIndexSize = kIntSize;
117   static const int kPcAndDeoptimizationIndexSize =
118       kPcSize + kDeoptimizationIndexSize;
119 
GetPcOffsetLocation(unsigned index)120   Address GetPcOffsetLocation(unsigned index) const {
121     return pc_and_deoptimization_indexes_ +
122            (index * kPcAndDeoptimizationIndexSize);
123   }
124 
GetInfoLocation(unsigned index)125   Address GetInfoLocation(unsigned index) const {
126     return GetPcOffsetLocation(index) + kPcSize;
127   }
128 
129   static void PrintBits(FILE* out, uint8_t byte, int digits);
130 
131   DisallowHeapAllocation no_allocation_;
132   Code* code_;
133   unsigned length_;
134   unsigned entry_size_;
135 
136   Address pc_and_deoptimization_indexes_;
137   Address entries_;
138 
139   friend class SafepointTableBuilder;
140   friend class SafepointEntry;
141 
142   DISALLOW_COPY_AND_ASSIGN(SafepointTable);
143 };
144 
145 
146 class Safepoint BASE_EMBEDDED {
147  public:
148   typedef enum {
149     kSimple = 0,
150     kWithRegisters = 1 << 0,
151     kWithDoubles = 1 << 1,
152     kWithRegistersAndDoubles = kWithRegisters | kWithDoubles
153   } Kind;
154 
155   enum DeoptMode {
156     kNoLazyDeopt,
157     kLazyDeopt
158   };
159 
160   static const int kNoDeoptimizationIndex =
161       (1 << (SafepointEntry::kDeoptIndexBits)) - 1;
162 
DefinePointerSlot(int index,Zone * zone)163   void DefinePointerSlot(int index, Zone* zone) { indexes_->Add(index, zone); }
164   void DefinePointerRegister(Register reg, Zone* zone);
165 
166  private:
Safepoint(ZoneList<int> * indexes,ZoneList<int> * registers)167   Safepoint(ZoneList<int>* indexes, ZoneList<int>* registers) :
168       indexes_(indexes), registers_(registers) { }
169   ZoneList<int>* indexes_;
170   ZoneList<int>* registers_;
171 
172   friend class SafepointTableBuilder;
173 };
174 
175 
176 class SafepointTableBuilder BASE_EMBEDDED {
177  public:
SafepointTableBuilder(Zone * zone)178   explicit SafepointTableBuilder(Zone* zone)
179       : deoptimization_info_(32, zone),
180         deopt_index_list_(32, zone),
181         indexes_(32, zone),
182         registers_(32, zone),
183         emitted_(false),
184         last_lazy_safepoint_(0),
185         zone_(zone) { }
186 
187   // Get the offset of the emitted safepoint table in the code.
188   unsigned GetCodeOffset() const;
189 
190   // Define a new safepoint for the current position in the body.
191   Safepoint DefineSafepoint(Assembler* assembler,
192                             Safepoint::Kind kind,
193                             int arguments,
194                             Safepoint::DeoptMode mode);
195 
196   // Record deoptimization index for lazy deoptimization for the last
197   // outstanding safepoints.
198   void RecordLazyDeoptimizationIndex(int index);
BumpLastLazySafepointIndex()199   void BumpLastLazySafepointIndex() {
200     last_lazy_safepoint_ = deopt_index_list_.length();
201   }
202 
203   // Emit the safepoint table after the body. The number of bits per
204   // entry must be enough to hold all the pointer indexes.
205   void Emit(Assembler* assembler, int bits_per_entry);
206 
207 
208  private:
209   struct DeoptimizationInfo {
210     unsigned pc;
211     unsigned arguments;
212     bool has_doubles;
213   };
214 
215   uint32_t EncodeExceptPC(const DeoptimizationInfo& info, unsigned index);
216 
217   ZoneList<DeoptimizationInfo> deoptimization_info_;
218   ZoneList<unsigned> deopt_index_list_;
219   ZoneList<ZoneList<int>*> indexes_;
220   ZoneList<ZoneList<int>*> registers_;
221 
222   unsigned offset_;
223   bool emitted_;
224   int last_lazy_safepoint_;
225 
226   Zone* zone_;
227 
228   DISALLOW_COPY_AND_ASSIGN(SafepointTableBuilder);
229 };
230 
231 } }  // namespace v8::internal
232 
233 #endif  // V8_SAFEPOINT_TABLE_H_
234