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