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

Generated by: LCOV version 1.10