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