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.
5 #ifndef V8_SAFEPOINT_TABLE_H_
6 #define V8_SAFEPOINT_TABLE_H_
8 #include "src/allocation.h"
9 #include "src/heap/heap.h"
10 #include "src/v8memory.h"
18 class SafepointEntry BASE_EMBEDDED {
20 SafepointEntry() : info_(0), deoptimization_pc_(0), bits_(NULL) {}
22 SafepointEntry(unsigned info, unsigned deoptimization_pc, uint8_t* bits)
23 : info_(info), deoptimization_pc_(deoptimization_pc), bits_(bits) {
27 bool is_valid() const { return bits_ != NULL; }
29 bool Equals(const SafepointEntry& other) const {
30 return info_ == other.info_ && bits_ == other.bits_;
38 int deoptimization_index() const {
40 return DeoptimizationIndexField::decode(info_);
43 unsigned deoptimization_pc() const {
45 return deoptimization_pc_;
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
55 public BitField<unsigned,
57 kArgumentsFieldBits> {}; // NOLINT
58 class SaveDoublesField:
60 kDeoptIndexBits + kArgumentsFieldBits,
61 kSaveDoublesFieldBits> { }; // NOLINT
63 int argument_count() const {
65 return ArgumentsField::decode(info_);
68 bool has_doubles() const {
70 return SaveDoublesField::decode(info_);
78 bool HasRegisters() const;
79 bool HasRegisterAt(int reg_index) const;
83 unsigned deoptimization_pc_;
88 class SafepointTable BASE_EMBEDDED {
90 explicit SafepointTable(Code* code);
94 (length_ * (kPcAndDeoptimizationInfoSize + entry_size_));
96 unsigned length() const { return length_; }
97 unsigned entry_size() const { return entry_size_; }
99 unsigned GetPcOffset(unsigned index) const {
100 DCHECK(index < length_);
101 return Memory::uint32_at(GetPcOffsetLocation(index));
104 unsigned GetDeoptimizationPcOffset(unsigned index) const {
105 DCHECK(index < length_);
106 return Memory::uint32_at(GetDeoptimizationPcLocation(index));
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);
117 // Returns the entry for the given pc.
118 SafepointEntry FindEntry(Address pc) const;
120 void PrintEntry(unsigned index, OStream& os) const; // NOLINT
123 static const uint8_t kNoRegisters = 0xFF;
125 static const int kLengthOffset = 0;
126 static const int kEntrySizeOffset = kLengthOffset + kIntSize;
127 static const int kHeaderSize = kEntrySizeOffset + kIntSize;
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;
135 Address GetPcOffsetLocation(unsigned index) const {
136 return pc_and_deoptimization_indexes_ +
137 (index * kPcAndDeoptimizationInfoSize);
140 Address GetInfoLocation(unsigned index) const {
141 return GetPcOffsetLocation(index) + kPcSize;
144 Address GetDeoptimizationPcLocation(unsigned index) const {
145 return GetInfoLocation(index) + kDeoptimizationIndexSize;
148 static void PrintBits(OStream& os, // NOLINT
149 uint8_t byte, int digits);
151 DisallowHeapAllocation no_allocation_;
154 unsigned entry_size_;
156 Address pc_and_deoptimization_indexes_;
159 friend class SafepointTableBuilder;
160 friend class SafepointEntry;
162 DISALLOW_COPY_AND_ASSIGN(SafepointTable);
166 class Safepoint BASE_EMBEDDED {
170 kWithRegisters = 1 << 0,
171 kWithDoubles = 1 << 1,
172 kWithRegistersAndDoubles = kWithRegisters | kWithDoubles
182 explicit Id(int id) : id_(id) {}
186 friend class SafepointTableBuilder;
187 friend class Safepoint;
190 static const int kNoDeoptimizationIndex =
191 (1 << (SafepointEntry::kDeoptIndexBits)) - 1;
193 static const unsigned kNoDeoptimizationPc = ~0U;
195 void DefinePointerSlot(int index, Zone* zone) { indexes_->Add(index, zone); }
196 void DefinePointerRegister(Register reg, Zone* zone);
198 Id id() const { return Id(id_); }
201 Safepoint(int id, ZoneList<int>* indexes, ZoneList<int>* registers)
202 : id_(id), indexes_(indexes), registers_(registers) {}
204 ZoneList<int>* indexes_;
205 ZoneList<int>* registers_;
207 friend class SafepointTableBuilder;
211 class SafepointTableBuilder BASE_EMBEDDED {
213 explicit SafepointTableBuilder(Zone* zone)
214 : deoptimization_info_(32, zone),
215 deopt_index_list_(32, zone),
217 registers_(32, zone),
219 last_lazy_safepoint_(0),
222 // Get the offset of the emitted safepoint table in the code.
223 unsigned GetCodeOffset() const;
225 // Define a new safepoint for the current position in the body.
226 Safepoint DefineSafepoint(Assembler* assembler,
227 Safepoint::Kind kind,
229 Safepoint::DeoptMode mode);
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();
237 void SetDeoptimizationPc(Safepoint::Id safepoint_id,
238 unsigned deoptimization_pc) {
239 deoptimization_info_[safepoint_id.id_].deoptimization_pc =
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);
249 struct DeoptimizationInfo {
253 unsigned deoptimization_pc;
256 uint32_t EncodeExceptPC(const DeoptimizationInfo& info, unsigned index);
258 ZoneList<DeoptimizationInfo> deoptimization_info_;
259 ZoneList<unsigned> deopt_index_list_;
260 ZoneList<ZoneList<int>*> indexes_;
261 ZoneList<ZoneList<int>*> registers_;
265 int last_lazy_safepoint_;
269 DISALLOW_COPY_AND_ASSIGN(SafepointTableBuilder);
272 } } // namespace v8::internal
274 #endif // V8_SAFEPOINT_TABLE_H_