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/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   int slot = This()->slots();
     18   int entries_per_slot = TypeFeedbackMetadata::GetSlotSize(kind);
     19   This()->append(kind);
     20   for (int i = 1; i < entries_per_slot; i++) {
     21     This()->append(FeedbackVectorSlotKind::INVALID);
     22   }
     23   return FeedbackVectorSlot(slot);
     24 }
     25 
     26 
     27 // static
     28 TypeFeedbackMetadata* TypeFeedbackMetadata::cast(Object* obj) {
     29   DCHECK(obj->IsTypeFeedbackVector());
     30   return reinterpret_cast<TypeFeedbackMetadata*>(obj);
     31 }
     32 
     33 bool TypeFeedbackMetadata::is_empty() const {
     34   if (length() == 0) return true;
     35   return false;
     36 }
     37 
     38 int TypeFeedbackMetadata::slot_count() const {
     39   if (length() == 0) return 0;
     40   DCHECK(length() > kReservedIndexCount);
     41   return Smi::cast(get(kSlotsCountIndex))->value();
     42 }
     43 
     44 
     45 // static
     46 TypeFeedbackVector* TypeFeedbackVector::cast(Object* obj) {
     47   DCHECK(obj->IsTypeFeedbackVector());
     48   return reinterpret_cast<TypeFeedbackVector*>(obj);
     49 }
     50 
     51 
     52 int TypeFeedbackMetadata::GetSlotSize(FeedbackVectorSlotKind kind) {
     53   DCHECK_NE(FeedbackVectorSlotKind::INVALID, kind);
     54   DCHECK_NE(FeedbackVectorSlotKind::KINDS_NUMBER, kind);
     55   return kind == FeedbackVectorSlotKind::GENERAL ? 1 : 2;
     56 }
     57 
     58 bool TypeFeedbackMetadata::SlotRequiresName(FeedbackVectorSlotKind kind) {
     59   switch (kind) {
     60     case FeedbackVectorSlotKind::LOAD_GLOBAL_IC:
     61       return true;
     62 
     63     case FeedbackVectorSlotKind::CALL_IC:
     64     case FeedbackVectorSlotKind::LOAD_IC:
     65     case FeedbackVectorSlotKind::KEYED_LOAD_IC:
     66     case FeedbackVectorSlotKind::STORE_IC:
     67     case FeedbackVectorSlotKind::KEYED_STORE_IC:
     68     case FeedbackVectorSlotKind::GENERAL:
     69     case FeedbackVectorSlotKind::INVALID:
     70       return false;
     71 
     72     case FeedbackVectorSlotKind::KINDS_NUMBER:
     73       break;
     74   }
     75   UNREACHABLE();
     76   return false;
     77 }
     78 
     79 bool TypeFeedbackVector::is_empty() const {
     80   if (length() == 0) return true;
     81   DCHECK(length() > kReservedIndexCount);
     82   return false;
     83 }
     84 
     85 
     86 int TypeFeedbackVector::slot_count() const {
     87   if (length() == 0) return 0;
     88   DCHECK(length() > kReservedIndexCount);
     89   return length() - kReservedIndexCount;
     90 }
     91 
     92 
     93 TypeFeedbackMetadata* TypeFeedbackVector::metadata() const {
     94   return is_empty() ? TypeFeedbackMetadata::cast(GetHeap()->empty_fixed_array())
     95                     : TypeFeedbackMetadata::cast(get(kMetadataIndex));
     96 }
     97 
     98 // Conversion from an integer index to either a slot or an ic slot.
     99 // static
    100 FeedbackVectorSlot TypeFeedbackVector::ToSlot(int index) {
    101   DCHECK(index >= kReservedIndexCount);
    102   return FeedbackVectorSlot(index - kReservedIndexCount);
    103 }
    104 
    105 
    106 Object* TypeFeedbackVector::Get(FeedbackVectorSlot slot) const {
    107   return get(GetIndex(slot));
    108 }
    109 
    110 
    111 void TypeFeedbackVector::Set(FeedbackVectorSlot slot, Object* value,
    112                              WriteBarrierMode mode) {
    113   set(GetIndex(slot), value, mode);
    114 }
    115 
    116 
    117 void TypeFeedbackVector::ComputeCounts(int* with_type_info, int* generic) {
    118   Object* uninitialized_sentinel =
    119       TypeFeedbackVector::RawUninitializedSentinel(GetIsolate());
    120   Object* megamorphic_sentinel =
    121       *TypeFeedbackVector::MegamorphicSentinel(GetIsolate());
    122   int with = 0;
    123   int gen = 0;
    124   TypeFeedbackMetadataIterator iter(metadata());
    125   while (iter.HasNext()) {
    126     FeedbackVectorSlot slot = iter.Next();
    127     FeedbackVectorSlotKind kind = iter.kind();
    128 
    129     Object* obj = Get(slot);
    130     if (obj != uninitialized_sentinel &&
    131         kind != FeedbackVectorSlotKind::GENERAL) {
    132       if (obj->IsWeakCell() || obj->IsFixedArray() || obj->IsString()) {
    133         with++;
    134       } else if (obj == megamorphic_sentinel) {
    135         gen++;
    136       }
    137     }
    138   }
    139 
    140   *with_type_info = with;
    141   *generic = gen;
    142 }
    143 
    144 Handle<Symbol> TypeFeedbackVector::UninitializedSentinel(Isolate* isolate) {
    145   return isolate->factory()->uninitialized_symbol();
    146 }
    147 
    148 Handle<Symbol> TypeFeedbackVector::MegamorphicSentinel(Isolate* isolate) {
    149   return isolate->factory()->megamorphic_symbol();
    150 }
    151 
    152 Handle<Symbol> TypeFeedbackVector::PremonomorphicSentinel(Isolate* isolate) {
    153   return isolate->factory()->premonomorphic_symbol();
    154 }
    155 
    156 Symbol* TypeFeedbackVector::RawUninitializedSentinel(Isolate* isolate) {
    157   return isolate->heap()->uninitialized_symbol();
    158 }
    159 
    160 bool TypeFeedbackMetadataIterator::HasNext() const {
    161   return next_slot_.ToInt() < metadata()->slot_count();
    162 }
    163 
    164 FeedbackVectorSlot TypeFeedbackMetadataIterator::Next() {
    165   DCHECK(HasNext());
    166   cur_slot_ = next_slot_;
    167   slot_kind_ = metadata()->GetKind(cur_slot_);
    168   next_slot_ = FeedbackVectorSlot(next_slot_.ToInt() + entry_size());
    169   return cur_slot_;
    170 }
    171 
    172 int TypeFeedbackMetadataIterator::entry_size() const {
    173   return TypeFeedbackMetadata::GetSlotSize(kind());
    174 }
    175 
    176 Object* FeedbackNexus::GetFeedback() const { return vector()->Get(slot()); }
    177 
    178 
    179 Object* FeedbackNexus::GetFeedbackExtra() const {
    180 #ifdef DEBUG
    181   FeedbackVectorSlotKind kind = vector()->GetKind(slot());
    182   DCHECK_LT(1, TypeFeedbackMetadata::GetSlotSize(kind));
    183 #endif
    184   int extra_index = vector()->GetIndex(slot()) + 1;
    185   return vector()->get(extra_index);
    186 }
    187 
    188 
    189 void FeedbackNexus::SetFeedback(Object* feedback, WriteBarrierMode mode) {
    190   vector()->Set(slot(), feedback, mode);
    191 }
    192 
    193 
    194 void FeedbackNexus::SetFeedbackExtra(Object* feedback_extra,
    195                                      WriteBarrierMode mode) {
    196 #ifdef DEBUG
    197   FeedbackVectorSlotKind kind = vector()->GetKind(slot());
    198   DCHECK_LT(1, TypeFeedbackMetadata::GetSlotSize(kind));
    199 #endif
    200   int index = vector()->GetIndex(slot()) + 1;
    201   vector()->set(index, feedback_extra, mode);
    202 }
    203 
    204 
    205 Isolate* FeedbackNexus::GetIsolate() const { return vector()->GetIsolate(); }
    206 }  // namespace internal
    207 }  // namespace v8
    208 
    209 #endif  // V8_TYPE_FEEDBACK_VECTOR_INL_H_
    210