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