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   return feedback->IsString() ||
     19          (feedback->IsSymbol() && !Symbol::cast(feedback)->is_private());
     20 }
     21 
     22 
     23 std::ostream& operator<<(std::ostream& os, FeedbackVectorSlotKind kind) {
     24   return os << TypeFeedbackMetadata::Kind2String(kind);
     25 }
     26 
     27 
     28 FeedbackVectorSlotKind TypeFeedbackMetadata::GetKind(
     29     FeedbackVectorSlot 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 
     36 void TypeFeedbackMetadata::SetKind(FeedbackVectorSlot slot,
     37                                    FeedbackVectorSlotKind kind) {
     38   int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt());
     39   int data = Smi::cast(get(index))->value();
     40   int new_data = VectorICComputer::encode(data, slot.ToInt(), kind);
     41   set(index, Smi::FromInt(new_data));
     42 }
     43 
     44 
     45 template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(
     46     Isolate* isolate, const StaticFeedbackVectorSpec* spec);
     47 template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(
     48     Isolate* isolate, const FeedbackVectorSpec* spec);
     49 
     50 
     51 // static
     52 template <typename Spec>
     53 Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(Isolate* isolate,
     54                                                        const Spec* spec) {
     55   const int slot_count = spec->slots();
     56   const int slot_kinds_length = VectorICComputer::word_count(slot_count);
     57   const int length = slot_kinds_length + kReservedIndexCount;
     58   if (length == kReservedIndexCount) {
     59     return Handle<TypeFeedbackMetadata>::cast(
     60         isolate->factory()->empty_fixed_array());
     61   }
     62 #ifdef DEBUG
     63   for (int i = 0; i < slot_count;) {
     64     FeedbackVectorSlotKind kind = spec->GetKind(i);
     65     int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
     66     for (int j = 1; j < entry_size; j++) {
     67       FeedbackVectorSlotKind kind = spec->GetKind(i + j);
     68       DCHECK_EQ(FeedbackVectorSlotKind::INVALID, kind);
     69     }
     70     i += entry_size;
     71   }
     72 #endif
     73 
     74   Handle<FixedArray> array = isolate->factory()->NewFixedArray(length, TENURED);
     75   array->set(kSlotsCountIndex, Smi::FromInt(slot_count));
     76   // Fill the bit-vector part with zeros.
     77   for (int i = 0; i < slot_kinds_length; i++) {
     78     array->set(kReservedIndexCount + i, Smi::FromInt(0));
     79   }
     80 
     81   Handle<TypeFeedbackMetadata> metadata =
     82       Handle<TypeFeedbackMetadata>::cast(array);
     83   for (int i = 0; i < slot_count; i++) {
     84     metadata->SetKind(FeedbackVectorSlot(i), spec->GetKind(i));
     85   }
     86   return metadata;
     87 }
     88 
     89 
     90 bool TypeFeedbackMetadata::SpecDiffersFrom(
     91     const FeedbackVectorSpec* other_spec) const {
     92   if (other_spec->slots() != slot_count()) {
     93     return true;
     94   }
     95 
     96   int slots = slot_count();
     97   for (int i = 0; i < slots; i++) {
     98     if (GetKind(FeedbackVectorSlot(i)) != other_spec->GetKind(i)) {
     99       return true;
    100     }
    101   }
    102   return false;
    103 }
    104 
    105 
    106 const char* TypeFeedbackMetadata::Kind2String(FeedbackVectorSlotKind kind) {
    107   switch (kind) {
    108     case FeedbackVectorSlotKind::INVALID:
    109       return "INVALID";
    110     case FeedbackVectorSlotKind::CALL_IC:
    111       return "CALL_IC";
    112     case FeedbackVectorSlotKind::LOAD_IC:
    113       return "LOAD_IC";
    114     case FeedbackVectorSlotKind::KEYED_LOAD_IC:
    115       return "KEYED_LOAD_IC";
    116     case FeedbackVectorSlotKind::STORE_IC:
    117       return "STORE_IC";
    118     case FeedbackVectorSlotKind::KEYED_STORE_IC:
    119       return "KEYED_STORE_IC";
    120     case FeedbackVectorSlotKind::GENERAL:
    121       return "STUB";
    122     case FeedbackVectorSlotKind::KINDS_NUMBER:
    123       break;
    124   }
    125   UNREACHABLE();
    126   return "?";
    127 }
    128 
    129 
    130 // static
    131 Handle<TypeFeedbackVector> TypeFeedbackVector::New(
    132     Isolate* isolate, Handle<TypeFeedbackMetadata> metadata) {
    133   Factory* factory = isolate->factory();
    134 
    135   const int slot_count = metadata->slot_count();
    136   const int length = slot_count + kReservedIndexCount;
    137   if (length == kReservedIndexCount) {
    138     return Handle<TypeFeedbackVector>::cast(factory->empty_fixed_array());
    139   }
    140 
    141   Handle<FixedArray> array = factory->NewFixedArray(length, TENURED);
    142   array->set(kMetadataIndex, *metadata);
    143 
    144   // Ensure we can skip the write barrier
    145   Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate);
    146   DCHECK_EQ(*factory->uninitialized_symbol(), *uninitialized_sentinel);
    147   for (int i = kReservedIndexCount; i < length; i++) {
    148     array->set(i, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
    149   }
    150 
    151   return Handle<TypeFeedbackVector>::cast(array);
    152 }
    153 
    154 
    155 // static
    156 int TypeFeedbackVector::GetIndexFromSpec(const FeedbackVectorSpec* spec,
    157                                          FeedbackVectorSlot slot) {
    158   return kReservedIndexCount + slot.ToInt();
    159 }
    160 
    161 
    162 // static
    163 Handle<TypeFeedbackVector> TypeFeedbackVector::Copy(
    164     Isolate* isolate, Handle<TypeFeedbackVector> vector) {
    165   Handle<TypeFeedbackVector> result;
    166   result = Handle<TypeFeedbackVector>::cast(
    167       isolate->factory()->CopyFixedArray(Handle<FixedArray>::cast(vector)));
    168   return result;
    169 }
    170 
    171 
    172 // This logic is copied from
    173 // StaticMarkingVisitor<StaticVisitor>::VisitCodeTarget.
    174 static bool ClearLogic(Isolate* isolate) {
    175   return FLAG_cleanup_code_caches_at_gc && isolate->serializer_enabled();
    176 }
    177 
    178 
    179 void TypeFeedbackVector::ClearSlotsImpl(SharedFunctionInfo* shared,
    180                                         bool force_clear) {
    181   Isolate* isolate = GetIsolate();
    182 
    183   if (!force_clear && !ClearLogic(isolate)) return;
    184 
    185   Object* uninitialized_sentinel =
    186       TypeFeedbackVector::RawUninitializedSentinel(isolate);
    187 
    188   TypeFeedbackMetadataIterator iter(metadata());
    189   while (iter.HasNext()) {
    190     FeedbackVectorSlot slot = iter.Next();
    191     FeedbackVectorSlotKind kind = iter.kind();
    192 
    193     Object* obj = Get(slot);
    194     if (obj != uninitialized_sentinel) {
    195       switch (kind) {
    196         case FeedbackVectorSlotKind::CALL_IC: {
    197           CallICNexus nexus(this, slot);
    198           nexus.Clear(shared->code());
    199           break;
    200         }
    201         case FeedbackVectorSlotKind::LOAD_IC: {
    202           LoadICNexus nexus(this, slot);
    203           nexus.Clear(shared->code());
    204           break;
    205         }
    206         case FeedbackVectorSlotKind::KEYED_LOAD_IC: {
    207           KeyedLoadICNexus nexus(this, slot);
    208           nexus.Clear(shared->code());
    209           break;
    210         }
    211         case FeedbackVectorSlotKind::STORE_IC: {
    212           StoreICNexus nexus(this, slot);
    213           nexus.Clear(shared->code());
    214           break;
    215         }
    216         case FeedbackVectorSlotKind::KEYED_STORE_IC: {
    217           KeyedStoreICNexus nexus(this, slot);
    218           nexus.Clear(shared->code());
    219           break;
    220         }
    221         case FeedbackVectorSlotKind::GENERAL: {
    222           if (obj->IsHeapObject()) {
    223             InstanceType instance_type =
    224                 HeapObject::cast(obj)->map()->instance_type();
    225             // AllocationSites are exempt from clearing. They don't store Maps
    226             // or Code pointers which can cause memory leaks if not cleared
    227             // regularly.
    228             if (instance_type != ALLOCATION_SITE_TYPE) {
    229               Set(slot, uninitialized_sentinel, SKIP_WRITE_BARRIER);
    230             }
    231           }
    232           break;
    233         }
    234         case FeedbackVectorSlotKind::INVALID:
    235         case FeedbackVectorSlotKind::KINDS_NUMBER:
    236           UNREACHABLE();
    237           break;
    238       }
    239     }
    240   }
    241 }
    242 
    243 
    244 // static
    245 void TypeFeedbackVector::ClearAllKeyedStoreICs(Isolate* isolate) {
    246   SharedFunctionInfo::Iterator iterator(isolate);
    247   SharedFunctionInfo* shared;
    248   while ((shared = iterator.Next())) {
    249     TypeFeedbackVector* vector = shared->feedback_vector();
    250     vector->ClearKeyedStoreICs(shared);
    251   }
    252 }
    253 
    254 
    255 void TypeFeedbackVector::ClearKeyedStoreICs(SharedFunctionInfo* shared) {
    256   Isolate* isolate = GetIsolate();
    257 
    258   Code* host = shared->code();
    259   Object* uninitialized_sentinel =
    260       TypeFeedbackVector::RawUninitializedSentinel(isolate);
    261 
    262   TypeFeedbackMetadataIterator iter(metadata());
    263   while (iter.HasNext()) {
    264     FeedbackVectorSlot slot = iter.Next();
    265     FeedbackVectorSlotKind kind = iter.kind();
    266     if (kind != FeedbackVectorSlotKind::KEYED_STORE_IC) continue;
    267     Object* obj = Get(slot);
    268     if (obj != uninitialized_sentinel) {
    269       KeyedStoreICNexus nexus(this, slot);
    270       nexus.Clear(host);
    271     }
    272   }
    273 }
    274 
    275 
    276 // static
    277 Handle<TypeFeedbackVector> TypeFeedbackVector::DummyVector(Isolate* isolate) {
    278   return isolate->factory()->dummy_vector();
    279 }
    280 
    281 
    282 Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) {
    283   Isolate* isolate = GetIsolate();
    284   Handle<Object> feedback = handle(GetFeedback(), isolate);
    285   if (!feedback->IsFixedArray() ||
    286       FixedArray::cast(*feedback)->length() != length) {
    287     Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
    288     SetFeedback(*array);
    289     return array;
    290   }
    291   return Handle<FixedArray>::cast(feedback);
    292 }
    293 
    294 
    295 Handle<FixedArray> FeedbackNexus::EnsureExtraArrayOfSize(int length) {
    296   Isolate* isolate = GetIsolate();
    297   Handle<Object> feedback_extra = handle(GetFeedbackExtra(), isolate);
    298   if (!feedback_extra->IsFixedArray() ||
    299       FixedArray::cast(*feedback_extra)->length() != length) {
    300     Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
    301     SetFeedbackExtra(*array);
    302     return array;
    303   }
    304   return Handle<FixedArray>::cast(feedback_extra);
    305 }
    306 
    307 
    308 void FeedbackNexus::InstallHandlers(Handle<FixedArray> array,
    309                                     MapHandleList* maps,
    310                                     CodeHandleList* handlers) {
    311   int receiver_count = maps->length();
    312   for (int current = 0; current < receiver_count; ++current) {
    313     Handle<Map> map = maps->at(current);
    314     Handle<WeakCell> cell = Map::WeakCellForMap(map);
    315     array->set(current * 2, *cell);
    316     array->set(current * 2 + 1, *handlers->at(current));
    317   }
    318 }
    319 
    320 
    321 void FeedbackNexus::ConfigureUninitialized() {
    322   SetFeedback(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
    323               SKIP_WRITE_BARRIER);
    324   SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
    325                    SKIP_WRITE_BARRIER);
    326 }
    327 
    328 
    329 void FeedbackNexus::ConfigurePremonomorphic() {
    330   SetFeedback(*TypeFeedbackVector::PremonomorphicSentinel(GetIsolate()),
    331               SKIP_WRITE_BARRIER);
    332   SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
    333                    SKIP_WRITE_BARRIER);
    334 }
    335 
    336 
    337 void FeedbackNexus::ConfigureMegamorphic() {
    338   Isolate* isolate = GetIsolate();
    339   SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate),
    340               SKIP_WRITE_BARRIER);
    341   SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
    342                    SKIP_WRITE_BARRIER);
    343 }
    344 
    345 
    346 InlineCacheState LoadICNexus::StateFromFeedback() const {
    347   Isolate* isolate = GetIsolate();
    348   Object* feedback = GetFeedback();
    349 
    350   if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
    351     return UNINITIALIZED;
    352   } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
    353     return MEGAMORPHIC;
    354   } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
    355     return PREMONOMORPHIC;
    356   } else if (feedback->IsFixedArray()) {
    357     // Determine state purely by our structure, don't check if the maps are
    358     // cleared.
    359     return POLYMORPHIC;
    360   } else if (feedback->IsWeakCell()) {
    361     // Don't check if the map is cleared.
    362     return MONOMORPHIC;
    363   }
    364 
    365   return UNINITIALIZED;
    366 }
    367 
    368 
    369 InlineCacheState KeyedLoadICNexus::StateFromFeedback() const {
    370   Isolate* isolate = GetIsolate();
    371   Object* feedback = GetFeedback();
    372 
    373   if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
    374     return UNINITIALIZED;
    375   } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
    376     return PREMONOMORPHIC;
    377   } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
    378     return MEGAMORPHIC;
    379   } else if (feedback->IsFixedArray()) {
    380     // Determine state purely by our structure, don't check if the maps are
    381     // cleared.
    382     return POLYMORPHIC;
    383   } else if (feedback->IsWeakCell()) {
    384     // Don't check if the map is cleared.
    385     return MONOMORPHIC;
    386   } else if (feedback->IsName()) {
    387     Object* extra = GetFeedbackExtra();
    388     FixedArray* extra_array = FixedArray::cast(extra);
    389     return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC;
    390   }
    391 
    392   return UNINITIALIZED;
    393 }
    394 
    395 
    396 InlineCacheState StoreICNexus::StateFromFeedback() const {
    397   Isolate* isolate = GetIsolate();
    398   Object* feedback = GetFeedback();
    399 
    400   if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
    401     return UNINITIALIZED;
    402   } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
    403     return MEGAMORPHIC;
    404   } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
    405     return PREMONOMORPHIC;
    406   } else if (feedback->IsFixedArray()) {
    407     // Determine state purely by our structure, don't check if the maps are
    408     // cleared.
    409     return POLYMORPHIC;
    410   } else if (feedback->IsWeakCell()) {
    411     // Don't check if the map is cleared.
    412     return MONOMORPHIC;
    413   }
    414 
    415   return UNINITIALIZED;
    416 }
    417 
    418 
    419 InlineCacheState KeyedStoreICNexus::StateFromFeedback() const {
    420   Isolate* isolate = GetIsolate();
    421   Object* feedback = GetFeedback();
    422 
    423   if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
    424     return UNINITIALIZED;
    425   } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
    426     return PREMONOMORPHIC;
    427   } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
    428     return MEGAMORPHIC;
    429   } else if (feedback->IsFixedArray()) {
    430     // Determine state purely by our structure, don't check if the maps are
    431     // cleared.
    432     return POLYMORPHIC;
    433   } else if (feedback->IsWeakCell()) {
    434     // Don't check if the map is cleared.
    435     return MONOMORPHIC;
    436   } else if (feedback->IsName()) {
    437     Object* extra = GetFeedbackExtra();
    438     FixedArray* extra_array = FixedArray::cast(extra);
    439     return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC;
    440   }
    441 
    442   return UNINITIALIZED;
    443 }
    444 
    445 
    446 InlineCacheState CallICNexus::StateFromFeedback() const {
    447   Isolate* isolate = GetIsolate();
    448   Object* feedback = GetFeedback();
    449   DCHECK(GetFeedbackExtra() ==
    450              *TypeFeedbackVector::UninitializedSentinel(isolate) ||
    451          GetFeedbackExtra()->IsSmi());
    452 
    453   if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
    454     return GENERIC;
    455   } else if (feedback->IsAllocationSite() || feedback->IsWeakCell()) {
    456     return MONOMORPHIC;
    457   }
    458 
    459   CHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate));
    460   return UNINITIALIZED;
    461 }
    462 
    463 
    464 int CallICNexus::ExtractCallCount() {
    465   Object* call_count = GetFeedbackExtra();
    466   if (call_count->IsSmi()) {
    467     int value = Smi::cast(call_count)->value() / 2;
    468     return value;
    469   }
    470   return -1;
    471 }
    472 
    473 
    474 void CallICNexus::Clear(Code* host) { CallIC::Clear(GetIsolate(), host, this); }
    475 
    476 
    477 void CallICNexus::ConfigureMonomorphicArray() {
    478   Object* feedback = GetFeedback();
    479   if (!feedback->IsAllocationSite()) {
    480     Handle<AllocationSite> new_site =
    481         GetIsolate()->factory()->NewAllocationSite();
    482     SetFeedback(*new_site);
    483   }
    484   SetFeedbackExtra(Smi::FromInt(kCallCountIncrement), SKIP_WRITE_BARRIER);
    485 }
    486 
    487 
    488 void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) {
    489   Handle<WeakCell> new_cell = GetIsolate()->factory()->NewWeakCell(function);
    490   SetFeedback(*new_cell);
    491   SetFeedbackExtra(Smi::FromInt(kCallCountIncrement), SKIP_WRITE_BARRIER);
    492 }
    493 
    494 
    495 void CallICNexus::ConfigureMegamorphic() {
    496   FeedbackNexus::ConfigureMegamorphic();
    497 }
    498 
    499 
    500 void CallICNexus::ConfigureMegamorphic(int call_count) {
    501   SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(GetIsolate()),
    502               SKIP_WRITE_BARRIER);
    503   SetFeedbackExtra(Smi::FromInt(call_count * kCallCountIncrement),
    504                    SKIP_WRITE_BARRIER);
    505 }
    506 
    507 
    508 void LoadICNexus::ConfigureMonomorphic(Handle<Map> receiver_map,
    509                                        Handle<Code> handler) {
    510   Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
    511   SetFeedback(*cell);
    512   SetFeedbackExtra(*handler);
    513 }
    514 
    515 
    516 void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name,
    517                                             Handle<Map> receiver_map,
    518                                             Handle<Code> handler) {
    519   Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
    520   if (name.is_null()) {
    521     SetFeedback(*cell);
    522     SetFeedbackExtra(*handler);
    523   } else {
    524     Handle<FixedArray> array = EnsureExtraArrayOfSize(2);
    525     SetFeedback(*name);
    526     array->set(0, *cell);
    527     array->set(1, *handler);
    528   }
    529 }
    530 
    531 
    532 void StoreICNexus::ConfigureMonomorphic(Handle<Map> receiver_map,
    533                                         Handle<Code> handler) {
    534   Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
    535   SetFeedback(*cell);
    536   SetFeedbackExtra(*handler);
    537 }
    538 
    539 
    540 void KeyedStoreICNexus::ConfigureMonomorphic(Handle<Name> name,
    541                                              Handle<Map> receiver_map,
    542                                              Handle<Code> handler) {
    543   Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
    544   if (name.is_null()) {
    545     SetFeedback(*cell);
    546     SetFeedbackExtra(*handler);
    547   } else {
    548     Handle<FixedArray> array = EnsureExtraArrayOfSize(2);
    549     SetFeedback(*name);
    550     array->set(0, *cell);
    551     array->set(1, *handler);
    552   }
    553 }
    554 
    555 
    556 void LoadICNexus::ConfigurePolymorphic(MapHandleList* maps,
    557                                        CodeHandleList* handlers) {
    558   Isolate* isolate = GetIsolate();
    559   int receiver_count = maps->length();
    560   Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 2);
    561   InstallHandlers(array, maps, handlers);
    562   SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
    563                    SKIP_WRITE_BARRIER);
    564 }
    565 
    566 
    567 void KeyedLoadICNexus::ConfigurePolymorphic(Handle<Name> name,
    568                                             MapHandleList* maps,
    569                                             CodeHandleList* handlers) {
    570   int receiver_count = maps->length();
    571   DCHECK(receiver_count > 1);
    572   Handle<FixedArray> array;
    573   if (name.is_null()) {
    574     array = EnsureArrayOfSize(receiver_count * 2);
    575     SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
    576                      SKIP_WRITE_BARRIER);
    577   } else {
    578     array = EnsureExtraArrayOfSize(receiver_count * 2);
    579     SetFeedback(*name);
    580   }
    581 
    582   InstallHandlers(array, maps, handlers);
    583 }
    584 
    585 
    586 void StoreICNexus::ConfigurePolymorphic(MapHandleList* maps,
    587                                         CodeHandleList* handlers) {
    588   Isolate* isolate = GetIsolate();
    589   int receiver_count = maps->length();
    590   Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 2);
    591   InstallHandlers(array, maps, handlers);
    592   SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
    593                    SKIP_WRITE_BARRIER);
    594 }
    595 
    596 
    597 void KeyedStoreICNexus::ConfigurePolymorphic(Handle<Name> name,
    598                                              MapHandleList* maps,
    599                                              CodeHandleList* handlers) {
    600   int receiver_count = maps->length();
    601   DCHECK(receiver_count > 1);
    602   Handle<FixedArray> array;
    603   if (name.is_null()) {
    604     array = EnsureArrayOfSize(receiver_count * 2);
    605     SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
    606                      SKIP_WRITE_BARRIER);
    607   } else {
    608     array = EnsureExtraArrayOfSize(receiver_count * 2);
    609     SetFeedback(*name);
    610   }
    611 
    612   InstallHandlers(array, maps, handlers);
    613 }
    614 
    615 
    616 void KeyedStoreICNexus::ConfigurePolymorphic(MapHandleList* maps,
    617                                              MapHandleList* transitioned_maps,
    618                                              CodeHandleList* handlers) {
    619   int receiver_count = maps->length();
    620   DCHECK(receiver_count > 1);
    621   Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 3);
    622   SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
    623                    SKIP_WRITE_BARRIER);
    624 
    625   Handle<Oddball> undefined_value = GetIsolate()->factory()->undefined_value();
    626   for (int i = 0; i < receiver_count; ++i) {
    627     Handle<Map> map = maps->at(i);
    628     Handle<WeakCell> cell = Map::WeakCellForMap(map);
    629     array->set(i * 3, *cell);
    630     if (!transitioned_maps->at(i).is_null()) {
    631       Handle<Map> transitioned_map = transitioned_maps->at(i);
    632       cell = Map::WeakCellForMap(transitioned_map);
    633       array->set((i * 3) + 1, *cell);
    634     } else {
    635       array->set((i * 3) + 1, *undefined_value);
    636     }
    637     array->set((i * 3) + 2, *handlers->at(i));
    638   }
    639 }
    640 
    641 
    642 int FeedbackNexus::ExtractMaps(MapHandleList* maps) const {
    643   Isolate* isolate = GetIsolate();
    644   Object* feedback = GetFeedback();
    645   bool is_named_feedback = IsPropertyNameFeedback(feedback);
    646   if (feedback->IsFixedArray() || is_named_feedback) {
    647     int found = 0;
    648     if (is_named_feedback) {
    649       feedback = GetFeedbackExtra();
    650     }
    651     FixedArray* array = FixedArray::cast(feedback);
    652     // The array should be of the form
    653     // [map, handler, map, handler, ...]
    654     // or
    655     // [map, map, handler, map, map, handler, ...]
    656     DCHECK(array->length() >= 2);
    657     int increment = array->get(1)->IsCode() ? 2 : 3;
    658     for (int i = 0; i < array->length(); i += increment) {
    659       DCHECK(array->get(i)->IsWeakCell());
    660       WeakCell* cell = WeakCell::cast(array->get(i));
    661       if (!cell->cleared()) {
    662         Map* map = Map::cast(cell->value());
    663         maps->Add(handle(map, isolate));
    664         found++;
    665       }
    666     }
    667     return found;
    668   } else if (feedback->IsWeakCell()) {
    669     WeakCell* cell = WeakCell::cast(feedback);
    670     if (!cell->cleared()) {
    671       Map* map = Map::cast(cell->value());
    672       maps->Add(handle(map, isolate));
    673       return 1;
    674     }
    675   }
    676 
    677   return 0;
    678 }
    679 
    680 
    681 MaybeHandle<Code> FeedbackNexus::FindHandlerForMap(Handle<Map> map) const {
    682   Object* feedback = GetFeedback();
    683   bool is_named_feedback = IsPropertyNameFeedback(feedback);
    684   if (feedback->IsFixedArray() || is_named_feedback) {
    685     if (is_named_feedback) {
    686       feedback = GetFeedbackExtra();
    687     }
    688     FixedArray* array = FixedArray::cast(feedback);
    689     DCHECK(array->length() >= 2);
    690     int increment = array->get(1)->IsCode() ? 2 : 3;
    691     for (int i = 0; i < array->length(); i += increment) {
    692       DCHECK(array->get(i)->IsWeakCell());
    693       WeakCell* cell = WeakCell::cast(array->get(i));
    694       if (!cell->cleared()) {
    695         Map* array_map = Map::cast(cell->value());
    696         if (array_map == *map) {
    697           Code* code = Code::cast(array->get(i + increment - 1));
    698           DCHECK(code->kind() == Code::HANDLER);
    699           return handle(code);
    700         }
    701       }
    702     }
    703   } else if (feedback->IsWeakCell()) {
    704     WeakCell* cell = WeakCell::cast(feedback);
    705     if (!cell->cleared()) {
    706       Map* cell_map = Map::cast(cell->value());
    707       if (cell_map == *map) {
    708         Code* code = Code::cast(GetFeedbackExtra());
    709         DCHECK(code->kind() == Code::HANDLER);
    710         return handle(code);
    711       }
    712     }
    713   }
    714 
    715   return MaybeHandle<Code>();
    716 }
    717 
    718 
    719 bool FeedbackNexus::FindHandlers(CodeHandleList* code_list, int length) const {
    720   Object* feedback = GetFeedback();
    721   int count = 0;
    722   bool is_named_feedback = IsPropertyNameFeedback(feedback);
    723   if (feedback->IsFixedArray() || is_named_feedback) {
    724     if (is_named_feedback) {
    725       feedback = GetFeedbackExtra();
    726     }
    727     FixedArray* array = FixedArray::cast(feedback);
    728     // The array should be of the form
    729     // [map, handler, map, handler, ...]
    730     // or
    731     // [map, map, handler, map, map, handler, ...]
    732     // Be sure to skip handlers whose maps have been cleared.
    733     DCHECK(array->length() >= 2);
    734     int increment = array->get(1)->IsCode() ? 2 : 3;
    735     for (int i = 0; i < array->length(); i += increment) {
    736       DCHECK(array->get(i)->IsWeakCell());
    737       WeakCell* cell = WeakCell::cast(array->get(i));
    738       if (!cell->cleared()) {
    739         Code* code = Code::cast(array->get(i + increment - 1));
    740         DCHECK(code->kind() == Code::HANDLER);
    741         code_list->Add(handle(code));
    742         count++;
    743       }
    744     }
    745   } else if (feedback->IsWeakCell()) {
    746     WeakCell* cell = WeakCell::cast(feedback);
    747     if (!cell->cleared()) {
    748       Code* code = Code::cast(GetFeedbackExtra());
    749       DCHECK(code->kind() == Code::HANDLER);
    750       code_list->Add(handle(code));
    751       count++;
    752     }
    753   }
    754   return count == length;
    755 }
    756 
    757 
    758 void LoadICNexus::Clear(Code* host) { LoadIC::Clear(GetIsolate(), host, this); }
    759 
    760 
    761 void KeyedLoadICNexus::Clear(Code* host) {
    762   KeyedLoadIC::Clear(GetIsolate(), host, this);
    763 }
    764 
    765 
    766 Name* KeyedLoadICNexus::FindFirstName() const {
    767   Object* feedback = GetFeedback();
    768   if (IsPropertyNameFeedback(feedback)) {
    769     return Name::cast(feedback);
    770   }
    771   return NULL;
    772 }
    773 
    774 
    775 Name* KeyedStoreICNexus::FindFirstName() const {
    776   Object* feedback = GetFeedback();
    777   if (IsPropertyNameFeedback(feedback)) {
    778     return Name::cast(feedback);
    779   }
    780   return NULL;
    781 }
    782 
    783 
    784 void StoreICNexus::Clear(Code* host) {
    785   StoreIC::Clear(GetIsolate(), host, this);
    786 }
    787 
    788 
    789 void KeyedStoreICNexus::Clear(Code* host) {
    790   KeyedStoreIC::Clear(GetIsolate(), host, this);
    791 }
    792 
    793 
    794 KeyedAccessStoreMode KeyedStoreICNexus::GetKeyedAccessStoreMode() const {
    795   KeyedAccessStoreMode mode = STANDARD_STORE;
    796   MapHandleList maps;
    797   CodeHandleList handlers;
    798 
    799   if (GetKeyType() == PROPERTY) return mode;
    800 
    801   ExtractMaps(&maps);
    802   FindHandlers(&handlers, maps.length());
    803   for (int i = 0; i < handlers.length(); i++) {
    804     // The first handler that isn't the slow handler will have the bits we need.
    805     Handle<Code> handler = handlers.at(i);
    806     CodeStub::Major major_key = CodeStub::MajorKeyFromKey(handler->stub_key());
    807     uint32_t minor_key = CodeStub::MinorKeyFromKey(handler->stub_key());
    808     CHECK(major_key == CodeStub::KeyedStoreSloppyArguments ||
    809           major_key == CodeStub::StoreFastElement ||
    810           major_key == CodeStub::StoreElement ||
    811           major_key == CodeStub::ElementsTransitionAndStore ||
    812           major_key == CodeStub::NoCache);
    813     if (major_key != CodeStub::NoCache) {
    814       mode = CommonStoreModeBits::decode(minor_key);
    815       break;
    816     }
    817   }
    818 
    819   return mode;
    820 }
    821 
    822 
    823 IcCheckType KeyedStoreICNexus::GetKeyType() const {
    824   // The structure of the vector slots tells us the type.
    825   return GetFeedback()->IsName() ? PROPERTY : ELEMENT;
    826 }
    827 }  // namespace internal
    828 }  // namespace v8
    829