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 #ifndef V8_TYPE_FEEDBACK_VECTOR_H_
      6 #define V8_TYPE_FEEDBACK_VECTOR_H_
      7 
      8 #include <vector>
      9 
     10 #include "src/base/logging.h"
     11 #include "src/elements-kind.h"
     12 #include "src/objects.h"
     13 #include "src/type-hints.h"
     14 #include "src/zone/zone-containers.h"
     15 
     16 namespace v8 {
     17 namespace internal {
     18 
     19 enum class FeedbackVectorSlotKind {
     20   // This kind means that the slot points to the middle of other slot
     21   // which occupies more than one feedback vector element.
     22   // There must be no such slots in the system.
     23   INVALID,
     24 
     25   CALL_IC,
     26   LOAD_IC,
     27   LOAD_GLOBAL_IC,
     28   KEYED_LOAD_IC,
     29   STORE_IC,
     30   KEYED_STORE_IC,
     31   INTERPRETER_BINARYOP_IC,
     32   INTERPRETER_COMPARE_IC,
     33 
     34   // This is a general purpose slot that occupies one feedback vector element.
     35   GENERAL,
     36 
     37   KINDS_NUMBER  // Last value indicating number of kinds.
     38 };
     39 
     40 std::ostream& operator<<(std::ostream& os, FeedbackVectorSlotKind kind);
     41 
     42 
     43 template <typename Derived>
     44 class FeedbackVectorSpecBase {
     45  public:
     46   inline FeedbackVectorSlot AddSlot(FeedbackVectorSlotKind kind);
     47 
     48   FeedbackVectorSlot AddCallICSlot() {
     49     return AddSlot(FeedbackVectorSlotKind::CALL_IC);
     50   }
     51 
     52   FeedbackVectorSlot AddLoadICSlot() {
     53     return AddSlot(FeedbackVectorSlotKind::LOAD_IC);
     54   }
     55 
     56   FeedbackVectorSlot AddLoadGlobalICSlot(Handle<String> name) {
     57     This()->append_name(name);
     58     return AddSlot(FeedbackVectorSlotKind::LOAD_GLOBAL_IC);
     59   }
     60 
     61   FeedbackVectorSlot AddKeyedLoadICSlot() {
     62     return AddSlot(FeedbackVectorSlotKind::KEYED_LOAD_IC);
     63   }
     64 
     65   FeedbackVectorSlot AddStoreICSlot() {
     66     return AddSlot(FeedbackVectorSlotKind::STORE_IC);
     67   }
     68 
     69   FeedbackVectorSlot AddKeyedStoreICSlot() {
     70     return AddSlot(FeedbackVectorSlotKind::KEYED_STORE_IC);
     71   }
     72 
     73   FeedbackVectorSlot AddInterpreterBinaryOpICSlot() {
     74     return AddSlot(FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC);
     75   }
     76 
     77   FeedbackVectorSlot AddInterpreterCompareICSlot() {
     78     return AddSlot(FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC);
     79   }
     80 
     81   FeedbackVectorSlot AddGeneralSlot() {
     82     return AddSlot(FeedbackVectorSlotKind::GENERAL);
     83   }
     84 
     85 #ifdef OBJECT_PRINT
     86   // For gdb debugging.
     87   void Print();
     88 #endif  // OBJECT_PRINT
     89 
     90   DECLARE_PRINTER(FeedbackVectorSpec)
     91 
     92  private:
     93   Derived* This() { return static_cast<Derived*>(this); }
     94 };
     95 
     96 
     97 class StaticFeedbackVectorSpec
     98     : public FeedbackVectorSpecBase<StaticFeedbackVectorSpec> {
     99  public:
    100   StaticFeedbackVectorSpec() : slot_count_(0), name_count_(0) {}
    101 
    102   int slots() const { return slot_count_; }
    103 
    104   FeedbackVectorSlotKind GetKind(int slot) const {
    105     DCHECK(slot >= 0 && slot < slot_count_);
    106     return kinds_[slot];
    107   }
    108 
    109   int name_count() const { return name_count_; }
    110 
    111   Handle<String> GetName(int index) const {
    112     DCHECK(index >= 0 && index < name_count_);
    113     return names_[index];
    114   }
    115 
    116  private:
    117   friend class FeedbackVectorSpecBase<StaticFeedbackVectorSpec>;
    118 
    119   void append(FeedbackVectorSlotKind kind) {
    120     DCHECK(slot_count_ < kMaxLength);
    121     kinds_[slot_count_++] = kind;
    122   }
    123 
    124   void append_name(Handle<String> name) {
    125     DCHECK(name_count_ < kMaxLength);
    126     names_[name_count_++] = name;
    127   }
    128 
    129   static const int kMaxLength = 12;
    130 
    131   int slot_count_;
    132   FeedbackVectorSlotKind kinds_[kMaxLength];
    133   int name_count_;
    134   Handle<String> names_[kMaxLength];
    135 };
    136 
    137 
    138 class FeedbackVectorSpec : public FeedbackVectorSpecBase<FeedbackVectorSpec> {
    139  public:
    140   explicit FeedbackVectorSpec(Zone* zone) : slot_kinds_(zone), names_(zone) {
    141     slot_kinds_.reserve(16);
    142     names_.reserve(8);
    143   }
    144 
    145   int slots() const { return static_cast<int>(slot_kinds_.size()); }
    146 
    147   FeedbackVectorSlotKind GetKind(int slot) const {
    148     return static_cast<FeedbackVectorSlotKind>(slot_kinds_.at(slot));
    149   }
    150 
    151   int name_count() const { return static_cast<int>(names_.size()); }
    152 
    153   Handle<String> GetName(int index) const { return names_.at(index); }
    154 
    155  private:
    156   friend class FeedbackVectorSpecBase<FeedbackVectorSpec>;
    157 
    158   void append(FeedbackVectorSlotKind kind) {
    159     slot_kinds_.push_back(static_cast<unsigned char>(kind));
    160   }
    161 
    162   void append_name(Handle<String> name) { names_.push_back(name); }
    163 
    164   ZoneVector<unsigned char> slot_kinds_;
    165   ZoneVector<Handle<String>> names_;
    166 };
    167 
    168 
    169 // The shape of the TypeFeedbackMetadata is an array with:
    170 // 0: slot_count
    171 // 1: names table
    172 // 2..N: slot kinds packed into a bit vector
    173 //
    174 class TypeFeedbackMetadata : public FixedArray {
    175  public:
    176   // Casting.
    177   static inline TypeFeedbackMetadata* cast(Object* obj);
    178 
    179   static const int kSlotsCountIndex = 0;
    180   static const int kNamesTableIndex = 1;
    181   static const int kReservedIndexCount = 2;
    182 
    183   static const int kNameTableEntrySize = 2;
    184   static const int kNameTableSlotIndex = 0;
    185   static const int kNameTableNameIndex = 1;
    186 
    187   // Returns number of feedback vector elements used by given slot kind.
    188   static inline int GetSlotSize(FeedbackVectorSlotKind kind);
    189 
    190   // Defines if slots of given kind require "name".
    191   static inline bool SlotRequiresName(FeedbackVectorSlotKind kind);
    192 
    193   bool SpecDiffersFrom(const FeedbackVectorSpec* other_spec) const;
    194 
    195   bool DiffersFrom(const TypeFeedbackMetadata* other_metadata) const;
    196 
    197   inline bool is_empty() const;
    198 
    199   // Returns number of slots in the vector.
    200   inline int slot_count() const;
    201 
    202   // Returns slot kind for given slot.
    203   FeedbackVectorSlotKind GetKind(FeedbackVectorSlot slot) const;
    204 
    205   // Returns name for given slot.
    206   String* GetName(FeedbackVectorSlot slot) const;
    207 
    208   template <typename Spec>
    209   static Handle<TypeFeedbackMetadata> New(Isolate* isolate, const Spec* spec);
    210 
    211 #ifdef OBJECT_PRINT
    212   // For gdb debugging.
    213   void Print();
    214 #endif  // OBJECT_PRINT
    215 
    216   DECLARE_PRINTER(TypeFeedbackMetadata)
    217 
    218   static const char* Kind2String(FeedbackVectorSlotKind kind);
    219 
    220  private:
    221   static const int kFeedbackVectorSlotKindBits = 5;
    222   STATIC_ASSERT(static_cast<int>(FeedbackVectorSlotKind::KINDS_NUMBER) <
    223                 (1 << kFeedbackVectorSlotKindBits));
    224 
    225   void SetKind(FeedbackVectorSlot slot, FeedbackVectorSlotKind kind);
    226 
    227   typedef BitSetComputer<FeedbackVectorSlotKind, kFeedbackVectorSlotKindBits,
    228                          kSmiValueSize, uint32_t> VectorICComputer;
    229 
    230   DISALLOW_IMPLICIT_CONSTRUCTORS(TypeFeedbackMetadata);
    231 };
    232 
    233 
    234 // The shape of the TypeFeedbackVector is an array with:
    235 // 0: feedback metadata
    236 // 1: invocation count
    237 // 2: feedback slot #0
    238 // ...
    239 // 2 + slot_count - 1: feedback slot #(slot_count-1)
    240 //
    241 class TypeFeedbackVector : public FixedArray {
    242  public:
    243   // Casting.
    244   static inline TypeFeedbackVector* cast(Object* obj);
    245 
    246   static const int kMetadataIndex = 0;
    247   static const int kInvocationCountIndex = 1;
    248   static const int kReservedIndexCount = 2;
    249 
    250   inline void ComputeCounts(int* with_type_info, int* generic,
    251                             int* vector_ic_count, bool code_is_interpreted);
    252 
    253   inline bool is_empty() const;
    254 
    255   // Returns number of slots in the vector.
    256   inline int slot_count() const;
    257 
    258   inline TypeFeedbackMetadata* metadata() const;
    259   inline int invocation_count() const;
    260 
    261   // Conversion from a slot to an integer index to the underlying array.
    262   static int GetIndex(FeedbackVectorSlot slot) {
    263     return kReservedIndexCount + slot.ToInt();
    264   }
    265   static int GetIndexFromSpec(const FeedbackVectorSpec* spec,
    266                               FeedbackVectorSlot slot);
    267 
    268   // Conversion from an integer index to the underlying array to a slot.
    269   static inline FeedbackVectorSlot ToSlot(int index);
    270   inline Object* Get(FeedbackVectorSlot slot) const;
    271   inline void Set(FeedbackVectorSlot slot, Object* value,
    272                   WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
    273 
    274   // Returns slot kind for given slot.
    275   FeedbackVectorSlotKind GetKind(FeedbackVectorSlot slot) const;
    276   // Returns name corresponding to given slot or an empty string.
    277   String* GetName(FeedbackVectorSlot slot) const;
    278 
    279   static Handle<TypeFeedbackVector> New(Isolate* isolate,
    280                                         Handle<TypeFeedbackMetadata> metadata);
    281 
    282   static Handle<TypeFeedbackVector> Copy(Isolate* isolate,
    283                                          Handle<TypeFeedbackVector> vector);
    284 
    285 #ifdef OBJECT_PRINT
    286   // For gdb debugging.
    287   void Print();
    288 #endif  // OBJECT_PRINT
    289 
    290   DECLARE_PRINTER(TypeFeedbackVector)
    291 
    292   // Clears the vector slots.
    293   void ClearSlots(SharedFunctionInfo* shared) { ClearSlotsImpl(shared, true); }
    294 
    295   void ClearSlotsAtGCTime(SharedFunctionInfo* shared) {
    296     ClearSlotsImpl(shared, false);
    297   }
    298 
    299   static void ClearAllKeyedStoreICs(Isolate* isolate);
    300   void ClearKeyedStoreICs(SharedFunctionInfo* shared);
    301 
    302   // The object that indicates an uninitialized cache.
    303   static inline Handle<Symbol> UninitializedSentinel(Isolate* isolate);
    304 
    305   // The object that indicates a megamorphic state.
    306   static inline Handle<Symbol> MegamorphicSentinel(Isolate* isolate);
    307 
    308   // The object that indicates a premonomorphic state.
    309   static inline Handle<Symbol> PremonomorphicSentinel(Isolate* isolate);
    310 
    311   // A raw version of the uninitialized sentinel that's safe to read during
    312   // garbage collection (e.g., for patching the cache).
    313   static inline Symbol* RawUninitializedSentinel(Isolate* isolate);
    314 
    315   static const int kDummyLoadICSlot = 0;
    316   static const int kDummyKeyedLoadICSlot = 2;
    317   static const int kDummyStoreICSlot = 4;
    318   static const int kDummyKeyedStoreICSlot = 6;
    319 
    320   static Handle<TypeFeedbackVector> DummyVector(Isolate* isolate);
    321   static FeedbackVectorSlot DummySlot(int dummyIndex) {
    322     DCHECK(dummyIndex >= 0 && dummyIndex <= kDummyKeyedStoreICSlot);
    323     return FeedbackVectorSlot(dummyIndex);
    324   }
    325 
    326  private:
    327   void ClearSlotsImpl(SharedFunctionInfo* shared, bool force_clear);
    328 
    329   DISALLOW_IMPLICIT_CONSTRUCTORS(TypeFeedbackVector);
    330 };
    331 
    332 
    333 // The following asserts protect an optimization in type feedback vector
    334 // code that looks into the contents of a slot assuming to find a String,
    335 // a Symbol, an AllocationSite, a WeakCell, or a FixedArray.
    336 STATIC_ASSERT(WeakCell::kSize >= 2 * kPointerSize);
    337 STATIC_ASSERT(WeakCell::kValueOffset == AllocationSite::kTransitionInfoOffset);
    338 STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset);
    339 STATIC_ASSERT(WeakCell::kValueOffset == Name::kHashFieldSlot);
    340 // Verify that an empty hash field looks like a tagged object, but can't
    341 // possibly be confused with a pointer.
    342 STATIC_ASSERT((Name::kEmptyHashField & kHeapObjectTag) == kHeapObjectTag);
    343 STATIC_ASSERT(Name::kEmptyHashField == 0x3);
    344 // Verify that a set hash field will not look like a tagged object.
    345 STATIC_ASSERT(Name::kHashNotComputedMask == kHeapObjectTag);
    346 
    347 
    348 class TypeFeedbackMetadataIterator {
    349  public:
    350   explicit TypeFeedbackMetadataIterator(Handle<TypeFeedbackMetadata> metadata)
    351       : metadata_handle_(metadata),
    352         next_slot_(FeedbackVectorSlot(0)),
    353         slot_kind_(FeedbackVectorSlotKind::INVALID) {}
    354 
    355   explicit TypeFeedbackMetadataIterator(TypeFeedbackMetadata* metadata)
    356       : metadata_(metadata),
    357         next_slot_(FeedbackVectorSlot(0)),
    358         slot_kind_(FeedbackVectorSlotKind::INVALID) {}
    359 
    360   inline bool HasNext() const;
    361 
    362   inline FeedbackVectorSlot Next();
    363 
    364   // Returns slot kind of the last slot returned by Next().
    365   FeedbackVectorSlotKind kind() const {
    366     DCHECK_NE(FeedbackVectorSlotKind::INVALID, slot_kind_);
    367     DCHECK_NE(FeedbackVectorSlotKind::KINDS_NUMBER, slot_kind_);
    368     return slot_kind_;
    369   }
    370 
    371   // Returns entry size of the last slot returned by Next().
    372   inline int entry_size() const;
    373 
    374   String* name() const {
    375     DCHECK(TypeFeedbackMetadata::SlotRequiresName(kind()));
    376     return metadata()->GetName(cur_slot_);
    377   }
    378 
    379  private:
    380   TypeFeedbackMetadata* metadata() const {
    381     return !metadata_handle_.is_null() ? *metadata_handle_ : metadata_;
    382   }
    383 
    384   // The reason for having a handle and a raw pointer to the meta data is
    385   // to have a single iterator implementation for both "handlified" and raw
    386   // pointer use cases.
    387   Handle<TypeFeedbackMetadata> metadata_handle_;
    388   TypeFeedbackMetadata* metadata_;
    389   FeedbackVectorSlot cur_slot_;
    390   FeedbackVectorSlot next_slot_;
    391   FeedbackVectorSlotKind slot_kind_;
    392 };
    393 
    394 
    395 // A FeedbackNexus is the combination of a TypeFeedbackVector and a slot.
    396 // Derived classes customize the update and retrieval of feedback.
    397 class FeedbackNexus {
    398  public:
    399   FeedbackNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
    400       : vector_handle_(vector), vector_(NULL), slot_(slot) {}
    401   FeedbackNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
    402       : vector_(vector), slot_(slot) {}
    403   virtual ~FeedbackNexus() {}
    404 
    405   Handle<TypeFeedbackVector> vector_handle() const {
    406     DCHECK(vector_ == NULL);
    407     return vector_handle_;
    408   }
    409   TypeFeedbackVector* vector() const {
    410     return vector_handle_.is_null() ? vector_ : *vector_handle_;
    411   }
    412   FeedbackVectorSlot slot() const { return slot_; }
    413 
    414   InlineCacheState ic_state() const { return StateFromFeedback(); }
    415   bool IsUninitialized() const { return StateFromFeedback() == UNINITIALIZED; }
    416   Map* FindFirstMap() const {
    417     MapHandleList maps;
    418     ExtractMaps(&maps);
    419     if (maps.length() > 0) return *maps.at(0);
    420     return NULL;
    421   }
    422 
    423   // TODO(mvstanton): remove FindAllMaps, it didn't survive a code review.
    424   void FindAllMaps(MapHandleList* maps) const { ExtractMaps(maps); }
    425 
    426   virtual InlineCacheState StateFromFeedback() const = 0;
    427   virtual int ExtractMaps(MapHandleList* maps) const;
    428   virtual MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const;
    429   virtual bool FindHandlers(List<Handle<Object>>* code_list,
    430                             int length = -1) const;
    431   virtual Name* FindFirstName() const { return NULL; }
    432 
    433   virtual void ConfigureUninitialized();
    434   virtual void ConfigurePremonomorphic();
    435   virtual void ConfigureMegamorphic();
    436 
    437   inline Object* GetFeedback() const;
    438   inline Object* GetFeedbackExtra() const;
    439 
    440   inline Isolate* GetIsolate() const;
    441 
    442  protected:
    443   inline void SetFeedback(Object* feedback,
    444                           WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
    445   inline void SetFeedbackExtra(Object* feedback_extra,
    446                                WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
    447 
    448   Handle<FixedArray> EnsureArrayOfSize(int length);
    449   Handle<FixedArray> EnsureExtraArrayOfSize(int length);
    450   void InstallHandlers(Handle<FixedArray> array, MapHandleList* maps,
    451                        List<Handle<Object>>* handlers);
    452 
    453  private:
    454   // The reason for having a vector handle and a raw pointer is that we can and
    455   // should use handles during IC miss, but not during GC when we clear ICs. If
    456   // you have a handle to the vector that is better because more operations can
    457   // be done, like allocation.
    458   Handle<TypeFeedbackVector> vector_handle_;
    459   TypeFeedbackVector* vector_;
    460   FeedbackVectorSlot slot_;
    461 };
    462 
    463 
    464 class CallICNexus final : public FeedbackNexus {
    465  public:
    466   CallICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
    467       : FeedbackNexus(vector, slot) {
    468     DCHECK_EQ(FeedbackVectorSlotKind::CALL_IC, vector->GetKind(slot));
    469   }
    470   CallICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
    471       : FeedbackNexus(vector, slot) {
    472     DCHECK_EQ(FeedbackVectorSlotKind::CALL_IC, vector->GetKind(slot));
    473   }
    474 
    475   void Clear(Code* host);
    476 
    477   void ConfigureUninitialized() override;
    478   void ConfigureMonomorphicArray();
    479   void ConfigureMonomorphic(Handle<JSFunction> function);
    480   void ConfigureMegamorphic() final;
    481   void ConfigureMegamorphic(int call_count);
    482 
    483   InlineCacheState StateFromFeedback() const final;
    484 
    485   int ExtractMaps(MapHandleList* maps) const final {
    486     // CallICs don't record map feedback.
    487     return 0;
    488   }
    489   MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
    490     return MaybeHandle<Code>();
    491   }
    492   bool FindHandlers(List<Handle<Object>>* code_list,
    493                     int length = -1) const final {
    494     return length == 0;
    495   }
    496 
    497   int ExtractCallCount();
    498 
    499   // Compute the call frequency based on the call count and the invocation
    500   // count (taken from the type feedback vector).
    501   float ComputeCallFrequency();
    502 };
    503 
    504 
    505 class LoadICNexus : public FeedbackNexus {
    506  public:
    507   LoadICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
    508       : FeedbackNexus(vector, slot) {
    509     DCHECK_EQ(FeedbackVectorSlotKind::LOAD_IC, vector->GetKind(slot));
    510   }
    511   explicit LoadICNexus(Isolate* isolate)
    512       : FeedbackNexus(
    513             TypeFeedbackVector::DummyVector(isolate),
    514             FeedbackVectorSlot(TypeFeedbackVector::kDummyLoadICSlot)) {}
    515   LoadICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
    516       : FeedbackNexus(vector, slot) {
    517     DCHECK_EQ(FeedbackVectorSlotKind::LOAD_IC, vector->GetKind(slot));
    518   }
    519 
    520   void Clear(Code* host);
    521 
    522   void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Object> handler);
    523 
    524   void ConfigurePolymorphic(MapHandleList* maps,
    525                             List<Handle<Object>>* handlers);
    526 
    527   InlineCacheState StateFromFeedback() const override;
    528 };
    529 
    530 class LoadGlobalICNexus : public FeedbackNexus {
    531  public:
    532   LoadGlobalICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
    533       : FeedbackNexus(vector, slot) {
    534     DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC, vector->GetKind(slot));
    535   }
    536   LoadGlobalICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
    537       : FeedbackNexus(vector, slot) {
    538     DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC, vector->GetKind(slot));
    539   }
    540 
    541   int ExtractMaps(MapHandleList* maps) const final {
    542     // LoadGlobalICs don't record map feedback.
    543     return 0;
    544   }
    545   MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
    546     return MaybeHandle<Code>();
    547   }
    548   bool FindHandlers(List<Handle<Object>>* code_list,
    549                     int length = -1) const final {
    550     return length == 0;
    551   }
    552 
    553   void ConfigureMegamorphic() override { UNREACHABLE(); }
    554   void Clear(Code* host);
    555 
    556   void ConfigureUninitialized() override;
    557   void ConfigurePropertyCellMode(Handle<PropertyCell> cell);
    558   void ConfigureHandlerMode(Handle<Code> handler);
    559 
    560   InlineCacheState StateFromFeedback() const override;
    561 };
    562 
    563 class KeyedLoadICNexus : public FeedbackNexus {
    564  public:
    565   KeyedLoadICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
    566       : FeedbackNexus(vector, slot) {
    567     DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector->GetKind(slot));
    568   }
    569   explicit KeyedLoadICNexus(Isolate* isolate)
    570       : FeedbackNexus(
    571             TypeFeedbackVector::DummyVector(isolate),
    572             FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedLoadICSlot)) {}
    573   KeyedLoadICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
    574       : FeedbackNexus(vector, slot) {
    575     DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector->GetKind(slot));
    576   }
    577 
    578   void Clear(Code* host);
    579 
    580   // name can be a null handle for element loads.
    581   void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
    582                             Handle<Object> handler);
    583   // name can be null.
    584   void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps,
    585                             List<Handle<Object>>* handlers);
    586 
    587   void ConfigureMegamorphicKeyed(IcCheckType property_type);
    588 
    589   IcCheckType GetKeyType() const;
    590   InlineCacheState StateFromFeedback() const override;
    591   Name* FindFirstName() const override;
    592 };
    593 
    594 
    595 class StoreICNexus : public FeedbackNexus {
    596  public:
    597   StoreICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
    598       : FeedbackNexus(vector, slot) {
    599     DCHECK_EQ(FeedbackVectorSlotKind::STORE_IC, vector->GetKind(slot));
    600   }
    601   explicit StoreICNexus(Isolate* isolate)
    602       : FeedbackNexus(
    603             TypeFeedbackVector::DummyVector(isolate),
    604             FeedbackVectorSlot(TypeFeedbackVector::kDummyStoreICSlot)) {}
    605   StoreICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
    606       : FeedbackNexus(vector, slot) {
    607     DCHECK_EQ(FeedbackVectorSlotKind::STORE_IC, vector->GetKind(slot));
    608   }
    609 
    610   void Clear(Code* host);
    611 
    612   void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Object> handler);
    613 
    614   void ConfigurePolymorphic(MapHandleList* maps,
    615                             List<Handle<Object>>* handlers);
    616 
    617   InlineCacheState StateFromFeedback() const override;
    618 };
    619 
    620 
    621 class KeyedStoreICNexus : public FeedbackNexus {
    622  public:
    623   KeyedStoreICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
    624       : FeedbackNexus(vector, slot) {
    625     DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, vector->GetKind(slot));
    626   }
    627   explicit KeyedStoreICNexus(Isolate* isolate)
    628       : FeedbackNexus(
    629             TypeFeedbackVector::DummyVector(isolate),
    630             FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedStoreICSlot)) {}
    631   KeyedStoreICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
    632       : FeedbackNexus(vector, slot) {
    633     DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, vector->GetKind(slot));
    634   }
    635 
    636   void Clear(Code* host);
    637 
    638   // name can be a null handle for element loads.
    639   void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
    640                             Handle<Object> handler);
    641   // name can be null.
    642   void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps,
    643                             List<Handle<Object>>* handlers);
    644   void ConfigurePolymorphic(MapHandleList* maps,
    645                             MapHandleList* transitioned_maps,
    646                             CodeHandleList* handlers);
    647   void ConfigureMegamorphicKeyed(IcCheckType property_type);
    648 
    649   KeyedAccessStoreMode GetKeyedAccessStoreMode() const;
    650   IcCheckType GetKeyType() const;
    651 
    652   InlineCacheState StateFromFeedback() const override;
    653   Name* FindFirstName() const override;
    654 };
    655 
    656 class BinaryOpICNexus final : public FeedbackNexus {
    657  public:
    658   BinaryOpICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
    659       : FeedbackNexus(vector, slot) {
    660     DCHECK_EQ(FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC,
    661               vector->GetKind(slot));
    662   }
    663   BinaryOpICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
    664       : FeedbackNexus(vector, slot) {
    665     DCHECK_EQ(FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC,
    666               vector->GetKind(slot));
    667   }
    668 
    669   void Clear(Code* host);
    670 
    671   InlineCacheState StateFromFeedback() const final;
    672   BinaryOperationHint GetBinaryOperationFeedback() const;
    673 
    674   int ExtractMaps(MapHandleList* maps) const final {
    675     // BinaryOpICs don't record map feedback.
    676     return 0;
    677   }
    678   MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
    679     return MaybeHandle<Code>();
    680   }
    681   bool FindHandlers(List<Handle<Object>>* code_list,
    682                     int length = -1) const final {
    683     return length == 0;
    684   }
    685 };
    686 
    687 class CompareICNexus final : public FeedbackNexus {
    688  public:
    689   CompareICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
    690       : FeedbackNexus(vector, slot) {
    691     DCHECK_EQ(FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC,
    692               vector->GetKind(slot));
    693   }
    694   CompareICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
    695       : FeedbackNexus(vector, slot) {
    696     DCHECK_EQ(FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC,
    697               vector->GetKind(slot));
    698   }
    699 
    700   void Clear(Code* host);
    701 
    702   InlineCacheState StateFromFeedback() const final;
    703   CompareOperationHint GetCompareOperationFeedback() const;
    704 
    705   int ExtractMaps(MapHandleList* maps) const final {
    706     // BinaryOpICs don't record map feedback.
    707     return 0;
    708   }
    709   MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
    710     return MaybeHandle<Code>();
    711   }
    712   bool FindHandlers(List<Handle<Object>>* code_list,
    713                     int length = -1) const final {
    714     return length == 0;
    715   }
    716 };
    717 
    718 inline BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback);
    719 inline CompareOperationHint CompareOperationHintFromFeedback(int type_feedback);
    720 
    721 }  // namespace internal
    722 }  // namespace v8
    723 
    724 #endif  // V8_TRANSITIONS_H_
    725