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" |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 static TypeFeedbackVector* cast(Object* obj) { | 67 static TypeFeedbackVector* cast(Object* obj) { |
68 DCHECK(obj->IsTypeFeedbackVector()); | 68 DCHECK(obj->IsTypeFeedbackVector()); |
69 return reinterpret_cast<TypeFeedbackVector*>(obj); | 69 return reinterpret_cast<TypeFeedbackVector*>(obj); |
70 } | 70 } |
71 | 71 |
72 static const int kReservedIndexCount = 3; | 72 static const int kReservedIndexCount = 3; |
73 static const int kFirstICSlotIndex = 0; | 73 static const int kFirstICSlotIndex = 0; |
74 static const int kWithTypesIndex = 1; | 74 static const int kWithTypesIndex = 1; |
75 static const int kGenericCountIndex = 2; | 75 static const int kGenericCountIndex = 2; |
76 | 76 |
| 77 static int elements_per_ic_slot() { return FLAG_vector_ics ? 2 : 1; } |
| 78 |
77 int first_ic_slot_index() const { | 79 int first_ic_slot_index() const { |
78 DCHECK(length() >= kReservedIndexCount); | 80 DCHECK(length() >= kReservedIndexCount); |
79 return Smi::cast(get(kFirstICSlotIndex))->value(); | 81 return Smi::cast(get(kFirstICSlotIndex))->value(); |
80 } | 82 } |
81 | 83 |
82 int ic_with_type_info_count() { | 84 int ic_with_type_info_count() { |
83 return length() > 0 ? Smi::cast(get(kWithTypesIndex))->value() : 0; | 85 return length() > 0 ? Smi::cast(get(kWithTypesIndex))->value() : 0; |
84 } | 86 } |
85 | 87 |
86 void change_ic_with_type_info_count(int delta) { | 88 void change_ic_with_type_info_count(int delta) { |
(...skipping 20 matching lines...) Expand all Loading... |
107 inline int ic_metadata_length() const; | 109 inline int ic_metadata_length() const; |
108 | 110 |
109 int Slots() const { | 111 int Slots() const { |
110 if (length() == 0) return 0; | 112 if (length() == 0) return 0; |
111 return Max( | 113 return Max( |
112 0, first_ic_slot_index() - ic_metadata_length() - kReservedIndexCount); | 114 0, first_ic_slot_index() - ic_metadata_length() - kReservedIndexCount); |
113 } | 115 } |
114 | 116 |
115 int ICSlots() const { | 117 int ICSlots() const { |
116 if (length() == 0) return 0; | 118 if (length() == 0) return 0; |
117 return length() - first_ic_slot_index(); | 119 return (length() - first_ic_slot_index()) / elements_per_ic_slot(); |
118 } | 120 } |
119 | 121 |
120 // Conversion from a slot or ic slot to an integer index to the underlying | 122 // Conversion from a slot or ic slot to an integer index to the underlying |
121 // array. | 123 // array. |
122 int GetIndex(FeedbackVectorSlot slot) const { | 124 int GetIndex(FeedbackVectorSlot slot) const { |
123 DCHECK(slot.ToInt() < first_ic_slot_index()); | 125 DCHECK(slot.ToInt() < first_ic_slot_index()); |
124 return kReservedIndexCount + ic_metadata_length() + slot.ToInt(); | 126 return kReservedIndexCount + ic_metadata_length() + slot.ToInt(); |
125 } | 127 } |
126 | 128 |
127 int GetIndex(FeedbackVectorICSlot slot) const { | 129 int GetIndex(FeedbackVectorICSlot slot) const { |
128 int first_ic_slot = first_ic_slot_index(); | 130 int first_ic_slot = first_ic_slot_index(); |
129 DCHECK(slot.ToInt() < ICSlots()); | 131 DCHECK(slot.ToInt() < ICSlots()); |
130 return first_ic_slot + slot.ToInt(); | 132 return first_ic_slot + slot.ToInt() * elements_per_ic_slot(); |
131 } | 133 } |
132 | 134 |
133 // Conversion from an integer index to either a slot or an ic slot. The caller | 135 // Conversion from an integer index to either a slot or an ic slot. The caller |
134 // should know what kind she expects. | 136 // should know what kind she expects. |
135 FeedbackVectorSlot ToSlot(int index) const { | 137 FeedbackVectorSlot ToSlot(int index) const { |
136 DCHECK(index >= kReservedIndexCount && index < first_ic_slot_index()); | 138 DCHECK(index >= kReservedIndexCount && index < first_ic_slot_index()); |
137 return FeedbackVectorSlot(index - ic_metadata_length() - | 139 return FeedbackVectorSlot(index - ic_metadata_length() - |
138 kReservedIndexCount); | 140 kReservedIndexCount); |
139 } | 141 } |
140 | 142 |
141 FeedbackVectorICSlot ToICSlot(int index) const { | 143 FeedbackVectorICSlot ToICSlot(int index) const { |
142 DCHECK(index >= first_ic_slot_index() && index < length()); | 144 DCHECK(index >= first_ic_slot_index() && index < length()); |
143 return FeedbackVectorICSlot(index - first_ic_slot_index()); | 145 int ic_slot = (index - first_ic_slot_index()) / elements_per_ic_slot(); |
| 146 return FeedbackVectorICSlot(ic_slot); |
144 } | 147 } |
145 | 148 |
146 Object* Get(FeedbackVectorSlot slot) const { return get(GetIndex(slot)); } | 149 Object* Get(FeedbackVectorSlot slot) const { return get(GetIndex(slot)); } |
147 void Set(FeedbackVectorSlot slot, Object* value, | 150 void Set(FeedbackVectorSlot slot, Object* value, |
148 WriteBarrierMode mode = UPDATE_WRITE_BARRIER) { | 151 WriteBarrierMode mode = UPDATE_WRITE_BARRIER) { |
149 set(GetIndex(slot), value, mode); | 152 set(GetIndex(slot), value, mode); |
150 } | 153 } |
151 | 154 |
152 Object* Get(FeedbackVectorICSlot slot) const { return get(GetIndex(slot)); } | 155 Object* Get(FeedbackVectorICSlot slot) const { return get(GetIndex(slot)); } |
153 void Set(FeedbackVectorICSlot slot, Object* value, | 156 void Set(FeedbackVectorICSlot slot, Object* value, |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 MapHandleList maps; | 240 MapHandleList maps; |
238 ExtractMaps(&maps); | 241 ExtractMaps(&maps); |
239 if (maps.length() > 0) return *maps.at(0); | 242 if (maps.length() > 0) return *maps.at(0); |
240 return NULL; | 243 return NULL; |
241 } | 244 } |
242 | 245 |
243 // TODO(mvstanton): remove FindAllMaps, it didn't survive a code review. | 246 // TODO(mvstanton): remove FindAllMaps, it didn't survive a code review. |
244 void FindAllMaps(MapHandleList* maps) const { ExtractMaps(maps); } | 247 void FindAllMaps(MapHandleList* maps) const { ExtractMaps(maps); } |
245 | 248 |
246 virtual InlineCacheState StateFromFeedback() const = 0; | 249 virtual InlineCacheState StateFromFeedback() const = 0; |
247 virtual int ExtractMaps(MapHandleList* maps) const = 0; | 250 virtual int ExtractMaps(MapHandleList* maps) const; |
248 virtual MaybeHandle<Code> FindHandlerForMap(Handle<Map> map) const = 0; | 251 virtual MaybeHandle<Code> FindHandlerForMap(Handle<Map> map) const; |
249 virtual bool FindHandlers(CodeHandleList* code_list, int length = -1) const { | 252 virtual bool FindHandlers(CodeHandleList* code_list, int length = -1) const; |
250 return length == 0; | |
251 } | |
252 virtual Name* FindFirstName() const { return NULL; } | 253 virtual Name* FindFirstName() const { return NULL; } |
253 | 254 |
254 Object* GetFeedback() const { return vector()->Get(slot()); } | 255 Object* GetFeedback() const { return vector()->Get(slot()); } |
| 256 Object* GetFeedbackExtra() const { |
| 257 DCHECK(TypeFeedbackVector::elements_per_ic_slot() > 1); |
| 258 int extra_index = vector()->GetIndex(slot()) + 1; |
| 259 return vector()->get(extra_index); |
| 260 } |
255 | 261 |
256 protected: | 262 protected: |
257 Isolate* GetIsolate() const { return vector()->GetIsolate(); } | 263 Isolate* GetIsolate() const { return vector()->GetIsolate(); } |
258 | 264 |
259 void SetFeedback(Object* feedback, | 265 void SetFeedback(Object* feedback, |
260 WriteBarrierMode mode = UPDATE_WRITE_BARRIER) { | 266 WriteBarrierMode mode = UPDATE_WRITE_BARRIER) { |
261 vector()->Set(slot(), feedback, mode); | 267 vector()->Set(slot(), feedback, mode); |
262 } | 268 } |
263 | 269 |
| 270 void SetFeedbackExtra(Object* feedback_extra, |
| 271 WriteBarrierMode mode = UPDATE_WRITE_BARRIER) { |
| 272 DCHECK(TypeFeedbackVector::elements_per_ic_slot() > 1); |
| 273 int index = vector()->GetIndex(slot()) + 1; |
| 274 vector()->set(index, feedback_extra, mode); |
| 275 } |
| 276 |
264 Handle<FixedArray> EnsureArrayOfSize(int length); | 277 Handle<FixedArray> EnsureArrayOfSize(int length); |
265 void InstallHandlers(int start_index, MapHandleList* maps, | 278 Handle<FixedArray> EnsureExtraArrayOfSize(int length); |
| 279 void InstallHandlers(Handle<FixedArray> array, MapHandleList* maps, |
266 CodeHandleList* handlers); | 280 CodeHandleList* handlers); |
267 int ExtractMaps(int start_index, MapHandleList* maps) const; | |
268 MaybeHandle<Code> FindHandlerForMap(int start_index, Handle<Map> map) const; | |
269 bool FindHandlers(int start_index, CodeHandleList* code_list, | |
270 int length) const; | |
271 | 281 |
272 private: | 282 private: |
273 // The reason for having a vector handle and a raw pointer is that we can and | 283 // The reason for having a vector handle and a raw pointer is that we can and |
274 // should use handles during IC miss, but not during GC when we clear ICs. If | 284 // should use handles during IC miss, but not during GC when we clear ICs. If |
275 // you have a handle to the vector that is better because more operations can | 285 // you have a handle to the vector that is better because more operations can |
276 // be done, like allocation. | 286 // be done, like allocation. |
277 Handle<TypeFeedbackVector> vector_handle_; | 287 Handle<TypeFeedbackVector> vector_handle_; |
278 TypeFeedbackVector* vector_; | 288 TypeFeedbackVector* vector_; |
279 FeedbackVectorICSlot slot_; | 289 FeedbackVectorICSlot slot_; |
280 }; | 290 }; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 | 337 |
328 void Clear(Code* host); | 338 void Clear(Code* host); |
329 | 339 |
330 void ConfigureMegamorphic(); | 340 void ConfigureMegamorphic(); |
331 void ConfigurePremonomorphic(); | 341 void ConfigurePremonomorphic(); |
332 void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Code> handler); | 342 void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Code> handler); |
333 | 343 |
334 void ConfigurePolymorphic(MapHandleList* maps, CodeHandleList* handlers); | 344 void ConfigurePolymorphic(MapHandleList* maps, CodeHandleList* handlers); |
335 | 345 |
336 InlineCacheState StateFromFeedback() const OVERRIDE; | 346 InlineCacheState StateFromFeedback() const OVERRIDE; |
337 int ExtractMaps(MapHandleList* maps) const OVERRIDE; | |
338 MaybeHandle<Code> FindHandlerForMap(Handle<Map> map) const OVERRIDE; | |
339 virtual bool FindHandlers(CodeHandleList* code_list, | |
340 int length = -1) const OVERRIDE; | |
341 }; | 347 }; |
342 | 348 |
343 | 349 |
344 class KeyedLoadICNexus : public FeedbackNexus { | 350 class KeyedLoadICNexus : public FeedbackNexus { |
345 public: | 351 public: |
346 KeyedLoadICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorICSlot slot) | 352 KeyedLoadICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorICSlot slot) |
347 : FeedbackNexus(vector, slot) { | 353 : FeedbackNexus(vector, slot) { |
348 DCHECK(vector->GetKind(slot) == Code::KEYED_LOAD_IC); | 354 DCHECK(vector->GetKind(slot) == Code::KEYED_LOAD_IC); |
349 } | 355 } |
350 KeyedLoadICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot) | 356 KeyedLoadICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot) |
351 : FeedbackNexus(vector, slot) { | 357 : FeedbackNexus(vector, slot) { |
352 DCHECK(vector->GetKind(slot) == Code::KEYED_LOAD_IC); | 358 DCHECK(vector->GetKind(slot) == Code::KEYED_LOAD_IC); |
353 } | 359 } |
354 | 360 |
355 void Clear(Code* host); | 361 void Clear(Code* host); |
356 | 362 |
357 void ConfigureMegamorphic(); | 363 void ConfigureMegamorphic(); |
358 void ConfigurePremonomorphic(); | 364 void ConfigurePremonomorphic(); |
359 // name can be a null handle for element loads. | 365 // name can be a null handle for element loads. |
360 void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map, | 366 void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map, |
361 Handle<Code> handler); | 367 Handle<Code> handler); |
362 // name can be null. | 368 // name can be null. |
363 void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps, | 369 void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps, |
364 CodeHandleList* handlers); | 370 CodeHandleList* handlers); |
365 | 371 |
366 InlineCacheState StateFromFeedback() const OVERRIDE; | 372 InlineCacheState StateFromFeedback() const OVERRIDE; |
367 int ExtractMaps(MapHandleList* maps) const OVERRIDE; | |
368 MaybeHandle<Code> FindHandlerForMap(Handle<Map> map) const OVERRIDE; | |
369 virtual bool FindHandlers(CodeHandleList* code_list, | |
370 int length = -1) const OVERRIDE; | |
371 Name* FindFirstName() const OVERRIDE; | 373 Name* FindFirstName() const OVERRIDE; |
372 }; | 374 }; |
373 } | 375 } |
374 } // namespace v8::internal | 376 } // namespace v8::internal |
375 | 377 |
376 #endif // V8_TRANSITIONS_H_ | 378 #endif // V8_TRANSITIONS_H_ |
OLD | NEW |