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