Chromium Code Reviews| Index: src/type-feedback-vector.h |
| diff --git a/src/type-feedback-vector.h b/src/type-feedback-vector.h |
| index 2d394b0ca40e364add2e1e6a13d339e301c6cc3e..c5d1cc17263e09b1a61e1a5327191ea88f0c8096 100644 |
| --- a/src/type-feedback-vector.h |
| +++ b/src/type-feedback-vector.h |
| @@ -19,13 +19,21 @@ namespace internal { |
| enum class FeedbackVectorSlotKind { |
| - UNUSED, |
| + // This kind means that the slot points to the middle of other slot |
| + // which occupies more than one feedback vector element. |
| + // There must be no such slots in the system. |
| + INVALID, |
| + |
| CALL_IC, |
| LOAD_IC, |
| KEYED_LOAD_IC, |
| STORE_IC, |
| KEYED_STORE_IC, |
| + // 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.
|
| + // element. |
| + STUB, |
| + |
| KINDS_NUMBER // Last value indicating number of kinds. |
| }; |
| @@ -35,128 +43,89 @@ std::ostream& operator<<(std::ostream& os, FeedbackVectorSlotKind kind); |
| class StaticFeedbackVectorSpec { |
| public: |
| - StaticFeedbackVectorSpec() : slots_(0), ic_slots_(0), ic_kinds_(NULL) {} |
| - StaticFeedbackVectorSpec(int slots, int ic_slots, |
| - FeedbackVectorSlotKind* ic_slot_kinds) |
| - : slots_(slots), ic_slots_(ic_slots), ic_kinds_(ic_slot_kinds) {} |
| + StaticFeedbackVectorSpec() : slots_(0), kinds_(NULL) {} |
| + StaticFeedbackVectorSpec(int slots, FeedbackVectorSlotKind* slot_kinds) |
| + : slots_(slots), kinds_(slot_kinds) {} |
| int slots() const { return slots_; } |
| - int ic_slots() const { return ic_slots_; } |
| - |
| - FeedbackVectorSlotKind GetKind(int ic_slot) const { |
| - DCHECK(ic_slots_ > 0 && ic_slot < ic_slots_); |
| - return ic_kinds_[ic_slot]; |
| + FeedbackVectorSlotKind GetKind(int slot) const { |
| + DCHECK(slots_ > 0 && slot < slots_); |
| + return kinds_[slot]; |
| } |
| private: |
| int slots_; |
| - int ic_slots_; |
| - FeedbackVectorSlotKind* ic_kinds_; |
| + FeedbackVectorSlotKind* kinds_; |
| }; |
| class FeedbackVectorSpec { |
| public: |
| - explicit FeedbackVectorSpec(Zone* zone) |
| - : slots_(0), ic_slots_(0), ic_slot_kinds_(zone) {} |
| - |
| - int slots() const { return slots_; } |
| - void increase_slots(int count) { |
| - DCHECK_LT(0, count); |
| - slots_ += count; |
| + explicit FeedbackVectorSpec(Zone* zone) : slot_kinds_(zone) { |
| + slot_kinds_.reserve(16); |
| } |
| - int ic_slots() const { return ic_slots_; } |
| - void increase_ic_slots(int count) { |
| - DCHECK_LT(0, count); |
| - ic_slots_ += count; |
| - ic_slot_kinds_.resize(ic_slots_); |
| - } |
| + int slots() const { return static_cast<int>(slot_kinds_.size()); } |
| - FeedbackVectorICSlot AddSlot(FeedbackVectorSlotKind kind) { |
| - int slot = ic_slots_; |
| - increase_ic_slots(1); |
| - ic_slot_kinds_[slot] = static_cast<unsigned char>(kind); |
| - return FeedbackVectorICSlot(slot); |
| - } |
| + inline FeedbackVectorSlot AddSlot(FeedbackVectorSlotKind kind); |
| - FeedbackVectorICSlot AddSlots(FeedbackVectorSlotKind kind, int count) { |
| - int slot = ic_slots_; |
| - increase_ic_slots(count); |
| - for (int i = 0; i < count; i++) { |
| - ic_slot_kinds_[slot + i] = static_cast<unsigned char>(kind); |
| - } |
| - return FeedbackVectorICSlot(slot); |
| - } |
| - |
| - FeedbackVectorICSlot AddCallICSlot() { |
| + FeedbackVectorSlot AddCallICSlot() { |
| return AddSlot(FeedbackVectorSlotKind::CALL_IC); |
| } |
| - FeedbackVectorICSlot AddLoadICSlot() { |
| + FeedbackVectorSlot AddLoadICSlot() { |
| return AddSlot(FeedbackVectorSlotKind::LOAD_IC); |
| } |
| - FeedbackVectorICSlot AddLoadICSlots(int count) { |
| - return AddSlots(FeedbackVectorSlotKind::LOAD_IC, count); |
| - } |
| - |
| - FeedbackVectorICSlot AddKeyedLoadICSlot() { |
| + FeedbackVectorSlot AddKeyedLoadICSlot() { |
| return AddSlot(FeedbackVectorSlotKind::KEYED_LOAD_IC); |
| } |
| - FeedbackVectorICSlot AddStoreICSlot() { |
| + FeedbackVectorSlot AddStoreICSlot() { |
| return AddSlot(FeedbackVectorSlotKind::STORE_IC); |
| } |
| - FeedbackVectorSlot AddStubSlot() { |
| - int slot = slots_; |
| - increase_slots(1); |
| - return FeedbackVectorSlot(slot); |
| + FeedbackVectorSlot AddKeyedStoreICSlot() { |
| + return AddSlot(FeedbackVectorSlotKind::KEYED_STORE_IC); |
| } |
| - FeedbackVectorSlot AddStubSlots(int count) { |
| - int slot = slots_; |
| - increase_slots(count); |
| - return FeedbackVectorSlot(slot); |
| + FeedbackVectorSlot AddStubSlot() { |
| + return AddSlot(FeedbackVectorSlotKind::STUB); |
| } |
| - FeedbackVectorSlotKind GetKind(int ic_slot) const { |
| - return static_cast<FeedbackVectorSlotKind>(ic_slot_kinds_.at(ic_slot)); |
| + FeedbackVectorSlotKind GetKind(int slot) const { |
| + return static_cast<FeedbackVectorSlotKind>(slot_kinds_.at(slot)); |
| } |
| private: |
| - int slots_; |
| - int ic_slots_; |
| - ZoneVector<unsigned char> ic_slot_kinds_; |
| + ZoneVector<unsigned char> slot_kinds_; |
| }; |
| // The shape of the TypeFeedbackVector is an array with: |
| -// 0: first_ic_slot_index (== length() if no ic slots are present) |
| +// 0: slot_count |
| // 1: ics_with_types |
| // 2: ics_with_generic_info |
| -// 3: type information for ic slots, if any |
| +// 3: slots metadata (a bit vector of slot kinds) |
| // ... |
| -// N: first feedback slot (N >= 3) |
| +// N: feedback slot #0 (N >= 3) |
| // ... |
| -// [<first_ic_slot_index>: feedback slot] |
| -// ...to length() - 1 |
| +// N + slot_count - 1: feedback slot #(slot_count-1) |
| // |
| class TypeFeedbackVector : public FixedArray { |
| public: |
| // Casting. |
| static inline TypeFeedbackVector* cast(Object* obj); |
| - static const int kReservedIndexCount = 3; |
| - static const int kFirstICSlotIndex = 0; |
| + static const int kSlotsCountIndex = 0; |
| static const int kWithTypesIndex = 1; |
| static const int kGenericCountIndex = 2; |
| + static const int kReservedIndexCount = 3; |
| - static int elements_per_ic_slot() { return 2; } |
| + // Returns number of feedback vector elements used by given slot kind. |
| + static inline int GetSlotSize(FeedbackVectorSlotKind kind); |
| - inline int first_ic_slot_index() const; |
| inline int ic_with_type_info_count(); |
| inline void change_ic_with_type_info_count(int delta); |
| inline int ic_generic_count(); |
| @@ -165,36 +134,27 @@ class TypeFeedbackVector : public FixedArray { |
| bool SpecDiffersFrom(const FeedbackVectorSpec* other_spec) const; |
| + inline bool is_empty() const; |
| + |
| + // Returns number of slots in the vector. |
| inline int Slots() const; |
| - inline int ICSlots() const; |
| - // Conversion from a slot or ic slot to an integer index to the underlying |
| - // array. |
| + // Conversion from a slot to an integer index to the underlying array. |
| inline int GetIndex(FeedbackVectorSlot slot) const; |
| - inline int GetIndex(FeedbackVectorICSlot slot) const; |
| - |
| - template <typename Spec> |
| - static int GetIndexFromSpec(const Spec* spec, FeedbackVectorSlot slot); |
| - template <typename Spec> |
| - static int GetIndexFromSpec(const Spec* spec, FeedbackVectorICSlot slot); |
| + static int GetIndexFromSpec(const FeedbackVectorSpec* spec, |
| + FeedbackVectorSlot slot); |
| - // Conversion from an integer index to either a slot or an ic slot. The caller |
| - // should know what kind she expects. |
| + // Conversion from an integer index to the underlying array to a slot. |
| inline FeedbackVectorSlot ToSlot(int index) const; |
| - inline FeedbackVectorICSlot ToICSlot(int index) const; |
| inline Object* Get(FeedbackVectorSlot slot) const; |
| inline void Set(FeedbackVectorSlot slot, Object* value, |
| WriteBarrierMode mode = UPDATE_WRITE_BARRIER); |
| - inline Object* Get(FeedbackVectorICSlot slot) const; |
| - inline void Set(FeedbackVectorICSlot slot, Object* value, |
| - WriteBarrierMode mode = UPDATE_WRITE_BARRIER); |
| - // IC slots need metadata to recognize the type of IC. |
| - FeedbackVectorSlotKind GetKind(FeedbackVectorICSlot slot) const; |
| + // Returns slot kind for given slot. |
| + FeedbackVectorSlotKind GetKind(FeedbackVectorSlot slot) const; |
| template <typename Spec> |
| - static Handle<TypeFeedbackVector> Allocate(Isolate* isolate, |
| - const Spec* spec); |
| + static Handle<TypeFeedbackVector> New(Isolate* isolate, const Spec* spec); |
| static Handle<TypeFeedbackVector> Copy(Isolate* isolate, |
| Handle<TypeFeedbackVector> vector); |
| @@ -206,19 +166,13 @@ class TypeFeedbackVector : public FixedArray { |
| DECLARE_PRINTER(TypeFeedbackVector) |
| - // Clears the vector slots and the vector ic slots. |
| + // Clears the vector slots. |
| void ClearSlots(SharedFunctionInfo* shared) { ClearSlotsImpl(shared, true); } |
| + |
| void ClearSlotsAtGCTime(SharedFunctionInfo* shared) { |
| ClearSlotsImpl(shared, false); |
| } |
| - void ClearICSlots(SharedFunctionInfo* shared) { |
| - ClearICSlotsImpl(shared, true); |
| - } |
| - void ClearICSlotsAtGCTime(SharedFunctionInfo* shared) { |
| - ClearICSlotsImpl(shared, false); |
| - } |
| - |
| static void ClearAllKeyedStoreICs(Isolate* isolate); |
| void ClearKeyedStoreICs(SharedFunctionInfo* shared); |
| @@ -233,17 +187,17 @@ class TypeFeedbackVector : public FixedArray { |
| // A raw version of the uninitialized sentinel that's safe to read during |
| // garbage collection (e.g., for patching the cache). |
| - static inline Object* RawUninitializedSentinel(Heap* heap); |
| + static inline Object* RawUninitializedSentinel(Isolate* isolate); |
| static const int kDummyLoadICSlot = 0; |
| - static const int kDummyKeyedLoadICSlot = 1; |
| - static const int kDummyStoreICSlot = 2; |
| - static const int kDummyKeyedStoreICSlot = 3; |
| + static const int kDummyKeyedLoadICSlot = 2; |
| + static const int kDummyStoreICSlot = 4; |
| + static const int kDummyKeyedStoreICSlot = 6; |
| static Handle<TypeFeedbackVector> DummyVector(Isolate* isolate); |
| - static FeedbackVectorICSlot DummySlot(int dummyIndex) { |
| + static FeedbackVectorSlot DummySlot(int dummyIndex) { |
| DCHECK(dummyIndex >= 0 && dummyIndex <= kDummyKeyedStoreICSlot); |
| - return FeedbackVectorICSlot(dummyIndex); |
| + return FeedbackVectorSlot(dummyIndex); |
| } |
| static int PushAppliedArgumentsIndex(); |
| @@ -257,13 +211,12 @@ class TypeFeedbackVector : public FixedArray { |
| STATIC_ASSERT(static_cast<int>(FeedbackVectorSlotKind::KINDS_NUMBER) < |
| (1 << kFeedbackVectorSlotKindBits)); |
| - void SetKind(FeedbackVectorICSlot slot, FeedbackVectorSlotKind kind); |
| + void SetKind(FeedbackVectorSlot slot, FeedbackVectorSlotKind kind); |
| typedef BitSetComputer<FeedbackVectorSlotKind, kFeedbackVectorSlotKindBits, |
| kSmiValueSize, uint32_t> VectorICComputer; |
| void ClearSlotsImpl(SharedFunctionInfo* shared, bool force_clear); |
| - void ClearICSlotsImpl(SharedFunctionInfo* shared, bool force_clear); |
| DISALLOW_IMPLICIT_CONSTRUCTORS(TypeFeedbackVector); |
| }; |
| @@ -284,13 +237,60 @@ STATIC_ASSERT(Name::kEmptyHashField == 0x3); |
| STATIC_ASSERT(Name::kHashNotComputedMask == kHeapObjectTag); |
| +class TypeFeedbackMetadataIterator { |
| + public: |
| + explicit TypeFeedbackMetadataIterator(Handle<TypeFeedbackVector> metadata) |
| + : metadata_handle_(metadata), |
| + slot_(FeedbackVectorSlot(0)), |
| + slot_kind_(FeedbackVectorSlotKind::INVALID) {} |
| + |
| + explicit TypeFeedbackMetadataIterator(TypeFeedbackVector* metadata) |
| + : metadata_(metadata), |
| + slot_(FeedbackVectorSlot(0)), |
| + slot_kind_(FeedbackVectorSlotKind::INVALID) {} |
| + |
| + bool HasNext() const { return slot_.ToInt() < metadata()->Slots(); } |
| + |
| + FeedbackVectorSlot Next() { |
| + DCHECK(HasNext()); |
| + FeedbackVectorSlot slot = slot_; |
| + slot_kind_ = metadata()->GetKind(slot); |
| + slot_ = FeedbackVectorSlot(slot_.ToInt() + entry_size()); |
| + return slot; |
| + } |
| + |
| + // Returns slot kind of the last slot returned by Next(). |
| + FeedbackVectorSlotKind kind() const { |
| + DCHECK_NE(FeedbackVectorSlotKind::INVALID, slot_kind_); |
| + DCHECK_NE(FeedbackVectorSlotKind::KINDS_NUMBER, slot_kind_); |
| + return slot_kind_; |
| + } |
| + |
| + // Returns entry size of the last slot returned by Next(). |
| + int entry_size() const { return TypeFeedbackVector::GetSlotSize(kind()); } |
| + |
| + private: |
| + TypeFeedbackVector* metadata() const { |
| + return !metadata_handle_.is_null() ? *metadata_handle_ : metadata_; |
| + } |
| + |
| + // The reason for having a handle and a raw pointer to the meta data is |
| + // to have a single iterator implementation for both "handlified" and raw |
| + // pointer use cases. |
| + Handle<TypeFeedbackVector> metadata_handle_; |
| + TypeFeedbackVector* metadata_; |
| + FeedbackVectorSlot slot_; |
| + FeedbackVectorSlotKind slot_kind_; |
| +}; |
| + |
| + |
| // A FeedbackNexus is the combination of a TypeFeedbackVector and a slot. |
| // Derived classes customize the update and retrieval of feedback. |
| class FeedbackNexus { |
| public: |
| - FeedbackNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorICSlot slot) |
| + FeedbackNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot) |
| : vector_handle_(vector), vector_(NULL), slot_(slot) {} |
| - FeedbackNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot) |
| + FeedbackNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot) |
| : vector_(vector), slot_(slot) {} |
| virtual ~FeedbackNexus() {} |
| @@ -301,7 +301,7 @@ class FeedbackNexus { |
| TypeFeedbackVector* vector() const { |
| return vector_handle_.is_null() ? vector_ : *vector_handle_; |
| } |
| - FeedbackVectorICSlot slot() const { return slot_; } |
| + FeedbackVectorSlot slot() const { return slot_; } |
| InlineCacheState ic_state() const { return StateFromFeedback(); } |
| Map* FindFirstMap() const { |
| @@ -347,7 +347,7 @@ class FeedbackNexus { |
| // be done, like allocation. |
| Handle<TypeFeedbackVector> vector_handle_; |
| TypeFeedbackVector* vector_; |
| - FeedbackVectorICSlot slot_; |
| + FeedbackVectorSlot slot_; |
| }; |
| @@ -357,11 +357,11 @@ class CallICNexus : public FeedbackNexus { |
| // the count appropriately (ie, by 2). |
| static const int kCallCountIncrement = 2; |
| - CallICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorICSlot slot) |
| + CallICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot) |
| : FeedbackNexus(vector, slot) { |
| DCHECK_EQ(FeedbackVectorSlotKind::CALL_IC, vector->GetKind(slot)); |
| } |
| - CallICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot) |
| + CallICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot) |
| : FeedbackNexus(vector, slot) { |
| DCHECK_EQ(FeedbackVectorSlotKind::CALL_IC, vector->GetKind(slot)); |
| } |
| @@ -390,7 +390,7 @@ class CallICNexus : public FeedbackNexus { |
| class LoadICNexus : public FeedbackNexus { |
| public: |
| - LoadICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorICSlot slot) |
| + LoadICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot) |
| : FeedbackNexus(vector, slot) { |
| DCHECK_EQ(FeedbackVectorSlotKind::LOAD_IC, vector->GetKind(slot)); |
| } |
| @@ -398,7 +398,7 @@ class LoadICNexus : public FeedbackNexus { |
| : FeedbackNexus(TypeFeedbackVector::DummyVector(isolate), |
| TypeFeedbackVector::DummySlot( |
| TypeFeedbackVector::kDummyLoadICSlot)) {} |
| - LoadICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot) |
| + LoadICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot) |
| : FeedbackNexus(vector, slot) { |
| DCHECK_EQ(FeedbackVectorSlotKind::LOAD_IC, vector->GetKind(slot)); |
| } |
| @@ -415,11 +415,11 @@ class LoadICNexus : public FeedbackNexus { |
| class KeyedLoadICNexus : public FeedbackNexus { |
| public: |
| - KeyedLoadICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorICSlot slot) |
| + KeyedLoadICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot) |
| : FeedbackNexus(vector, slot) { |
| DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector->GetKind(slot)); |
| } |
| - KeyedLoadICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot) |
| + KeyedLoadICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot) |
| : FeedbackNexus(vector, slot) { |
| DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector->GetKind(slot)); |
| } |
| @@ -440,7 +440,7 @@ class KeyedLoadICNexus : public FeedbackNexus { |
| class StoreICNexus : public FeedbackNexus { |
| public: |
| - StoreICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorICSlot slot) |
| + StoreICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot) |
| : FeedbackNexus(vector, slot) { |
| DCHECK_EQ(FeedbackVectorSlotKind::STORE_IC, vector->GetKind(slot)); |
| } |
| @@ -448,7 +448,7 @@ class StoreICNexus : public FeedbackNexus { |
| : FeedbackNexus(TypeFeedbackVector::DummyVector(isolate), |
| TypeFeedbackVector::DummySlot( |
| TypeFeedbackVector::kDummyStoreICSlot)) {} |
| - StoreICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot) |
| + StoreICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot) |
| : FeedbackNexus(vector, slot) { |
| DCHECK_EQ(FeedbackVectorSlotKind::STORE_IC, vector->GetKind(slot)); |
| } |
| @@ -465,8 +465,7 @@ class StoreICNexus : public FeedbackNexus { |
| class KeyedStoreICNexus : public FeedbackNexus { |
| public: |
| - KeyedStoreICNexus(Handle<TypeFeedbackVector> vector, |
| - FeedbackVectorICSlot slot) |
| + KeyedStoreICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot) |
| : FeedbackNexus(vector, slot) { |
| DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, vector->GetKind(slot)); |
| } |
| @@ -474,7 +473,7 @@ class KeyedStoreICNexus : public FeedbackNexus { |
| : FeedbackNexus(TypeFeedbackVector::DummyVector(isolate), |
| TypeFeedbackVector::DummySlot( |
| TypeFeedbackVector::kDummyKeyedStoreICSlot)) {} |
| - KeyedStoreICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot) |
| + KeyedStoreICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot) |
| : FeedbackNexus(vector, slot) { |
| DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, vector->GetKind(slot)); |
| } |