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