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