| 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 |