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/base/macros.h"
     12 #include "src/elements-kind.h"
     13 #include "src/globals.h"
     14 #include "src/objects/map.h"
     15 #include "src/objects/name.h"
     16 #include "src/objects/object-macros.h"
     17 #include "src/type-hints.h"
     18 #include "src/zone/zone-containers.h"
     19 
     20 namespace v8 {
     21 namespace internal {
     22 
     23 enum class FeedbackSlotKind {
     24   // This kind means that the slot points to the middle of other slot
     25   // which occupies more than one feedback vector element.
     26   // There must be no such slots in the system.
     27   kInvalid,
     28 
     29   // Sloppy kinds come first, for easy language mode testing.
     30   kStoreGlobalSloppy,
     31   kStoreNamedSloppy,
     32   kStoreKeyedSloppy,
     33   kLastSloppyKind = kStoreKeyedSloppy,
     34 
     35   // Strict and language mode unaware kinds.
     36   kCall,
     37   kLoadProperty,
     38   kLoadGlobalNotInsideTypeof,
     39   kLoadGlobalInsideTypeof,
     40   kLoadKeyed,
     41   kStoreGlobalStrict,
     42   kStoreNamedStrict,
     43   kStoreOwnNamed,
     44   kStoreKeyedStrict,
     45   kStoreInArrayLiteral,
     46   kBinaryOp,
     47   kCompareOp,
     48   kStoreDataPropertyInLiteral,
     49   kTypeProfile,
     50   kCreateClosure,
     51   kLiteral,
     52   kForIn,
     53   kInstanceOf,
     54   kCloneObject,
     55 
     56   kKindsNumber  // Last value indicating number of kinds.
     57 };
     58 
     59 inline bool IsCallICKind(FeedbackSlotKind kind) {
     60   return kind == FeedbackSlotKind::kCall;
     61 }
     62 
     63 inline bool IsLoadICKind(FeedbackSlotKind kind) {
     64   return kind == FeedbackSlotKind::kLoadProperty;
     65 }
     66 
     67 inline bool IsLoadGlobalICKind(FeedbackSlotKind kind) {
     68   return kind == FeedbackSlotKind::kLoadGlobalNotInsideTypeof ||
     69          kind == FeedbackSlotKind::kLoadGlobalInsideTypeof;
     70 }
     71 
     72 inline bool IsKeyedLoadICKind(FeedbackSlotKind kind) {
     73   return kind == FeedbackSlotKind::kLoadKeyed;
     74 }
     75 
     76 inline bool IsStoreGlobalICKind(FeedbackSlotKind kind) {
     77   return kind == FeedbackSlotKind::kStoreGlobalSloppy ||
     78          kind == FeedbackSlotKind::kStoreGlobalStrict;
     79 }
     80 
     81 inline bool IsStoreICKind(FeedbackSlotKind kind) {
     82   return kind == FeedbackSlotKind::kStoreNamedSloppy ||
     83          kind == FeedbackSlotKind::kStoreNamedStrict;
     84 }
     85 
     86 inline bool IsStoreOwnICKind(FeedbackSlotKind kind) {
     87   return kind == FeedbackSlotKind::kStoreOwnNamed;
     88 }
     89 
     90 inline bool IsStoreDataPropertyInLiteralKind(FeedbackSlotKind kind) {
     91   return kind == FeedbackSlotKind::kStoreDataPropertyInLiteral;
     92 }
     93 
     94 inline bool IsKeyedStoreICKind(FeedbackSlotKind kind) {
     95   return kind == FeedbackSlotKind::kStoreKeyedSloppy ||
     96          kind == FeedbackSlotKind::kStoreKeyedStrict;
     97 }
     98 
     99 inline bool IsStoreInArrayLiteralICKind(FeedbackSlotKind kind) {
    100   return kind == FeedbackSlotKind::kStoreInArrayLiteral;
    101 }
    102 
    103 inline bool IsGlobalICKind(FeedbackSlotKind kind) {
    104   return IsLoadGlobalICKind(kind) || IsStoreGlobalICKind(kind);
    105 }
    106 
    107 inline bool IsTypeProfileKind(FeedbackSlotKind kind) {
    108   return kind == FeedbackSlotKind::kTypeProfile;
    109 }
    110 
    111 inline bool IsCloneObjectKind(FeedbackSlotKind kind) {
    112   return kind == FeedbackSlotKind::kCloneObject;
    113 }
    114 
    115 inline TypeofMode GetTypeofModeFromSlotKind(FeedbackSlotKind kind) {
    116   DCHECK(IsLoadGlobalICKind(kind));
    117   return (kind == FeedbackSlotKind::kLoadGlobalInsideTypeof)
    118              ? INSIDE_TYPEOF
    119              : NOT_INSIDE_TYPEOF;
    120 }
    121 
    122 inline LanguageMode GetLanguageModeFromSlotKind(FeedbackSlotKind kind) {
    123   DCHECK(IsStoreICKind(kind) || IsStoreOwnICKind(kind) ||
    124          IsStoreGlobalICKind(kind) || IsKeyedStoreICKind(kind));
    125   STATIC_ASSERT(FeedbackSlotKind::kStoreGlobalSloppy <=
    126                 FeedbackSlotKind::kLastSloppyKind);
    127   STATIC_ASSERT(FeedbackSlotKind::kStoreKeyedSloppy <=
    128                 FeedbackSlotKind::kLastSloppyKind);
    129   STATIC_ASSERT(FeedbackSlotKind::kStoreNamedSloppy <=
    130                 FeedbackSlotKind::kLastSloppyKind);
    131   return (kind <= FeedbackSlotKind::kLastSloppyKind) ? LanguageMode::kSloppy
    132                                                      : LanguageMode::kStrict;
    133 }
    134 
    135 std::ostream& operator<<(std::ostream& os, FeedbackSlotKind kind);
    136 
    137 typedef std::vector<MaybeObjectHandle> MaybeObjectHandles;
    138 
    139 class FeedbackMetadata;
    140 
    141 // A FeedbackVector has a fixed header with:
    142 //  - shared function info (which includes feedback metadata)
    143 //  - invocation count
    144 //  - runtime profiler ticks
    145 //  - optimized code cell (weak cell or Smi marker)
    146 // followed by an array of feedback slots, of length determined by the feedback
    147 // metadata.
    148 class FeedbackVector : public HeapObject, public NeverReadOnlySpaceObject {
    149  public:
    150   // Use the mixin methods over the HeapObject methods.
    151   // TODO(v8:7786) Remove once the HeapObject methods are gone.
    152   using NeverReadOnlySpaceObject::GetHeap;
    153   using NeverReadOnlySpaceObject::GetIsolate;
    154 
    155   // Casting.
    156   static inline FeedbackVector* cast(Object* obj);
    157 
    158   inline void ComputeCounts(int* with_type_info, int* generic,
    159                             int* vector_ic_count);
    160 
    161   inline bool is_empty() const;
    162 
    163   inline FeedbackMetadata* metadata() const;
    164 
    165   // [shared_function_info]: The shared function info for the function with this
    166   // feedback vector.
    167   DECL_ACCESSORS(shared_function_info, SharedFunctionInfo)
    168 
    169   // [optimized_code_weak_or_smi]: weak reference to optimized code or a Smi
    170   // marker defining optimization behaviour.
    171   DECL_ACCESSORS(optimized_code_weak_or_smi, MaybeObject)
    172 
    173   // [length]: The length of the feedback vector (not including the header, i.e.
    174   // the number of feedback slots).
    175   DECL_INT32_ACCESSORS(length)
    176 
    177   // [invocation_count]: The number of times this function has been invoked.
    178   DECL_INT32_ACCESSORS(invocation_count)
    179 
    180   // [invocation_count]: The number of times this function has been seen by the
    181   // runtime profiler.
    182   DECL_INT32_ACCESSORS(profiler_ticks)
    183 
    184   // [deopt_count]: The number of times this function has deoptimized.
    185   DECL_INT32_ACCESSORS(deopt_count)
    186 
    187   inline void clear_invocation_count();
    188   inline void increment_deopt_count();
    189 
    190   inline Code* optimized_code() const;
    191   inline OptimizationMarker optimization_marker() const;
    192   inline bool has_optimized_code() const;
    193   inline bool has_optimization_marker() const;
    194   void ClearOptimizedCode();
    195   void EvictOptimizedCodeMarkedForDeoptimization(SharedFunctionInfo* shared,
    196                                                  const char* reason);
    197   static void SetOptimizedCode(Handle<FeedbackVector> vector,
    198                                Handle<Code> code);
    199   void SetOptimizationMarker(OptimizationMarker marker);
    200 
    201   // Clears the optimization marker in the feedback vector.
    202   void ClearOptimizationMarker();
    203 
    204   // Conversion from a slot to an integer index to the underlying array.
    205   static int GetIndex(FeedbackSlot slot) { return slot.ToInt(); }
    206 
    207   // Conversion from an integer index to the underlying array to a slot.
    208   static inline FeedbackSlot ToSlot(int index);
    209   inline MaybeObject* Get(FeedbackSlot slot) const;
    210   inline MaybeObject* get(int index) const;
    211   inline void Set(FeedbackSlot slot, MaybeObject* value,
    212                   WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
    213   inline void set(int index, MaybeObject* value,
    214                   WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
    215   inline void Set(FeedbackSlot slot, Object* value,
    216                   WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
    217   inline void set(int index, Object* value,
    218                   WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
    219 
    220   // Gives access to raw memory which stores the array's data.
    221   inline MaybeObject** slots_start();
    222 
    223   // Returns slot kind for given slot.
    224   FeedbackSlotKind GetKind(FeedbackSlot slot) const;
    225 
    226   FeedbackSlot GetTypeProfileSlot() const;
    227 
    228   V8_EXPORT_PRIVATE static Handle<FeedbackVector> New(
    229       Isolate* isolate, Handle<SharedFunctionInfo> shared);
    230 
    231 #define DEFINE_SLOT_KIND_PREDICATE(Name) \
    232   bool Name(FeedbackSlot slot) const { return Name##Kind(GetKind(slot)); }
    233 
    234   DEFINE_SLOT_KIND_PREDICATE(IsCallIC)
    235   DEFINE_SLOT_KIND_PREDICATE(IsGlobalIC)
    236   DEFINE_SLOT_KIND_PREDICATE(IsLoadIC)
    237   DEFINE_SLOT_KIND_PREDICATE(IsLoadGlobalIC)
    238   DEFINE_SLOT_KIND_PREDICATE(IsKeyedLoadIC)
    239   DEFINE_SLOT_KIND_PREDICATE(IsStoreIC)
    240   DEFINE_SLOT_KIND_PREDICATE(IsStoreOwnIC)
    241   DEFINE_SLOT_KIND_PREDICATE(IsStoreGlobalIC)
    242   DEFINE_SLOT_KIND_PREDICATE(IsKeyedStoreIC)
    243   DEFINE_SLOT_KIND_PREDICATE(IsTypeProfile)
    244 #undef DEFINE_SLOT_KIND_PREDICATE
    245 
    246   // Returns typeof mode encoded into kind of given slot.
    247   inline TypeofMode GetTypeofMode(FeedbackSlot slot) const {
    248     return GetTypeofModeFromSlotKind(GetKind(slot));
    249   }
    250 
    251   // Returns language mode encoded into kind of given slot.
    252   inline LanguageMode GetLanguageMode(FeedbackSlot slot) const {
    253     return GetLanguageModeFromSlotKind(GetKind(slot));
    254   }
    255 
    256   static void AssertNoLegacyTypes(MaybeObject* object);
    257 
    258   DECL_PRINTER(FeedbackVector)
    259   DECL_VERIFIER(FeedbackVector)
    260 
    261   void FeedbackSlotPrint(std::ostream& os, FeedbackSlot slot);  // NOLINT
    262 
    263   // Clears the vector slots. Return true if feedback has changed.
    264   bool ClearSlots(Isolate* isolate);
    265 
    266   // The object that indicates an uninitialized cache.
    267   static inline Handle<Symbol> UninitializedSentinel(Isolate* isolate);
    268 
    269   // The object that indicates a generic state.
    270   static inline Handle<Symbol> GenericSentinel(Isolate* isolate);
    271 
    272   // The object that indicates a megamorphic state.
    273   static inline Handle<Symbol> MegamorphicSentinel(Isolate* isolate);
    274 
    275   // The object that indicates a premonomorphic state.
    276   static inline Handle<Symbol> PremonomorphicSentinel(Isolate* isolate);
    277 
    278   // A raw version of the uninitialized sentinel that's safe to read during
    279   // garbage collection (e.g., for patching the cache).
    280   static inline Symbol* RawUninitializedSentinel(Isolate* isolate);
    281 
    282 // Layout description.
    283 #define FEEDBACK_VECTOR_FIELDS(V)            \
    284   /* Header fields. */                       \
    285   V(kSharedFunctionInfoOffset, kPointerSize) \
    286   V(kOptimizedCodeOffset, kPointerSize)      \
    287   V(kLengthOffset, kInt32Size)               \
    288   V(kInvocationCountOffset, kInt32Size)      \
    289   V(kProfilerTicksOffset, kInt32Size)        \
    290   V(kDeoptCountOffset, kInt32Size)           \
    291   V(kUnalignedHeaderSize, 0)
    292 
    293   DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, FEEDBACK_VECTOR_FIELDS)
    294 #undef FEEDBACK_VECTOR_FIELDS
    295 
    296   static const int kHeaderSize =
    297       RoundUp<kPointerAlignment>(kUnalignedHeaderSize);
    298   static const int kFeedbackSlotsOffset = kHeaderSize;
    299 
    300   class BodyDescriptor;
    301   // No weak fields.
    302   typedef BodyDescriptor BodyDescriptorWeak;
    303 
    304   // Garbage collection support.
    305   static constexpr int SizeFor(int length) {
    306     return kFeedbackSlotsOffset + length * kPointerSize;
    307   }
    308 
    309  private:
    310   static void AddToVectorsForProfilingTools(Isolate* isolate,
    311                                             Handle<FeedbackVector> vector);
    312 
    313   DISALLOW_IMPLICIT_CONSTRUCTORS(FeedbackVector);
    314 };
    315 
    316 class V8_EXPORT_PRIVATE FeedbackVectorSpec {
    317  public:
    318   explicit FeedbackVectorSpec(Zone* zone) : slot_kinds_(zone) {
    319     slot_kinds_.reserve(16);
    320   }
    321 
    322   int slots() const { return static_cast<int>(slot_kinds_.size()); }
    323 
    324   FeedbackSlotKind GetKind(FeedbackSlot slot) const {
    325     return static_cast<FeedbackSlotKind>(slot_kinds_.at(slot.ToInt()));
    326   }
    327 
    328   bool HasTypeProfileSlot() const;
    329 
    330   // If used, the TypeProfileSlot is always added as the first slot and its
    331   // index is constant. If other slots are added before the TypeProfileSlot,
    332   // this number changes.
    333   static const int kTypeProfileSlotIndex = 0;
    334 
    335   FeedbackSlot AddCallICSlot() { return AddSlot(FeedbackSlotKind::kCall); }
    336 
    337   FeedbackSlot AddLoadICSlot() {
    338     return AddSlot(FeedbackSlotKind::kLoadProperty);
    339   }
    340 
    341   FeedbackSlot AddLoadGlobalICSlot(TypeofMode typeof_mode) {
    342     return AddSlot(typeof_mode == INSIDE_TYPEOF
    343                        ? FeedbackSlotKind::kLoadGlobalInsideTypeof
    344                        : FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
    345   }
    346 
    347   FeedbackSlot AddCreateClosureSlot() {
    348     return AddSlot(FeedbackSlotKind::kCreateClosure);
    349   }
    350 
    351   FeedbackSlot AddKeyedLoadICSlot() {
    352     return AddSlot(FeedbackSlotKind::kLoadKeyed);
    353   }
    354 
    355   FeedbackSlot AddStoreICSlot(LanguageMode language_mode) {
    356     STATIC_ASSERT(LanguageModeSize == 2);
    357     return AddSlot(is_strict(language_mode)
    358                        ? FeedbackSlotKind::kStoreNamedStrict
    359                        : FeedbackSlotKind::kStoreNamedSloppy);
    360   }
    361 
    362   FeedbackSlot AddStoreOwnICSlot() {
    363     return AddSlot(FeedbackSlotKind::kStoreOwnNamed);
    364   }
    365 
    366   FeedbackSlot AddStoreGlobalICSlot(LanguageMode language_mode) {
    367     STATIC_ASSERT(LanguageModeSize == 2);
    368     return AddSlot(is_strict(language_mode)
    369                        ? FeedbackSlotKind::kStoreGlobalStrict
    370                        : FeedbackSlotKind::kStoreGlobalSloppy);
    371   }
    372 
    373   FeedbackSlot AddKeyedStoreICSlot(LanguageMode language_mode) {
    374     STATIC_ASSERT(LanguageModeSize == 2);
    375     return AddSlot(is_strict(language_mode)
    376                        ? FeedbackSlotKind::kStoreKeyedStrict
    377                        : FeedbackSlotKind::kStoreKeyedSloppy);
    378   }
    379 
    380   FeedbackSlot AddStoreInArrayLiteralICSlot() {
    381     return AddSlot(FeedbackSlotKind::kStoreInArrayLiteral);
    382   }
    383 
    384   FeedbackSlot AddBinaryOpICSlot() {
    385     return AddSlot(FeedbackSlotKind::kBinaryOp);
    386   }
    387 
    388   FeedbackSlot AddCompareICSlot() {
    389     return AddSlot(FeedbackSlotKind::kCompareOp);
    390   }
    391 
    392   FeedbackSlot AddForInSlot() { return AddSlot(FeedbackSlotKind::kForIn); }
    393 
    394   FeedbackSlot AddInstanceOfSlot() {
    395     return AddSlot(FeedbackSlotKind::kInstanceOf);
    396   }
    397 
    398   FeedbackSlot AddLiteralSlot() { return AddSlot(FeedbackSlotKind::kLiteral); }
    399 
    400   FeedbackSlot AddStoreDataPropertyInLiteralICSlot() {
    401     return AddSlot(FeedbackSlotKind::kStoreDataPropertyInLiteral);
    402   }
    403 
    404   FeedbackSlot AddTypeProfileSlot();
    405 
    406   FeedbackSlot AddCloneObjectSlot() {
    407     return AddSlot(FeedbackSlotKind::kCloneObject);
    408   }
    409 
    410 #ifdef OBJECT_PRINT
    411   // For gdb debugging.
    412   void Print();
    413 #endif  // OBJECT_PRINT
    414 
    415   DECL_PRINTER(FeedbackVectorSpec)
    416 
    417  private:
    418   FeedbackSlot AddSlot(FeedbackSlotKind kind);
    419 
    420   void append(FeedbackSlotKind kind) {
    421     slot_kinds_.push_back(static_cast<unsigned char>(kind));
    422   }
    423 
    424   ZoneVector<unsigned char> slot_kinds_;
    425 };
    426 
    427 // FeedbackMetadata is an array-like object with a slot count (indicating how
    428 // many slots are stored). We save space by packing several slots into an array
    429 // of int32 data. The length is never stored - it is always calculated from
    430 // slot_count. All instances are created through the static New function, and
    431 // the number of slots is static once an instance is created.
    432 class FeedbackMetadata : public HeapObject {
    433  public:
    434   // Casting.
    435   static inline FeedbackMetadata* cast(Object* obj);
    436 
    437   // The number of slots that this metadata contains. Stored as an int32.
    438   DECL_INT32_ACCESSORS(slot_count)
    439 
    440   // Get slot_count using an acquire load.
    441   inline int32_t synchronized_slot_count() const;
    442 
    443   // Returns number of feedback vector elements used by given slot kind.
    444   static inline int GetSlotSize(FeedbackSlotKind kind);
    445 
    446   bool SpecDiffersFrom(const FeedbackVectorSpec* other_spec) const;
    447 
    448   inline bool is_empty() const;
    449 
    450   // Returns slot kind for given slot.
    451   FeedbackSlotKind GetKind(FeedbackSlot slot) const;
    452 
    453   // If {spec} is null, then it is considered empty.
    454   V8_EXPORT_PRIVATE static Handle<FeedbackMetadata> New(
    455       Isolate* isolate, const FeedbackVectorSpec* spec = nullptr);
    456 
    457   DECL_PRINTER(FeedbackMetadata)
    458   DECL_VERIFIER(FeedbackMetadata)
    459 
    460   static const char* Kind2String(FeedbackSlotKind kind);
    461   bool HasTypeProfileSlot() const;
    462 
    463   // Garbage collection support.
    464   // This includes any necessary padding at the end of the object for pointer
    465   // size alignment.
    466   static int SizeFor(int slot_count) {
    467     return OBJECT_POINTER_ALIGN(kHeaderSize + length(slot_count) * kInt32Size);
    468   }
    469 
    470   static const int kSlotCountOffset = HeapObject::kHeaderSize;
    471   static const int kHeaderSize = kSlotCountOffset + kInt32Size;
    472 
    473   class BodyDescriptor;
    474   // No weak fields.
    475   typedef BodyDescriptor BodyDescriptorWeak;
    476 
    477  private:
    478   friend class AccessorAssembler;
    479 
    480   // Raw accessors to the encoded slot data.
    481   inline int32_t get(int index) const;
    482   inline void set(int index, int32_t value);
    483 
    484   // The number of int32 data fields needed to store {slot_count} slots.
    485   // Does not include any extra padding for pointer size alignment.
    486   static int length(int slot_count) {
    487     return VectorICComputer::word_count(slot_count);
    488   }
    489   inline int length() const;
    490 
    491   static const int kFeedbackSlotKindBits = 5;
    492   STATIC_ASSERT(static_cast<int>(FeedbackSlotKind::kKindsNumber) <
    493                 (1 << kFeedbackSlotKindBits));
    494 
    495   void SetKind(FeedbackSlot slot, FeedbackSlotKind kind);
    496 
    497   typedef BitSetComputer<FeedbackSlotKind, kFeedbackSlotKindBits,
    498                          kInt32Size * kBitsPerByte, uint32_t>
    499       VectorICComputer;
    500 
    501   DISALLOW_IMPLICIT_CONSTRUCTORS(FeedbackMetadata);
    502 };
    503 
    504 // Verify that an empty hash field looks like a tagged object, but can't
    505 // possibly be confused with a pointer.
    506 STATIC_ASSERT((Name::kEmptyHashField & kHeapObjectTag) == kHeapObjectTag);
    507 STATIC_ASSERT(Name::kEmptyHashField == 0x3);
    508 // Verify that a set hash field will not look like a tagged object.
    509 STATIC_ASSERT(Name::kHashNotComputedMask == kHeapObjectTag);
    510 
    511 class FeedbackMetadataIterator {
    512  public:
    513   explicit FeedbackMetadataIterator(Handle<FeedbackMetadata> metadata)
    514       : metadata_handle_(metadata),
    515         next_slot_(FeedbackSlot(0)),
    516         slot_kind_(FeedbackSlotKind::kInvalid) {}
    517 
    518   explicit FeedbackMetadataIterator(FeedbackMetadata* metadata)
    519       : metadata_(metadata),
    520         next_slot_(FeedbackSlot(0)),
    521         slot_kind_(FeedbackSlotKind::kInvalid) {}
    522 
    523   inline bool HasNext() const;
    524 
    525   inline FeedbackSlot Next();
    526 
    527   // Returns slot kind of the last slot returned by Next().
    528   FeedbackSlotKind kind() const {
    529     DCHECK_NE(FeedbackSlotKind::kInvalid, slot_kind_);
    530     DCHECK_NE(FeedbackSlotKind::kKindsNumber, slot_kind_);
    531     return slot_kind_;
    532   }
    533 
    534   // Returns entry size of the last slot returned by Next().
    535   inline int entry_size() const;
    536 
    537  private:
    538   FeedbackMetadata* metadata() const {
    539     return !metadata_handle_.is_null() ? *metadata_handle_ : metadata_;
    540   }
    541 
    542   // The reason for having a handle and a raw pointer to the meta data is
    543   // to have a single iterator implementation for both "handlified" and raw
    544   // pointer use cases.
    545   Handle<FeedbackMetadata> metadata_handle_;
    546   FeedbackMetadata* metadata_;
    547   FeedbackSlot cur_slot_;
    548   FeedbackSlot next_slot_;
    549   FeedbackSlotKind slot_kind_;
    550 };
    551 
    552 // A FeedbackNexus is the combination of a FeedbackVector and a slot.
    553 class FeedbackNexus final {
    554  public:
    555   FeedbackNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
    556       : vector_handle_(vector),
    557         vector_(nullptr),
    558         slot_(slot),
    559         kind_(vector->GetKind(slot)) {}
    560   FeedbackNexus(FeedbackVector* vector, FeedbackSlot slot)
    561       : vector_(vector), slot_(slot), kind_(vector->GetKind(slot)) {}
    562 
    563   Handle<FeedbackVector> vector_handle() const {
    564     DCHECK_NULL(vector_);
    565     return vector_handle_;
    566   }
    567   FeedbackVector* vector() const {
    568     return vector_handle_.is_null() ? vector_ : *vector_handle_;
    569   }
    570   FeedbackSlot slot() const { return slot_; }
    571   FeedbackSlotKind kind() const { return kind_; }
    572 
    573   inline LanguageMode GetLanguageMode() const {
    574     return vector()->GetLanguageMode(slot());
    575   }
    576 
    577   InlineCacheState ic_state() const { return StateFromFeedback(); }
    578   bool IsUninitialized() const { return StateFromFeedback() == UNINITIALIZED; }
    579   bool IsMegamorphic() const { return StateFromFeedback() == MEGAMORPHIC; }
    580   bool IsGeneric() const { return StateFromFeedback() == GENERIC; }
    581 
    582   void Print(std::ostream& os);  // NOLINT
    583 
    584   // For map-based ICs (load, keyed-load, store, keyed-store).
    585   Map* FindFirstMap() const {
    586     MapHandles maps;
    587     ExtractMaps(&maps);
    588     if (maps.size() > 0) return *maps.at(0);
    589     return nullptr;
    590   }
    591 
    592   InlineCacheState StateFromFeedback() const;
    593   int ExtractMaps(MapHandles* maps) const;
    594   MaybeObjectHandle FindHandlerForMap(Handle<Map> map) const;
    595   bool FindHandlers(MaybeObjectHandles* code_list, int length = -1) const;
    596 
    597   bool IsCleared() const {
    598     InlineCacheState state = StateFromFeedback();
    599     return !FLAG_use_ic || state == UNINITIALIZED || state == PREMONOMORPHIC;
    600   }
    601 
    602   // Clear() returns true if the state of the underlying vector was changed.
    603   bool Clear();
    604   void ConfigureUninitialized();
    605   void ConfigurePremonomorphic(Handle<Map> receiver_map);
    606   // ConfigureMegamorphic() returns true if the state of the underlying vector
    607   // was changed. Extra feedback is cleared if the 0 parameter version is used.
    608   bool ConfigureMegamorphic();
    609   bool ConfigureMegamorphic(IcCheckType property_type);
    610 
    611   inline MaybeObject* GetFeedback() const;
    612   inline MaybeObject* GetFeedbackExtra() const;
    613 
    614   inline Isolate* GetIsolate() const;
    615 
    616   void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
    617                             const MaybeObjectHandle& handler);
    618 
    619   void ConfigurePolymorphic(Handle<Name> name, MapHandles const& maps,
    620                             MaybeObjectHandles* handlers);
    621 
    622   BinaryOperationHint GetBinaryOperationFeedback() const;
    623   CompareOperationHint GetCompareOperationFeedback() const;
    624   ForInHint GetForInFeedback() const;
    625 
    626   // For KeyedLoad ICs.
    627   KeyedAccessLoadMode GetKeyedAccessLoadMode() const;
    628 
    629   // For KeyedStore ICs.
    630   KeyedAccessStoreMode GetKeyedAccessStoreMode() const;
    631 
    632   // For KeyedLoad and KeyedStore ICs.
    633   IcCheckType GetKeyType() const;
    634   Name* FindFirstName() const;
    635 
    636   // For Call ICs.
    637   int GetCallCount();
    638   void SetSpeculationMode(SpeculationMode mode);
    639   SpeculationMode GetSpeculationMode();
    640 
    641   // Compute the call frequency based on the call count and the invocation
    642   // count (taken from the type feedback vector).
    643   float ComputeCallFrequency();
    644 
    645   typedef BitField<SpeculationMode, 0, 1> SpeculationModeField;
    646   typedef BitField<uint32_t, 1, 31> CallCountField;
    647 
    648   // For CreateClosure ICs.
    649   Handle<FeedbackCell> GetFeedbackCell() const;
    650 
    651   // For InstanceOf ICs.
    652   MaybeHandle<JSObject> GetConstructorFeedback() const;
    653 
    654   // For Global Load and Store ICs.
    655   void ConfigurePropertyCellMode(Handle<PropertyCell> cell);
    656   // Returns false if given combination of indices is not allowed.
    657   bool ConfigureLexicalVarMode(int script_context_index,
    658                                int context_slot_index);
    659   void ConfigureHandlerMode(const MaybeObjectHandle& handler);
    660 
    661   // For CloneObject ICs
    662   static constexpr int kCloneObjectPolymorphicEntrySize = 2;
    663   void ConfigureCloneObject(Handle<Map> source_map, Handle<Map> result_map);
    664 
    665 // Bit positions in a smi that encodes lexical environment variable access.
    666 #define LEXICAL_MODE_BIT_FIELDS(V, _)  \
    667   V(ContextIndexBits, unsigned, 12, _) \
    668   V(SlotIndexBits, unsigned, 19, _)
    669 
    670   DEFINE_BIT_FIELDS(LEXICAL_MODE_BIT_FIELDS)
    671 #undef LEXICAL_MODE_BIT_FIELDS
    672 
    673   // Make sure we don't overflow the smi.
    674   STATIC_ASSERT(LEXICAL_MODE_BIT_FIELDS_Ranges::kBitsCount <= kSmiValueSize);
    675 
    676   // For TypeProfile feedback vector slots.
    677   // ResetTypeProfile will always reset type profile information.
    678   void ResetTypeProfile();
    679 
    680   // Add a type to the list of types for source position <position>.
    681   void Collect(Handle<String> type, int position);
    682   JSObject* GetTypeProfile() const;
    683 
    684   std::vector<int> GetSourcePositions() const;
    685   std::vector<Handle<String>> GetTypesForSourcePositions(uint32_t pos) const;
    686 
    687   inline void SetFeedback(Object* feedback,
    688                           WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
    689   inline void SetFeedback(MaybeObject* feedback,
    690                           WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
    691   inline void SetFeedbackExtra(Object* feedback_extra,
    692                                WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
    693   inline void SetFeedbackExtra(MaybeObject* feedback_extra,
    694                                WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
    695 
    696   Handle<WeakFixedArray> EnsureArrayOfSize(int length);
    697   Handle<WeakFixedArray> EnsureExtraArrayOfSize(int length);
    698 
    699  private:
    700   // The reason for having a vector handle and a raw pointer is that we can and
    701   // should use handles during IC miss, but not during GC when we clear ICs. If
    702   // you have a handle to the vector that is better because more operations can
    703   // be done, like allocation.
    704   Handle<FeedbackVector> vector_handle_;
    705   FeedbackVector* vector_;
    706   FeedbackSlot slot_;
    707   FeedbackSlotKind kind_;
    708 };
    709 
    710 inline BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback);
    711 inline CompareOperationHint CompareOperationHintFromFeedback(int type_feedback);
    712 inline ForInHint ForInHintFromFeedback(int type_feedback);
    713 
    714 }  // namespace internal
    715 }  // namespace v8
    716 
    717 #endif  // V8_FEEDBACK_VECTOR_H_
    718