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