Home | History | Annotate | Download | only in src
      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