Index: src/type-feedback-vector.h |
diff --git a/src/type-feedback-vector.h b/src/type-feedback-vector.h |
index 2d394b0ca40e364add2e1e6a13d339e301c6cc3e..f9a3fe3e4623d14a20032cabead34132f6686f80 100644 |
--- a/src/type-feedback-vector.h |
+++ b/src/type-feedback-vector.h |
@@ -19,13 +19,20 @@ 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, |
+ // This is a general purpose slot that occupies one feedback vector element. |
+ GENERAL, |
+ |
KINDS_NUMBER // Last value indicating number of kinds. |
}; |
@@ -33,130 +40,110 @@ enum class FeedbackVectorSlotKind { |
std::ostream& operator<<(std::ostream& os, FeedbackVectorSlotKind kind); |
-class StaticFeedbackVectorSpec { |
+template <typename Derived> |
+class FeedbackVectorSpecBase { |
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) {} |
+ inline FeedbackVectorSlot AddSlot(FeedbackVectorSlotKind kind); |
- int slots() const { return slots_; } |
+ FeedbackVectorSlot AddCallICSlot() { |
+ return AddSlot(FeedbackVectorSlotKind::CALL_IC); |
+ } |
- int ic_slots() const { return ic_slots_; } |
+ FeedbackVectorSlot AddLoadICSlot() { |
+ return AddSlot(FeedbackVectorSlotKind::LOAD_IC); |
+ } |
- FeedbackVectorSlotKind GetKind(int ic_slot) const { |
- DCHECK(ic_slots_ > 0 && ic_slot < ic_slots_); |
- return ic_kinds_[ic_slot]; |
+ FeedbackVectorSlot AddKeyedLoadICSlot() { |
+ return AddSlot(FeedbackVectorSlotKind::KEYED_LOAD_IC); |
} |
- private: |
- int slots_; |
- int ic_slots_; |
- FeedbackVectorSlotKind* ic_kinds_; |
+ FeedbackVectorSlot AddStoreICSlot() { |
+ return AddSlot(FeedbackVectorSlotKind::STORE_IC); |
+ } |
+ |
+ FeedbackVectorSlot AddKeyedStoreICSlot() { |
+ return AddSlot(FeedbackVectorSlotKind::KEYED_STORE_IC); |
+ } |
+ |
+ FeedbackVectorSlot AddGeneralSlot() { |
+ return AddSlot(FeedbackVectorSlotKind::GENERAL); |
+ } |
}; |
-class FeedbackVectorSpec { |
+class StaticFeedbackVectorSpec |
+ : public FeedbackVectorSpecBase<StaticFeedbackVectorSpec> { |
public: |
- explicit FeedbackVectorSpec(Zone* zone) |
- : slots_(0), ic_slots_(0), ic_slot_kinds_(zone) {} |
+ StaticFeedbackVectorSpec() : slots_(0) {} |
int slots() const { return slots_; } |
- void increase_slots(int count) { |
- DCHECK_LT(0, count); |
- slots_ += count; |
- } |
- 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_); |
+ FeedbackVectorSlotKind GetKind(int slot) const { |
+ DCHECK(slot >= 0 && slot < slots_); |
+ return kinds_[slot]; |
} |
- FeedbackVectorICSlot AddSlot(FeedbackVectorSlotKind kind) { |
- int slot = ic_slots_; |
- increase_ic_slots(1); |
- ic_slot_kinds_[slot] = static_cast<unsigned char>(kind); |
- return FeedbackVectorICSlot(slot); |
- } |
+ private: |
+ friend class FeedbackVectorSpecBase<StaticFeedbackVectorSpec>; |
- 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); |
+ void append(FeedbackVectorSlotKind kind) { |
+ DCHECK(slots_ < kMaxLength); |
+ kinds_[slots_++] = kind; |
} |
- FeedbackVectorICSlot AddCallICSlot() { |
- return AddSlot(FeedbackVectorSlotKind::CALL_IC); |
- } |
+ static const int kMaxLength = 12; |
- FeedbackVectorICSlot AddLoadICSlot() { |
- return AddSlot(FeedbackVectorSlotKind::LOAD_IC); |
- } |
+ int slots_; |
+ FeedbackVectorSlotKind kinds_[kMaxLength]; |
+}; |
- FeedbackVectorICSlot AddLoadICSlots(int count) { |
- return AddSlots(FeedbackVectorSlotKind::LOAD_IC, count); |
- } |
- FeedbackVectorICSlot AddKeyedLoadICSlot() { |
- return AddSlot(FeedbackVectorSlotKind::KEYED_LOAD_IC); |
+class FeedbackVectorSpec : public FeedbackVectorSpecBase<FeedbackVectorSpec> { |
+ public: |
+ explicit FeedbackVectorSpec(Zone* zone) : slot_kinds_(zone) { |
+ slot_kinds_.reserve(16); |
} |
- FeedbackVectorICSlot AddStoreICSlot() { |
- return AddSlot(FeedbackVectorSlotKind::STORE_IC); |
- } |
+ int slots() const { return static_cast<int>(slot_kinds_.size()); } |
- FeedbackVectorSlot AddStubSlot() { |
- int slot = slots_; |
- increase_slots(1); |
- return FeedbackVectorSlot(slot); |
+ FeedbackVectorSlotKind GetKind(int slot) const { |
+ return static_cast<FeedbackVectorSlotKind>(slot_kinds_.at(slot)); |
} |
- FeedbackVectorSlot AddStubSlots(int count) { |
- int slot = slots_; |
- increase_slots(count); |
- return FeedbackVectorSlot(slot); |
- } |
+ private: |
+ friend class FeedbackVectorSpecBase<FeedbackVectorSpec>; |
- FeedbackVectorSlotKind GetKind(int ic_slot) const { |
- return static_cast<FeedbackVectorSlotKind>(ic_slot_kinds_.at(ic_slot)); |
+ void append(FeedbackVectorSlotKind kind) { |
+ slot_kinds_.push_back(static_cast<unsigned char>(kind)); |
} |
- 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 +152,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; |
+ static int GetIndexFromSpec(const FeedbackVectorSpec* spec, |
+ FeedbackVectorSlot slot); |
- template <typename Spec> |
- static int GetIndexFromSpec(const Spec* spec, FeedbackVectorSlot slot); |
- template <typename Spec> |
- static int GetIndexFromSpec(const Spec* spec, FeedbackVectorICSlot 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 +184,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 +205,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 +229,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 +255,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 +319,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 +365,7 @@ class FeedbackNexus { |
// be done, like allocation. |
Handle<TypeFeedbackVector> vector_handle_; |
TypeFeedbackVector* vector_; |
- FeedbackVectorICSlot slot_; |
+ FeedbackVectorSlot slot_; |
}; |
@@ -357,11 +375,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,15 +408,15 @@ 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)); |
} |
explicit LoadICNexus(Isolate* isolate) |
- : FeedbackNexus(TypeFeedbackVector::DummyVector(isolate), |
- TypeFeedbackVector::DummySlot( |
- TypeFeedbackVector::kDummyLoadICSlot)) {} |
- LoadICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot) |
+ : FeedbackNexus( |
+ TypeFeedbackVector::DummyVector(isolate), |
+ FeedbackVectorSlot(TypeFeedbackVector::kDummyLoadICSlot)) {} |
+ LoadICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot) |
: FeedbackNexus(vector, slot) { |
DCHECK_EQ(FeedbackVectorSlotKind::LOAD_IC, vector->GetKind(slot)); |
} |
@@ -415,11 +433,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,15 +458,15 @@ 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)); |
} |
explicit StoreICNexus(Isolate* isolate) |
- : FeedbackNexus(TypeFeedbackVector::DummyVector(isolate), |
- TypeFeedbackVector::DummySlot( |
- TypeFeedbackVector::kDummyStoreICSlot)) {} |
- StoreICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot) |
+ : FeedbackNexus( |
+ TypeFeedbackVector::DummyVector(isolate), |
+ FeedbackVectorSlot(TypeFeedbackVector::kDummyStoreICSlot)) {} |
+ StoreICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot) |
: FeedbackNexus(vector, slot) { |
DCHECK_EQ(FeedbackVectorSlotKind::STORE_IC, vector->GetKind(slot)); |
} |
@@ -465,16 +483,15 @@ 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)); |
} |
explicit KeyedStoreICNexus(Isolate* isolate) |
- : FeedbackNexus(TypeFeedbackVector::DummyVector(isolate), |
- TypeFeedbackVector::DummySlot( |
- TypeFeedbackVector::kDummyKeyedStoreICSlot)) {} |
- KeyedStoreICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot) |
+ : FeedbackNexus( |
+ TypeFeedbackVector::DummyVector(isolate), |
+ FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedStoreICSlot)) {} |
+ KeyedStoreICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot) |
: FeedbackNexus(vector, slot) { |
DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, vector->GetKind(slot)); |
} |