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

Generated by: LCOV version 1.10