V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
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/assert-scope.h"
10 #include "src/utils.h"
11 #include "src/v8memory.h"
12 #include "src/zone/zone-chunk-list.h"
13 #include "src/zone/zone.h"
14 
15 namespace v8 {
16 namespace internal {
17 
18 class Register;
19 
21  public:
22  SafepointEntry() : info_(0), bits_(nullptr), trampoline_pc_(-1) {}
23 
24  SafepointEntry(unsigned info, uint8_t* bits, int trampoline_pc)
25  : info_(info), bits_(bits), trampoline_pc_(trampoline_pc) {
26  DCHECK(is_valid());
27  }
28 
29  bool is_valid() const { return bits_ != nullptr; }
30 
31  bool Equals(const SafepointEntry& other) const {
32  return info_ == other.info_ && bits_ == other.bits_;
33  }
34 
35  void Reset() {
36  info_ = 0;
37  bits_ = nullptr;
38  }
39 
40  int deoptimization_index() const {
41  DCHECK(is_valid());
42  return DeoptimizationIndexField::decode(info_);
43  }
44 
45  int trampoline_pc() { return trampoline_pc_; }
46 
47  void set_trampoline_pc(int trampoline_pc) { trampoline_pc_ = trampoline_pc; }
48 
49  static const int kArgumentsFieldBits = 3;
50  static const int kSaveDoublesFieldBits = 1;
51  static const int kDeoptIndexBits =
52  32 - kArgumentsFieldBits - kSaveDoublesFieldBits;
53 
55  public BitField<int, 0, kDeoptIndexBits> {}; // NOLINT
57  public BitField<unsigned,
58  kDeoptIndexBits,
59  kArgumentsFieldBits> {}; // NOLINT
61  public BitField<bool,
62  kDeoptIndexBits + kArgumentsFieldBits,
63  kSaveDoublesFieldBits> { }; // NOLINT
64 
65  int argument_count() const {
66  DCHECK(is_valid());
67  return ArgumentsField::decode(info_);
68  }
69 
70  bool has_doubles() const {
71  DCHECK(is_valid());
72  return SaveDoublesField::decode(info_);
73  }
74 
75  uint8_t* bits() {
76  DCHECK(is_valid());
77  return bits_;
78  }
79 
80  bool HasRegisters() const;
81  bool HasRegisterAt(int reg_index) const;
82 
83  private:
84  unsigned info_;
85  uint8_t* bits_;
86  // It needs to be an integer as it is -1 for eager deoptimizations.
87  int trampoline_pc_;
88 };
89 
91  public:
92  explicit SafepointTable(Code code);
93  explicit SafepointTable(Address instruction_start,
94  size_t safepoint_table_offset, uint32_t stack_slots,
95  bool has_deopt = false);
96 
97  int size() const {
98  return kHeaderSize + (length_ * (kFixedEntrySize + entry_size_));
99  }
100  unsigned length() const { return length_; }
101  unsigned entry_size() const { return entry_size_; }
102 
103  unsigned GetPcOffset(unsigned index) const {
104  DCHECK(index < length_);
105  return Memory<uint32_t>(GetPcOffsetLocation(index));
106  }
107 
108  int GetTrampolinePcOffset(unsigned index) const {
109  DCHECK(index < length_);
110  return Memory<int>(GetTrampolineLocation(index));
111  }
112 
113  unsigned find_return_pc(unsigned pc_offset);
114 
115  SafepointEntry GetEntry(unsigned index) const {
116  DCHECK(index < length_);
117  unsigned info = Memory<uint32_t>(GetInfoLocation(index));
118  uint8_t* bits = &Memory<uint8_t>(entries_ + (index * entry_size_));
119  int trampoline_pc =
120  has_deopt_ ? Memory<int>(GetTrampolineLocation(index)) : -1;
121  return SafepointEntry(info, bits, trampoline_pc);
122  }
123 
124  // Returns the entry for the given pc.
125  SafepointEntry FindEntry(Address pc) const;
126 
127  void PrintEntry(unsigned index, std::ostream& os) const; // NOLINT
128 
129  private:
130  static const uint8_t kNoRegisters = 0xFF;
131 
132  // Layout information
133  static const int kLengthOffset = 0;
134  static const int kEntrySizeOffset = kLengthOffset + kIntSize;
135  static const int kHeaderSize = kEntrySizeOffset + kIntSize;
136  static const int kPcOffset = 0;
137  static const int kDeoptimizationIndexOffset = kPcOffset + kIntSize;
138  static const int kTrampolinePcOffset = kDeoptimizationIndexOffset + kIntSize;
139  static const int kFixedEntrySize = kTrampolinePcOffset + kIntSize;
140 
141  Address GetPcOffsetLocation(unsigned index) const {
142  return pc_and_deoptimization_indexes_ + (index * kFixedEntrySize);
143  }
144 
145  // TODO(juliana): rename this to GetDeoptimizationIndexLocation
146  Address GetInfoLocation(unsigned index) const {
147  return GetPcOffsetLocation(index) + kDeoptimizationIndexOffset;
148  }
149 
150  Address GetTrampolineLocation(unsigned index) const {
151  return GetPcOffsetLocation(index) + kTrampolinePcOffset;
152  }
153 
154  static void PrintBits(std::ostream& os, // NOLINT
155  uint8_t byte, int digits);
156 
157  DISALLOW_HEAP_ALLOCATION(no_allocation_);
158  Address instruction_start_;
159  uint32_t stack_slots_;
160  unsigned length_;
161  unsigned entry_size_;
162 
163  Address pc_and_deoptimization_indexes_;
164  Address entries_;
165  bool has_deopt_;
166 
167  friend class SafepointTableBuilder;
168  friend class SafepointEntry;
169 
170  DISALLOW_COPY_AND_ASSIGN(SafepointTable);
171 };
172 
173 class Safepoint {
174  public:
175  typedef enum {
176  kSimple = 0,
177  kWithRegisters = 1 << 0,
178  kWithDoubles = 1 << 1,
179  kWithRegistersAndDoubles = kWithRegisters | kWithDoubles
180  } Kind;
181 
182  enum DeoptMode {
183  kNoLazyDeopt,
184  kLazyDeopt
185  };
186 
187  static const int kNoDeoptimizationIndex =
188  (1 << (SafepointEntry::kDeoptIndexBits)) - 1;
189 
190  void DefinePointerSlot(int index) { indexes_->push_back(index); }
191  void DefinePointerRegister(Register reg);
192 
193  private:
194  Safepoint(ZoneChunkList<int>* indexes, ZoneChunkList<int>* registers)
195  : indexes_(indexes), registers_(registers) {}
196  ZoneChunkList<int>* const indexes_;
197  ZoneChunkList<int>* const registers_;
198 
199  friend class SafepointTableBuilder;
200 };
201 
203  public:
204  explicit SafepointTableBuilder(Zone* zone)
205  : deoptimization_info_(zone),
206  emitted_(false),
207  last_lazy_safepoint_(0),
208  zone_(zone) {}
209 
210  // Get the offset of the emitted safepoint table in the code.
211  unsigned GetCodeOffset() const;
212 
213  // Define a new safepoint for the current position in the body.
214  Safepoint DefineSafepoint(Assembler* assembler,
215  Safepoint::Kind kind,
216  int arguments,
217  Safepoint::DeoptMode mode);
218 
219  // Record deoptimization index for lazy deoptimization for the last
220  // outstanding safepoints.
221  void RecordLazyDeoptimizationIndex(int index);
222  void BumpLastLazySafepointIndex() {
223  last_lazy_safepoint_ = deoptimization_info_.size();
224  }
225 
226  // Emit the safepoint table after the body. The number of bits per
227  // entry must be enough to hold all the pointer indexes.
228  void Emit(Assembler* assembler, int bits_per_entry);
229 
230  // Find the Deoptimization Info with pc offset {pc} and update its
231  // trampoline field. Calling this function ensures that the safepoint
232  // table contains the trampoline PC (trampoline} that replaced the
233  // return PC {pc} on the stack.
234  int UpdateDeoptimizationInfo(int pc, int trampoline, int start);
235 
236  private:
237  struct DeoptimizationInfo {
238  unsigned pc;
239  unsigned arguments;
240  bool has_doubles;
241  int trampoline;
242  ZoneChunkList<int>* indexes;
243  ZoneChunkList<int>* registers;
244  unsigned deopt_index;
245  DeoptimizationInfo(Zone* zone, unsigned pc, unsigned arguments,
246  Safepoint::Kind kind)
247  : pc(pc),
248  arguments(arguments),
249  has_doubles(kind & Safepoint::kWithDoubles),
250  trampoline(-1),
251  indexes(new (zone) ZoneChunkList<int>(
253  registers(kind & Safepoint::kWithRegisters
254  ? new (zone) ZoneChunkList<int>(
256  : nullptr),
257  deopt_index(Safepoint::kNoDeoptimizationIndex) {}
258  };
259 
260  uint32_t EncodeExceptPC(const DeoptimizationInfo&);
261 
262  bool IsIdenticalExceptForPc(const DeoptimizationInfo&,
263  const DeoptimizationInfo&) const;
264  // If all entries are identical, replace them by 1 entry with pc = kMaxUInt32.
265  void RemoveDuplicates();
266 
267  ZoneChunkList<DeoptimizationInfo> deoptimization_info_;
268 
269  unsigned offset_;
270  bool emitted_;
271  size_t last_lazy_safepoint_;
272 
273  Zone* zone_;
274 
275  DISALLOW_COPY_AND_ASSIGN(SafepointTableBuilder);
276 };
277 
278 } // namespace internal
279 } // namespace v8
280 
281 #endif // V8_SAFEPOINT_TABLE_H_
Definition: libplatform.h:13