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