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/objects/map.h"
14 : #include "src/objects/name.h"
15 : #include "src/objects/object-macros.h"
16 : #include "src/type-hints.h"
17 : #include "src/zone/zone-containers.h"
18 :
19 : namespace v8 {
20 : namespace internal {
21 :
22 : enum class FeedbackSlotKind {
23 : // This kind means that the slot points to the middle of other slot
24 : // which occupies more than one feedback vector element.
25 : // There must be no such slots in the system.
26 : kInvalid,
27 :
28 : // Sloppy kinds come first, for easy language mode testing.
29 : kStoreGlobalSloppy,
30 : kStoreNamedSloppy,
31 : kStoreKeyedSloppy,
32 : kLastSloppyKind = kStoreKeyedSloppy,
33 :
34 : // Strict and language mode unaware kinds.
35 : kCall,
36 : kLoadProperty,
37 : kLoadGlobalNotInsideTypeof,
38 : kLoadGlobalInsideTypeof,
39 : kLoadKeyed,
40 : kStoreGlobalStrict,
41 : kStoreNamedStrict,
42 : kStoreOwnNamed,
43 : kStoreKeyedStrict,
44 : kBinaryOp,
45 : kCompareOp,
46 : kStoreDataPropertyInLiteral,
47 : kTypeProfile,
48 : kCreateClosure,
49 : kLiteral,
50 : kForIn,
51 :
52 : kKindsNumber // Last value indicating number of kinds.
53 : };
54 :
55 : inline bool IsCallICKind(FeedbackSlotKind kind) {
56 : return kind == FeedbackSlotKind::kCall;
57 : }
58 :
59 1860583 : inline bool IsLoadICKind(FeedbackSlotKind kind) {
60 1860583 : return kind == FeedbackSlotKind::kLoadProperty;
61 : }
62 :
63 128 : inline bool IsLoadGlobalICKind(FeedbackSlotKind kind) {
64 8392367 : return kind == FeedbackSlotKind::kLoadGlobalNotInsideTypeof ||
65 128 : kind == FeedbackSlotKind::kLoadGlobalInsideTypeof;
66 : }
67 :
68 : inline bool IsKeyedLoadICKind(FeedbackSlotKind kind) {
69 : return kind == FeedbackSlotKind::kLoadKeyed;
70 : }
71 :
72 1508137 : inline bool IsStoreGlobalICKind(FeedbackSlotKind kind) {
73 1508137 : return kind == FeedbackSlotKind::kStoreGlobalSloppy ||
74 1508137 : kind == FeedbackSlotKind::kStoreGlobalStrict;
75 : }
76 :
77 4253295 : inline bool IsStoreICKind(FeedbackSlotKind kind) {
78 4253295 : return kind == FeedbackSlotKind::kStoreNamedSloppy ||
79 4253295 : kind == FeedbackSlotKind::kStoreNamedStrict;
80 : }
81 :
82 1895143 : inline bool IsStoreOwnICKind(FeedbackSlotKind kind) {
83 1895143 : return kind == FeedbackSlotKind::kStoreOwnNamed;
84 : }
85 :
86 : inline bool IsKeyedStoreICKind(FeedbackSlotKind kind) {
87 3270733 : return kind == FeedbackSlotKind::kStoreKeyedSloppy ||
88 3270733 : kind == FeedbackSlotKind::kStoreKeyedStrict;
89 : }
90 :
91 : inline bool IsTypeProfileKind(FeedbackSlotKind kind) {
92 : return kind == FeedbackSlotKind::kTypeProfile;
93 : }
94 :
95 : inline TypeofMode GetTypeofModeFromSlotKind(FeedbackSlotKind kind) {
96 : DCHECK(IsLoadGlobalICKind(kind));
97 : return (kind == FeedbackSlotKind::kLoadGlobalInsideTypeof)
98 : ? INSIDE_TYPEOF
99 : : NOT_INSIDE_TYPEOF;
100 : }
101 :
102 : inline LanguageMode GetLanguageModeFromSlotKind(FeedbackSlotKind kind) {
103 : DCHECK(IsStoreICKind(kind) || IsStoreOwnICKind(kind) ||
104 : IsStoreGlobalICKind(kind) || IsKeyedStoreICKind(kind));
105 : STATIC_ASSERT(FeedbackSlotKind::kStoreGlobalSloppy <=
106 : FeedbackSlotKind::kLastSloppyKind);
107 : STATIC_ASSERT(FeedbackSlotKind::kStoreKeyedSloppy <=
108 : FeedbackSlotKind::kLastSloppyKind);
109 : STATIC_ASSERT(FeedbackSlotKind::kStoreNamedSloppy <=
110 : FeedbackSlotKind::kLastSloppyKind);
111 : return (kind <= FeedbackSlotKind::kLastSloppyKind) ? LanguageMode::kSloppy
112 6315258 : : LanguageMode::kStrict;
113 : }
114 :
115 : std::ostream& operator<<(std::ostream& os, FeedbackSlotKind kind);
116 :
117 : typedef std::vector<Handle<Object>> ObjectHandles;
118 :
119 : class FeedbackMetadata;
120 :
121 : // A FeedbackVector has a fixed header with:
122 : // - shared function info (which includes feedback metadata)
123 : // - invocation count
124 : // - runtime profiler ticks
125 : // - optimized code cell (weak cell or Smi marker)
126 : // followed by an array of feedback slots, of length determined by the feedback
127 : // metadata.
128 : class FeedbackVector : public HeapObject {
129 : public:
130 : // Casting.
131 : static inline FeedbackVector* cast(Object* obj);
132 :
133 : inline void ComputeCounts(int* with_type_info, int* generic,
134 : int* vector_ic_count);
135 :
136 : inline bool is_empty() const;
137 :
138 : inline FeedbackMetadata* metadata() const;
139 :
140 : // [shared_function_info]: The shared function info for the function with this
141 : // feedback vector.
142 : DECL_ACCESSORS(shared_function_info, SharedFunctionInfo)
143 :
144 : // [optimized_code_cell]: WeakCell containing optimized code or a Smi marker
145 : // defining optimization behaviour.
146 : DECL_ACCESSORS(optimized_code_cell, Object)
147 :
148 : // [length]: The length of the feedback vector (not including the header, i.e.
149 : // the number of feedback slots).
150 : DECL_INT32_ACCESSORS(length)
151 :
152 : // [invocation_count]: The number of times this function has been invoked.
153 : DECL_INT32_ACCESSORS(invocation_count)
154 :
155 : // [invocation_count]: The number of times this function has been seen by the
156 : // runtime profiler.
157 : DECL_INT32_ACCESSORS(profiler_ticks)
158 :
159 : // [deopt_count]: The number of times this function has deoptimized.
160 : DECL_INT32_ACCESSORS(deopt_count)
161 :
162 : inline void clear_invocation_count();
163 : inline void increment_deopt_count();
164 :
165 : inline Code* optimized_code() const;
166 : inline OptimizationMarker optimization_marker() const;
167 : inline bool has_optimized_code() const;
168 : inline bool has_optimization_marker() const;
169 : void ClearOptimizedCode();
170 : void EvictOptimizedCodeMarkedForDeoptimization(SharedFunctionInfo* shared,
171 : const char* reason);
172 : static void SetOptimizedCode(Handle<FeedbackVector> vector,
173 : Handle<Code> code);
174 : void SetOptimizationMarker(OptimizationMarker marker);
175 :
176 : // Conversion from a slot to an integer index to the underlying array.
177 : static int GetIndex(FeedbackSlot slot) { return slot.ToInt(); }
178 :
179 : // Conversion from an integer index to the underlying array to a slot.
180 : static inline FeedbackSlot ToSlot(int index);
181 : inline Object* Get(FeedbackSlot slot) const;
182 : inline Object* get(int index) const;
183 : inline void Set(FeedbackSlot slot, Object* value,
184 : WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
185 : inline void set(int index, Object* value,
186 : WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
187 :
188 : // Gives access to raw memory which stores the array's data.
189 : inline Object** slots_start();
190 :
191 : // Returns slot kind for given slot.
192 : FeedbackSlotKind GetKind(FeedbackSlot slot) const;
193 :
194 : FeedbackSlot GetTypeProfileSlot() const;
195 :
196 : static Handle<FeedbackVector> New(Isolate* isolate,
197 : Handle<SharedFunctionInfo> shared);
198 :
199 : static Handle<FeedbackVector> Copy(Isolate* isolate,
200 : Handle<FeedbackVector> vector);
201 :
202 : #define DEFINE_SLOT_KIND_PREDICATE(Name) \
203 : bool Name(FeedbackSlot slot) const { return Name##Kind(GetKind(slot)); }
204 :
205 : DEFINE_SLOT_KIND_PREDICATE(IsCallIC)
206 24 : DEFINE_SLOT_KIND_PREDICATE(IsLoadIC)
207 : DEFINE_SLOT_KIND_PREDICATE(IsLoadGlobalIC)
208 0 : DEFINE_SLOT_KIND_PREDICATE(IsKeyedLoadIC)
209 : DEFINE_SLOT_KIND_PREDICATE(IsStoreIC)
210 : DEFINE_SLOT_KIND_PREDICATE(IsStoreOwnIC)
211 : DEFINE_SLOT_KIND_PREDICATE(IsStoreGlobalIC)
212 : DEFINE_SLOT_KIND_PREDICATE(IsKeyedStoreIC)
213 : DEFINE_SLOT_KIND_PREDICATE(IsTypeProfile)
214 : #undef DEFINE_SLOT_KIND_PREDICATE
215 :
216 : // Returns typeof mode encoded into kind of given slot.
217 : inline TypeofMode GetTypeofMode(FeedbackSlot slot) const {
218 : return GetTypeofModeFromSlotKind(GetKind(slot));
219 : }
220 :
221 : // Returns language mode encoded into kind of given slot.
222 1311061 : inline LanguageMode GetLanguageMode(FeedbackSlot slot) const {
223 7626319 : return GetLanguageModeFromSlotKind(GetKind(slot));
224 : }
225 :
226 : #ifdef OBJECT_PRINT
227 : // For gdb debugging.
228 : void Print();
229 : #endif // OBJECT_PRINT
230 :
231 : DECL_PRINTER(FeedbackVector)
232 : DECL_VERIFIER(FeedbackVector)
233 :
234 : // Clears the vector slots. Return true if feedback has changed.
235 : bool ClearSlots(Isolate* isolate);
236 :
237 : // The object that indicates an uninitialized cache.
238 : static inline Handle<Symbol> UninitializedSentinel(Isolate* isolate);
239 :
240 : // The object that indicates a generic state.
241 : static inline Handle<Symbol> GenericSentinel(Isolate* isolate);
242 :
243 : // The object that indicates a megamorphic state.
244 : static inline Handle<Symbol> MegamorphicSentinel(Isolate* isolate);
245 :
246 : // The object that indicates a premonomorphic state.
247 : static inline Handle<Symbol> PremonomorphicSentinel(Isolate* isolate);
248 :
249 : // A raw version of the uninitialized sentinel that's safe to read during
250 : // garbage collection (e.g., for patching the cache).
251 : static inline Symbol* RawUninitializedSentinel(Isolate* isolate);
252 :
253 : // Layout description.
254 : #define FEEDBACK_VECTOR_FIELDS(V) \
255 : /* Header fields. */ \
256 : V(kSharedFunctionInfoOffset, kPointerSize) \
257 : V(kOptimizedCodeOffset, kPointerSize) \
258 : V(kLengthOffset, kInt32Size) \
259 : V(kInvocationCountOffset, kInt32Size) \
260 : V(kProfilerTicksOffset, kInt32Size) \
261 : V(kDeoptCountOffset, kInt32Size) \
262 : V(kUnalignedHeaderSize, 0)
263 :
264 : DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, FEEDBACK_VECTOR_FIELDS)
265 : #undef FEEDBACK_VECTOR_FIELDS
266 :
267 : static const int kHeaderSize =
268 : RoundUp<kPointerAlignment>(kUnalignedHeaderSize);
269 : static const int kFeedbackSlotsOffset = kHeaderSize;
270 :
271 : class BodyDescriptor;
272 : // No weak fields.
273 : typedef BodyDescriptor BodyDescriptorWeak;
274 :
275 : // Garbage collection support.
276 : static constexpr int SizeFor(int length) {
277 38224055 : return kFeedbackSlotsOffset + length * kPointerSize;
278 : }
279 :
280 : private:
281 : static void AddToVectorsForProfilingTools(Isolate* isolate,
282 : Handle<FeedbackVector> vector);
283 :
284 : DISALLOW_IMPLICIT_CONSTRUCTORS(FeedbackVector);
285 : };
286 :
287 : template <typename Derived>
288 : class V8_EXPORT_PRIVATE FeedbackVectorSpecBase {
289 : public:
290 2850206 : FeedbackSlot AddCallICSlot() { return AddSlot(FeedbackSlotKind::kCall); }
291 :
292 : FeedbackSlot AddLoadICSlot() {
293 3545119 : return AddSlot(FeedbackSlotKind::kLoadProperty);
294 : }
295 :
296 : FeedbackSlot AddLoadGlobalICSlot(TypeofMode typeof_mode) {
297 : return AddSlot(typeof_mode == INSIDE_TYPEOF
298 : ? FeedbackSlotKind::kLoadGlobalInsideTypeof
299 2416265 : : FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
300 : }
301 :
302 : FeedbackSlot AddCreateClosureSlot() {
303 4158758 : return AddSlot(FeedbackSlotKind::kCreateClosure);
304 : }
305 :
306 : FeedbackSlot AddKeyedLoadICSlot() {
307 217492 : return AddSlot(FeedbackSlotKind::kLoadKeyed);
308 : }
309 :
310 : FeedbackSlot AddStoreICSlot(LanguageMode language_mode) {
311 : STATIC_ASSERT(LanguageModeSize == 2);
312 : return AddSlot(is_strict(language_mode)
313 : ? FeedbackSlotKind::kStoreNamedStrict
314 1657759 : : FeedbackSlotKind::kStoreNamedSloppy);
315 : }
316 :
317 : FeedbackSlot AddStoreOwnICSlot() {
318 327969 : return AddSlot(FeedbackSlotKind::kStoreOwnNamed);
319 : }
320 :
321 : FeedbackSlot AddStoreGlobalICSlot(LanguageMode language_mode) {
322 : STATIC_ASSERT(LanguageModeSize == 2);
323 : return AddSlot(is_strict(language_mode)
324 : ? FeedbackSlotKind::kStoreGlobalStrict
325 1064786 : : FeedbackSlotKind::kStoreGlobalSloppy);
326 : }
327 :
328 : FeedbackSlot AddKeyedStoreICSlot(LanguageMode language_mode) {
329 : STATIC_ASSERT(LanguageModeSize == 2);
330 : return AddSlot(is_strict(language_mode)
331 : ? FeedbackSlotKind::kStoreKeyedStrict
332 124980 : : FeedbackSlotKind::kStoreKeyedSloppy);
333 : }
334 :
335 : FeedbackSlot AddBinaryOpICSlot() {
336 1131150 : return AddSlot(FeedbackSlotKind::kBinaryOp);
337 : }
338 :
339 : FeedbackSlot AddCompareICSlot() {
340 960036 : return AddSlot(FeedbackSlotKind::kCompareOp);
341 : }
342 :
343 6169 : FeedbackSlot AddForInSlot() { return AddSlot(FeedbackSlotKind::kForIn); }
344 :
345 569813 : FeedbackSlot AddLiteralSlot() { return AddSlot(FeedbackSlotKind::kLiteral); }
346 :
347 : FeedbackSlot AddStoreDataPropertyInLiteralICSlot() {
348 391768 : return AddSlot(FeedbackSlotKind::kStoreDataPropertyInLiteral);
349 : }
350 :
351 : FeedbackSlot AddTypeProfileSlot();
352 :
353 : #ifdef OBJECT_PRINT
354 : // For gdb debugging.
355 : void Print();
356 : #endif // OBJECT_PRINT
357 :
358 : DECL_PRINTER(FeedbackVectorSpec)
359 :
360 : private:
361 : FeedbackSlot AddSlot(FeedbackSlotKind kind);
362 :
363 : Derived* This() { return static_cast<Derived*>(this); }
364 : };
365 :
366 : class StaticFeedbackVectorSpec
367 : : public FeedbackVectorSpecBase<StaticFeedbackVectorSpec> {
368 : public:
369 9374395 : StaticFeedbackVectorSpec() : slot_count_(0) {}
370 :
371 : int slots() const { return slot_count_; }
372 :
373 : FeedbackSlotKind GetKind(FeedbackSlot slot) const {
374 : DCHECK(slot.ToInt() >= 0 && slot.ToInt() < slot_count_);
375 0 : return kinds_[slot.ToInt()];
376 : }
377 :
378 : private:
379 : friend class FeedbackVectorSpecBase<StaticFeedbackVectorSpec>;
380 :
381 : void append(FeedbackSlotKind kind) {
382 : DCHECK_LT(slot_count_, kMaxLength);
383 0 : kinds_[slot_count_++] = kind;
384 : }
385 :
386 : static const int kMaxLength = 12;
387 :
388 : int slot_count_;
389 : FeedbackSlotKind kinds_[kMaxLength];
390 : };
391 :
392 : class V8_EXPORT_PRIVATE FeedbackVectorSpec
393 : : public FeedbackVectorSpecBase<FeedbackVectorSpec> {
394 : public:
395 : explicit FeedbackVectorSpec(Zone* zone) : slot_kinds_(zone) {
396 3817500 : slot_kinds_.reserve(16);
397 : }
398 :
399 47425452 : int slots() const { return static_cast<int>(slot_kinds_.size()); }
400 :
401 : FeedbackSlotKind GetKind(FeedbackSlot slot) const {
402 102810876 : return static_cast<FeedbackSlotKind>(slot_kinds_.at(slot.ToInt()));
403 : }
404 :
405 : bool HasTypeProfileSlot() const;
406 :
407 : // If used, the TypeProfileSlot is always added as the first slot and its
408 : // index is constant. If other slots are added before the TypeProfileSlot,
409 : // this number changes.
410 : static const int kTypeProfileSlotIndex = 0;
411 :
412 : private:
413 : friend class FeedbackVectorSpecBase<FeedbackVectorSpec>;
414 :
415 : void append(FeedbackSlotKind kind) {
416 64037786 : slot_kinds_.push_back(static_cast<unsigned char>(kind));
417 : }
418 :
419 : ZoneVector<unsigned char> slot_kinds_;
420 : };
421 :
422 : // The shape of the FeedbackMetadata is an array with:
423 : // 0: slot_count
424 : // 1: names table
425 : // 2: parameters table
426 : // 3..N: slot kinds packed into a bit vector
427 : //
428 : class FeedbackMetadata : public FixedArray {
429 : public:
430 : // Casting.
431 : static inline FeedbackMetadata* cast(Object* obj);
432 :
433 : static const int kSlotsCountIndex = 0;
434 : static const int kReservedIndexCount = 1;
435 :
436 : // Returns number of feedback vector elements used by given slot kind.
437 : static inline int GetSlotSize(FeedbackSlotKind kind);
438 :
439 : bool SpecDiffersFrom(const FeedbackVectorSpec* other_spec) const;
440 :
441 : inline bool is_empty() const;
442 :
443 : // Returns number of slots in the vector.
444 : inline int slot_count() const;
445 :
446 : // Returns slot kind for given slot.
447 : FeedbackSlotKind GetKind(FeedbackSlot slot) const;
448 :
449 : template <typename Spec>
450 9374395 : static Handle<FeedbackMetadata> New(Isolate* isolate, const Spec* spec);
451 :
452 : #ifdef OBJECT_PRINT
453 : // For gdb debugging.
454 : void Print();
455 : #endif // OBJECT_PRINT
456 :
457 : DECL_PRINTER(FeedbackMetadata)
458 :
459 : static const char* Kind2String(FeedbackSlotKind kind);
460 : bool HasTypeProfileSlot() const;
461 :
462 : private:
463 : friend class AccessorAssembler;
464 :
465 : static const int kFeedbackSlotKindBits = 5;
466 : STATIC_ASSERT(static_cast<int>(FeedbackSlotKind::kKindsNumber) <
467 : (1 << kFeedbackSlotKindBits));
468 :
469 : void SetKind(FeedbackSlot slot, FeedbackSlotKind kind);
470 :
471 : typedef BitSetComputer<FeedbackSlotKind, kFeedbackSlotKindBits, kSmiValueSize,
472 : uint32_t>
473 : VectorICComputer;
474 :
475 : DISALLOW_IMPLICIT_CONSTRUCTORS(FeedbackMetadata);
476 : };
477 :
478 : // The following asserts protect an optimization in type feedback vector
479 : // code that looks into the contents of a slot assuming to find a String,
480 : // a Symbol, an AllocationSite, a WeakCell, or a FixedArray.
481 : STATIC_ASSERT(WeakCell::kSize >= 2 * kPointerSize);
482 : STATIC_ASSERT(WeakCell::kValueOffset ==
483 : AllocationSite::kTransitionInfoOrBoilerplateOffset);
484 : STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset);
485 : STATIC_ASSERT(WeakCell::kValueOffset == Name::kHashFieldSlot);
486 : // Verify that an empty hash field looks like a tagged object, but can't
487 : // possibly be confused with a pointer.
488 : STATIC_ASSERT((Name::kEmptyHashField & kHeapObjectTag) == kHeapObjectTag);
489 : STATIC_ASSERT(Name::kEmptyHashField == 0x3);
490 : // Verify that a set hash field will not look like a tagged object.
491 : STATIC_ASSERT(Name::kHashNotComputedMask == kHeapObjectTag);
492 :
493 : class FeedbackMetadataIterator {
494 : public:
495 : explicit FeedbackMetadataIterator(Handle<FeedbackMetadata> metadata)
496 : : metadata_handle_(metadata),
497 : next_slot_(FeedbackSlot(0)),
498 : slot_kind_(FeedbackSlotKind::kInvalid) {}
499 :
500 : explicit FeedbackMetadataIterator(FeedbackMetadata* metadata)
501 : : metadata_(metadata),
502 : next_slot_(FeedbackSlot(0)),
503 134822 : slot_kind_(FeedbackSlotKind::kInvalid) {}
504 :
505 : inline bool HasNext() const;
506 :
507 : inline FeedbackSlot Next();
508 :
509 : // Returns slot kind of the last slot returned by Next().
510 : FeedbackSlotKind kind() const {
511 : DCHECK_NE(FeedbackSlotKind::kInvalid, slot_kind_);
512 : DCHECK_NE(FeedbackSlotKind::kKindsNumber, slot_kind_);
513 : return slot_kind_;
514 : }
515 :
516 : // Returns entry size of the last slot returned by Next().
517 : inline int entry_size() const;
518 :
519 : private:
520 : FeedbackMetadata* metadata() const {
521 1069442 : return !metadata_handle_.is_null() ? *metadata_handle_ : metadata_;
522 : }
523 :
524 : // The reason for having a handle and a raw pointer to the meta data is
525 : // to have a single iterator implementation for both "handlified" and raw
526 : // pointer use cases.
527 : Handle<FeedbackMetadata> metadata_handle_;
528 : FeedbackMetadata* metadata_;
529 : FeedbackSlot cur_slot_;
530 : FeedbackSlot next_slot_;
531 : FeedbackSlotKind slot_kind_;
532 : };
533 :
534 : // A FeedbackNexus is the combination of a FeedbackVector and a slot.
535 : // Derived classes customize the update and retrieval of feedback.
536 : class FeedbackNexus {
537 : public:
538 : FeedbackNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
539 16423540 : : vector_handle_(vector), vector_(nullptr), slot_(slot) {}
540 : FeedbackNexus(FeedbackVector* vector, FeedbackSlot slot)
541 246200 : : vector_(vector), slot_(slot) {}
542 13443436 : virtual ~FeedbackNexus() {}
543 :
544 : Handle<FeedbackVector> vector_handle() const {
545 : DCHECK_NULL(vector_);
546 : return vector_handle_;
547 : }
548 : FeedbackVector* vector() const {
549 76917628 : return vector_handle_.is_null() ? vector_ : *vector_handle_;
550 : }
551 : FeedbackSlot slot() const { return slot_; }
552 17196664 : FeedbackSlotKind kind() const { return vector()->GetKind(slot()); }
553 :
554 819934 : InlineCacheState ic_state() const { return StateFromFeedback(); }
555 2174752 : bool IsUninitialized() const { return StateFromFeedback() == UNINITIALIZED; }
556 : bool IsMegamorphic() const { return StateFromFeedback() == MEGAMORPHIC; }
557 : bool IsGeneric() const { return StateFromFeedback() == GENERIC; }
558 131768 : Map* FindFirstMap() const {
559 : MapHandles maps;
560 131768 : ExtractMaps(&maps);
561 395294 : if (maps.size() > 0) return *maps.at(0);
562 : return nullptr;
563 : }
564 :
565 : virtual InlineCacheState StateFromFeedback() const = 0;
566 : virtual int ExtractMaps(MapHandles* maps) const;
567 : virtual MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const;
568 : virtual bool FindHandlers(ObjectHandles* code_list, int length = -1) const;
569 0 : virtual Name* FindFirstName() const { return nullptr; }
570 :
571 : bool IsCleared() {
572 122799 : InlineCacheState state = StateFromFeedback();
573 122799 : return !FLAG_use_ic || state == UNINITIALIZED || state == PREMONOMORPHIC;
574 : }
575 :
576 14499 : virtual void Clear() { ConfigureUninitialized(); }
577 : virtual void ConfigureUninitialized();
578 : void ConfigurePremonomorphic();
579 : void ConfigureMegamorphic(IcCheckType property_type);
580 :
581 : inline Object* GetFeedback() const;
582 : inline Object* GetFeedbackExtra() const;
583 :
584 : inline Isolate* GetIsolate() const;
585 :
586 : void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
587 : Handle<Object> handler);
588 :
589 : void ConfigurePolymorphic(Handle<Name> name, MapHandles const& maps,
590 : ObjectHandles* handlers);
591 :
592 : protected:
593 : inline void SetFeedback(Object* feedback,
594 : WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
595 : inline void SetFeedbackExtra(Object* feedback_extra,
596 : WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
597 :
598 : Handle<FixedArray> EnsureArrayOfSize(int length);
599 : Handle<FixedArray> EnsureExtraArrayOfSize(int length);
600 :
601 : private:
602 : // The reason for having a vector handle and a raw pointer is that we can and
603 : // should use handles during IC miss, but not during GC when we clear ICs. If
604 : // you have a handle to the vector that is better because more operations can
605 : // be done, like allocation.
606 : Handle<FeedbackVector> vector_handle_;
607 : FeedbackVector* vector_;
608 : FeedbackSlot slot_;
609 : };
610 :
611 643422 : class CallICNexus final : public FeedbackNexus {
612 : public:
613 : CallICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
614 1598511 : : FeedbackNexus(vector, slot) {
615 : DCHECK(vector->IsCallIC(slot));
616 : }
617 : CallICNexus(FeedbackVector* vector, FeedbackSlot slot)
618 7701 : : FeedbackNexus(vector, slot) {
619 : DCHECK(vector->IsCallIC(slot));
620 : }
621 :
622 : void ConfigureUninitialized() final;
623 :
624 : InlineCacheState StateFromFeedback() const final;
625 :
626 5 : int ExtractMaps(MapHandles* maps) const final {
627 : // CallICs don't record map feedback.
628 5 : return 0;
629 : }
630 0 : MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
631 0 : return MaybeHandle<Code>();
632 : }
633 0 : bool FindHandlers(ObjectHandles* code_list, int length = -1) const final {
634 0 : return length == 0;
635 : }
636 :
637 : int ExtractCallCount();
638 :
639 : // Compute the call frequency based on the call count and the invocation
640 : // count (taken from the type feedback vector).
641 : float ComputeCallFrequency();
642 : };
643 :
644 4359020 : class LoadICNexus : public FeedbackNexus {
645 : public:
646 1860455 : LoadICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
647 3023994 : : FeedbackNexus(vector, slot) {
648 : DCHECK(vector->IsLoadIC(slot));
649 1860455 : }
650 : LoadICNexus(FeedbackVector* vector, FeedbackSlot slot)
651 39189 : : FeedbackNexus(vector, slot) {
652 : DCHECK(vector->IsLoadIC(slot));
653 : }
654 :
655 4843 : void Clear() override { ConfigurePremonomorphic(); }
656 :
657 : InlineCacheState StateFromFeedback() const override;
658 : };
659 :
660 5409234 : class LoadGlobalICNexus : public FeedbackNexus {
661 : public:
662 1882870 : LoadGlobalICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
663 3519615 : : FeedbackNexus(vector, slot) {
664 : DCHECK(vector->IsLoadGlobalIC(slot));
665 1882870 : }
666 : LoadGlobalICNexus(FeedbackVector* vector, FeedbackSlot slot)
667 6749 : : FeedbackNexus(vector, slot) {
668 : DCHECK(vector->IsLoadGlobalIC(slot));
669 : }
670 :
671 0 : int ExtractMaps(MapHandles* maps) const final {
672 : // LoadGlobalICs don't record map feedback.
673 0 : return 0;
674 : }
675 593 : MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
676 593 : return MaybeHandle<Code>();
677 : }
678 0 : bool FindHandlers(ObjectHandles* code_list, int length = -1) const final {
679 0 : return length == 0;
680 : }
681 :
682 : void ConfigureUninitialized() override;
683 : void ConfigurePropertyCellMode(Handle<PropertyCell> cell);
684 : void ConfigureHandlerMode(Handle<Object> handler);
685 :
686 : InlineCacheState StateFromFeedback() const override;
687 : };
688 :
689 621555 : class KeyedLoadICNexus : public FeedbackNexus {
690 : public:
691 280851 : KeyedLoadICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
692 396246 : : FeedbackNexus(vector, slot) {
693 : DCHECK(vector->IsKeyedLoadIC(slot));
694 280851 : }
695 : KeyedLoadICNexus(FeedbackVector* vector, FeedbackSlot slot)
696 4837 : : FeedbackNexus(vector, slot) {
697 : DCHECK(vector->IsKeyedLoadIC(slot));
698 : }
699 :
700 3111 : void Clear() override { ConfigurePremonomorphic(); }
701 :
702 : IcCheckType GetKeyType() const;
703 : InlineCacheState StateFromFeedback() const override;
704 : Name* FindFirstName() const override;
705 : };
706 :
707 8877187 : class StoreICNexus : public FeedbackNexus {
708 : public:
709 4253295 : StoreICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
710 4876019 : : FeedbackNexus(vector, slot) {
711 : DCHECK(vector->IsStoreIC(slot) || vector->IsStoreOwnIC(slot) ||
712 : vector->IsStoreGlobalIC(slot));
713 4253295 : }
714 : StoreICNexus(FeedbackVector* vector, FeedbackSlot slot)
715 59863 : : FeedbackNexus(vector, slot) {
716 : DCHECK(vector->IsStoreIC(slot) || vector->IsStoreOwnIC(slot) ||
717 : vector->IsStoreGlobalIC(slot));
718 : }
719 :
720 27363 : void Clear() override { ConfigurePremonomorphic(); }
721 :
722 : InlineCacheState StateFromFeedback() const override;
723 : };
724 :
725 : // TODO(ishell): Currently we use StoreOwnIC only for storing properties that
726 : // already exist in the boilerplate therefore we can use StoreIC.
727 : typedef StoreICNexus StoreOwnICNexus;
728 :
729 708902 : class KeyedStoreICNexus : public FeedbackNexus {
730 : public:
731 320862 : KeyedStoreICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
732 449930 : : FeedbackNexus(vector, slot) {
733 : DCHECK(vector->IsKeyedStoreIC(slot));
734 320862 : }
735 : KeyedStoreICNexus(FeedbackVector* vector, FeedbackSlot slot)
736 4003 : : FeedbackNexus(vector, slot) {
737 : DCHECK(vector->IsKeyedStoreIC(slot));
738 : }
739 :
740 2871 : void Clear() override { ConfigurePremonomorphic(); }
741 :
742 : KeyedAccessStoreMode GetKeyedAccessStoreMode() const;
743 : IcCheckType GetKeyType() const;
744 :
745 : InlineCacheState StateFromFeedback() const override;
746 : Name* FindFirstName() const override;
747 : };
748 :
749 483275 : class BinaryOpICNexus final : public FeedbackNexus {
750 : public:
751 : BinaryOpICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
752 1165131 : : FeedbackNexus(vector, slot) {
753 : DCHECK_EQ(FeedbackSlotKind::kBinaryOp, vector->GetKind(slot));
754 : }
755 : BinaryOpICNexus(FeedbackVector* vector, FeedbackSlot slot)
756 : : FeedbackNexus(vector, slot) {
757 : DCHECK_EQ(FeedbackSlotKind::kBinaryOp, vector->GetKind(slot));
758 : }
759 :
760 : InlineCacheState StateFromFeedback() const final;
761 : BinaryOperationHint GetBinaryOperationFeedback() const;
762 :
763 0 : int ExtractMaps(MapHandles* maps) const final {
764 : // BinaryOpICs don't record map feedback.
765 0 : return 0;
766 : }
767 0 : MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
768 0 : return MaybeHandle<Code>();
769 : }
770 0 : bool FindHandlers(ObjectHandles* code_list, int length = -1) const final {
771 0 : return length == 0;
772 : }
773 : };
774 :
775 285565 : class CompareICNexus final : public FeedbackNexus {
776 : public:
777 : CompareICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
778 682809 : : FeedbackNexus(vector, slot) {
779 : DCHECK_EQ(FeedbackSlotKind::kCompareOp, vector->GetKind(slot));
780 : }
781 : CompareICNexus(FeedbackVector* vector, FeedbackSlot slot)
782 : : FeedbackNexus(vector, slot) {
783 : DCHECK_EQ(FeedbackSlotKind::kCompareOp, vector->GetKind(slot));
784 : }
785 :
786 : InlineCacheState StateFromFeedback() const final;
787 : CompareOperationHint GetCompareOperationFeedback() const;
788 :
789 0 : int ExtractMaps(MapHandles* maps) const final {
790 : // CompareICs don't record map feedback.
791 0 : return 0;
792 : }
793 0 : MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
794 0 : return MaybeHandle<Code>();
795 : }
796 0 : bool FindHandlers(ObjectHandles* code_list, int length = -1) const final {
797 0 : return length == 0;
798 : }
799 : };
800 :
801 3258 : class ForInICNexus final : public FeedbackNexus {
802 : public:
803 : ForInICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
804 6480 : : FeedbackNexus(vector, slot) {
805 : DCHECK_EQ(FeedbackSlotKind::kForIn, vector->GetKind(slot));
806 : }
807 : ForInICNexus(FeedbackVector* vector, FeedbackSlot slot)
808 : : FeedbackNexus(vector, slot) {
809 : DCHECK_EQ(FeedbackSlotKind::kForIn, vector->GetKind(slot));
810 : }
811 :
812 : InlineCacheState StateFromFeedback() const final;
813 : ForInHint GetForInFeedback() const;
814 :
815 0 : int ExtractMaps(MapHandles* maps) const final { return 0; }
816 0 : MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
817 0 : return MaybeHandle<Code>();
818 : }
819 0 : bool FindHandlers(ObjectHandles* code_list, int length = -1) const final {
820 0 : return length == 0;
821 : }
822 : };
823 :
824 1299087 : class StoreDataPropertyInLiteralICNexus : public FeedbackNexus {
825 : public:
826 649307 : StoreDataPropertyInLiteralICNexus(Handle<FeedbackVector> vector,
827 : FeedbackSlot slot)
828 704520 : : FeedbackNexus(vector, slot) {
829 : DCHECK_EQ(FeedbackSlotKind::kStoreDataPropertyInLiteral,
830 : vector->GetKind(slot));
831 649307 : }
832 : StoreDataPropertyInLiteralICNexus(FeedbackVector* vector, FeedbackSlot slot)
833 473 : : FeedbackNexus(vector, slot) {
834 : DCHECK_EQ(FeedbackSlotKind::kStoreDataPropertyInLiteral,
835 : vector->GetKind(slot));
836 : }
837 :
838 : void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map);
839 :
840 : InlineCacheState StateFromFeedback() const override;
841 : };
842 :
843 : // For each assignment, store the type of the value in the collection of types
844 : // in the feedback vector.
845 855 : class CollectTypeProfileNexus : public FeedbackNexus {
846 : public:
847 285 : CollectTypeProfileNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
848 285 : : FeedbackNexus(vector, slot) {
849 : DCHECK_EQ(FeedbackSlotKind::kTypeProfile, vector->GetKind(slot));
850 285 : }
851 0 : CollectTypeProfileNexus(FeedbackVector* vector, FeedbackSlot slot)
852 285 : : FeedbackNexus(vector, slot) {
853 : DCHECK_EQ(FeedbackSlotKind::kTypeProfile, vector->GetKind(slot));
854 0 : }
855 :
856 : // Add a type to the list of types for source position <position>.
857 : void Collect(Handle<String> type, int position);
858 : JSObject* GetTypeProfile() const;
859 :
860 : std::vector<int> GetSourcePositions() const;
861 : std::vector<Handle<String>> GetTypesForSourcePositions(uint32_t pos) const;
862 :
863 : void Clear() override;
864 :
865 : InlineCacheState StateFromFeedback() const override;
866 : };
867 :
868 : inline BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback);
869 : inline CompareOperationHint CompareOperationHintFromFeedback(int type_feedback);
870 : inline ForInHint ForInHintFromFeedback(int type_feedback);
871 :
872 : } // namespace internal
873 : } // namespace v8
874 :
875 : #endif // V8_FEEDBACK_VECTOR_H_
|