blob: fbb0152eb31267d1267a927f59760a9623c5ad32 [file] [log] [blame]
Steve Block1e0659c2011-05-24 12:43:12 +01001// Copyright 2011 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004
5#ifndef V8_SAFEPOINT_TABLE_H_
6#define V8_SAFEPOINT_TABLE_H_
7
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include "src/allocation.h"
9#include "src/heap/heap.h"
10#include "src/v8memory.h"
11#include "src/zone.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010012
13namespace v8 {
14namespace internal {
15
Ben Murdochb8e0da22011-05-16 14:20:40 +010016struct Register;
17
18class SafepointEntry BASE_EMBEDDED {
19 public:
20 SafepointEntry() : info_(0), bits_(NULL) {}
21
22 SafepointEntry(unsigned info, uint8_t* bits) : info_(info), bits_(bits) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023 DCHECK(is_valid());
Ben Murdochb8e0da22011-05-16 14:20:40 +010024 }
25
26 bool is_valid() const { return bits_ != NULL; }
27
28 bool Equals(const SafepointEntry& other) const {
29 return info_ == other.info_ && bits_ == other.bits_;
30 }
31
32 void Reset() {
33 info_ = 0;
34 bits_ = NULL;
35 }
36
37 int deoptimization_index() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000038 DCHECK(is_valid());
Ben Murdochb8e0da22011-05-16 14:20:40 +010039 return DeoptimizationIndexField::decode(info_);
40 }
41
Ben Murdoch2b4ba112012-01-20 14:57:15 +000042 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
Ben Murdochb8e0da22011-05-16 14:20:40 +010056
57 int argument_count() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000058 DCHECK(is_valid());
Ben Murdochb8e0da22011-05-16 14:20:40 +010059 return ArgumentsField::decode(info_);
60 }
61
62 bool has_doubles() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000063 DCHECK(is_valid());
Ben Murdochb8e0da22011-05-16 14:20:40 +010064 return SaveDoublesField::decode(info_);
65 }
66
67 uint8_t* bits() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000068 DCHECK(is_valid());
Ben Murdochb8e0da22011-05-16 14:20:40 +010069 return bits_;
70 }
71
72 bool HasRegisters() const;
73 bool HasRegisterAt(int reg_index) const;
74
Ben Murdochb8e0da22011-05-16 14:20:40 +010075 private:
76 unsigned info_;
77 uint8_t* bits_;
78};
79
80
Ben Murdochb0fe1622011-05-05 13:52:32 +010081class SafepointTable BASE_EMBEDDED {
82 public:
83 explicit SafepointTable(Code* code);
84
85 int size() const {
86 return kHeaderSize +
Ben Murdochb8a8cc12014-11-26 15:28:44 +000087 (length_ * (kPcAndDeoptimizationIndexSize + entry_size_));
88 }
Ben Murdochb0fe1622011-05-05 13:52:32 +010089 unsigned length() const { return length_; }
90 unsigned entry_size() const { return entry_size_; }
91
92 unsigned GetPcOffset(unsigned index) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000093 DCHECK(index < length_);
Ben Murdochb0fe1622011-05-05 13:52:32 +010094 return Memory::uint32_at(GetPcOffsetLocation(index));
95 }
96
Ben Murdochb8e0da22011-05-16 14:20:40 +010097 SafepointEntry GetEntry(unsigned index) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000098 DCHECK(index < length_);
Ben Murdochb8e0da22011-05-16 14:20:40 +010099 unsigned info = Memory::uint32_at(GetInfoLocation(index));
100 uint8_t* bits = &Memory::uint8_at(entries_ + (index * entry_size_));
101 return SafepointEntry(info, bits);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100102 }
103
Ben Murdochb8e0da22011-05-16 14:20:40 +0100104 // Returns the entry for the given pc.
105 SafepointEntry FindEntry(Address pc) const;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100106
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400107 void PrintEntry(unsigned index, std::ostream& os) const; // NOLINT
Ben Murdochb0fe1622011-05-05 13:52:32 +0100108
109 private:
110 static const uint8_t kNoRegisters = 0xFF;
111
112 static const int kLengthOffset = 0;
113 static const int kEntrySizeOffset = kLengthOffset + kIntSize;
114 static const int kHeaderSize = kEntrySizeOffset + kIntSize;
115
116 static const int kPcSize = kIntSize;
117 static const int kDeoptimizationIndexSize = kIntSize;
118 static const int kPcAndDeoptimizationIndexSize =
119 kPcSize + kDeoptimizationIndexSize;
120
121 Address GetPcOffsetLocation(unsigned index) const {
122 return pc_and_deoptimization_indexes_ +
123 (index * kPcAndDeoptimizationIndexSize);
124 }
125
Ben Murdochb8e0da22011-05-16 14:20:40 +0100126 Address GetInfoLocation(unsigned index) const {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100127 return GetPcOffsetLocation(index) + kPcSize;
128 }
129
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400130 static void PrintBits(std::ostream& os, // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000131 uint8_t byte, int digits);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100132
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000133 DisallowHeapAllocation no_allocation_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100134 Code* code_;
135 unsigned length_;
136 unsigned entry_size_;
137
138 Address pc_and_deoptimization_indexes_;
139 Address entries_;
140
141 friend class SafepointTableBuilder;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100142 friend class SafepointEntry;
143
144 DISALLOW_COPY_AND_ASSIGN(SafepointTable);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100145};
146
147
148class Safepoint BASE_EMBEDDED {
149 public:
Steve Block1e0659c2011-05-24 12:43:12 +0100150 typedef enum {
151 kSimple = 0,
152 kWithRegisters = 1 << 0,
153 kWithDoubles = 1 << 1,
154 kWithRegistersAndDoubles = kWithRegisters | kWithDoubles
155 } Kind;
156
Ben Murdoch2b4ba112012-01-20 14:57:15 +0000157 enum DeoptMode {
158 kNoLazyDeopt,
159 kLazyDeopt
160 };
161
Ben Murdochb8e0da22011-05-16 14:20:40 +0100162 static const int kNoDeoptimizationIndex =
163 (1 << (SafepointEntry::kDeoptIndexBits)) - 1;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100164
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000165 void DefinePointerSlot(int index, Zone* zone) { indexes_->Add(index, zone); }
166 void DefinePointerRegister(Register reg, Zone* zone);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100167
168 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000169 Safepoint(ZoneList<int>* indexes, ZoneList<int>* registers)
170 : indexes_(indexes), registers_(registers) {}
Ben Murdochb0fe1622011-05-05 13:52:32 +0100171 ZoneList<int>* indexes_;
172 ZoneList<int>* registers_;
173
174 friend class SafepointTableBuilder;
175};
176
177
178class SafepointTableBuilder BASE_EMBEDDED {
179 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000180 explicit SafepointTableBuilder(Zone* zone)
181 : deoptimization_info_(32, zone),
182 deopt_index_list_(32, zone),
183 indexes_(32, zone),
184 registers_(32, zone),
Ben Murdoch2b4ba112012-01-20 14:57:15 +0000185 emitted_(false),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000186 last_lazy_safepoint_(0),
187 zone_(zone) { }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100188
189 // Get the offset of the emitted safepoint table in the code.
190 unsigned GetCodeOffset() const;
191
192 // Define a new safepoint for the current position in the body.
Steve Block1e0659c2011-05-24 12:43:12 +0100193 Safepoint DefineSafepoint(Assembler* assembler,
194 Safepoint::Kind kind,
195 int arguments,
Ben Murdoch2b4ba112012-01-20 14:57:15 +0000196 Safepoint::DeoptMode mode);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100197
Ben Murdoch2b4ba112012-01-20 14:57:15 +0000198 // Record deoptimization index for lazy deoptimization for the last
199 // outstanding safepoints.
200 void RecordLazyDeoptimizationIndex(int index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000201 void BumpLastLazySafepointIndex() {
202 last_lazy_safepoint_ = deopt_index_list_.length();
203 }
Steve Block44f0eee2011-05-26 01:26:41 +0100204
Ben Murdochb0fe1622011-05-05 13:52:32 +0100205 // Emit the safepoint table after the body. The number of bits per
206 // entry must be enough to hold all the pointer indexes.
207 void Emit(Assembler* assembler, int bits_per_entry);
208
Steve Block1e0659c2011-05-24 12:43:12 +0100209
Ben Murdochb0fe1622011-05-05 13:52:32 +0100210 private:
211 struct DeoptimizationInfo {
212 unsigned pc;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100213 unsigned arguments;
214 bool has_doubles;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100215 };
216
Ben Murdoch2b4ba112012-01-20 14:57:15 +0000217 uint32_t EncodeExceptPC(const DeoptimizationInfo& info, unsigned index);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100218
219 ZoneList<DeoptimizationInfo> deoptimization_info_;
Ben Murdoch2b4ba112012-01-20 14:57:15 +0000220 ZoneList<unsigned> deopt_index_list_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100221 ZoneList<ZoneList<int>*> indexes_;
222 ZoneList<ZoneList<int>*> registers_;
223
Ben Murdochb0fe1622011-05-05 13:52:32 +0100224 unsigned offset_;
Steve Block1e0659c2011-05-24 12:43:12 +0100225 bool emitted_;
Ben Murdoch2b4ba112012-01-20 14:57:15 +0000226 int last_lazy_safepoint_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100227
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000228 Zone* zone_;
229
Ben Murdochb0fe1622011-05-05 13:52:32 +0100230 DISALLOW_COPY_AND_ASSIGN(SafepointTableBuilder);
231};
232
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000233} // namespace internal
234} // namespace v8
Ben Murdochb0fe1622011-05-05 13:52:32 +0100235
236#endif // V8_SAFEPOINT_TABLE_H_