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_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