LCOV - code coverage report
Current view: top level - src - feedback-vector.h (source / functions) Hit Total Coverage
Test: app.info Lines: 107 138 77.5 %
Date: 2017-10-20 Functions: 25 62 40.3 %

          Line data    Source code
       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/objects/map.h"
      14             : #include "src/objects/name.h"
      15             : #include "src/objects/object-macros.h"
      16             : #include "src/type-hints.h"
      17             : #include "src/zone/zone-containers.h"
      18             : 
      19             : namespace v8 {
      20             : namespace internal {
      21             : 
      22             : enum class FeedbackSlotKind {
      23             :   // This kind means that the slot points to the middle of other slot
      24             :   // which occupies more than one feedback vector element.
      25             :   // There must be no such slots in the system.
      26             :   kInvalid,
      27             : 
      28             :   // Sloppy kinds come first, for easy language mode testing.
      29             :   kStoreGlobalSloppy,
      30             :   kStoreNamedSloppy,
      31             :   kStoreKeyedSloppy,
      32             :   kLastSloppyKind = kStoreKeyedSloppy,
      33             : 
      34             :   // Strict and language mode unaware kinds.
      35             :   kCall,
      36             :   kLoadProperty,
      37             :   kLoadGlobalNotInsideTypeof,
      38             :   kLoadGlobalInsideTypeof,
      39             :   kLoadKeyed,
      40             :   kStoreGlobalStrict,
      41             :   kStoreNamedStrict,
      42             :   kStoreOwnNamed,
      43             :   kStoreKeyedStrict,
      44             :   kBinaryOp,
      45             :   kCompareOp,
      46             :   kStoreDataPropertyInLiteral,
      47             :   kTypeProfile,
      48             :   kCreateClosure,
      49             :   kLiteral,
      50             :   kForIn,
      51             : 
      52             :   kKindsNumber  // Last value indicating number of kinds.
      53             : };
      54             : 
      55             : inline bool IsCallICKind(FeedbackSlotKind kind) {
      56             :   return kind == FeedbackSlotKind::kCall;
      57             : }
      58             : 
      59     1860583 : inline bool IsLoadICKind(FeedbackSlotKind kind) {
      60     1860583 :   return kind == FeedbackSlotKind::kLoadProperty;
      61             : }
      62             : 
      63         128 : inline bool IsLoadGlobalICKind(FeedbackSlotKind kind) {
      64     8392367 :   return kind == FeedbackSlotKind::kLoadGlobalNotInsideTypeof ||
      65         128 :          kind == FeedbackSlotKind::kLoadGlobalInsideTypeof;
      66             : }
      67             : 
      68             : inline bool IsKeyedLoadICKind(FeedbackSlotKind kind) {
      69             :   return kind == FeedbackSlotKind::kLoadKeyed;
      70             : }
      71             : 
      72     1508137 : inline bool IsStoreGlobalICKind(FeedbackSlotKind kind) {
      73     1508137 :   return kind == FeedbackSlotKind::kStoreGlobalSloppy ||
      74     1508137 :          kind == FeedbackSlotKind::kStoreGlobalStrict;
      75             : }
      76             : 
      77     4253295 : inline bool IsStoreICKind(FeedbackSlotKind kind) {
      78     4253295 :   return kind == FeedbackSlotKind::kStoreNamedSloppy ||
      79     4253295 :          kind == FeedbackSlotKind::kStoreNamedStrict;
      80             : }
      81             : 
      82     1895143 : inline bool IsStoreOwnICKind(FeedbackSlotKind kind) {
      83     1895143 :   return kind == FeedbackSlotKind::kStoreOwnNamed;
      84             : }
      85             : 
      86             : inline bool IsKeyedStoreICKind(FeedbackSlotKind kind) {
      87     3270733 :   return kind == FeedbackSlotKind::kStoreKeyedSloppy ||
      88     3270733 :          kind == FeedbackSlotKind::kStoreKeyedStrict;
      89             : }
      90             : 
      91             : inline bool IsTypeProfileKind(FeedbackSlotKind kind) {
      92             :   return kind == FeedbackSlotKind::kTypeProfile;
      93             : }
      94             : 
      95             : inline TypeofMode GetTypeofModeFromSlotKind(FeedbackSlotKind kind) {
      96             :   DCHECK(IsLoadGlobalICKind(kind));
      97             :   return (kind == FeedbackSlotKind::kLoadGlobalInsideTypeof)
      98             :              ? INSIDE_TYPEOF
      99             :              : NOT_INSIDE_TYPEOF;
     100             : }
     101             : 
     102             : inline LanguageMode GetLanguageModeFromSlotKind(FeedbackSlotKind kind) {
     103             :   DCHECK(IsStoreICKind(kind) || IsStoreOwnICKind(kind) ||
     104             :          IsStoreGlobalICKind(kind) || IsKeyedStoreICKind(kind));
     105             :   STATIC_ASSERT(FeedbackSlotKind::kStoreGlobalSloppy <=
     106             :                 FeedbackSlotKind::kLastSloppyKind);
     107             :   STATIC_ASSERT(FeedbackSlotKind::kStoreKeyedSloppy <=
     108             :                 FeedbackSlotKind::kLastSloppyKind);
     109             :   STATIC_ASSERT(FeedbackSlotKind::kStoreNamedSloppy <=
     110             :                 FeedbackSlotKind::kLastSloppyKind);
     111             :   return (kind <= FeedbackSlotKind::kLastSloppyKind) ? LanguageMode::kSloppy
     112     6315258 :                                                      : LanguageMode::kStrict;
     113             : }
     114             : 
     115             : std::ostream& operator<<(std::ostream& os, FeedbackSlotKind kind);
     116             : 
     117             : typedef std::vector<Handle<Object>> ObjectHandles;
     118             : 
     119             : class FeedbackMetadata;
     120             : 
     121             : // A FeedbackVector has a fixed header with:
     122             : //  - shared function info (which includes feedback metadata)
     123             : //  - invocation count
     124             : //  - runtime profiler ticks
     125             : //  - optimized code cell (weak cell or Smi marker)
     126             : // followed by an array of feedback slots, of length determined by the feedback
     127             : // metadata.
     128             : class FeedbackVector : public HeapObject {
     129             :  public:
     130             :   // Casting.
     131             :   static inline FeedbackVector* cast(Object* obj);
     132             : 
     133             :   inline void ComputeCounts(int* with_type_info, int* generic,
     134             :                             int* vector_ic_count);
     135             : 
     136             :   inline bool is_empty() const;
     137             : 
     138             :   inline FeedbackMetadata* metadata() const;
     139             : 
     140             :   // [shared_function_info]: The shared function info for the function with this
     141             :   // feedback vector.
     142             :   DECL_ACCESSORS(shared_function_info, SharedFunctionInfo)
     143             : 
     144             :   // [optimized_code_cell]: WeakCell containing optimized code or a Smi marker
     145             :   // defining optimization behaviour.
     146             :   DECL_ACCESSORS(optimized_code_cell, Object)
     147             : 
     148             :   // [length]: The length of the feedback vector (not including the header, i.e.
     149             :   // the number of feedback slots).
     150             :   DECL_INT32_ACCESSORS(length)
     151             : 
     152             :   // [invocation_count]: The number of times this function has been invoked.
     153             :   DECL_INT32_ACCESSORS(invocation_count)
     154             : 
     155             :   // [invocation_count]: The number of times this function has been seen by the
     156             :   // runtime profiler.
     157             :   DECL_INT32_ACCESSORS(profiler_ticks)
     158             : 
     159             :   // [deopt_count]: The number of times this function has deoptimized.
     160             :   DECL_INT32_ACCESSORS(deopt_count)
     161             : 
     162             :   inline void clear_invocation_count();
     163             :   inline void increment_deopt_count();
     164             : 
     165             :   inline Code* optimized_code() const;
     166             :   inline OptimizationMarker optimization_marker() const;
     167             :   inline bool has_optimized_code() const;
     168             :   inline bool has_optimization_marker() const;
     169             :   void ClearOptimizedCode();
     170             :   void EvictOptimizedCodeMarkedForDeoptimization(SharedFunctionInfo* shared,
     171             :                                                  const char* reason);
     172             :   static void SetOptimizedCode(Handle<FeedbackVector> vector,
     173             :                                Handle<Code> code);
     174             :   void SetOptimizationMarker(OptimizationMarker marker);
     175             : 
     176             :   // Conversion from a slot to an integer index to the underlying array.
     177             :   static int GetIndex(FeedbackSlot slot) { return slot.ToInt(); }
     178             : 
     179             :   // Conversion from an integer index to the underlying array to a slot.
     180             :   static inline FeedbackSlot ToSlot(int index);
     181             :   inline Object* Get(FeedbackSlot slot) const;
     182             :   inline Object* get(int index) const;
     183             :   inline void Set(FeedbackSlot slot, Object* value,
     184             :                   WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
     185             :   inline void set(int index, Object* value,
     186             :                   WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
     187             : 
     188             :   // Gives access to raw memory which stores the array's data.
     189             :   inline Object** slots_start();
     190             : 
     191             :   // Returns slot kind for given slot.
     192             :   FeedbackSlotKind GetKind(FeedbackSlot slot) const;
     193             : 
     194             :   FeedbackSlot GetTypeProfileSlot() const;
     195             : 
     196             :   static Handle<FeedbackVector> New(Isolate* isolate,
     197             :                                     Handle<SharedFunctionInfo> shared);
     198             : 
     199             :   static Handle<FeedbackVector> Copy(Isolate* isolate,
     200             :                                      Handle<FeedbackVector> vector);
     201             : 
     202             : #define DEFINE_SLOT_KIND_PREDICATE(Name) \
     203             :   bool Name(FeedbackSlot slot) const { return Name##Kind(GetKind(slot)); }
     204             : 
     205             :   DEFINE_SLOT_KIND_PREDICATE(IsCallIC)
     206          24 :   DEFINE_SLOT_KIND_PREDICATE(IsLoadIC)
     207             :   DEFINE_SLOT_KIND_PREDICATE(IsLoadGlobalIC)
     208           0 :   DEFINE_SLOT_KIND_PREDICATE(IsKeyedLoadIC)
     209             :   DEFINE_SLOT_KIND_PREDICATE(IsStoreIC)
     210             :   DEFINE_SLOT_KIND_PREDICATE(IsStoreOwnIC)
     211             :   DEFINE_SLOT_KIND_PREDICATE(IsStoreGlobalIC)
     212             :   DEFINE_SLOT_KIND_PREDICATE(IsKeyedStoreIC)
     213             :   DEFINE_SLOT_KIND_PREDICATE(IsTypeProfile)
     214             : #undef DEFINE_SLOT_KIND_PREDICATE
     215             : 
     216             :   // Returns typeof mode encoded into kind of given slot.
     217             :   inline TypeofMode GetTypeofMode(FeedbackSlot slot) const {
     218             :     return GetTypeofModeFromSlotKind(GetKind(slot));
     219             :   }
     220             : 
     221             :   // Returns language mode encoded into kind of given slot.
     222     1311061 :   inline LanguageMode GetLanguageMode(FeedbackSlot slot) const {
     223     7626319 :     return GetLanguageModeFromSlotKind(GetKind(slot));
     224             :   }
     225             : 
     226             : #ifdef OBJECT_PRINT
     227             :   // For gdb debugging.
     228             :   void Print();
     229             : #endif  // OBJECT_PRINT
     230             : 
     231             :   DECL_PRINTER(FeedbackVector)
     232             :   DECL_VERIFIER(FeedbackVector)
     233             : 
     234             :   // Clears the vector slots. Return true if feedback has changed.
     235             :   bool ClearSlots(Isolate* isolate);
     236             : 
     237             :   // The object that indicates an uninitialized cache.
     238             :   static inline Handle<Symbol> UninitializedSentinel(Isolate* isolate);
     239             : 
     240             :   // The object that indicates a generic state.
     241             :   static inline Handle<Symbol> GenericSentinel(Isolate* isolate);
     242             : 
     243             :   // The object that indicates a megamorphic state.
     244             :   static inline Handle<Symbol> MegamorphicSentinel(Isolate* isolate);
     245             : 
     246             :   // The object that indicates a premonomorphic state.
     247             :   static inline Handle<Symbol> PremonomorphicSentinel(Isolate* isolate);
     248             : 
     249             :   // A raw version of the uninitialized sentinel that's safe to read during
     250             :   // garbage collection (e.g., for patching the cache).
     251             :   static inline Symbol* RawUninitializedSentinel(Isolate* isolate);
     252             : 
     253             : // Layout description.
     254             : #define FEEDBACK_VECTOR_FIELDS(V)            \
     255             :   /* Header fields. */                       \
     256             :   V(kSharedFunctionInfoOffset, kPointerSize) \
     257             :   V(kOptimizedCodeOffset, kPointerSize)      \
     258             :   V(kLengthOffset, kInt32Size)               \
     259             :   V(kInvocationCountOffset, kInt32Size)      \
     260             :   V(kProfilerTicksOffset, kInt32Size)        \
     261             :   V(kDeoptCountOffset, kInt32Size)           \
     262             :   V(kUnalignedHeaderSize, 0)
     263             : 
     264             :   DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, FEEDBACK_VECTOR_FIELDS)
     265             : #undef FEEDBACK_VECTOR_FIELDS
     266             : 
     267             :   static const int kHeaderSize =
     268             :       RoundUp<kPointerAlignment>(kUnalignedHeaderSize);
     269             :   static const int kFeedbackSlotsOffset = kHeaderSize;
     270             : 
     271             :   class BodyDescriptor;
     272             :   // No weak fields.
     273             :   typedef BodyDescriptor BodyDescriptorWeak;
     274             : 
     275             :   // Garbage collection support.
     276             :   static constexpr int SizeFor(int length) {
     277    38224055 :     return kFeedbackSlotsOffset + length * kPointerSize;
     278             :   }
     279             : 
     280             :  private:
     281             :   static void AddToVectorsForProfilingTools(Isolate* isolate,
     282             :                                             Handle<FeedbackVector> vector);
     283             : 
     284             :   DISALLOW_IMPLICIT_CONSTRUCTORS(FeedbackVector);
     285             : };
     286             : 
     287             : template <typename Derived>
     288             : class V8_EXPORT_PRIVATE FeedbackVectorSpecBase {
     289             :  public:
     290     2850206 :   FeedbackSlot AddCallICSlot() { return AddSlot(FeedbackSlotKind::kCall); }
     291             : 
     292             :   FeedbackSlot AddLoadICSlot() {
     293     3545119 :     return AddSlot(FeedbackSlotKind::kLoadProperty);
     294             :   }
     295             : 
     296             :   FeedbackSlot AddLoadGlobalICSlot(TypeofMode typeof_mode) {
     297             :     return AddSlot(typeof_mode == INSIDE_TYPEOF
     298             :                        ? FeedbackSlotKind::kLoadGlobalInsideTypeof
     299     2416265 :                        : FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
     300             :   }
     301             : 
     302             :   FeedbackSlot AddCreateClosureSlot() {
     303     4158758 :     return AddSlot(FeedbackSlotKind::kCreateClosure);
     304             :   }
     305             : 
     306             :   FeedbackSlot AddKeyedLoadICSlot() {
     307      217492 :     return AddSlot(FeedbackSlotKind::kLoadKeyed);
     308             :   }
     309             : 
     310             :   FeedbackSlot AddStoreICSlot(LanguageMode language_mode) {
     311             :     STATIC_ASSERT(LanguageModeSize == 2);
     312             :     return AddSlot(is_strict(language_mode)
     313             :                        ? FeedbackSlotKind::kStoreNamedStrict
     314     1657759 :                        : FeedbackSlotKind::kStoreNamedSloppy);
     315             :   }
     316             : 
     317             :   FeedbackSlot AddStoreOwnICSlot() {
     318      327969 :     return AddSlot(FeedbackSlotKind::kStoreOwnNamed);
     319             :   }
     320             : 
     321             :   FeedbackSlot AddStoreGlobalICSlot(LanguageMode language_mode) {
     322             :     STATIC_ASSERT(LanguageModeSize == 2);
     323             :     return AddSlot(is_strict(language_mode)
     324             :                        ? FeedbackSlotKind::kStoreGlobalStrict
     325     1064786 :                        : FeedbackSlotKind::kStoreGlobalSloppy);
     326             :   }
     327             : 
     328             :   FeedbackSlot AddKeyedStoreICSlot(LanguageMode language_mode) {
     329             :     STATIC_ASSERT(LanguageModeSize == 2);
     330             :     return AddSlot(is_strict(language_mode)
     331             :                        ? FeedbackSlotKind::kStoreKeyedStrict
     332      124980 :                        : FeedbackSlotKind::kStoreKeyedSloppy);
     333             :   }
     334             : 
     335             :   FeedbackSlot AddBinaryOpICSlot() {
     336     1131150 :     return AddSlot(FeedbackSlotKind::kBinaryOp);
     337             :   }
     338             : 
     339             :   FeedbackSlot AddCompareICSlot() {
     340      960036 :     return AddSlot(FeedbackSlotKind::kCompareOp);
     341             :   }
     342             : 
     343        6169 :   FeedbackSlot AddForInSlot() { return AddSlot(FeedbackSlotKind::kForIn); }
     344             : 
     345      569813 :   FeedbackSlot AddLiteralSlot() { return AddSlot(FeedbackSlotKind::kLiteral); }
     346             : 
     347             :   FeedbackSlot AddStoreDataPropertyInLiteralICSlot() {
     348      391768 :     return AddSlot(FeedbackSlotKind::kStoreDataPropertyInLiteral);
     349             :   }
     350             : 
     351             :   FeedbackSlot AddTypeProfileSlot();
     352             : 
     353             : #ifdef OBJECT_PRINT
     354             :   // For gdb debugging.
     355             :   void Print();
     356             : #endif  // OBJECT_PRINT
     357             : 
     358             :   DECL_PRINTER(FeedbackVectorSpec)
     359             : 
     360             :  private:
     361             :   FeedbackSlot AddSlot(FeedbackSlotKind kind);
     362             : 
     363             :   Derived* This() { return static_cast<Derived*>(this); }
     364             : };
     365             : 
     366             : class StaticFeedbackVectorSpec
     367             :     : public FeedbackVectorSpecBase<StaticFeedbackVectorSpec> {
     368             :  public:
     369     9374395 :   StaticFeedbackVectorSpec() : slot_count_(0) {}
     370             : 
     371             :   int slots() const { return slot_count_; }
     372             : 
     373             :   FeedbackSlotKind GetKind(FeedbackSlot slot) const {
     374             :     DCHECK(slot.ToInt() >= 0 && slot.ToInt() < slot_count_);
     375           0 :     return kinds_[slot.ToInt()];
     376             :   }
     377             : 
     378             :  private:
     379             :   friend class FeedbackVectorSpecBase<StaticFeedbackVectorSpec>;
     380             : 
     381             :   void append(FeedbackSlotKind kind) {
     382             :     DCHECK_LT(slot_count_, kMaxLength);
     383           0 :     kinds_[slot_count_++] = kind;
     384             :   }
     385             : 
     386             :   static const int kMaxLength = 12;
     387             : 
     388             :   int slot_count_;
     389             :   FeedbackSlotKind kinds_[kMaxLength];
     390             : };
     391             : 
     392             : class V8_EXPORT_PRIVATE FeedbackVectorSpec
     393             :     : public FeedbackVectorSpecBase<FeedbackVectorSpec> {
     394             :  public:
     395             :   explicit FeedbackVectorSpec(Zone* zone) : slot_kinds_(zone) {
     396     3817500 :     slot_kinds_.reserve(16);
     397             :   }
     398             : 
     399    47425452 :   int slots() const { return static_cast<int>(slot_kinds_.size()); }
     400             : 
     401             :   FeedbackSlotKind GetKind(FeedbackSlot slot) const {
     402   102810876 :     return static_cast<FeedbackSlotKind>(slot_kinds_.at(slot.ToInt()));
     403             :   }
     404             : 
     405             :   bool HasTypeProfileSlot() const;
     406             : 
     407             :   // If used, the TypeProfileSlot is always added as the first slot and its
     408             :   // index is constant. If other slots are added before the TypeProfileSlot,
     409             :   // this number changes.
     410             :   static const int kTypeProfileSlotIndex = 0;
     411             : 
     412             :  private:
     413             :   friend class FeedbackVectorSpecBase<FeedbackVectorSpec>;
     414             : 
     415             :   void append(FeedbackSlotKind kind) {
     416    64037786 :     slot_kinds_.push_back(static_cast<unsigned char>(kind));
     417             :   }
     418             : 
     419             :   ZoneVector<unsigned char> slot_kinds_;
     420             : };
     421             : 
     422             : // The shape of the FeedbackMetadata is an array with:
     423             : // 0: slot_count
     424             : // 1: names table
     425             : // 2: parameters table
     426             : // 3..N: slot kinds packed into a bit vector
     427             : //
     428             : class FeedbackMetadata : public FixedArray {
     429             :  public:
     430             :   // Casting.
     431             :   static inline FeedbackMetadata* cast(Object* obj);
     432             : 
     433             :   static const int kSlotsCountIndex = 0;
     434             :   static const int kReservedIndexCount = 1;
     435             : 
     436             :   // Returns number of feedback vector elements used by given slot kind.
     437             :   static inline int GetSlotSize(FeedbackSlotKind kind);
     438             : 
     439             :   bool SpecDiffersFrom(const FeedbackVectorSpec* other_spec) const;
     440             : 
     441             :   inline bool is_empty() const;
     442             : 
     443             :   // Returns number of slots in the vector.
     444             :   inline int slot_count() const;
     445             : 
     446             :   // Returns slot kind for given slot.
     447             :   FeedbackSlotKind GetKind(FeedbackSlot slot) const;
     448             : 
     449             :   template <typename Spec>
     450     9374395 :   static Handle<FeedbackMetadata> New(Isolate* isolate, const Spec* spec);
     451             : 
     452             : #ifdef OBJECT_PRINT
     453             :   // For gdb debugging.
     454             :   void Print();
     455             : #endif  // OBJECT_PRINT
     456             : 
     457             :   DECL_PRINTER(FeedbackMetadata)
     458             : 
     459             :   static const char* Kind2String(FeedbackSlotKind kind);
     460             :   bool HasTypeProfileSlot() const;
     461             : 
     462             :  private:
     463             :   friend class AccessorAssembler;
     464             : 
     465             :   static const int kFeedbackSlotKindBits = 5;
     466             :   STATIC_ASSERT(static_cast<int>(FeedbackSlotKind::kKindsNumber) <
     467             :                 (1 << kFeedbackSlotKindBits));
     468             : 
     469             :   void SetKind(FeedbackSlot slot, FeedbackSlotKind kind);
     470             : 
     471             :   typedef BitSetComputer<FeedbackSlotKind, kFeedbackSlotKindBits, kSmiValueSize,
     472             :                          uint32_t>
     473             :       VectorICComputer;
     474             : 
     475             :   DISALLOW_IMPLICIT_CONSTRUCTORS(FeedbackMetadata);
     476             : };
     477             : 
     478             : // The following asserts protect an optimization in type feedback vector
     479             : // code that looks into the contents of a slot assuming to find a String,
     480             : // a Symbol, an AllocationSite, a WeakCell, or a FixedArray.
     481             : STATIC_ASSERT(WeakCell::kSize >= 2 * kPointerSize);
     482             : STATIC_ASSERT(WeakCell::kValueOffset ==
     483             :               AllocationSite::kTransitionInfoOrBoilerplateOffset);
     484             : STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset);
     485             : STATIC_ASSERT(WeakCell::kValueOffset == Name::kHashFieldSlot);
     486             : // Verify that an empty hash field looks like a tagged object, but can't
     487             : // possibly be confused with a pointer.
     488             : STATIC_ASSERT((Name::kEmptyHashField & kHeapObjectTag) == kHeapObjectTag);
     489             : STATIC_ASSERT(Name::kEmptyHashField == 0x3);
     490             : // Verify that a set hash field will not look like a tagged object.
     491             : STATIC_ASSERT(Name::kHashNotComputedMask == kHeapObjectTag);
     492             : 
     493             : class FeedbackMetadataIterator {
     494             :  public:
     495             :   explicit FeedbackMetadataIterator(Handle<FeedbackMetadata> metadata)
     496             :       : metadata_handle_(metadata),
     497             :         next_slot_(FeedbackSlot(0)),
     498             :         slot_kind_(FeedbackSlotKind::kInvalid) {}
     499             : 
     500             :   explicit FeedbackMetadataIterator(FeedbackMetadata* metadata)
     501             :       : metadata_(metadata),
     502             :         next_slot_(FeedbackSlot(0)),
     503      134822 :         slot_kind_(FeedbackSlotKind::kInvalid) {}
     504             : 
     505             :   inline bool HasNext() const;
     506             : 
     507             :   inline FeedbackSlot Next();
     508             : 
     509             :   // Returns slot kind of the last slot returned by Next().
     510             :   FeedbackSlotKind kind() const {
     511             :     DCHECK_NE(FeedbackSlotKind::kInvalid, slot_kind_);
     512             :     DCHECK_NE(FeedbackSlotKind::kKindsNumber, slot_kind_);
     513             :     return slot_kind_;
     514             :   }
     515             : 
     516             :   // Returns entry size of the last slot returned by Next().
     517             :   inline int entry_size() const;
     518             : 
     519             :  private:
     520             :   FeedbackMetadata* metadata() const {
     521     1069442 :     return !metadata_handle_.is_null() ? *metadata_handle_ : metadata_;
     522             :   }
     523             : 
     524             :   // The reason for having a handle and a raw pointer to the meta data is
     525             :   // to have a single iterator implementation for both "handlified" and raw
     526             :   // pointer use cases.
     527             :   Handle<FeedbackMetadata> metadata_handle_;
     528             :   FeedbackMetadata* metadata_;
     529             :   FeedbackSlot cur_slot_;
     530             :   FeedbackSlot next_slot_;
     531             :   FeedbackSlotKind slot_kind_;
     532             : };
     533             : 
     534             : // A FeedbackNexus is the combination of a FeedbackVector and a slot.
     535             : // Derived classes customize the update and retrieval of feedback.
     536             : class FeedbackNexus {
     537             :  public:
     538             :   FeedbackNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
     539    16423540 :       : vector_handle_(vector), vector_(nullptr), slot_(slot) {}
     540             :   FeedbackNexus(FeedbackVector* vector, FeedbackSlot slot)
     541      246200 :       : vector_(vector), slot_(slot) {}
     542    13443436 :   virtual ~FeedbackNexus() {}
     543             : 
     544             :   Handle<FeedbackVector> vector_handle() const {
     545             :     DCHECK_NULL(vector_);
     546             :     return vector_handle_;
     547             :   }
     548             :   FeedbackVector* vector() const {
     549    76917628 :     return vector_handle_.is_null() ? vector_ : *vector_handle_;
     550             :   }
     551             :   FeedbackSlot slot() const { return slot_; }
     552    17196664 :   FeedbackSlotKind kind() const { return vector()->GetKind(slot()); }
     553             : 
     554      819934 :   InlineCacheState ic_state() const { return StateFromFeedback(); }
     555     2174752 :   bool IsUninitialized() const { return StateFromFeedback() == UNINITIALIZED; }
     556             :   bool IsMegamorphic() const { return StateFromFeedback() == MEGAMORPHIC; }
     557             :   bool IsGeneric() const { return StateFromFeedback() == GENERIC; }
     558      131768 :   Map* FindFirstMap() const {
     559             :     MapHandles maps;
     560      131768 :     ExtractMaps(&maps);
     561      395294 :     if (maps.size() > 0) return *maps.at(0);
     562             :     return nullptr;
     563             :   }
     564             : 
     565             :   virtual InlineCacheState StateFromFeedback() const = 0;
     566             :   virtual int ExtractMaps(MapHandles* maps) const;
     567             :   virtual MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const;
     568             :   virtual bool FindHandlers(ObjectHandles* code_list, int length = -1) const;
     569           0 :   virtual Name* FindFirstName() const { return nullptr; }
     570             : 
     571             :   bool IsCleared() {
     572      122799 :     InlineCacheState state = StateFromFeedback();
     573      122799 :     return !FLAG_use_ic || state == UNINITIALIZED || state == PREMONOMORPHIC;
     574             :   }
     575             : 
     576       14499 :   virtual void Clear() { ConfigureUninitialized(); }
     577             :   virtual void ConfigureUninitialized();
     578             :   void ConfigurePremonomorphic();
     579             :   void ConfigureMegamorphic(IcCheckType property_type);
     580             : 
     581             :   inline Object* GetFeedback() const;
     582             :   inline Object* GetFeedbackExtra() const;
     583             : 
     584             :   inline Isolate* GetIsolate() const;
     585             : 
     586             :   void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
     587             :                             Handle<Object> handler);
     588             : 
     589             :   void ConfigurePolymorphic(Handle<Name> name, MapHandles const& maps,
     590             :                             ObjectHandles* handlers);
     591             : 
     592             :  protected:
     593             :   inline void SetFeedback(Object* feedback,
     594             :                           WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
     595             :   inline void SetFeedbackExtra(Object* feedback_extra,
     596             :                                WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
     597             : 
     598             :   Handle<FixedArray> EnsureArrayOfSize(int length);
     599             :   Handle<FixedArray> EnsureExtraArrayOfSize(int length);
     600             : 
     601             :  private:
     602             :   // The reason for having a vector handle and a raw pointer is that we can and
     603             :   // should use handles during IC miss, but not during GC when we clear ICs. If
     604             :   // you have a handle to the vector that is better because more operations can
     605             :   // be done, like allocation.
     606             :   Handle<FeedbackVector> vector_handle_;
     607             :   FeedbackVector* vector_;
     608             :   FeedbackSlot slot_;
     609             : };
     610             : 
     611      643422 : class CallICNexus final : public FeedbackNexus {
     612             :  public:
     613             :   CallICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
     614     1598511 :       : FeedbackNexus(vector, slot) {
     615             :     DCHECK(vector->IsCallIC(slot));
     616             :   }
     617             :   CallICNexus(FeedbackVector* vector, FeedbackSlot slot)
     618        7701 :       : FeedbackNexus(vector, slot) {
     619             :     DCHECK(vector->IsCallIC(slot));
     620             :   }
     621             : 
     622             :   void ConfigureUninitialized() final;
     623             : 
     624             :   InlineCacheState StateFromFeedback() const final;
     625             : 
     626           5 :   int ExtractMaps(MapHandles* maps) const final {
     627             :     // CallICs don't record map feedback.
     628           5 :     return 0;
     629             :   }
     630           0 :   MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
     631           0 :     return MaybeHandle<Code>();
     632             :   }
     633           0 :   bool FindHandlers(ObjectHandles* code_list, int length = -1) const final {
     634           0 :     return length == 0;
     635             :   }
     636             : 
     637             :   int ExtractCallCount();
     638             : 
     639             :   // Compute the call frequency based on the call count and the invocation
     640             :   // count (taken from the type feedback vector).
     641             :   float ComputeCallFrequency();
     642             : };
     643             : 
     644     4359020 : class LoadICNexus : public FeedbackNexus {
     645             :  public:
     646     1860455 :   LoadICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
     647     3023994 :       : FeedbackNexus(vector, slot) {
     648             :     DCHECK(vector->IsLoadIC(slot));
     649     1860455 :   }
     650             :   LoadICNexus(FeedbackVector* vector, FeedbackSlot slot)
     651       39189 :       : FeedbackNexus(vector, slot) {
     652             :     DCHECK(vector->IsLoadIC(slot));
     653             :   }
     654             : 
     655        4843 :   void Clear() override { ConfigurePremonomorphic(); }
     656             : 
     657             :   InlineCacheState StateFromFeedback() const override;
     658             : };
     659             : 
     660     5409234 : class LoadGlobalICNexus : public FeedbackNexus {
     661             :  public:
     662     1882870 :   LoadGlobalICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
     663     3519615 :       : FeedbackNexus(vector, slot) {
     664             :     DCHECK(vector->IsLoadGlobalIC(slot));
     665     1882870 :   }
     666             :   LoadGlobalICNexus(FeedbackVector* vector, FeedbackSlot slot)
     667        6749 :       : FeedbackNexus(vector, slot) {
     668             :     DCHECK(vector->IsLoadGlobalIC(slot));
     669             :   }
     670             : 
     671           0 :   int ExtractMaps(MapHandles* maps) const final {
     672             :     // LoadGlobalICs don't record map feedback.
     673           0 :     return 0;
     674             :   }
     675         593 :   MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
     676         593 :     return MaybeHandle<Code>();
     677             :   }
     678           0 :   bool FindHandlers(ObjectHandles* code_list, int length = -1) const final {
     679           0 :     return length == 0;
     680             :   }
     681             : 
     682             :   void ConfigureUninitialized() override;
     683             :   void ConfigurePropertyCellMode(Handle<PropertyCell> cell);
     684             :   void ConfigureHandlerMode(Handle<Object> handler);
     685             : 
     686             :   InlineCacheState StateFromFeedback() const override;
     687             : };
     688             : 
     689      621555 : class KeyedLoadICNexus : public FeedbackNexus {
     690             :  public:
     691      280851 :   KeyedLoadICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
     692      396246 :       : FeedbackNexus(vector, slot) {
     693             :     DCHECK(vector->IsKeyedLoadIC(slot));
     694      280851 :   }
     695             :   KeyedLoadICNexus(FeedbackVector* vector, FeedbackSlot slot)
     696        4837 :       : FeedbackNexus(vector, slot) {
     697             :     DCHECK(vector->IsKeyedLoadIC(slot));
     698             :   }
     699             : 
     700        3111 :   void Clear() override { ConfigurePremonomorphic(); }
     701             : 
     702             :   IcCheckType GetKeyType() const;
     703             :   InlineCacheState StateFromFeedback() const override;
     704             :   Name* FindFirstName() const override;
     705             : };
     706             : 
     707     8877187 : class StoreICNexus : public FeedbackNexus {
     708             :  public:
     709     4253295 :   StoreICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
     710     4876019 :       : FeedbackNexus(vector, slot) {
     711             :     DCHECK(vector->IsStoreIC(slot) || vector->IsStoreOwnIC(slot) ||
     712             :            vector->IsStoreGlobalIC(slot));
     713     4253295 :   }
     714             :   StoreICNexus(FeedbackVector* vector, FeedbackSlot slot)
     715       59863 :       : FeedbackNexus(vector, slot) {
     716             :     DCHECK(vector->IsStoreIC(slot) || vector->IsStoreOwnIC(slot) ||
     717             :            vector->IsStoreGlobalIC(slot));
     718             :   }
     719             : 
     720       27363 :   void Clear() override { ConfigurePremonomorphic(); }
     721             : 
     722             :   InlineCacheState StateFromFeedback() const override;
     723             : };
     724             : 
     725             : // TODO(ishell): Currently we use StoreOwnIC only for storing properties that
     726             : // already exist in the boilerplate therefore we can use StoreIC.
     727             : typedef StoreICNexus StoreOwnICNexus;
     728             : 
     729      708902 : class KeyedStoreICNexus : public FeedbackNexus {
     730             :  public:
     731      320862 :   KeyedStoreICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
     732      449930 :       : FeedbackNexus(vector, slot) {
     733             :     DCHECK(vector->IsKeyedStoreIC(slot));
     734      320862 :   }
     735             :   KeyedStoreICNexus(FeedbackVector* vector, FeedbackSlot slot)
     736        4003 :       : FeedbackNexus(vector, slot) {
     737             :     DCHECK(vector->IsKeyedStoreIC(slot));
     738             :   }
     739             : 
     740        2871 :   void Clear() override { ConfigurePremonomorphic(); }
     741             : 
     742             :   KeyedAccessStoreMode GetKeyedAccessStoreMode() const;
     743             :   IcCheckType GetKeyType() const;
     744             : 
     745             :   InlineCacheState StateFromFeedback() const override;
     746             :   Name* FindFirstName() const override;
     747             : };
     748             : 
     749      483275 : class BinaryOpICNexus final : public FeedbackNexus {
     750             :  public:
     751             :   BinaryOpICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
     752     1165131 :       : FeedbackNexus(vector, slot) {
     753             :     DCHECK_EQ(FeedbackSlotKind::kBinaryOp, vector->GetKind(slot));
     754             :   }
     755             :   BinaryOpICNexus(FeedbackVector* vector, FeedbackSlot slot)
     756             :       : FeedbackNexus(vector, slot) {
     757             :     DCHECK_EQ(FeedbackSlotKind::kBinaryOp, vector->GetKind(slot));
     758             :   }
     759             : 
     760             :   InlineCacheState StateFromFeedback() const final;
     761             :   BinaryOperationHint GetBinaryOperationFeedback() const;
     762             : 
     763           0 :   int ExtractMaps(MapHandles* maps) const final {
     764             :     // BinaryOpICs don't record map feedback.
     765           0 :     return 0;
     766             :   }
     767           0 :   MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
     768           0 :     return MaybeHandle<Code>();
     769             :   }
     770           0 :   bool FindHandlers(ObjectHandles* code_list, int length = -1) const final {
     771           0 :     return length == 0;
     772             :   }
     773             : };
     774             : 
     775      285565 : class CompareICNexus final : public FeedbackNexus {
     776             :  public:
     777             :   CompareICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
     778      682809 :       : FeedbackNexus(vector, slot) {
     779             :     DCHECK_EQ(FeedbackSlotKind::kCompareOp, vector->GetKind(slot));
     780             :   }
     781             :   CompareICNexus(FeedbackVector* vector, FeedbackSlot slot)
     782             :       : FeedbackNexus(vector, slot) {
     783             :     DCHECK_EQ(FeedbackSlotKind::kCompareOp, vector->GetKind(slot));
     784             :   }
     785             : 
     786             :   InlineCacheState StateFromFeedback() const final;
     787             :   CompareOperationHint GetCompareOperationFeedback() const;
     788             : 
     789           0 :   int ExtractMaps(MapHandles* maps) const final {
     790             :     // CompareICs don't record map feedback.
     791           0 :     return 0;
     792             :   }
     793           0 :   MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
     794           0 :     return MaybeHandle<Code>();
     795             :   }
     796           0 :   bool FindHandlers(ObjectHandles* code_list, int length = -1) const final {
     797           0 :     return length == 0;
     798             :   }
     799             : };
     800             : 
     801        3258 : class ForInICNexus final : public FeedbackNexus {
     802             :  public:
     803             :   ForInICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
     804        6480 :       : FeedbackNexus(vector, slot) {
     805             :     DCHECK_EQ(FeedbackSlotKind::kForIn, vector->GetKind(slot));
     806             :   }
     807             :   ForInICNexus(FeedbackVector* vector, FeedbackSlot slot)
     808             :       : FeedbackNexus(vector, slot) {
     809             :     DCHECK_EQ(FeedbackSlotKind::kForIn, vector->GetKind(slot));
     810             :   }
     811             : 
     812             :   InlineCacheState StateFromFeedback() const final;
     813             :   ForInHint GetForInFeedback() const;
     814             : 
     815           0 :   int ExtractMaps(MapHandles* maps) const final { return 0; }
     816           0 :   MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
     817           0 :     return MaybeHandle<Code>();
     818             :   }
     819           0 :   bool FindHandlers(ObjectHandles* code_list, int length = -1) const final {
     820           0 :     return length == 0;
     821             :   }
     822             : };
     823             : 
     824     1299087 : class StoreDataPropertyInLiteralICNexus : public FeedbackNexus {
     825             :  public:
     826      649307 :   StoreDataPropertyInLiteralICNexus(Handle<FeedbackVector> vector,
     827             :                                     FeedbackSlot slot)
     828      704520 :       : FeedbackNexus(vector, slot) {
     829             :     DCHECK_EQ(FeedbackSlotKind::kStoreDataPropertyInLiteral,
     830             :               vector->GetKind(slot));
     831      649307 :   }
     832             :   StoreDataPropertyInLiteralICNexus(FeedbackVector* vector, FeedbackSlot slot)
     833         473 :       : FeedbackNexus(vector, slot) {
     834             :     DCHECK_EQ(FeedbackSlotKind::kStoreDataPropertyInLiteral,
     835             :               vector->GetKind(slot));
     836             :   }
     837             : 
     838             :   void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map);
     839             : 
     840             :   InlineCacheState StateFromFeedback() const override;
     841             : };
     842             : 
     843             : // For each assignment, store the type of the value in the collection of types
     844             : // in the feedback vector.
     845         855 : class CollectTypeProfileNexus : public FeedbackNexus {
     846             :  public:
     847         285 :   CollectTypeProfileNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
     848         285 :       : FeedbackNexus(vector, slot) {
     849             :     DCHECK_EQ(FeedbackSlotKind::kTypeProfile, vector->GetKind(slot));
     850         285 :   }
     851           0 :   CollectTypeProfileNexus(FeedbackVector* vector, FeedbackSlot slot)
     852         285 :       : FeedbackNexus(vector, slot) {
     853             :     DCHECK_EQ(FeedbackSlotKind::kTypeProfile, vector->GetKind(slot));
     854           0 :   }
     855             : 
     856             :   // Add a type to the list of types for source position <position>.
     857             :   void Collect(Handle<String> type, int position);
     858             :   JSObject* GetTypeProfile() const;
     859             : 
     860             :   std::vector<int> GetSourcePositions() const;
     861             :   std::vector<Handle<String>> GetTypesForSourcePositions(uint32_t pos) const;
     862             : 
     863             :   void Clear() override;
     864             : 
     865             :   InlineCacheState StateFromFeedback() const override;
     866             : };
     867             : 
     868             : inline BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback);
     869             : inline CompareOperationHint CompareOperationHintFromFeedback(int type_feedback);
     870             : inline ForInHint ForInHintFromFeedback(int type_feedback);
     871             : 
     872             : }  // namespace internal
     873             : }  // namespace v8
     874             : 
     875             : #endif  // V8_FEEDBACK_VECTOR_H_

Generated by: LCOV version 1.10