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