Fix deoptimization address patching in Turbofan to use safepoints.
[platform/upstream/v8.git] / src / safepoint-table.h
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/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:
20   SafepointEntry() : info_(0), deoptimization_pc_(0), bits_(NULL) {}
21
22   SafepointEntry(unsigned info, unsigned deoptimization_pc, uint8_t* bits)
23       : info_(info), deoptimization_pc_(deoptimization_pc), bits_(bits) {
24     DCHECK(is_valid());
25   }
26
27   bool is_valid() const { return bits_ != NULL; }
28
29   bool Equals(const SafepointEntry& other) const {
30     return info_ == other.info_ && bits_ == other.bits_;
31   }
32
33   void Reset() {
34     info_ = 0;
35     bits_ = NULL;
36   }
37
38   int deoptimization_index() const {
39     DCHECK(is_valid());
40     return DeoptimizationIndexField::decode(info_);
41   }
42
43   unsigned deoptimization_pc() const {
44     DCHECK(is_valid());
45     return deoptimization_pc_;
46   }
47
48   static const int kArgumentsFieldBits = 3;
49   static const int kSaveDoublesFieldBits = 1;
50   static const int kDeoptIndexBits =
51       32 - kArgumentsFieldBits - kSaveDoublesFieldBits;
52   class DeoptimizationIndexField:
53     public BitField<int, 0, kDeoptIndexBits> {};  // NOLINT
54   class ArgumentsField:
55     public BitField<unsigned,
56                     kDeoptIndexBits,
57                     kArgumentsFieldBits> {};  // NOLINT
58   class SaveDoublesField:
59     public BitField<bool,
60                     kDeoptIndexBits + kArgumentsFieldBits,
61                     kSaveDoublesFieldBits> { }; // NOLINT
62
63   int argument_count() const {
64     DCHECK(is_valid());
65     return ArgumentsField::decode(info_);
66   }
67
68   bool has_doubles() const {
69     DCHECK(is_valid());
70     return SaveDoublesField::decode(info_);
71   }
72
73   uint8_t* bits() {
74     DCHECK(is_valid());
75     return bits_;
76   }
77
78   bool HasRegisters() const;
79   bool HasRegisterAt(int reg_index) const;
80
81  private:
82   unsigned info_;
83   unsigned deoptimization_pc_;
84   uint8_t* bits_;
85 };
86
87
88 class SafepointTable BASE_EMBEDDED {
89  public:
90   explicit SafepointTable(Code* code);
91
92   int size() const {
93     return kHeaderSize +
94            (length_ * (kPcAndDeoptimizationInfoSize + entry_size_));
95   }
96   unsigned length() const { return length_; }
97   unsigned entry_size() const { return entry_size_; }
98
99   unsigned GetPcOffset(unsigned index) const {
100     DCHECK(index < length_);
101     return Memory::uint32_at(GetPcOffsetLocation(index));
102   }
103
104   unsigned GetDeoptimizationPcOffset(unsigned index) const {
105     DCHECK(index < length_);
106     return Memory::uint32_at(GetDeoptimizationPcLocation(index));
107   }
108
109   SafepointEntry GetEntry(unsigned index) const {
110     DCHECK(index < length_);
111     unsigned info = Memory::uint32_at(GetInfoLocation(index));
112     unsigned deopt_pc = Memory::uint32_at(GetDeoptimizationPcLocation(index));
113     uint8_t* bits = &Memory::uint8_at(entries_ + (index * entry_size_));
114     return SafepointEntry(info, deopt_pc, bits);
115   }
116
117   // Returns the entry for the given pc.
118   SafepointEntry FindEntry(Address pc) const;
119
120   void PrintEntry(unsigned index, OStream& os) const;  // NOLINT
121
122  private:
123   static const uint8_t kNoRegisters = 0xFF;
124
125   static const int kLengthOffset = 0;
126   static const int kEntrySizeOffset = kLengthOffset + kIntSize;
127   static const int kHeaderSize = kEntrySizeOffset + kIntSize;
128
129   static const int kPcSize = kIntSize;
130   static const int kDeoptimizationIndexSize = kIntSize;
131   static const int kDeoptimizationPcSize = kIntSize;
132   static const int kPcAndDeoptimizationInfoSize =
133       kPcSize + kDeoptimizationIndexSize + kDeoptimizationPcSize;
134
135   Address GetPcOffsetLocation(unsigned index) const {
136     return pc_and_deoptimization_indexes_ +
137            (index * kPcAndDeoptimizationInfoSize);
138   }
139
140   Address GetInfoLocation(unsigned index) const {
141     return GetPcOffsetLocation(index) + kPcSize;
142   }
143
144   Address GetDeoptimizationPcLocation(unsigned index) const {
145     return GetInfoLocation(index) + kDeoptimizationIndexSize;
146   }
147
148   static void PrintBits(OStream& os,  // NOLINT
149                         uint8_t byte, int digits);
150
151   DisallowHeapAllocation no_allocation_;
152   Code* code_;
153   unsigned length_;
154   unsigned entry_size_;
155
156   Address pc_and_deoptimization_indexes_;
157   Address entries_;
158
159   friend class SafepointTableBuilder;
160   friend class SafepointEntry;
161
162   DISALLOW_COPY_AND_ASSIGN(SafepointTable);
163 };
164
165
166 class Safepoint BASE_EMBEDDED {
167  public:
168   typedef enum {
169     kSimple = 0,
170     kWithRegisters = 1 << 0,
171     kWithDoubles = 1 << 1,
172     kWithRegistersAndDoubles = kWithRegisters | kWithDoubles
173   } Kind;
174
175   enum DeoptMode {
176     kNoLazyDeopt,
177     kLazyDeopt
178   };
179
180   class Id {
181    private:
182     explicit Id(int id) : id_(id) {}
183
184     int id_;
185
186     friend class SafepointTableBuilder;
187     friend class Safepoint;
188   };
189
190   static const int kNoDeoptimizationIndex =
191       (1 << (SafepointEntry::kDeoptIndexBits)) - 1;
192
193   static const unsigned kNoDeoptimizationPc = ~0U;
194
195   void DefinePointerSlot(int index, Zone* zone) { indexes_->Add(index, zone); }
196   void DefinePointerRegister(Register reg, Zone* zone);
197
198   Id id() const { return Id(id_); }
199
200  private:
201   Safepoint(int id, ZoneList<int>* indexes, ZoneList<int>* registers)
202       : id_(id), indexes_(indexes), registers_(registers) {}
203   int id_;
204   ZoneList<int>* indexes_;
205   ZoneList<int>* registers_;
206
207   friend class SafepointTableBuilder;
208 };
209
210
211 class SafepointTableBuilder BASE_EMBEDDED {
212  public:
213   explicit SafepointTableBuilder(Zone* zone)
214       : deoptimization_info_(32, zone),
215         deopt_index_list_(32, zone),
216         indexes_(32, zone),
217         registers_(32, zone),
218         emitted_(false),
219         last_lazy_safepoint_(0),
220         zone_(zone) { }
221
222   // Get the offset of the emitted safepoint table in the code.
223   unsigned GetCodeOffset() const;
224
225   // Define a new safepoint for the current position in the body.
226   Safepoint DefineSafepoint(Assembler* assembler,
227                             Safepoint::Kind kind,
228                             int arguments,
229                             Safepoint::DeoptMode mode);
230
231   // Record deoptimization index for lazy deoptimization for the last
232   // outstanding safepoints.
233   void RecordLazyDeoptimizationIndex(int index);
234   void BumpLastLazySafepointIndex() {
235     last_lazy_safepoint_ = deopt_index_list_.length();
236   }
237   void SetDeoptimizationPc(Safepoint::Id safepoint_id,
238                            unsigned deoptimization_pc) {
239     deoptimization_info_[safepoint_id.id_].deoptimization_pc =
240         deoptimization_pc;
241   }
242
243   // Emit the safepoint table after the body. The number of bits per
244   // entry must be enough to hold all the pointer indexes.
245   void Emit(Assembler* assembler, int bits_per_entry);
246
247
248  private:
249   struct DeoptimizationInfo {
250     unsigned pc;
251     unsigned arguments;
252     bool has_doubles;
253     unsigned deoptimization_pc;
254   };
255
256   uint32_t EncodeExceptPC(const DeoptimizationInfo& info, unsigned index);
257
258   ZoneList<DeoptimizationInfo> deoptimization_info_;
259   ZoneList<unsigned> deopt_index_list_;
260   ZoneList<ZoneList<int>*> indexes_;
261   ZoneList<ZoneList<int>*> registers_;
262
263   unsigned offset_;
264   bool emitted_;
265   int last_lazy_safepoint_;
266
267   Zone* zone_;
268
269   DISALLOW_COPY_AND_ASSIGN(SafepointTableBuilder);
270 };
271
272 } }  // namespace v8::internal
273
274 #endif  // V8_SAFEPOINT_TABLE_H_