Chromium Code Reviews| 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 |