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/globals.h" 9 #include "src/type-feedback-vector.h" 10 11 namespace v8 { 12 namespace internal { 13 14 15 template <typename Derived> 16 FeedbackVectorSlot FeedbackVectorSpecBase<Derived>::AddSlot( 17 FeedbackVectorSlotKind kind) { 18 int slot = This()->slots(); 19 int entries_per_slot = TypeFeedbackMetadata::GetSlotSize(kind); 20 This()->append(kind); 21 for (int i = 1; i < entries_per_slot; i++) { 22 This()->append(FeedbackVectorSlotKind::INVALID); 23 } 24 return FeedbackVectorSlot(slot); 25 } 26 27 28 // static 29 TypeFeedbackMetadata* TypeFeedbackMetadata::cast(Object* obj) { 30 DCHECK(obj->IsTypeFeedbackVector()); 31 return reinterpret_cast<TypeFeedbackMetadata*>(obj); 32 } 33 34 bool TypeFeedbackMetadata::is_empty() const { 35 if (length() == 0) return true; 36 return false; 37 } 38 39 int TypeFeedbackMetadata::slot_count() const { 40 if (length() == 0) return 0; 41 DCHECK(length() > kReservedIndexCount); 42 return Smi::cast(get(kSlotsCountIndex))->value(); 43 } 44 45 46 // static 47 TypeFeedbackVector* TypeFeedbackVector::cast(Object* obj) { 48 DCHECK(obj->IsTypeFeedbackVector()); 49 return reinterpret_cast<TypeFeedbackVector*>(obj); 50 } 51 52 53 int TypeFeedbackMetadata::GetSlotSize(FeedbackVectorSlotKind kind) { 54 DCHECK_NE(FeedbackVectorSlotKind::INVALID, kind); 55 DCHECK_NE(FeedbackVectorSlotKind::KINDS_NUMBER, kind); 56 if (kind == FeedbackVectorSlotKind::GENERAL || 57 kind == FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC || 58 kind == FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC) { 59 return 1; 60 } 61 62 return 2; 63 } 64 65 bool TypeFeedbackMetadata::SlotRequiresName(FeedbackVectorSlotKind kind) { 66 switch (kind) { 67 case FeedbackVectorSlotKind::LOAD_GLOBAL_IC: 68 return true; 69 70 case FeedbackVectorSlotKind::CALL_IC: 71 case FeedbackVectorSlotKind::LOAD_IC: 72 case FeedbackVectorSlotKind::KEYED_LOAD_IC: 73 case FeedbackVectorSlotKind::STORE_IC: 74 case FeedbackVectorSlotKind::KEYED_STORE_IC: 75 case FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC: 76 case FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC: 77 case FeedbackVectorSlotKind::GENERAL: 78 case FeedbackVectorSlotKind::INVALID: 79 return false; 80 81 case FeedbackVectorSlotKind::KINDS_NUMBER: 82 break; 83 } 84 UNREACHABLE(); 85 return false; 86 } 87 88 bool TypeFeedbackVector::is_empty() const { 89 return length() == kReservedIndexCount; 90 } 91 92 int TypeFeedbackVector::slot_count() const { 93 return length() - kReservedIndexCount; 94 } 95 96 97 TypeFeedbackMetadata* TypeFeedbackVector::metadata() const { 98 return TypeFeedbackMetadata::cast(get(kMetadataIndex)); 99 } 100 101 int TypeFeedbackVector::invocation_count() const { 102 return Smi::cast(get(kInvocationCountIndex))->value(); 103 } 104 105 // Conversion from an integer index to either a slot or an ic slot. 106 // static 107 FeedbackVectorSlot TypeFeedbackVector::ToSlot(int index) { 108 DCHECK(index >= kReservedIndexCount); 109 return FeedbackVectorSlot(index - kReservedIndexCount); 110 } 111 112 113 Object* TypeFeedbackVector::Get(FeedbackVectorSlot slot) const { 114 return get(GetIndex(slot)); 115 } 116 117 118 void TypeFeedbackVector::Set(FeedbackVectorSlot slot, Object* value, 119 WriteBarrierMode mode) { 120 set(GetIndex(slot), value, mode); 121 } 122 123 // Helper function to transform the feedback to BinaryOperationHint. 124 BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) { 125 switch (type_feedback) { 126 case BinaryOperationFeedback::kNone: 127 return BinaryOperationHint::kNone; 128 case BinaryOperationFeedback::kSignedSmall: 129 return BinaryOperationHint::kSignedSmall; 130 case BinaryOperationFeedback::kNumber: 131 case BinaryOperationFeedback::kNumberOrOddball: 132 return BinaryOperationHint::kNumberOrOddball; 133 case BinaryOperationFeedback::kString: 134 return BinaryOperationHint::kString; 135 case BinaryOperationFeedback::kAny: 136 default: 137 return BinaryOperationHint::kAny; 138 } 139 UNREACHABLE(); 140 return BinaryOperationHint::kNone; 141 } 142 143 // Helper function to transform the feedback to CompareOperationHint. 144 CompareOperationHint CompareOperationHintFromFeedback(int type_feedback) { 145 switch (type_feedback) { 146 case CompareOperationFeedback::kNone: 147 return CompareOperationHint::kNone; 148 case CompareOperationFeedback::kSignedSmall: 149 return CompareOperationHint::kSignedSmall; 150 case CompareOperationFeedback::kNumber: 151 return CompareOperationHint::kNumber; 152 default: 153 return CompareOperationHint::kAny; 154 } 155 UNREACHABLE(); 156 return CompareOperationHint::kNone; 157 } 158 159 void TypeFeedbackVector::ComputeCounts(int* with_type_info, int* generic, 160 int* vector_ic_count, 161 bool code_is_interpreted) { 162 Object* megamorphic_sentinel = 163 *TypeFeedbackVector::MegamorphicSentinel(GetIsolate()); 164 int with = 0; 165 int gen = 0; 166 int total = 0; 167 TypeFeedbackMetadataIterator iter(metadata()); 168 while (iter.HasNext()) { 169 FeedbackVectorSlot slot = iter.Next(); 170 FeedbackVectorSlotKind kind = iter.kind(); 171 172 Object* const obj = Get(slot); 173 switch (kind) { 174 case FeedbackVectorSlotKind::CALL_IC: 175 case FeedbackVectorSlotKind::LOAD_IC: 176 case FeedbackVectorSlotKind::LOAD_GLOBAL_IC: 177 case FeedbackVectorSlotKind::KEYED_LOAD_IC: 178 case FeedbackVectorSlotKind::STORE_IC: 179 case FeedbackVectorSlotKind::KEYED_STORE_IC: { 180 if (obj->IsWeakCell() || obj->IsFixedArray() || obj->IsString()) { 181 with++; 182 } else if (obj == megamorphic_sentinel) { 183 gen++; 184 } 185 total++; 186 break; 187 } 188 case FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC: 189 case FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC: { 190 // If we are not running interpreted code, we need to ignore the special 191 // IC slots for binaryop/compare used by the interpreter. 192 // TODO(mvstanton): Remove code_is_interpreted when full code is retired 193 // from service. 194 if (code_is_interpreted) { 195 int const feedback = Smi::cast(obj)->value(); 196 if (kind == FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC) { 197 CompareOperationHint hint = 198 CompareOperationHintFromFeedback(feedback); 199 if (hint == CompareOperationHint::kAny) { 200 gen++; 201 } else if (hint != CompareOperationHint::kNone) { 202 with++; 203 } 204 } else { 205 DCHECK_EQ(FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC, kind); 206 BinaryOperationHint hint = 207 BinaryOperationHintFromFeedback(feedback); 208 if (hint == BinaryOperationHint::kAny) { 209 gen++; 210 } else if (hint != BinaryOperationHint::kNone) { 211 with++; 212 } 213 } 214 total++; 215 } 216 break; 217 } 218 case FeedbackVectorSlotKind::GENERAL: 219 break; 220 case FeedbackVectorSlotKind::INVALID: 221 case FeedbackVectorSlotKind::KINDS_NUMBER: 222 UNREACHABLE(); 223 break; 224 } 225 } 226 227 *with_type_info = with; 228 *generic = gen; 229 *vector_ic_count = total; 230 } 231 232 Handle<Symbol> TypeFeedbackVector::UninitializedSentinel(Isolate* isolate) { 233 return isolate->factory()->uninitialized_symbol(); 234 } 235 236 Handle<Symbol> TypeFeedbackVector::MegamorphicSentinel(Isolate* isolate) { 237 return isolate->factory()->megamorphic_symbol(); 238 } 239 240 Handle<Symbol> TypeFeedbackVector::PremonomorphicSentinel(Isolate* isolate) { 241 return isolate->factory()->premonomorphic_symbol(); 242 } 243 244 Symbol* TypeFeedbackVector::RawUninitializedSentinel(Isolate* isolate) { 245 return isolate->heap()->uninitialized_symbol(); 246 } 247 248 bool TypeFeedbackMetadataIterator::HasNext() const { 249 return next_slot_.ToInt() < metadata()->slot_count(); 250 } 251 252 FeedbackVectorSlot TypeFeedbackMetadataIterator::Next() { 253 DCHECK(HasNext()); 254 cur_slot_ = next_slot_; 255 slot_kind_ = metadata()->GetKind(cur_slot_); 256 next_slot_ = FeedbackVectorSlot(next_slot_.ToInt() + entry_size()); 257 return cur_slot_; 258 } 259 260 int TypeFeedbackMetadataIterator::entry_size() const { 261 return TypeFeedbackMetadata::GetSlotSize(kind()); 262 } 263 264 Object* FeedbackNexus::GetFeedback() const { return vector()->Get(slot()); } 265 266 267 Object* FeedbackNexus::GetFeedbackExtra() const { 268 #ifdef DEBUG 269 FeedbackVectorSlotKind kind = vector()->GetKind(slot()); 270 DCHECK_LT(1, TypeFeedbackMetadata::GetSlotSize(kind)); 271 #endif 272 int extra_index = vector()->GetIndex(slot()) + 1; 273 return vector()->get(extra_index); 274 } 275 276 277 void FeedbackNexus::SetFeedback(Object* feedback, WriteBarrierMode mode) { 278 vector()->Set(slot(), feedback, mode); 279 } 280 281 282 void FeedbackNexus::SetFeedbackExtra(Object* feedback_extra, 283 WriteBarrierMode mode) { 284 #ifdef DEBUG 285 FeedbackVectorSlotKind kind = vector()->GetKind(slot()); 286 DCHECK_LT(1, TypeFeedbackMetadata::GetSlotSize(kind)); 287 #endif 288 int index = vector()->GetIndex(slot()) + 1; 289 vector()->set(index, feedback_extra, mode); 290 } 291 292 293 Isolate* FeedbackNexus::GetIsolate() const { return vector()->GetIsolate(); } 294 } // namespace internal 295 } // namespace v8 296 297 #endif // V8_TYPE_FEEDBACK_VECTOR_INL_H_ 298