OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_TYPE_FEEDBACK_VECTOR_H_ | 5 #ifndef V8_TYPE_FEEDBACK_VECTOR_H_ |
6 #define V8_TYPE_FEEDBACK_VECTOR_H_ | 6 #define V8_TYPE_FEEDBACK_VECTOR_H_ |
7 | 7 |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "src/checks.h" | 10 #include "src/checks.h" |
11 #include "src/elements-kind.h" | 11 #include "src/elements-kind.h" |
12 #include "src/heap/heap.h" | 12 #include "src/heap/heap.h" |
13 #include "src/isolate.h" | 13 #include "src/isolate.h" |
14 #include "src/objects.h" | 14 #include "src/objects.h" |
15 #include "src/zone-containers.h" | 15 #include "src/zone-containers.h" |
16 | 16 |
17 namespace v8 { | 17 namespace v8 { |
18 namespace internal { | 18 namespace internal { |
19 | 19 |
20 | 20 |
21 enum class FeedbackVectorSlotKind { | 21 enum class FeedbackVectorSlotKind { |
22 UNUSED, | 22 // This kind means that the slot points to the middle of other slot |
| 23 // which occupies more than one feedback vector element. |
| 24 // There must be no such slots in the system. |
| 25 INVALID, |
| 26 |
23 CALL_IC, | 27 CALL_IC, |
24 LOAD_IC, | 28 LOAD_IC, |
25 KEYED_LOAD_IC, | 29 KEYED_LOAD_IC, |
26 STORE_IC, | 30 STORE_IC, |
27 KEYED_STORE_IC, | 31 KEYED_STORE_IC, |
28 | 32 |
| 33 // This is a general purpose slot that occupies one feedback vector element. |
| 34 GENERAL, |
| 35 |
29 KINDS_NUMBER // Last value indicating number of kinds. | 36 KINDS_NUMBER // Last value indicating number of kinds. |
30 }; | 37 }; |
31 | 38 |
32 | 39 |
33 std::ostream& operator<<(std::ostream& os, FeedbackVectorSlotKind kind); | 40 std::ostream& operator<<(std::ostream& os, FeedbackVectorSlotKind kind); |
34 | 41 |
35 | 42 |
36 class StaticFeedbackVectorSpec { | 43 template <typename Derived> |
| 44 class FeedbackVectorSpecBase { |
37 public: | 45 public: |
38 StaticFeedbackVectorSpec() : slots_(0), ic_slots_(0), ic_kinds_(NULL) {} | 46 inline FeedbackVectorSlot AddSlot(FeedbackVectorSlotKind kind); |
39 StaticFeedbackVectorSpec(int slots, int ic_slots, | 47 |
40 FeedbackVectorSlotKind* ic_slot_kinds) | 48 FeedbackVectorSlot AddCallICSlot() { |
41 : slots_(slots), ic_slots_(ic_slots), ic_kinds_(ic_slot_kinds) {} | 49 return AddSlot(FeedbackVectorSlotKind::CALL_IC); |
| 50 } |
| 51 |
| 52 FeedbackVectorSlot AddLoadICSlot() { |
| 53 return AddSlot(FeedbackVectorSlotKind::LOAD_IC); |
| 54 } |
| 55 |
| 56 FeedbackVectorSlot AddKeyedLoadICSlot() { |
| 57 return AddSlot(FeedbackVectorSlotKind::KEYED_LOAD_IC); |
| 58 } |
| 59 |
| 60 FeedbackVectorSlot AddStoreICSlot() { |
| 61 return AddSlot(FeedbackVectorSlotKind::STORE_IC); |
| 62 } |
| 63 |
| 64 FeedbackVectorSlot AddKeyedStoreICSlot() { |
| 65 return AddSlot(FeedbackVectorSlotKind::KEYED_STORE_IC); |
| 66 } |
| 67 |
| 68 FeedbackVectorSlot AddGeneralSlot() { |
| 69 return AddSlot(FeedbackVectorSlotKind::GENERAL); |
| 70 } |
| 71 }; |
| 72 |
| 73 |
| 74 class StaticFeedbackVectorSpec |
| 75 : public FeedbackVectorSpecBase<StaticFeedbackVectorSpec> { |
| 76 public: |
| 77 StaticFeedbackVectorSpec() : slots_(0) {} |
42 | 78 |
43 int slots() const { return slots_; } | 79 int slots() const { return slots_; } |
44 | 80 |
45 int ic_slots() const { return ic_slots_; } | 81 FeedbackVectorSlotKind GetKind(int slot) const { |
46 | 82 DCHECK(slot >= 0 && slot < slots_); |
47 FeedbackVectorSlotKind GetKind(int ic_slot) const { | 83 return kinds_[slot]; |
48 DCHECK(ic_slots_ > 0 && ic_slot < ic_slots_); | |
49 return ic_kinds_[ic_slot]; | |
50 } | 84 } |
51 | 85 |
52 private: | 86 private: |
| 87 friend class FeedbackVectorSpecBase<StaticFeedbackVectorSpec>; |
| 88 |
| 89 void append(FeedbackVectorSlotKind kind) { |
| 90 DCHECK(slots_ < kMaxLength); |
| 91 kinds_[slots_++] = kind; |
| 92 } |
| 93 |
| 94 static const int kMaxLength = 12; |
| 95 |
53 int slots_; | 96 int slots_; |
54 int ic_slots_; | 97 FeedbackVectorSlotKind kinds_[kMaxLength]; |
55 FeedbackVectorSlotKind* ic_kinds_; | |
56 }; | 98 }; |
57 | 99 |
58 | 100 |
59 class FeedbackVectorSpec { | 101 class FeedbackVectorSpec : public FeedbackVectorSpecBase<FeedbackVectorSpec> { |
60 public: | 102 public: |
61 explicit FeedbackVectorSpec(Zone* zone) | 103 explicit FeedbackVectorSpec(Zone* zone) : slot_kinds_(zone) { |
62 : slots_(0), ic_slots_(0), ic_slot_kinds_(zone) {} | 104 slot_kinds_.reserve(16); |
63 | |
64 int slots() const { return slots_; } | |
65 void increase_slots(int count) { | |
66 DCHECK_LT(0, count); | |
67 slots_ += count; | |
68 } | 105 } |
69 | 106 |
70 int ic_slots() const { return ic_slots_; } | 107 int slots() const { return static_cast<int>(slot_kinds_.size()); } |
71 void increase_ic_slots(int count) { | |
72 DCHECK_LT(0, count); | |
73 ic_slots_ += count; | |
74 ic_slot_kinds_.resize(ic_slots_); | |
75 } | |
76 | 108 |
77 FeedbackVectorICSlot AddSlot(FeedbackVectorSlotKind kind) { | 109 FeedbackVectorSlotKind GetKind(int slot) const { |
78 int slot = ic_slots_; | 110 return static_cast<FeedbackVectorSlotKind>(slot_kinds_.at(slot)); |
79 increase_ic_slots(1); | |
80 ic_slot_kinds_[slot] = static_cast<unsigned char>(kind); | |
81 return FeedbackVectorICSlot(slot); | |
82 } | |
83 | |
84 FeedbackVectorICSlot AddSlots(FeedbackVectorSlotKind kind, int count) { | |
85 int slot = ic_slots_; | |
86 increase_ic_slots(count); | |
87 for (int i = 0; i < count; i++) { | |
88 ic_slot_kinds_[slot + i] = static_cast<unsigned char>(kind); | |
89 } | |
90 return FeedbackVectorICSlot(slot); | |
91 } | |
92 | |
93 FeedbackVectorICSlot AddCallICSlot() { | |
94 return AddSlot(FeedbackVectorSlotKind::CALL_IC); | |
95 } | |
96 | |
97 FeedbackVectorICSlot AddLoadICSlot() { | |
98 return AddSlot(FeedbackVectorSlotKind::LOAD_IC); | |
99 } | |
100 | |
101 FeedbackVectorICSlot AddLoadICSlots(int count) { | |
102 return AddSlots(FeedbackVectorSlotKind::LOAD_IC, count); | |
103 } | |
104 | |
105 FeedbackVectorICSlot AddKeyedLoadICSlot() { | |
106 return AddSlot(FeedbackVectorSlotKind::KEYED_LOAD_IC); | |
107 } | |
108 | |
109 FeedbackVectorICSlot AddStoreICSlot() { | |
110 return AddSlot(FeedbackVectorSlotKind::STORE_IC); | |
111 } | |
112 | |
113 FeedbackVectorSlot AddStubSlot() { | |
114 int slot = slots_; | |
115 increase_slots(1); | |
116 return FeedbackVectorSlot(slot); | |
117 } | |
118 | |
119 FeedbackVectorSlot AddStubSlots(int count) { | |
120 int slot = slots_; | |
121 increase_slots(count); | |
122 return FeedbackVectorSlot(slot); | |
123 } | |
124 | |
125 FeedbackVectorSlotKind GetKind(int ic_slot) const { | |
126 return static_cast<FeedbackVectorSlotKind>(ic_slot_kinds_.at(ic_slot)); | |
127 } | 111 } |
128 | 112 |
129 private: | 113 private: |
130 int slots_; | 114 friend class FeedbackVectorSpecBase<FeedbackVectorSpec>; |
131 int ic_slots_; | 115 |
132 ZoneVector<unsigned char> ic_slot_kinds_; | 116 void append(FeedbackVectorSlotKind kind) { |
| 117 slot_kinds_.push_back(static_cast<unsigned char>(kind)); |
| 118 } |
| 119 |
| 120 ZoneVector<unsigned char> slot_kinds_; |
133 }; | 121 }; |
134 | 122 |
135 | 123 |
136 // The shape of the TypeFeedbackVector is an array with: | 124 // The shape of the TypeFeedbackVector is an array with: |
137 // 0: first_ic_slot_index (== length() if no ic slots are present) | 125 // 0: slot_count |
138 // 1: ics_with_types | 126 // 1: ics_with_types |
139 // 2: ics_with_generic_info | 127 // 2: ics_with_generic_info |
140 // 3: type information for ic slots, if any | 128 // 3: slots metadata (a bit vector of slot kinds) |
141 // ... | 129 // ... |
142 // N: first feedback slot (N >= 3) | 130 // N: feedback slot #0 (N >= 3) |
143 // ... | 131 // ... |
144 // [<first_ic_slot_index>: feedback slot] | 132 // N + slot_count - 1: feedback slot #(slot_count-1) |
145 // ...to length() - 1 | |
146 // | 133 // |
147 class TypeFeedbackVector : public FixedArray { | 134 class TypeFeedbackVector : public FixedArray { |
148 public: | 135 public: |
149 // Casting. | 136 // Casting. |
150 static inline TypeFeedbackVector* cast(Object* obj); | 137 static inline TypeFeedbackVector* cast(Object* obj); |
151 | 138 |
152 static const int kReservedIndexCount = 3; | 139 static const int kSlotsCountIndex = 0; |
153 static const int kFirstICSlotIndex = 0; | |
154 static const int kWithTypesIndex = 1; | 140 static const int kWithTypesIndex = 1; |
155 static const int kGenericCountIndex = 2; | 141 static const int kGenericCountIndex = 2; |
| 142 static const int kReservedIndexCount = 3; |
156 | 143 |
157 static int elements_per_ic_slot() { return 2; } | 144 // Returns number of feedback vector elements used by given slot kind. |
| 145 static inline int GetSlotSize(FeedbackVectorSlotKind kind); |
158 | 146 |
159 inline int first_ic_slot_index() const; | |
160 inline int ic_with_type_info_count(); | 147 inline int ic_with_type_info_count(); |
161 inline void change_ic_with_type_info_count(int delta); | 148 inline void change_ic_with_type_info_count(int delta); |
162 inline int ic_generic_count(); | 149 inline int ic_generic_count(); |
163 inline void change_ic_generic_count(int delta); | 150 inline void change_ic_generic_count(int delta); |
164 inline int ic_metadata_length() const; | 151 inline int ic_metadata_length() const; |
165 | 152 |
166 bool SpecDiffersFrom(const FeedbackVectorSpec* other_spec) const; | 153 bool SpecDiffersFrom(const FeedbackVectorSpec* other_spec) const; |
167 | 154 |
| 155 inline bool is_empty() const; |
| 156 |
| 157 // Returns number of slots in the vector. |
168 inline int Slots() const; | 158 inline int Slots() const; |
169 inline int ICSlots() const; | |
170 | 159 |
171 // Conversion from a slot or ic slot to an integer index to the underlying | 160 // Conversion from a slot to an integer index to the underlying array. |
172 // array. | |
173 inline int GetIndex(FeedbackVectorSlot slot) const; | 161 inline int GetIndex(FeedbackVectorSlot slot) const; |
174 inline int GetIndex(FeedbackVectorICSlot slot) const; | 162 static int GetIndexFromSpec(const FeedbackVectorSpec* spec, |
| 163 FeedbackVectorSlot slot); |
175 | 164 |
176 template <typename Spec> | 165 // Conversion from an integer index to the underlying array to a slot. |
177 static int GetIndexFromSpec(const Spec* spec, FeedbackVectorSlot slot); | |
178 template <typename Spec> | |
179 static int GetIndexFromSpec(const Spec* spec, FeedbackVectorICSlot slot); | |
180 | |
181 // Conversion from an integer index to either a slot or an ic slot. The caller | |
182 // should know what kind she expects. | |
183 inline FeedbackVectorSlot ToSlot(int index) const; | 166 inline FeedbackVectorSlot ToSlot(int index) const; |
184 inline FeedbackVectorICSlot ToICSlot(int index) const; | |
185 inline Object* Get(FeedbackVectorSlot slot) const; | 167 inline Object* Get(FeedbackVectorSlot slot) const; |
186 inline void Set(FeedbackVectorSlot slot, Object* value, | 168 inline void Set(FeedbackVectorSlot slot, Object* value, |
187 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); | 169 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); |
188 inline Object* Get(FeedbackVectorICSlot slot) const; | |
189 inline void Set(FeedbackVectorICSlot slot, Object* value, | |
190 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); | |
191 | 170 |
192 // IC slots need metadata to recognize the type of IC. | 171 // Returns slot kind for given slot. |
193 FeedbackVectorSlotKind GetKind(FeedbackVectorICSlot slot) const; | 172 FeedbackVectorSlotKind GetKind(FeedbackVectorSlot slot) const; |
194 | 173 |
195 template <typename Spec> | 174 template <typename Spec> |
196 static Handle<TypeFeedbackVector> Allocate(Isolate* isolate, | 175 static Handle<TypeFeedbackVector> New(Isolate* isolate, const Spec* spec); |
197 const Spec* spec); | |
198 | 176 |
199 static Handle<TypeFeedbackVector> Copy(Isolate* isolate, | 177 static Handle<TypeFeedbackVector> Copy(Isolate* isolate, |
200 Handle<TypeFeedbackVector> vector); | 178 Handle<TypeFeedbackVector> vector); |
201 | 179 |
202 #ifdef OBJECT_PRINT | 180 #ifdef OBJECT_PRINT |
203 // For gdb debugging. | 181 // For gdb debugging. |
204 void Print(); | 182 void Print(); |
205 #endif // OBJECT_PRINT | 183 #endif // OBJECT_PRINT |
206 | 184 |
207 DECLARE_PRINTER(TypeFeedbackVector) | 185 DECLARE_PRINTER(TypeFeedbackVector) |
208 | 186 |
209 // Clears the vector slots and the vector ic slots. | 187 // Clears the vector slots. |
210 void ClearSlots(SharedFunctionInfo* shared) { ClearSlotsImpl(shared, true); } | 188 void ClearSlots(SharedFunctionInfo* shared) { ClearSlotsImpl(shared, true); } |
| 189 |
211 void ClearSlotsAtGCTime(SharedFunctionInfo* shared) { | 190 void ClearSlotsAtGCTime(SharedFunctionInfo* shared) { |
212 ClearSlotsImpl(shared, false); | 191 ClearSlotsImpl(shared, false); |
213 } | 192 } |
214 | 193 |
215 void ClearICSlots(SharedFunctionInfo* shared) { | |
216 ClearICSlotsImpl(shared, true); | |
217 } | |
218 void ClearICSlotsAtGCTime(SharedFunctionInfo* shared) { | |
219 ClearICSlotsImpl(shared, false); | |
220 } | |
221 | |
222 static void ClearAllKeyedStoreICs(Isolate* isolate); | 194 static void ClearAllKeyedStoreICs(Isolate* isolate); |
223 void ClearKeyedStoreICs(SharedFunctionInfo* shared); | 195 void ClearKeyedStoreICs(SharedFunctionInfo* shared); |
224 | 196 |
225 // The object that indicates an uninitialized cache. | 197 // The object that indicates an uninitialized cache. |
226 static inline Handle<Object> UninitializedSentinel(Isolate* isolate); | 198 static inline Handle<Object> UninitializedSentinel(Isolate* isolate); |
227 | 199 |
228 // The object that indicates a megamorphic state. | 200 // The object that indicates a megamorphic state. |
229 static inline Handle<Object> MegamorphicSentinel(Isolate* isolate); | 201 static inline Handle<Object> MegamorphicSentinel(Isolate* isolate); |
230 | 202 |
231 // The object that indicates a premonomorphic state. | 203 // The object that indicates a premonomorphic state. |
232 static inline Handle<Object> PremonomorphicSentinel(Isolate* isolate); | 204 static inline Handle<Object> PremonomorphicSentinel(Isolate* isolate); |
233 | 205 |
234 // A raw version of the uninitialized sentinel that's safe to read during | 206 // A raw version of the uninitialized sentinel that's safe to read during |
235 // garbage collection (e.g., for patching the cache). | 207 // garbage collection (e.g., for patching the cache). |
236 static inline Object* RawUninitializedSentinel(Heap* heap); | 208 static inline Object* RawUninitializedSentinel(Isolate* isolate); |
237 | 209 |
238 static const int kDummyLoadICSlot = 0; | 210 static const int kDummyLoadICSlot = 0; |
239 static const int kDummyKeyedLoadICSlot = 1; | 211 static const int kDummyKeyedLoadICSlot = 2; |
240 static const int kDummyStoreICSlot = 2; | 212 static const int kDummyStoreICSlot = 4; |
241 static const int kDummyKeyedStoreICSlot = 3; | 213 static const int kDummyKeyedStoreICSlot = 6; |
242 | 214 |
243 static Handle<TypeFeedbackVector> DummyVector(Isolate* isolate); | 215 static Handle<TypeFeedbackVector> DummyVector(Isolate* isolate); |
244 static FeedbackVectorICSlot DummySlot(int dummyIndex) { | 216 static FeedbackVectorSlot DummySlot(int dummyIndex) { |
245 DCHECK(dummyIndex >= 0 && dummyIndex <= kDummyKeyedStoreICSlot); | 217 DCHECK(dummyIndex >= 0 && dummyIndex <= kDummyKeyedStoreICSlot); |
246 return FeedbackVectorICSlot(dummyIndex); | 218 return FeedbackVectorSlot(dummyIndex); |
247 } | 219 } |
248 | 220 |
249 static int PushAppliedArgumentsIndex(); | 221 static int PushAppliedArgumentsIndex(); |
250 static Handle<TypeFeedbackVector> CreatePushAppliedArgumentsVector( | 222 static Handle<TypeFeedbackVector> CreatePushAppliedArgumentsVector( |
251 Isolate* isolate); | 223 Isolate* isolate); |
252 | 224 |
253 static const char* Kind2String(FeedbackVectorSlotKind kind); | 225 static const char* Kind2String(FeedbackVectorSlotKind kind); |
254 | 226 |
255 private: | 227 private: |
256 static const int kFeedbackVectorSlotKindBits = 3; | 228 static const int kFeedbackVectorSlotKindBits = 3; |
257 STATIC_ASSERT(static_cast<int>(FeedbackVectorSlotKind::KINDS_NUMBER) < | 229 STATIC_ASSERT(static_cast<int>(FeedbackVectorSlotKind::KINDS_NUMBER) < |
258 (1 << kFeedbackVectorSlotKindBits)); | 230 (1 << kFeedbackVectorSlotKindBits)); |
259 | 231 |
260 void SetKind(FeedbackVectorICSlot slot, FeedbackVectorSlotKind kind); | 232 void SetKind(FeedbackVectorSlot slot, FeedbackVectorSlotKind kind); |
261 | 233 |
262 typedef BitSetComputer<FeedbackVectorSlotKind, kFeedbackVectorSlotKindBits, | 234 typedef BitSetComputer<FeedbackVectorSlotKind, kFeedbackVectorSlotKindBits, |
263 kSmiValueSize, uint32_t> VectorICComputer; | 235 kSmiValueSize, uint32_t> VectorICComputer; |
264 | 236 |
265 void ClearSlotsImpl(SharedFunctionInfo* shared, bool force_clear); | 237 void ClearSlotsImpl(SharedFunctionInfo* shared, bool force_clear); |
266 void ClearICSlotsImpl(SharedFunctionInfo* shared, bool force_clear); | |
267 | 238 |
268 DISALLOW_IMPLICIT_CONSTRUCTORS(TypeFeedbackVector); | 239 DISALLOW_IMPLICIT_CONSTRUCTORS(TypeFeedbackVector); |
269 }; | 240 }; |
270 | 241 |
271 | 242 |
272 // The following asserts protect an optimization in type feedback vector | 243 // The following asserts protect an optimization in type feedback vector |
273 // code that looks into the contents of a slot assuming to find a String, | 244 // code that looks into the contents of a slot assuming to find a String, |
274 // a Symbol, an AllocationSite, a WeakCell, or a FixedArray. | 245 // a Symbol, an AllocationSite, a WeakCell, or a FixedArray. |
275 STATIC_ASSERT(WeakCell::kSize >= 2 * kPointerSize); | 246 STATIC_ASSERT(WeakCell::kSize >= 2 * kPointerSize); |
276 STATIC_ASSERT(WeakCell::kValueOffset == AllocationSite::kTransitionInfoOffset); | 247 STATIC_ASSERT(WeakCell::kValueOffset == AllocationSite::kTransitionInfoOffset); |
277 STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset); | 248 STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset); |
278 STATIC_ASSERT(WeakCell::kValueOffset == Name::kHashFieldSlot); | 249 STATIC_ASSERT(WeakCell::kValueOffset == Name::kHashFieldSlot); |
279 // Verify that an empty hash field looks like a tagged object, but can't | 250 // Verify that an empty hash field looks like a tagged object, but can't |
280 // possibly be confused with a pointer. | 251 // possibly be confused with a pointer. |
281 STATIC_ASSERT((Name::kEmptyHashField & kHeapObjectTag) == kHeapObjectTag); | 252 STATIC_ASSERT((Name::kEmptyHashField & kHeapObjectTag) == kHeapObjectTag); |
282 STATIC_ASSERT(Name::kEmptyHashField == 0x3); | 253 STATIC_ASSERT(Name::kEmptyHashField == 0x3); |
283 // Verify that a set hash field will not look like a tagged object. | 254 // Verify that a set hash field will not look like a tagged object. |
284 STATIC_ASSERT(Name::kHashNotComputedMask == kHeapObjectTag); | 255 STATIC_ASSERT(Name::kHashNotComputedMask == kHeapObjectTag); |
285 | 256 |
286 | 257 |
| 258 class TypeFeedbackMetadataIterator { |
| 259 public: |
| 260 explicit TypeFeedbackMetadataIterator(Handle<TypeFeedbackVector> metadata) |
| 261 : metadata_handle_(metadata), |
| 262 slot_(FeedbackVectorSlot(0)), |
| 263 slot_kind_(FeedbackVectorSlotKind::INVALID) {} |
| 264 |
| 265 explicit TypeFeedbackMetadataIterator(TypeFeedbackVector* metadata) |
| 266 : metadata_(metadata), |
| 267 slot_(FeedbackVectorSlot(0)), |
| 268 slot_kind_(FeedbackVectorSlotKind::INVALID) {} |
| 269 |
| 270 bool HasNext() const { return slot_.ToInt() < metadata()->Slots(); } |
| 271 |
| 272 FeedbackVectorSlot Next() { |
| 273 DCHECK(HasNext()); |
| 274 FeedbackVectorSlot slot = slot_; |
| 275 slot_kind_ = metadata()->GetKind(slot); |
| 276 slot_ = FeedbackVectorSlot(slot_.ToInt() + entry_size()); |
| 277 return slot; |
| 278 } |
| 279 |
| 280 // Returns slot kind of the last slot returned by Next(). |
| 281 FeedbackVectorSlotKind kind() const { |
| 282 DCHECK_NE(FeedbackVectorSlotKind::INVALID, slot_kind_); |
| 283 DCHECK_NE(FeedbackVectorSlotKind::KINDS_NUMBER, slot_kind_); |
| 284 return slot_kind_; |
| 285 } |
| 286 |
| 287 // Returns entry size of the last slot returned by Next(). |
| 288 int entry_size() const { return TypeFeedbackVector::GetSlotSize(kind()); } |
| 289 |
| 290 private: |
| 291 TypeFeedbackVector* metadata() const { |
| 292 return !metadata_handle_.is_null() ? *metadata_handle_ : metadata_; |
| 293 } |
| 294 |
| 295 // The reason for having a handle and a raw pointer to the meta data is |
| 296 // to have a single iterator implementation for both "handlified" and raw |
| 297 // pointer use cases. |
| 298 Handle<TypeFeedbackVector> metadata_handle_; |
| 299 TypeFeedbackVector* metadata_; |
| 300 FeedbackVectorSlot slot_; |
| 301 FeedbackVectorSlotKind slot_kind_; |
| 302 }; |
| 303 |
| 304 |
287 // A FeedbackNexus is the combination of a TypeFeedbackVector and a slot. | 305 // A FeedbackNexus is the combination of a TypeFeedbackVector and a slot. |
288 // Derived classes customize the update and retrieval of feedback. | 306 // Derived classes customize the update and retrieval of feedback. |
289 class FeedbackNexus { | 307 class FeedbackNexus { |
290 public: | 308 public: |
291 FeedbackNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorICSlot slot) | 309 FeedbackNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot) |
292 : vector_handle_(vector), vector_(NULL), slot_(slot) {} | 310 : vector_handle_(vector), vector_(NULL), slot_(slot) {} |
293 FeedbackNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot) | 311 FeedbackNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot) |
294 : vector_(vector), slot_(slot) {} | 312 : vector_(vector), slot_(slot) {} |
295 virtual ~FeedbackNexus() {} | 313 virtual ~FeedbackNexus() {} |
296 | 314 |
297 Handle<TypeFeedbackVector> vector_handle() const { | 315 Handle<TypeFeedbackVector> vector_handle() const { |
298 DCHECK(vector_ == NULL); | 316 DCHECK(vector_ == NULL); |
299 return vector_handle_; | 317 return vector_handle_; |
300 } | 318 } |
301 TypeFeedbackVector* vector() const { | 319 TypeFeedbackVector* vector() const { |
302 return vector_handle_.is_null() ? vector_ : *vector_handle_; | 320 return vector_handle_.is_null() ? vector_ : *vector_handle_; |
303 } | 321 } |
304 FeedbackVectorICSlot slot() const { return slot_; } | 322 FeedbackVectorSlot slot() const { return slot_; } |
305 | 323 |
306 InlineCacheState ic_state() const { return StateFromFeedback(); } | 324 InlineCacheState ic_state() const { return StateFromFeedback(); } |
307 Map* FindFirstMap() const { | 325 Map* FindFirstMap() const { |
308 MapHandleList maps; | 326 MapHandleList maps; |
309 ExtractMaps(&maps); | 327 ExtractMaps(&maps); |
310 if (maps.length() > 0) return *maps.at(0); | 328 if (maps.length() > 0) return *maps.at(0); |
311 return NULL; | 329 return NULL; |
312 } | 330 } |
313 | 331 |
314 // TODO(mvstanton): remove FindAllMaps, it didn't survive a code review. | 332 // TODO(mvstanton): remove FindAllMaps, it didn't survive a code review. |
(...skipping 25 matching lines...) Expand all Loading... |
340 void InstallHandlers(Handle<FixedArray> array, MapHandleList* maps, | 358 void InstallHandlers(Handle<FixedArray> array, MapHandleList* maps, |
341 CodeHandleList* handlers); | 359 CodeHandleList* handlers); |
342 | 360 |
343 private: | 361 private: |
344 // The reason for having a vector handle and a raw pointer is that we can and | 362 // The reason for having a vector handle and a raw pointer is that we can and |
345 // should use handles during IC miss, but not during GC when we clear ICs. If | 363 // should use handles during IC miss, but not during GC when we clear ICs. If |
346 // you have a handle to the vector that is better because more operations can | 364 // you have a handle to the vector that is better because more operations can |
347 // be done, like allocation. | 365 // be done, like allocation. |
348 Handle<TypeFeedbackVector> vector_handle_; | 366 Handle<TypeFeedbackVector> vector_handle_; |
349 TypeFeedbackVector* vector_; | 367 TypeFeedbackVector* vector_; |
350 FeedbackVectorICSlot slot_; | 368 FeedbackVectorSlot slot_; |
351 }; | 369 }; |
352 | 370 |
353 | 371 |
354 class CallICNexus : public FeedbackNexus { | 372 class CallICNexus : public FeedbackNexus { |
355 public: | 373 public: |
356 // Monomorphic call ics store call counts. Platform code needs to increment | 374 // Monomorphic call ics store call counts. Platform code needs to increment |
357 // the count appropriately (ie, by 2). | 375 // the count appropriately (ie, by 2). |
358 static const int kCallCountIncrement = 2; | 376 static const int kCallCountIncrement = 2; |
359 | 377 |
360 CallICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorICSlot slot) | 378 CallICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot) |
361 : FeedbackNexus(vector, slot) { | 379 : FeedbackNexus(vector, slot) { |
362 DCHECK_EQ(FeedbackVectorSlotKind::CALL_IC, vector->GetKind(slot)); | 380 DCHECK_EQ(FeedbackVectorSlotKind::CALL_IC, vector->GetKind(slot)); |
363 } | 381 } |
364 CallICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot) | 382 CallICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot) |
365 : FeedbackNexus(vector, slot) { | 383 : FeedbackNexus(vector, slot) { |
366 DCHECK_EQ(FeedbackVectorSlotKind::CALL_IC, vector->GetKind(slot)); | 384 DCHECK_EQ(FeedbackVectorSlotKind::CALL_IC, vector->GetKind(slot)); |
367 } | 385 } |
368 | 386 |
369 void Clear(Code* host); | 387 void Clear(Code* host); |
370 | 388 |
371 void ConfigureMonomorphicArray(); | 389 void ConfigureMonomorphicArray(); |
372 void ConfigureMonomorphic(Handle<JSFunction> function); | 390 void ConfigureMonomorphic(Handle<JSFunction> function); |
373 | 391 |
374 InlineCacheState StateFromFeedback() const override; | 392 InlineCacheState StateFromFeedback() const override; |
375 | 393 |
376 int ExtractMaps(MapHandleList* maps) const override { | 394 int ExtractMaps(MapHandleList* maps) const override { |
377 // CallICs don't record map feedback. | 395 // CallICs don't record map feedback. |
378 return 0; | 396 return 0; |
379 } | 397 } |
380 MaybeHandle<Code> FindHandlerForMap(Handle<Map> map) const override { | 398 MaybeHandle<Code> FindHandlerForMap(Handle<Map> map) const override { |
381 return MaybeHandle<Code>(); | 399 return MaybeHandle<Code>(); |
382 } | 400 } |
383 bool FindHandlers(CodeHandleList* code_list, int length = -1) const override { | 401 bool FindHandlers(CodeHandleList* code_list, int length = -1) const override { |
384 return length == 0; | 402 return length == 0; |
385 } | 403 } |
386 | 404 |
387 int ExtractCallCount(); | 405 int ExtractCallCount(); |
388 }; | 406 }; |
389 | 407 |
390 | 408 |
391 class LoadICNexus : public FeedbackNexus { | 409 class LoadICNexus : public FeedbackNexus { |
392 public: | 410 public: |
393 LoadICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorICSlot slot) | 411 LoadICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot) |
394 : FeedbackNexus(vector, slot) { | 412 : FeedbackNexus(vector, slot) { |
395 DCHECK_EQ(FeedbackVectorSlotKind::LOAD_IC, vector->GetKind(slot)); | 413 DCHECK_EQ(FeedbackVectorSlotKind::LOAD_IC, vector->GetKind(slot)); |
396 } | 414 } |
397 explicit LoadICNexus(Isolate* isolate) | 415 explicit LoadICNexus(Isolate* isolate) |
398 : FeedbackNexus(TypeFeedbackVector::DummyVector(isolate), | 416 : FeedbackNexus( |
399 TypeFeedbackVector::DummySlot( | 417 TypeFeedbackVector::DummyVector(isolate), |
400 TypeFeedbackVector::kDummyLoadICSlot)) {} | 418 FeedbackVectorSlot(TypeFeedbackVector::kDummyLoadICSlot)) {} |
401 LoadICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot) | 419 LoadICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot) |
402 : FeedbackNexus(vector, slot) { | 420 : FeedbackNexus(vector, slot) { |
403 DCHECK_EQ(FeedbackVectorSlotKind::LOAD_IC, vector->GetKind(slot)); | 421 DCHECK_EQ(FeedbackVectorSlotKind::LOAD_IC, vector->GetKind(slot)); |
404 } | 422 } |
405 | 423 |
406 void Clear(Code* host); | 424 void Clear(Code* host); |
407 | 425 |
408 void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Code> handler); | 426 void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Code> handler); |
409 | 427 |
410 void ConfigurePolymorphic(MapHandleList* maps, CodeHandleList* handlers); | 428 void ConfigurePolymorphic(MapHandleList* maps, CodeHandleList* handlers); |
411 | 429 |
412 InlineCacheState StateFromFeedback() const override; | 430 InlineCacheState StateFromFeedback() const override; |
413 }; | 431 }; |
414 | 432 |
415 | 433 |
416 class KeyedLoadICNexus : public FeedbackNexus { | 434 class KeyedLoadICNexus : public FeedbackNexus { |
417 public: | 435 public: |
418 KeyedLoadICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorICSlot slot) | 436 KeyedLoadICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot) |
419 : FeedbackNexus(vector, slot) { | 437 : FeedbackNexus(vector, slot) { |
420 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector->GetKind(slot)); | 438 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector->GetKind(slot)); |
421 } | 439 } |
422 KeyedLoadICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot) | 440 KeyedLoadICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot) |
423 : FeedbackNexus(vector, slot) { | 441 : FeedbackNexus(vector, slot) { |
424 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector->GetKind(slot)); | 442 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector->GetKind(slot)); |
425 } | 443 } |
426 | 444 |
427 void Clear(Code* host); | 445 void Clear(Code* host); |
428 | 446 |
429 // name can be a null handle for element loads. | 447 // name can be a null handle for element loads. |
430 void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map, | 448 void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map, |
431 Handle<Code> handler); | 449 Handle<Code> handler); |
432 // name can be null. | 450 // name can be null. |
433 void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps, | 451 void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps, |
434 CodeHandleList* handlers); | 452 CodeHandleList* handlers); |
435 | 453 |
436 InlineCacheState StateFromFeedback() const override; | 454 InlineCacheState StateFromFeedback() const override; |
437 Name* FindFirstName() const override; | 455 Name* FindFirstName() const override; |
438 }; | 456 }; |
439 | 457 |
440 | 458 |
441 class StoreICNexus : public FeedbackNexus { | 459 class StoreICNexus : public FeedbackNexus { |
442 public: | 460 public: |
443 StoreICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorICSlot slot) | 461 StoreICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot) |
444 : FeedbackNexus(vector, slot) { | 462 : FeedbackNexus(vector, slot) { |
445 DCHECK_EQ(FeedbackVectorSlotKind::STORE_IC, vector->GetKind(slot)); | 463 DCHECK_EQ(FeedbackVectorSlotKind::STORE_IC, vector->GetKind(slot)); |
446 } | 464 } |
447 explicit StoreICNexus(Isolate* isolate) | 465 explicit StoreICNexus(Isolate* isolate) |
448 : FeedbackNexus(TypeFeedbackVector::DummyVector(isolate), | 466 : FeedbackNexus( |
449 TypeFeedbackVector::DummySlot( | 467 TypeFeedbackVector::DummyVector(isolate), |
450 TypeFeedbackVector::kDummyStoreICSlot)) {} | 468 FeedbackVectorSlot(TypeFeedbackVector::kDummyStoreICSlot)) {} |
451 StoreICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot) | 469 StoreICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot) |
452 : FeedbackNexus(vector, slot) { | 470 : FeedbackNexus(vector, slot) { |
453 DCHECK_EQ(FeedbackVectorSlotKind::STORE_IC, vector->GetKind(slot)); | 471 DCHECK_EQ(FeedbackVectorSlotKind::STORE_IC, vector->GetKind(slot)); |
454 } | 472 } |
455 | 473 |
456 void Clear(Code* host); | 474 void Clear(Code* host); |
457 | 475 |
458 void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Code> handler); | 476 void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Code> handler); |
459 | 477 |
460 void ConfigurePolymorphic(MapHandleList* maps, CodeHandleList* handlers); | 478 void ConfigurePolymorphic(MapHandleList* maps, CodeHandleList* handlers); |
461 | 479 |
462 InlineCacheState StateFromFeedback() const override; | 480 InlineCacheState StateFromFeedback() const override; |
463 }; | 481 }; |
464 | 482 |
465 | 483 |
466 class KeyedStoreICNexus : public FeedbackNexus { | 484 class KeyedStoreICNexus : public FeedbackNexus { |
467 public: | 485 public: |
468 KeyedStoreICNexus(Handle<TypeFeedbackVector> vector, | 486 KeyedStoreICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot) |
469 FeedbackVectorICSlot slot) | |
470 : FeedbackNexus(vector, slot) { | 487 : FeedbackNexus(vector, slot) { |
471 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, vector->GetKind(slot)); | 488 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, vector->GetKind(slot)); |
472 } | 489 } |
473 explicit KeyedStoreICNexus(Isolate* isolate) | 490 explicit KeyedStoreICNexus(Isolate* isolate) |
474 : FeedbackNexus(TypeFeedbackVector::DummyVector(isolate), | 491 : FeedbackNexus( |
475 TypeFeedbackVector::DummySlot( | 492 TypeFeedbackVector::DummyVector(isolate), |
476 TypeFeedbackVector::kDummyKeyedStoreICSlot)) {} | 493 FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedStoreICSlot)) {} |
477 KeyedStoreICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot) | 494 KeyedStoreICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot) |
478 : FeedbackNexus(vector, slot) { | 495 : FeedbackNexus(vector, slot) { |
479 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, vector->GetKind(slot)); | 496 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, vector->GetKind(slot)); |
480 } | 497 } |
481 | 498 |
482 void Clear(Code* host); | 499 void Clear(Code* host); |
483 | 500 |
484 // name can be a null handle for element loads. | 501 // name can be a null handle for element loads. |
485 void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map, | 502 void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map, |
486 Handle<Code> handler); | 503 Handle<Code> handler); |
487 // name can be null. | 504 // name can be null. |
488 void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps, | 505 void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps, |
489 CodeHandleList* handlers); | 506 CodeHandleList* handlers); |
490 void ConfigurePolymorphic(MapHandleList* maps, | 507 void ConfigurePolymorphic(MapHandleList* maps, |
491 MapHandleList* transitioned_maps, | 508 MapHandleList* transitioned_maps, |
492 CodeHandleList* handlers); | 509 CodeHandleList* handlers); |
493 | 510 |
494 KeyedAccessStoreMode GetKeyedAccessStoreMode() const; | 511 KeyedAccessStoreMode GetKeyedAccessStoreMode() const; |
495 IcCheckType GetKeyType() const; | 512 IcCheckType GetKeyType() const; |
496 | 513 |
497 InlineCacheState StateFromFeedback() const override; | 514 InlineCacheState StateFromFeedback() const override; |
498 Name* FindFirstName() const override; | 515 Name* FindFirstName() const override; |
499 }; | 516 }; |
500 } // namespace internal | 517 } // namespace internal |
501 } // namespace v8 | 518 } // namespace v8 |
502 | 519 |
503 #endif // V8_TRANSITIONS_H_ | 520 #endif // V8_TRANSITIONS_H_ |
OLD | NEW |