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