Home | History | Annotate | Download | only in src
      1 // Copyright 2014 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 #include "src/type-feedback-vector.h"
      6 
      7 #include "src/code-stubs.h"
      8 #include "src/ic/ic-inl.h"
      9 #include "src/ic/ic-state.h"
     10 #include "src/objects.h"
     11 #include "src/type-feedback-vector-inl.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 
     16 
     17 static bool IsPropertyNameFeedback(Object* feedback) {
     18   if (feedback->IsString()) return true;
     19   if (!feedback->IsSymbol()) return false;
     20   Symbol* symbol = Symbol::cast(feedback);
     21   Heap* heap = symbol->GetHeap();
     22   return symbol != heap->uninitialized_symbol() &&
     23          symbol != heap->premonomorphic_symbol() &&
     24          symbol != heap->megamorphic_symbol();
     25 }
     26 
     27 
     28 std::ostream& operator<<(std::ostream& os, FeedbackVectorSlotKind kind) {
     29   return os << TypeFeedbackMetadata::Kind2String(kind);
     30 }
     31 
     32 
     33 FeedbackVectorSlotKind TypeFeedbackMetadata::GetKind(
     34     FeedbackVectorSlot slot) const {
     35   int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt());
     36   int data = Smi::cast(get(index))->value();
     37   return VectorICComputer::decode(data, slot.ToInt());
     38 }
     39 
     40 String* TypeFeedbackMetadata::GetName(FeedbackVectorSlot slot) const {
     41   DCHECK(SlotRequiresName(GetKind(slot)));
     42   UnseededNumberDictionary* names =
     43       UnseededNumberDictionary::cast(get(kNamesTableIndex));
     44   int entry = names->FindEntry(GetIsolate(), slot.ToInt());
     45   CHECK_NE(UnseededNumberDictionary::kNotFound, entry);
     46   Object* name = names->ValueAt(entry);
     47   DCHECK(name->IsString());
     48   return String::cast(name);
     49 }
     50 
     51 void TypeFeedbackMetadata::SetKind(FeedbackVectorSlot slot,
     52                                    FeedbackVectorSlotKind kind) {
     53   int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt());
     54   int data = Smi::cast(get(index))->value();
     55   int new_data = VectorICComputer::encode(data, slot.ToInt(), kind);
     56   set(index, Smi::FromInt(new_data));
     57 }
     58 
     59 
     60 template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(
     61     Isolate* isolate, const StaticFeedbackVectorSpec* spec);
     62 template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(
     63     Isolate* isolate, const FeedbackVectorSpec* spec);
     64 
     65 
     66 // static
     67 template <typename Spec>
     68 Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(Isolate* isolate,
     69                                                        const Spec* spec) {
     70   Factory* factory = isolate->factory();
     71 
     72   const int slot_count = spec->slots();
     73   const int slot_kinds_length = VectorICComputer::word_count(slot_count);
     74   const int length = slot_kinds_length + kReservedIndexCount;
     75   if (length == kReservedIndexCount) {
     76     return Handle<TypeFeedbackMetadata>::cast(factory->empty_fixed_array());
     77   }
     78 #ifdef DEBUG
     79   for (int i = 0; i < slot_count;) {
     80     FeedbackVectorSlotKind kind = spec->GetKind(i);
     81     int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
     82     for (int j = 1; j < entry_size; j++) {
     83       FeedbackVectorSlotKind kind = spec->GetKind(i + j);
     84       DCHECK_EQ(FeedbackVectorSlotKind::INVALID, kind);
     85     }
     86     i += entry_size;
     87   }
     88 #endif
     89 
     90   Handle<FixedArray> array = factory->NewFixedArray(length, TENURED);
     91   array->set(kSlotsCountIndex, Smi::FromInt(slot_count));
     92   // Fill the bit-vector part with zeros.
     93   for (int i = 0; i < slot_kinds_length; i++) {
     94     array->set(kReservedIndexCount + i, Smi::kZero);
     95   }
     96 
     97   Handle<TypeFeedbackMetadata> metadata =
     98       Handle<TypeFeedbackMetadata>::cast(array);
     99 
    100   // Add names to NamesTable.
    101   const int name_count = spec->name_count();
    102 
    103   Handle<UnseededNumberDictionary> names;
    104   if (name_count) {
    105     names = UnseededNumberDictionary::New(isolate, name_count, TENURED);
    106   }
    107 
    108   int name_index = 0;
    109   for (int i = 0; i < slot_count; i++) {
    110     FeedbackVectorSlotKind kind = spec->GetKind(i);
    111     metadata->SetKind(FeedbackVectorSlot(i), kind);
    112     if (SlotRequiresName(kind)) {
    113       Handle<String> name = spec->GetName(name_index);
    114       DCHECK(!name.is_null());
    115       Handle<UnseededNumberDictionary> new_names =
    116           UnseededNumberDictionary::AtNumberPut(names, i, name);
    117       DCHECK_EQ(*new_names, *names);
    118       names = new_names;
    119       name_index++;
    120     }
    121   }
    122   DCHECK_EQ(name_count, name_index);
    123   metadata->set(kNamesTableIndex,
    124                 name_count ? static_cast<Object*>(*names) : Smi::kZero);
    125 
    126   // It's important that the TypeFeedbackMetadata have a COW map, since it's
    127   // pointed to by both a SharedFunctionInfo and indirectly by closures through
    128   // the TypeFeedbackVector. The serializer uses the COW map type to decide
    129   // this object belongs in the startup snapshot and not the partial
    130   // snapshot(s).
    131   metadata->set_map(isolate->heap()->fixed_cow_array_map());
    132 
    133   return metadata;
    134 }
    135 
    136 
    137 bool TypeFeedbackMetadata::SpecDiffersFrom(
    138     const FeedbackVectorSpec* other_spec) const {
    139   if (other_spec->slots() != slot_count()) {
    140     return true;
    141   }
    142 
    143   int slots = slot_count();
    144   int name_index = 0;
    145   for (int i = 0; i < slots;) {
    146     FeedbackVectorSlot slot(i);
    147     FeedbackVectorSlotKind kind = GetKind(slot);
    148     int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
    149 
    150     if (kind != other_spec->GetKind(i)) {
    151       return true;
    152     }
    153     if (SlotRequiresName(kind)) {
    154       String* name = GetName(slot);
    155       DCHECK(name != GetHeap()->empty_string());
    156       String* other_name = *other_spec->GetName(name_index++);
    157       if (name != other_name) {
    158         return true;
    159       }
    160     }
    161     i += entry_size;
    162   }
    163   return false;
    164 }
    165 
    166 bool TypeFeedbackMetadata::DiffersFrom(
    167     const TypeFeedbackMetadata* other_metadata) const {
    168   if (other_metadata->slot_count() != slot_count()) {
    169     return true;
    170   }
    171 
    172   int slots = slot_count();
    173   for (int i = 0; i < slots;) {
    174     FeedbackVectorSlot slot(i);
    175     FeedbackVectorSlotKind kind = GetKind(slot);
    176     int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
    177     if (GetKind(slot) != other_metadata->GetKind(slot)) {
    178       return true;
    179     }
    180     if (SlotRequiresName(kind)) {
    181       if (GetName(slot) != other_metadata->GetName(slot)) {
    182         return true;
    183       }
    184     }
    185     i += entry_size;
    186   }
    187   return false;
    188 }
    189 
    190 const char* TypeFeedbackMetadata::Kind2String(FeedbackVectorSlotKind kind) {
    191   switch (kind) {
    192     case FeedbackVectorSlotKind::INVALID:
    193       return "INVALID";
    194     case FeedbackVectorSlotKind::CALL_IC:
    195       return "CALL_IC";
    196     case FeedbackVectorSlotKind::LOAD_IC:
    197       return "LOAD_IC";
    198     case FeedbackVectorSlotKind::LOAD_GLOBAL_IC:
    199       return "LOAD_GLOBAL_IC";
    200     case FeedbackVectorSlotKind::KEYED_LOAD_IC:
    201       return "KEYED_LOAD_IC";
    202     case FeedbackVectorSlotKind::STORE_IC:
    203       return "STORE_IC";
    204     case FeedbackVectorSlotKind::KEYED_STORE_IC:
    205       return "KEYED_STORE_IC";
    206     case FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC:
    207       return "INTERPRETER_BINARYOP_IC";
    208     case FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC:
    209       return "INTERPRETER_COMPARE_IC";
    210     case FeedbackVectorSlotKind::GENERAL:
    211       return "STUB";
    212     case FeedbackVectorSlotKind::KINDS_NUMBER:
    213       break;
    214   }
    215   UNREACHABLE();
    216   return "?";
    217 }
    218 
    219 FeedbackVectorSlotKind TypeFeedbackVector::GetKind(
    220     FeedbackVectorSlot slot) const {
    221   DCHECK(!is_empty());
    222   return metadata()->GetKind(slot);
    223 }
    224 
    225 String* TypeFeedbackVector::GetName(FeedbackVectorSlot slot) const {
    226   DCHECK(!is_empty());
    227   return metadata()->GetName(slot);
    228 }
    229 
    230 // static
    231 Handle<TypeFeedbackVector> TypeFeedbackVector::New(
    232     Isolate* isolate, Handle<TypeFeedbackMetadata> metadata) {
    233   Factory* factory = isolate->factory();
    234 
    235   const int slot_count = metadata->slot_count();
    236   const int length = slot_count + kReservedIndexCount;
    237   if (length == kReservedIndexCount) {
    238     return Handle<TypeFeedbackVector>::cast(
    239         factory->empty_type_feedback_vector());
    240   }
    241 
    242   Handle<FixedArray> array = factory->NewFixedArray(length, TENURED);
    243   array->set(kMetadataIndex, *metadata);
    244   array->set(kInvocationCountIndex, Smi::kZero);
    245 
    246   DisallowHeapAllocation no_gc;
    247 
    248   // Ensure we can skip the write barrier
    249   Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate);
    250   DCHECK_EQ(isolate->heap()->uninitialized_symbol(), *uninitialized_sentinel);
    251   for (int i = 0; i < slot_count;) {
    252     FeedbackVectorSlot slot(i);
    253     FeedbackVectorSlotKind kind = metadata->GetKind(slot);
    254     int index = TypeFeedbackVector::GetIndex(slot);
    255     int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
    256 
    257     Object* value;
    258     if (kind == FeedbackVectorSlotKind::LOAD_GLOBAL_IC) {
    259       value = isolate->heap()->empty_weak_cell();
    260     } else if (kind == FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC ||
    261                kind == FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC) {
    262       value = Smi::kZero;
    263     } else {
    264       value = *uninitialized_sentinel;
    265     }
    266     array->set(index, value, SKIP_WRITE_BARRIER);
    267 
    268     value = kind == FeedbackVectorSlotKind::CALL_IC ? Smi::kZero
    269                                                     : *uninitialized_sentinel;
    270     for (int j = 1; j < entry_size; j++) {
    271       array->set(index + j, value, SKIP_WRITE_BARRIER);
    272     }
    273     i += entry_size;
    274   }
    275   return Handle<TypeFeedbackVector>::cast(array);
    276 }
    277 
    278 
    279 // static
    280 int TypeFeedbackVector::GetIndexFromSpec(const FeedbackVectorSpec* spec,
    281                                          FeedbackVectorSlot slot) {
    282   return kReservedIndexCount + slot.ToInt();
    283 }
    284 
    285 
    286 // static
    287 Handle<TypeFeedbackVector> TypeFeedbackVector::Copy(
    288     Isolate* isolate, Handle<TypeFeedbackVector> vector) {
    289   Handle<TypeFeedbackVector> result;
    290   result = Handle<TypeFeedbackVector>::cast(
    291       isolate->factory()->CopyFixedArray(Handle<FixedArray>::cast(vector)));
    292   return result;
    293 }
    294 
    295 
    296 // This logic is copied from
    297 // StaticMarkingVisitor<StaticVisitor>::VisitCodeTarget.
    298 static bool ClearLogic(Isolate* isolate) {
    299   return FLAG_cleanup_code_caches_at_gc && isolate->serializer_enabled();
    300 }
    301 
    302 
    303 void TypeFeedbackVector::ClearSlotsImpl(SharedFunctionInfo* shared,
    304                                         bool force_clear) {
    305   Isolate* isolate = GetIsolate();
    306 
    307   if (!force_clear && !ClearLogic(isolate)) return;
    308 
    309   Object* uninitialized_sentinel =
    310       TypeFeedbackVector::RawUninitializedSentinel(isolate);
    311 
    312   TypeFeedbackMetadataIterator iter(metadata());
    313   while (iter.HasNext()) {
    314     FeedbackVectorSlot slot = iter.Next();
    315     FeedbackVectorSlotKind kind = iter.kind();
    316 
    317     Object* obj = Get(slot);
    318     if (obj != uninitialized_sentinel) {
    319       switch (kind) {
    320         case FeedbackVectorSlotKind::CALL_IC: {
    321           CallICNexus nexus(this, slot);
    322           nexus.Clear(shared->code());
    323           break;
    324         }
    325         case FeedbackVectorSlotKind::LOAD_IC: {
    326           LoadICNexus nexus(this, slot);
    327           nexus.Clear(shared->code());
    328           break;
    329         }
    330         case FeedbackVectorSlotKind::LOAD_GLOBAL_IC: {
    331           LoadGlobalICNexus nexus(this, slot);
    332           nexus.Clear(shared->code());
    333           break;
    334         }
    335         case FeedbackVectorSlotKind::KEYED_LOAD_IC: {
    336           KeyedLoadICNexus nexus(this, slot);
    337           nexus.Clear(shared->code());
    338           break;
    339         }
    340         case FeedbackVectorSlotKind::STORE_IC: {
    341           StoreICNexus nexus(this, slot);
    342           nexus.Clear(shared->code());
    343           break;
    344         }
    345         case FeedbackVectorSlotKind::KEYED_STORE_IC: {
    346           KeyedStoreICNexus nexus(this, slot);
    347           nexus.Clear(shared->code());
    348           break;
    349         }
    350         case FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC:
    351         case FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC: {
    352           DCHECK(Get(slot)->IsSmi());
    353           // don't clear these smi slots.
    354           // Set(slot, Smi::kZero);
    355           break;
    356         }
    357         case FeedbackVectorSlotKind::GENERAL: {
    358           if (obj->IsHeapObject()) {
    359             InstanceType instance_type =
    360                 HeapObject::cast(obj)->map()->instance_type();
    361             // AllocationSites are exempt from clearing. They don't store Maps
    362             // or Code pointers which can cause memory leaks if not cleared
    363             // regularly.
    364             if (instance_type != ALLOCATION_SITE_TYPE) {
    365               Set(slot, uninitialized_sentinel, SKIP_WRITE_BARRIER);
    366             }
    367           }
    368           break;
    369         }
    370         case FeedbackVectorSlotKind::INVALID:
    371         case FeedbackVectorSlotKind::KINDS_NUMBER:
    372           UNREACHABLE();
    373           break;
    374       }
    375     }
    376   }
    377 }
    378 
    379 
    380 // static
    381 void TypeFeedbackVector::ClearAllKeyedStoreICs(Isolate* isolate) {
    382   SharedFunctionInfo::Iterator iterator(isolate);
    383   SharedFunctionInfo* shared;
    384   while ((shared = iterator.Next())) {
    385     if (!shared->OptimizedCodeMapIsCleared()) {
    386       FixedArray* optimized_code_map = shared->optimized_code_map();
    387       int length = optimized_code_map->length();
    388       for (int i = SharedFunctionInfo::kEntriesStart; i < length;
    389            i += SharedFunctionInfo::kEntryLength) {
    390         WeakCell* cell = WeakCell::cast(
    391             optimized_code_map->get(i + SharedFunctionInfo::kLiteralsOffset));
    392         if (cell->value()->IsLiteralsArray()) {
    393           TypeFeedbackVector* vector =
    394               LiteralsArray::cast(cell->value())->feedback_vector();
    395           vector->ClearKeyedStoreICs(shared);
    396         }
    397       }
    398     }
    399   }
    400 }
    401 
    402 
    403 void TypeFeedbackVector::ClearKeyedStoreICs(SharedFunctionInfo* shared) {
    404   Isolate* isolate = GetIsolate();
    405 
    406   Code* host = shared->code();
    407   Object* uninitialized_sentinel =
    408       TypeFeedbackVector::RawUninitializedSentinel(isolate);
    409 
    410   TypeFeedbackMetadataIterator iter(metadata());
    411   while (iter.HasNext()) {
    412     FeedbackVectorSlot slot = iter.Next();
    413     FeedbackVectorSlotKind kind = iter.kind();
    414     if (kind != FeedbackVectorSlotKind::KEYED_STORE_IC) continue;
    415     Object* obj = Get(slot);
    416     if (obj != uninitialized_sentinel) {
    417       KeyedStoreICNexus nexus(this, slot);
    418       nexus.Clear(host);
    419     }
    420   }
    421 }
    422 
    423 
    424 // static
    425 Handle<TypeFeedbackVector> TypeFeedbackVector::DummyVector(Isolate* isolate) {
    426   return isolate->factory()->dummy_vector();
    427 }
    428 
    429 
    430 Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) {
    431   Isolate* isolate = GetIsolate();
    432   Handle<Object> feedback = handle(GetFeedback(), isolate);
    433   if (!feedback->IsFixedArray() ||
    434       FixedArray::cast(*feedback)->length() != length) {
    435     Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
    436     SetFeedback(*array);
    437     return array;
    438   }
    439   return Handle<FixedArray>::cast(feedback);
    440 }
    441 
    442 
    443 Handle<FixedArray> FeedbackNexus::EnsureExtraArrayOfSize(int length) {
    444   Isolate* isolate = GetIsolate();
    445   Handle<Object> feedback_extra = handle(GetFeedbackExtra(), isolate);
    446   if (!feedback_extra->IsFixedArray() ||
    447       FixedArray::cast(*feedback_extra)->length() != length) {
    448     Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
    449     SetFeedbackExtra(*array);
    450     return array;
    451   }
    452   return Handle<FixedArray>::cast(feedback_extra);
    453 }
    454 
    455 void FeedbackNexus::InstallHandlers(Handle<FixedArray> array,
    456                                     MapHandleList* maps,
    457                                     List<Handle<Object>>* handlers) {
    458   int receiver_count = maps->length();
    459   for (int current = 0; current < receiver_count; ++current) {
    460     Handle<Map> map = maps->at(current);
    461     Handle<WeakCell> cell = Map::WeakCellForMap(map);
    462     array->set(current * 2, *cell);
    463     array->set(current * 2 + 1, *handlers->at(current));
    464   }
    465 }
    466 
    467 
    468 void FeedbackNexus::ConfigureUninitialized() {
    469   SetFeedback(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
    470               SKIP_WRITE_BARRIER);
    471   SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
    472                    SKIP_WRITE_BARRIER);
    473 }
    474 
    475 
    476 void FeedbackNexus::ConfigurePremonomorphic() {
    477   SetFeedback(*TypeFeedbackVector::PremonomorphicSentinel(GetIsolate()),
    478               SKIP_WRITE_BARRIER);
    479   SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
    480                    SKIP_WRITE_BARRIER);
    481 }
    482 
    483 
    484 void FeedbackNexus::ConfigureMegamorphic() {
    485   // Keyed ICs must use ConfigureMegamorphicKeyed.
    486   DCHECK_NE(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector()->GetKind(slot()));
    487   DCHECK_NE(FeedbackVectorSlotKind::KEYED_STORE_IC, vector()->GetKind(slot()));
    488 
    489   Isolate* isolate = GetIsolate();
    490   SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate),
    491               SKIP_WRITE_BARRIER);
    492   SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
    493                    SKIP_WRITE_BARRIER);
    494 }
    495 
    496 void KeyedLoadICNexus::ConfigureMegamorphicKeyed(IcCheckType property_type) {
    497   Isolate* isolate = GetIsolate();
    498   SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate),
    499               SKIP_WRITE_BARRIER);
    500   SetFeedbackExtra(Smi::FromInt(static_cast<int>(property_type)),
    501                    SKIP_WRITE_BARRIER);
    502 }
    503 
    504 void KeyedStoreICNexus::ConfigureMegamorphicKeyed(IcCheckType property_type) {
    505   Isolate* isolate = GetIsolate();
    506   SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate),
    507               SKIP_WRITE_BARRIER);
    508   SetFeedbackExtra(Smi::FromInt(static_cast<int>(property_type)),
    509                    SKIP_WRITE_BARRIER);
    510 }
    511 
    512 InlineCacheState LoadICNexus::StateFromFeedback() const {
    513   Isolate* isolate = GetIsolate();
    514   Object* feedback = GetFeedback();
    515 
    516   if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
    517     return UNINITIALIZED;
    518   } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
    519     return MEGAMORPHIC;
    520   } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
    521     return PREMONOMORPHIC;
    522   } else if (feedback->IsFixedArray()) {
    523     // Determine state purely by our structure, don't check if the maps are
    524     // cleared.
    525     return POLYMORPHIC;
    526   } else if (feedback->IsWeakCell()) {
    527     // Don't check if the map is cleared.
    528     return MONOMORPHIC;
    529   }
    530 
    531   return UNINITIALIZED;
    532 }
    533 
    534 InlineCacheState LoadGlobalICNexus::StateFromFeedback() const {
    535   Isolate* isolate = GetIsolate();
    536   Object* feedback = GetFeedback();
    537 
    538   Object* extra = GetFeedbackExtra();
    539   if (!WeakCell::cast(feedback)->cleared() ||
    540       extra != *TypeFeedbackVector::UninitializedSentinel(isolate)) {
    541     return MONOMORPHIC;
    542   }
    543   return UNINITIALIZED;
    544 }
    545 
    546 InlineCacheState KeyedLoadICNexus::StateFromFeedback() const {
    547   Isolate* isolate = GetIsolate();
    548   Object* feedback = GetFeedback();
    549 
    550   if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
    551     return UNINITIALIZED;
    552   } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
    553     return PREMONOMORPHIC;
    554   } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
    555     return MEGAMORPHIC;
    556   } else if (feedback->IsFixedArray()) {
    557     // Determine state purely by our structure, don't check if the maps are
    558     // cleared.
    559     return POLYMORPHIC;
    560   } else if (feedback->IsWeakCell()) {
    561     // Don't check if the map is cleared.
    562     return MONOMORPHIC;
    563   } else if (feedback->IsName()) {
    564     Object* extra = GetFeedbackExtra();
    565     FixedArray* extra_array = FixedArray::cast(extra);
    566     return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC;
    567   }
    568 
    569   return UNINITIALIZED;
    570 }
    571 
    572 
    573 InlineCacheState StoreICNexus::StateFromFeedback() const {
    574   Isolate* isolate = GetIsolate();
    575   Object* feedback = GetFeedback();
    576 
    577   if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
    578     return UNINITIALIZED;
    579   } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
    580     return MEGAMORPHIC;
    581   } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
    582     return PREMONOMORPHIC;
    583   } else if (feedback->IsFixedArray()) {
    584     // Determine state purely by our structure, don't check if the maps are
    585     // cleared.
    586     return POLYMORPHIC;
    587   } else if (feedback->IsWeakCell()) {
    588     // Don't check if the map is cleared.
    589     return MONOMORPHIC;
    590   }
    591 
    592   return UNINITIALIZED;
    593 }
    594 
    595 
    596 InlineCacheState KeyedStoreICNexus::StateFromFeedback() const {
    597   Isolate* isolate = GetIsolate();
    598   Object* feedback = GetFeedback();
    599 
    600   if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
    601     return UNINITIALIZED;
    602   } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
    603     return PREMONOMORPHIC;
    604   } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
    605     return MEGAMORPHIC;
    606   } else if (feedback->IsFixedArray()) {
    607     // Determine state purely by our structure, don't check if the maps are
    608     // cleared.
    609     return POLYMORPHIC;
    610   } else if (feedback->IsWeakCell()) {
    611     // Don't check if the map is cleared.
    612     return MONOMORPHIC;
    613   } else if (feedback->IsName()) {
    614     Object* extra = GetFeedbackExtra();
    615     FixedArray* extra_array = FixedArray::cast(extra);
    616     return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC;
    617   }
    618 
    619   return UNINITIALIZED;
    620 }
    621 
    622 
    623 InlineCacheState CallICNexus::StateFromFeedback() const {
    624   Isolate* isolate = GetIsolate();
    625   Object* feedback = GetFeedback();
    626   DCHECK(GetFeedbackExtra() ==
    627              *TypeFeedbackVector::UninitializedSentinel(isolate) ||
    628          GetFeedbackExtra()->IsSmi());
    629 
    630   if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
    631     return GENERIC;
    632   } else if (feedback->IsAllocationSite() || feedback->IsWeakCell()) {
    633     return MONOMORPHIC;
    634   }
    635 
    636   CHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate));
    637   return UNINITIALIZED;
    638 }
    639 
    640 
    641 int CallICNexus::ExtractCallCount() {
    642   Object* call_count = GetFeedbackExtra();
    643   CHECK(call_count->IsSmi());
    644   int value = Smi::cast(call_count)->value();
    645   return value;
    646 }
    647 
    648 float CallICNexus::ComputeCallFrequency() {
    649   double const invocation_count = vector()->invocation_count();
    650   double const call_count = ExtractCallCount();
    651   return static_cast<float>(call_count / invocation_count);
    652 }
    653 
    654 void CallICNexus::Clear(Code* host) { CallIC::Clear(GetIsolate(), host, this); }
    655 
    656 void CallICNexus::ConfigureUninitialized() {
    657   Isolate* isolate = GetIsolate();
    658   SetFeedback(*TypeFeedbackVector::UninitializedSentinel(isolate),
    659               SKIP_WRITE_BARRIER);
    660   SetFeedbackExtra(Smi::kZero, SKIP_WRITE_BARRIER);
    661 }
    662 
    663 void CallICNexus::ConfigureMonomorphicArray() {
    664   Object* feedback = GetFeedback();
    665   if (!feedback->IsAllocationSite()) {
    666     Handle<AllocationSite> new_site =
    667         GetIsolate()->factory()->NewAllocationSite();
    668     SetFeedback(*new_site);
    669   }
    670   SetFeedbackExtra(Smi::FromInt(1), SKIP_WRITE_BARRIER);
    671 }
    672 
    673 
    674 void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) {
    675   Handle<WeakCell> new_cell = GetIsolate()->factory()->NewWeakCell(function);
    676   SetFeedback(*new_cell);
    677   SetFeedbackExtra(Smi::FromInt(1), SKIP_WRITE_BARRIER);
    678 }
    679 
    680 
    681 void CallICNexus::ConfigureMegamorphic() {
    682   SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(GetIsolate()),
    683               SKIP_WRITE_BARRIER);
    684   Smi* count = Smi::cast(GetFeedbackExtra());
    685   int new_count = count->value() + 1;
    686   SetFeedbackExtra(Smi::FromInt(new_count), SKIP_WRITE_BARRIER);
    687 }
    688 
    689 void CallICNexus::ConfigureMegamorphic(int call_count) {
    690   SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(GetIsolate()),
    691               SKIP_WRITE_BARRIER);
    692   SetFeedbackExtra(Smi::FromInt(call_count), SKIP_WRITE_BARRIER);
    693 }
    694 
    695 void LoadICNexus::ConfigureMonomorphic(Handle<Map> receiver_map,
    696                                        Handle<Object> handler) {
    697   Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
    698   SetFeedback(*cell);
    699   SetFeedbackExtra(*handler);
    700 }
    701 
    702 void LoadGlobalICNexus::ConfigureUninitialized() {
    703   Isolate* isolate = GetIsolate();
    704   SetFeedback(isolate->heap()->empty_weak_cell(), SKIP_WRITE_BARRIER);
    705   SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
    706                    SKIP_WRITE_BARRIER);
    707 }
    708 
    709 void LoadGlobalICNexus::ConfigurePropertyCellMode(Handle<PropertyCell> cell) {
    710   Isolate* isolate = GetIsolate();
    711   SetFeedback(*isolate->factory()->NewWeakCell(cell));
    712   SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
    713                    SKIP_WRITE_BARRIER);
    714 }
    715 
    716 void LoadGlobalICNexus::ConfigureHandlerMode(Handle<Code> handler) {
    717   SetFeedback(GetIsolate()->heap()->empty_weak_cell());
    718   SetFeedbackExtra(*handler);
    719 }
    720 
    721 void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name,
    722                                             Handle<Map> receiver_map,
    723                                             Handle<Object> handler) {
    724   Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
    725   if (name.is_null()) {
    726     SetFeedback(*cell);
    727     SetFeedbackExtra(*handler);
    728   } else {
    729     Handle<FixedArray> array = EnsureExtraArrayOfSize(2);
    730     SetFeedback(*name);
    731     array->set(0, *cell);
    732     array->set(1, *handler);
    733   }
    734 }
    735 
    736 void StoreICNexus::ConfigureMonomorphic(Handle<Map> receiver_map,
    737                                         Handle<Object> handler) {
    738   Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
    739   SetFeedback(*cell);
    740   SetFeedbackExtra(*handler);
    741 }
    742 
    743 void KeyedStoreICNexus::ConfigureMonomorphic(Handle<Name> name,
    744                                              Handle<Map> receiver_map,
    745                                              Handle<Object> handler) {
    746   Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
    747   if (name.is_null()) {
    748     SetFeedback(*cell);
    749     SetFeedbackExtra(*handler);
    750   } else {
    751     Handle<FixedArray> array = EnsureExtraArrayOfSize(2);
    752     SetFeedback(*name);
    753     array->set(0, *cell);
    754     array->set(1, *handler);
    755   }
    756 }
    757 
    758 void LoadICNexus::ConfigurePolymorphic(MapHandleList* maps,
    759                                        List<Handle<Object>>* handlers) {
    760   Isolate* isolate = GetIsolate();
    761   int receiver_count = maps->length();
    762   Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 2);
    763   InstallHandlers(array, maps, handlers);
    764   SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
    765                    SKIP_WRITE_BARRIER);
    766 }
    767 
    768 void KeyedLoadICNexus::ConfigurePolymorphic(Handle<Name> name,
    769                                             MapHandleList* maps,
    770                                             List<Handle<Object>>* handlers) {
    771   int receiver_count = maps->length();
    772   DCHECK(receiver_count > 1);
    773   Handle<FixedArray> array;
    774   if (name.is_null()) {
    775     array = EnsureArrayOfSize(receiver_count * 2);
    776     SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
    777                      SKIP_WRITE_BARRIER);
    778   } else {
    779     array = EnsureExtraArrayOfSize(receiver_count * 2);
    780     SetFeedback(*name);
    781   }
    782 
    783   InstallHandlers(array, maps, handlers);
    784 }
    785 
    786 void StoreICNexus::ConfigurePolymorphic(MapHandleList* maps,
    787                                         List<Handle<Object>>* handlers) {
    788   Isolate* isolate = GetIsolate();
    789   int receiver_count = maps->length();
    790   Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 2);
    791   InstallHandlers(array, maps, handlers);
    792   SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
    793                    SKIP_WRITE_BARRIER);
    794 }
    795 
    796 void KeyedStoreICNexus::ConfigurePolymorphic(Handle<Name> name,
    797                                              MapHandleList* maps,
    798                                              List<Handle<Object>>* handlers) {
    799   int receiver_count = maps->length();
    800   DCHECK(receiver_count > 1);
    801   Handle<FixedArray> array;
    802   if (name.is_null()) {
    803     array = EnsureArrayOfSize(receiver_count * 2);
    804     SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
    805                      SKIP_WRITE_BARRIER);
    806   } else {
    807     array = EnsureExtraArrayOfSize(receiver_count * 2);
    808     SetFeedback(*name);
    809   }
    810 
    811   InstallHandlers(array, maps, handlers);
    812 }
    813 
    814 
    815 void KeyedStoreICNexus::ConfigurePolymorphic(MapHandleList* maps,
    816                                              MapHandleList* transitioned_maps,
    817                                              CodeHandleList* handlers) {
    818   int receiver_count = maps->length();
    819   DCHECK(receiver_count > 1);
    820   Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 3);
    821   SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
    822                    SKIP_WRITE_BARRIER);
    823 
    824   Handle<Oddball> undefined_value = GetIsolate()->factory()->undefined_value();
    825   for (int i = 0; i < receiver_count; ++i) {
    826     Handle<Map> map = maps->at(i);
    827     Handle<WeakCell> cell = Map::WeakCellForMap(map);
    828     array->set(i * 3, *cell);
    829     if (!transitioned_maps->at(i).is_null()) {
    830       Handle<Map> transitioned_map = transitioned_maps->at(i);
    831       cell = Map::WeakCellForMap(transitioned_map);
    832       array->set((i * 3) + 1, *cell);
    833     } else {
    834       array->set((i * 3) + 1, *undefined_value);
    835     }
    836     array->set((i * 3) + 2, *handlers->at(i));
    837   }
    838 }
    839 
    840 namespace {
    841 
    842 int GetStepSize(FixedArray* array, Isolate* isolate) {
    843   // The array should be of the form
    844   // [map, handler, map, handler, ...]
    845   // or
    846   // [map, map, handler, map, map, handler, ...]
    847   // where "map" is either a WeakCell or |undefined|,
    848   // and "handler" is either a Code object or a Smi.
    849   DCHECK(array->length() >= 2);
    850   Object* second = array->get(1);
    851   if (second->IsWeakCell() || second->IsUndefined(isolate)) return 3;
    852   DCHECK(IC::IsHandler(second));
    853   return 2;
    854 }
    855 
    856 }  // namespace
    857 
    858 int FeedbackNexus::ExtractMaps(MapHandleList* maps) const {
    859   Isolate* isolate = GetIsolate();
    860   Object* feedback = GetFeedback();
    861   bool is_named_feedback = IsPropertyNameFeedback(feedback);
    862   if (feedback->IsFixedArray() || is_named_feedback) {
    863     int found = 0;
    864     if (is_named_feedback) {
    865       feedback = GetFeedbackExtra();
    866     }
    867     FixedArray* array = FixedArray::cast(feedback);
    868     int increment = GetStepSize(array, isolate);
    869     for (int i = 0; i < array->length(); i += increment) {
    870       DCHECK(array->get(i)->IsWeakCell());
    871       WeakCell* cell = WeakCell::cast(array->get(i));
    872       if (!cell->cleared()) {
    873         Map* map = Map::cast(cell->value());
    874         maps->Add(handle(map, isolate));
    875         found++;
    876       }
    877     }
    878     return found;
    879   } else if (feedback->IsWeakCell()) {
    880     WeakCell* cell = WeakCell::cast(feedback);
    881     if (!cell->cleared()) {
    882       Map* map = Map::cast(cell->value());
    883       maps->Add(handle(map, isolate));
    884       return 1;
    885     }
    886   }
    887 
    888   return 0;
    889 }
    890 
    891 MaybeHandle<Object> FeedbackNexus::FindHandlerForMap(Handle<Map> map) const {
    892   Object* feedback = GetFeedback();
    893   Isolate* isolate = GetIsolate();
    894   bool is_named_feedback = IsPropertyNameFeedback(feedback);
    895   if (feedback->IsFixedArray() || is_named_feedback) {
    896     if (is_named_feedback) {
    897       feedback = GetFeedbackExtra();
    898     }
    899     FixedArray* array = FixedArray::cast(feedback);
    900     int increment = GetStepSize(array, isolate);
    901     for (int i = 0; i < array->length(); i += increment) {
    902       DCHECK(array->get(i)->IsWeakCell());
    903       WeakCell* cell = WeakCell::cast(array->get(i));
    904       if (!cell->cleared()) {
    905         Map* array_map = Map::cast(cell->value());
    906         if (array_map == *map) {
    907           Object* code = array->get(i + increment - 1);
    908           DCHECK(IC::IsHandler(code));
    909           return handle(code, isolate);
    910         }
    911       }
    912     }
    913   } else if (feedback->IsWeakCell()) {
    914     WeakCell* cell = WeakCell::cast(feedback);
    915     if (!cell->cleared()) {
    916       Map* cell_map = Map::cast(cell->value());
    917       if (cell_map == *map) {
    918         Object* code = GetFeedbackExtra();
    919         DCHECK(IC::IsHandler(code));
    920         return handle(code, isolate);
    921       }
    922     }
    923   }
    924 
    925   return MaybeHandle<Code>();
    926 }
    927 
    928 bool FeedbackNexus::FindHandlers(List<Handle<Object>>* code_list,
    929                                  int length) const {
    930   Object* feedback = GetFeedback();
    931   Isolate* isolate = GetIsolate();
    932   int count = 0;
    933   bool is_named_feedback = IsPropertyNameFeedback(feedback);
    934   if (feedback->IsFixedArray() || is_named_feedback) {
    935     if (is_named_feedback) {
    936       feedback = GetFeedbackExtra();
    937     }
    938     FixedArray* array = FixedArray::cast(feedback);
    939     int increment = GetStepSize(array, isolate);
    940     for (int i = 0; i < array->length(); i += increment) {
    941       DCHECK(array->get(i)->IsWeakCell());
    942       WeakCell* cell = WeakCell::cast(array->get(i));
    943       // Be sure to skip handlers whose maps have been cleared.
    944       if (!cell->cleared()) {
    945         Object* code = array->get(i + increment - 1);
    946         DCHECK(IC::IsHandler(code));
    947         code_list->Add(handle(code, isolate));
    948         count++;
    949       }
    950     }
    951   } else if (feedback->IsWeakCell()) {
    952     WeakCell* cell = WeakCell::cast(feedback);
    953     if (!cell->cleared()) {
    954       Object* code = GetFeedbackExtra();
    955       DCHECK(IC::IsHandler(code));
    956       code_list->Add(handle(code, isolate));
    957       count++;
    958     }
    959   }
    960   return count == length;
    961 }
    962 
    963 
    964 void LoadICNexus::Clear(Code* host) { LoadIC::Clear(GetIsolate(), host, this); }
    965 
    966 void LoadGlobalICNexus::Clear(Code* host) {
    967   LoadGlobalIC::Clear(GetIsolate(), host, this);
    968 }
    969 
    970 void KeyedLoadICNexus::Clear(Code* host) {
    971   KeyedLoadIC::Clear(GetIsolate(), host, this);
    972 }
    973 
    974 
    975 Name* KeyedLoadICNexus::FindFirstName() const {
    976   Object* feedback = GetFeedback();
    977   if (IsPropertyNameFeedback(feedback)) {
    978     return Name::cast(feedback);
    979   }
    980   return NULL;
    981 }
    982 
    983 
    984 Name* KeyedStoreICNexus::FindFirstName() const {
    985   Object* feedback = GetFeedback();
    986   if (IsPropertyNameFeedback(feedback)) {
    987     return Name::cast(feedback);
    988   }
    989   return NULL;
    990 }
    991 
    992 
    993 void StoreICNexus::Clear(Code* host) {
    994   StoreIC::Clear(GetIsolate(), host, this);
    995 }
    996 
    997 
    998 void KeyedStoreICNexus::Clear(Code* host) {
    999   KeyedStoreIC::Clear(GetIsolate(), host, this);
   1000 }
   1001 
   1002 
   1003 KeyedAccessStoreMode KeyedStoreICNexus::GetKeyedAccessStoreMode() const {
   1004   KeyedAccessStoreMode mode = STANDARD_STORE;
   1005   MapHandleList maps;
   1006   List<Handle<Object>> handlers;
   1007 
   1008   if (GetKeyType() == PROPERTY) return mode;
   1009 
   1010   ExtractMaps(&maps);
   1011   FindHandlers(&handlers, maps.length());
   1012   for (int i = 0; i < handlers.length(); i++) {
   1013     // The first handler that isn't the slow handler will have the bits we need.
   1014     Handle<Code> handler = Handle<Code>::cast(handlers.at(i));
   1015     CodeStub::Major major_key = CodeStub::MajorKeyFromKey(handler->stub_key());
   1016     uint32_t minor_key = CodeStub::MinorKeyFromKey(handler->stub_key());
   1017     CHECK(major_key == CodeStub::KeyedStoreSloppyArguments ||
   1018           major_key == CodeStub::StoreFastElement ||
   1019           major_key == CodeStub::StoreElement ||
   1020           major_key == CodeStub::ElementsTransitionAndStore ||
   1021           major_key == CodeStub::NoCache);
   1022     if (major_key != CodeStub::NoCache) {
   1023       mode = CommonStoreModeBits::decode(minor_key);
   1024       break;
   1025     }
   1026   }
   1027 
   1028   return mode;
   1029 }
   1030 
   1031 IcCheckType KeyedLoadICNexus::GetKeyType() const {
   1032   Object* feedback = GetFeedback();
   1033   if (feedback == *TypeFeedbackVector::MegamorphicSentinel(GetIsolate())) {
   1034     return static_cast<IcCheckType>(Smi::cast(GetFeedbackExtra())->value());
   1035   }
   1036   return IsPropertyNameFeedback(feedback) ? PROPERTY : ELEMENT;
   1037 }
   1038 
   1039 IcCheckType KeyedStoreICNexus::GetKeyType() const {
   1040   Object* feedback = GetFeedback();
   1041   if (feedback == *TypeFeedbackVector::MegamorphicSentinel(GetIsolate())) {
   1042     return static_cast<IcCheckType>(Smi::cast(GetFeedbackExtra())->value());
   1043   }
   1044   return IsPropertyNameFeedback(feedback) ? PROPERTY : ELEMENT;
   1045 }
   1046 
   1047 InlineCacheState BinaryOpICNexus::StateFromFeedback() const {
   1048   BinaryOperationHint hint = GetBinaryOperationFeedback();
   1049   if (hint == BinaryOperationHint::kNone) {
   1050     return UNINITIALIZED;
   1051   } else if (hint == BinaryOperationHint::kAny) {
   1052     return GENERIC;
   1053   }
   1054 
   1055   return MONOMORPHIC;
   1056 }
   1057 
   1058 InlineCacheState CompareICNexus::StateFromFeedback() const {
   1059   CompareOperationHint hint = GetCompareOperationFeedback();
   1060   if (hint == CompareOperationHint::kNone) {
   1061     return UNINITIALIZED;
   1062   } else if (hint == CompareOperationHint::kAny) {
   1063     return GENERIC;
   1064   }
   1065 
   1066   return MONOMORPHIC;
   1067 }
   1068 
   1069 BinaryOperationHint BinaryOpICNexus::GetBinaryOperationFeedback() const {
   1070   int feedback = Smi::cast(GetFeedback())->value();
   1071   return BinaryOperationHintFromFeedback(feedback);
   1072 }
   1073 
   1074 CompareOperationHint CompareICNexus::GetCompareOperationFeedback() const {
   1075   int feedback = Smi::cast(GetFeedback())->value();
   1076   return CompareOperationHintFromFeedback(feedback);
   1077 }
   1078 
   1079 }  // namespace internal
   1080 }  // namespace v8
   1081