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