LCOV - code coverage report
Current view: top level - src - feedback-vector.h (source / functions) Hit Total Coverage
Test: app.info Lines: 52 52 100.0 %
Date: 2019-03-21 Functions: 1 1 100.0 %

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

Generated by: LCOV version 1.10