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