1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_TYPE_FEEDBACK_VECTOR_INL_H_ 6 #define V8_TYPE_FEEDBACK_VECTOR_INL_H_ 7 8 #include "src/type-feedback-vector.h" 9 10 namespace v8 { 11 namespace internal { 12 13 14 template <typename Derived> 15 FeedbackVectorSlot FeedbackVectorSpecBase<Derived>::AddSlot( 16 FeedbackVectorSlotKind kind) { 17 Derived* derived = static_cast<Derived*>(this); 18 19 int slot = derived->slots(); 20 int entries_per_slot = TypeFeedbackMetadata::GetSlotSize(kind); 21 derived->append(kind); 22 for (int i = 1; i < entries_per_slot; i++) { 23 derived->append(FeedbackVectorSlotKind::INVALID); 24 } 25 return FeedbackVectorSlot(slot); 26 } 27 28 29 // static 30 TypeFeedbackMetadata* TypeFeedbackMetadata::cast(Object* obj) { 31 DCHECK(obj->IsTypeFeedbackVector()); 32 return reinterpret_cast<TypeFeedbackMetadata*>(obj); 33 } 34 35 36 int TypeFeedbackMetadata::slot_count() const { 37 if (length() == 0) return 0; 38 DCHECK(length() > kReservedIndexCount); 39 return Smi::cast(get(kSlotsCountIndex))->value(); 40 } 41 42 43 // static 44 TypeFeedbackVector* TypeFeedbackVector::cast(Object* obj) { 45 DCHECK(obj->IsTypeFeedbackVector()); 46 return reinterpret_cast<TypeFeedbackVector*>(obj); 47 } 48 49 50 int TypeFeedbackMetadata::GetSlotSize(FeedbackVectorSlotKind kind) { 51 DCHECK_NE(FeedbackVectorSlotKind::INVALID, kind); 52 DCHECK_NE(FeedbackVectorSlotKind::KINDS_NUMBER, kind); 53 return kind == FeedbackVectorSlotKind::GENERAL ? 1 : 2; 54 } 55 56 57 bool TypeFeedbackVector::is_empty() const { 58 if (length() == 0) return true; 59 DCHECK(length() > kReservedIndexCount); 60 return false; 61 } 62 63 64 int TypeFeedbackVector::slot_count() const { 65 if (length() == 0) return 0; 66 DCHECK(length() > kReservedIndexCount); 67 return length() - kReservedIndexCount; 68 } 69 70 71 TypeFeedbackMetadata* TypeFeedbackVector::metadata() const { 72 return is_empty() ? TypeFeedbackMetadata::cast(GetHeap()->empty_fixed_array()) 73 : TypeFeedbackMetadata::cast(get(kMetadataIndex)); 74 } 75 76 77 FeedbackVectorSlotKind TypeFeedbackVector::GetKind( 78 FeedbackVectorSlot slot) const { 79 DCHECK(!is_empty()); 80 return metadata()->GetKind(slot); 81 } 82 83 84 int TypeFeedbackVector::GetIndex(FeedbackVectorSlot slot) const { 85 DCHECK(slot.ToInt() < slot_count()); 86 return kReservedIndexCount + slot.ToInt(); 87 } 88 89 90 // Conversion from an integer index to either a slot or an ic slot. The caller 91 // should know what kind she expects. 92 FeedbackVectorSlot TypeFeedbackVector::ToSlot(int index) const { 93 DCHECK(index >= kReservedIndexCount && index < length()); 94 return FeedbackVectorSlot(index - kReservedIndexCount); 95 } 96 97 98 Object* TypeFeedbackVector::Get(FeedbackVectorSlot slot) const { 99 return get(GetIndex(slot)); 100 } 101 102 103 void TypeFeedbackVector::Set(FeedbackVectorSlot slot, Object* value, 104 WriteBarrierMode mode) { 105 set(GetIndex(slot), value, mode); 106 } 107 108 109 void TypeFeedbackVector::ComputeCounts(int* with_type_info, int* generic) { 110 Object* uninitialized_sentinel = 111 TypeFeedbackVector::RawUninitializedSentinel(GetIsolate()); 112 Object* megamorphic_sentinel = 113 *TypeFeedbackVector::MegamorphicSentinel(GetIsolate()); 114 int with = 0; 115 int gen = 0; 116 TypeFeedbackMetadataIterator iter(metadata()); 117 while (iter.HasNext()) { 118 FeedbackVectorSlot slot = iter.Next(); 119 FeedbackVectorSlotKind kind = iter.kind(); 120 121 Object* obj = Get(slot); 122 if (obj != uninitialized_sentinel && 123 kind != FeedbackVectorSlotKind::GENERAL) { 124 if (obj->IsWeakCell() || obj->IsFixedArray() || obj->IsString()) { 125 with++; 126 } else if (obj == megamorphic_sentinel) { 127 gen++; 128 } 129 } 130 } 131 132 *with_type_info = with; 133 *generic = gen; 134 } 135 136 137 Handle<Object> TypeFeedbackVector::UninitializedSentinel(Isolate* isolate) { 138 return isolate->factory()->uninitialized_symbol(); 139 } 140 141 142 Handle<Object> TypeFeedbackVector::MegamorphicSentinel(Isolate* isolate) { 143 return isolate->factory()->megamorphic_symbol(); 144 } 145 146 147 Handle<Object> TypeFeedbackVector::PremonomorphicSentinel(Isolate* isolate) { 148 return isolate->factory()->premonomorphic_symbol(); 149 } 150 151 152 Object* TypeFeedbackVector::RawUninitializedSentinel(Isolate* isolate) { 153 return isolate->heap()->uninitialized_symbol(); 154 } 155 156 157 Object* FeedbackNexus::GetFeedback() const { return vector()->Get(slot()); } 158 159 160 Object* FeedbackNexus::GetFeedbackExtra() const { 161 #ifdef DEBUG 162 FeedbackVectorSlotKind kind = vector()->GetKind(slot()); 163 DCHECK_LT(1, TypeFeedbackMetadata::GetSlotSize(kind)); 164 #endif 165 int extra_index = vector()->GetIndex(slot()) + 1; 166 return vector()->get(extra_index); 167 } 168 169 170 void FeedbackNexus::SetFeedback(Object* feedback, WriteBarrierMode mode) { 171 vector()->Set(slot(), feedback, mode); 172 } 173 174 175 void FeedbackNexus::SetFeedbackExtra(Object* feedback_extra, 176 WriteBarrierMode mode) { 177 #ifdef DEBUG 178 FeedbackVectorSlotKind kind = vector()->GetKind(slot()); 179 DCHECK_LT(1, TypeFeedbackMetadata::GetSlotSize(kind)); 180 #endif 181 int index = vector()->GetIndex(slot()) + 1; 182 vector()->set(index, feedback_extra, mode); 183 } 184 185 186 Isolate* FeedbackNexus::GetIsolate() const { return vector()->GetIsolate(); } 187 } // namespace internal 188 } // namespace v8 189 190 #endif // V8_TYPE_FEEDBACK_VECTOR_INL_H_ 191