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/elements-kind.h"
12 : #include "src/objects.h"
13 : #include "src/type-hints.h"
14 : #include "src/zone/zone-containers.h"
15 :
16 : namespace v8 {
17 : namespace internal {
18 :
19 : enum class FeedbackSlotKind {
20 : // This kind means that the slot points to the middle of other slot
21 : // which occupies more than one feedback vector element.
22 : // There must be no such slots in the system.
23 : kInvalid,
24 :
25 : kCall,
26 : kLoadProperty,
27 : kLoadGlobalNotInsideTypeof,
28 : kLoadGlobalInsideTypeof,
29 : kLoadKeyed,
30 : kStoreGlobalSloppy,
31 : kStoreGlobalStrict,
32 : kStoreNamedSloppy,
33 : kStoreNamedStrict,
34 : kStoreOwnNamed,
35 : kStoreKeyedSloppy,
36 : kStoreKeyedStrict,
37 : kBinaryOp,
38 : kCompareOp,
39 : kToBoolean,
40 : kStoreDataPropertyInLiteral,
41 : kTypeProfile,
42 : kCreateClosure,
43 : kLiteral,
44 : // This is a general purpose slot that occupies one feedback vector element.
45 : kGeneral,
46 :
47 : kKindsNumber // Last value indicating number of kinds.
48 : };
49 :
50 : inline bool IsCallICKind(FeedbackSlotKind kind) {
51 : return kind == FeedbackSlotKind::kCall;
52 : }
53 :
54 4359778 : inline bool IsLoadICKind(FeedbackSlotKind kind) {
55 4359778 : return kind == FeedbackSlotKind::kLoadProperty;
56 : }
57 :
58 158 : inline bool IsLoadGlobalICKind(FeedbackSlotKind kind) {
59 17996567 : return kind == FeedbackSlotKind::kLoadGlobalNotInsideTypeof ||
60 158 : kind == FeedbackSlotKind::kLoadGlobalInsideTypeof;
61 : }
62 :
63 : inline bool IsKeyedLoadICKind(FeedbackSlotKind kind) {
64 : return kind == FeedbackSlotKind::kLoadKeyed;
65 : }
66 :
67 1690942 : inline bool IsStoreGlobalICKind(FeedbackSlotKind kind) {
68 1715876 : return kind == FeedbackSlotKind::kStoreGlobalSloppy ||
69 1690942 : kind == FeedbackSlotKind::kStoreGlobalStrict;
70 : }
71 :
72 5895934 : inline bool IsStoreICKind(FeedbackSlotKind kind) {
73 6004692 : return kind == FeedbackSlotKind::kStoreNamedSloppy ||
74 5895934 : kind == FeedbackSlotKind::kStoreNamedStrict;
75 : }
76 :
77 2341694 : inline bool IsStoreOwnICKind(FeedbackSlotKind kind) {
78 2341694 : return kind == FeedbackSlotKind::kStoreOwnNamed;
79 : }
80 :
81 : inline bool IsKeyedStoreICKind(FeedbackSlotKind kind) {
82 12021925 : return kind == FeedbackSlotKind::kStoreKeyedSloppy ||
83 : kind == FeedbackSlotKind::kStoreKeyedStrict;
84 : }
85 :
86 : inline bool IsTypeProfileKind(FeedbackSlotKind kind) {
87 : return kind == FeedbackSlotKind::kTypeProfile;
88 : }
89 :
90 : inline TypeofMode GetTypeofModeFromSlotKind(FeedbackSlotKind kind) {
91 : DCHECK(IsLoadGlobalICKind(kind));
92 : return (kind == FeedbackSlotKind::kLoadGlobalInsideTypeof)
93 : ? INSIDE_TYPEOF
94 1786888 : : NOT_INSIDE_TYPEOF;
95 : }
96 :
97 : inline LanguageMode GetLanguageModeFromSlotKind(FeedbackSlotKind kind) {
98 : DCHECK(IsStoreICKind(kind) || IsStoreOwnICKind(kind) ||
99 : IsStoreGlobalICKind(kind) || IsKeyedStoreICKind(kind));
100 20123702 : return (kind == FeedbackSlotKind::kStoreNamedSloppy ||
101 10061851 : kind == FeedbackSlotKind::kStoreGlobalSloppy ||
102 : kind == FeedbackSlotKind::kStoreKeyedSloppy)
103 : ? SLOPPY
104 10061851 : : STRICT;
105 : }
106 :
107 : std::ostream& operator<<(std::ostream& os, FeedbackSlotKind kind);
108 :
109 : template <typename Derived>
110 : class FeedbackVectorSpecBase {
111 : public:
112 4573643 : FeedbackSlot AddCallICSlot() { return AddSlot(FeedbackSlotKind::kCall); }
113 :
114 : FeedbackSlot AddLoadICSlot() {
115 6341436 : return AddSlot(FeedbackSlotKind::kLoadProperty);
116 : }
117 :
118 : FeedbackSlot AddLoadGlobalICSlot(TypeofMode typeof_mode) {
119 : return AddSlot(typeof_mode == INSIDE_TYPEOF
120 : ? FeedbackSlotKind::kLoadGlobalInsideTypeof
121 3032345 : : FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
122 : }
123 :
124 : FeedbackSlot AddCreateClosureSlot() {
125 5461758 : return AddSlot(FeedbackSlotKind::kCreateClosure);
126 : }
127 :
128 : FeedbackSlot AddKeyedLoadICSlot() {
129 668064 : return AddSlot(FeedbackSlotKind::kLoadKeyed);
130 : }
131 :
132 : FeedbackSlot AddStoreICSlot(LanguageMode language_mode) {
133 : STATIC_ASSERT(LANGUAGE_END == 2);
134 : return AddSlot(is_strict(language_mode)
135 : ? FeedbackSlotKind::kStoreNamedStrict
136 2558506 : : FeedbackSlotKind::kStoreNamedSloppy);
137 : }
138 :
139 : FeedbackSlot AddStoreOwnICSlot() {
140 574804 : return AddSlot(FeedbackSlotKind::kStoreOwnNamed);
141 : }
142 :
143 : FeedbackSlot AddStoreGlobalICSlot(LanguageMode language_mode) {
144 : STATIC_ASSERT(LANGUAGE_END == 2);
145 : return AddSlot(is_strict(language_mode)
146 : ? FeedbackSlotKind::kStoreGlobalStrict
147 998372 : : FeedbackSlotKind::kStoreGlobalSloppy);
148 : }
149 :
150 : FeedbackSlot AddKeyedStoreICSlot(LanguageMode language_mode) {
151 : STATIC_ASSERT(LANGUAGE_END == 2);
152 : return AddSlot(is_strict(language_mode)
153 : ? FeedbackSlotKind::kStoreKeyedStrict
154 292685 : : FeedbackSlotKind::kStoreKeyedSloppy);
155 : }
156 :
157 : FeedbackSlot AddInterpreterBinaryOpICSlot() {
158 3050288 : return AddSlot(FeedbackSlotKind::kBinaryOp);
159 : }
160 :
161 : FeedbackSlot AddInterpreterCompareICSlot() {
162 2504962 : return AddSlot(FeedbackSlotKind::kCompareOp);
163 : }
164 :
165 11513 : FeedbackSlot AddGeneralSlot() { return AddSlot(FeedbackSlotKind::kGeneral); }
166 :
167 1145104 : FeedbackSlot AddLiteralSlot() { return AddSlot(FeedbackSlotKind::kLiteral); }
168 :
169 : FeedbackSlot AddStoreDataPropertyInLiteralICSlot() {
170 307523 : return AddSlot(FeedbackSlotKind::kStoreDataPropertyInLiteral);
171 : }
172 :
173 : FeedbackSlot AddTypeProfileSlot();
174 :
175 : #ifdef OBJECT_PRINT
176 : // For gdb debugging.
177 : void Print();
178 : #endif // OBJECT_PRINT
179 :
180 : DECLARE_PRINTER(FeedbackVectorSpec)
181 :
182 : private:
183 : inline FeedbackSlot AddSlot(FeedbackSlotKind kind);
184 :
185 : Derived* This() { return static_cast<Derived*>(this); }
186 : };
187 :
188 : class StaticFeedbackVectorSpec
189 : : public FeedbackVectorSpecBase<StaticFeedbackVectorSpec> {
190 : public:
191 10654406 : StaticFeedbackVectorSpec() : slot_count_(0) {}
192 :
193 : int slots() const { return slot_count_; }
194 :
195 : FeedbackSlotKind GetKind(FeedbackSlot slot) const {
196 : DCHECK(slot.ToInt() >= 0 && slot.ToInt() < slot_count_);
197 0 : return kinds_[slot.ToInt()];
198 : }
199 :
200 : private:
201 : friend class FeedbackVectorSpecBase<StaticFeedbackVectorSpec>;
202 :
203 : void append(FeedbackSlotKind kind) {
204 : DCHECK(slot_count_ < kMaxLength);
205 : kinds_[slot_count_++] = kind;
206 : }
207 :
208 : static const int kMaxLength = 12;
209 :
210 : int slot_count_;
211 : FeedbackSlotKind kinds_[kMaxLength];
212 : };
213 :
214 : class FeedbackVectorSpec : public FeedbackVectorSpecBase<FeedbackVectorSpec> {
215 : public:
216 : explicit FeedbackVectorSpec(Zone* zone) : slot_kinds_(zone) {
217 13519498 : slot_kinds_.reserve(16);
218 : }
219 :
220 86598860 : int slots() const { return static_cast<int>(slot_kinds_.size()); }
221 :
222 : FeedbackSlotKind GetKind(FeedbackSlot slot) const {
223 171347991 : return static_cast<FeedbackSlotKind>(slot_kinds_.at(slot.ToInt()));
224 : }
225 :
226 : bool HasTypeProfileSlot() const;
227 :
228 : // If used, the TypeProfileSlot is always added as the first slot and its
229 : // index is constant. If other slots are added before the TypeProfileSlot,
230 : // this number changes.
231 : static const int kTypeProfileSlotIndex = 2;
232 :
233 : private:
234 : friend class FeedbackVectorSpecBase<FeedbackVectorSpec>;
235 :
236 : void append(FeedbackSlotKind kind) {
237 101736953 : slot_kinds_.push_back(static_cast<unsigned char>(kind));
238 : }
239 :
240 : ZoneVector<unsigned char> slot_kinds_;
241 : };
242 :
243 : // The shape of the FeedbackMetadata is an array with:
244 : // 0: slot_count
245 : // 1: names table
246 : // 2: parameters table
247 : // 3..N: slot kinds packed into a bit vector
248 : //
249 : class FeedbackMetadata : public FixedArray {
250 : public:
251 : // Casting.
252 : static inline FeedbackMetadata* cast(Object* obj);
253 :
254 : static const int kSlotsCountIndex = 0;
255 : static const int kReservedIndexCount = 1;
256 :
257 : // Returns number of feedback vector elements used by given slot kind.
258 : static inline int GetSlotSize(FeedbackSlotKind kind);
259 :
260 : bool SpecDiffersFrom(const FeedbackVectorSpec* other_spec) const;
261 :
262 : inline bool is_empty() const;
263 :
264 : // Returns number of slots in the vector.
265 : inline int slot_count() const;
266 :
267 : // Returns slot kind for given slot.
268 : FeedbackSlotKind GetKind(FeedbackSlot slot) const;
269 :
270 : template <typename Spec>
271 10654402 : static Handle<FeedbackMetadata> New(Isolate* isolate, const Spec* spec);
272 :
273 : #ifdef OBJECT_PRINT
274 : // For gdb debugging.
275 : void Print();
276 : #endif // OBJECT_PRINT
277 :
278 : DECLARE_PRINTER(FeedbackMetadata)
279 :
280 : static const char* Kind2String(FeedbackSlotKind kind);
281 : bool HasTypeProfileSlot() const;
282 :
283 : private:
284 : static const int kFeedbackSlotKindBits = 5;
285 : STATIC_ASSERT(static_cast<int>(FeedbackSlotKind::kKindsNumber) <
286 : (1 << kFeedbackSlotKindBits));
287 :
288 : void SetKind(FeedbackSlot slot, FeedbackSlotKind kind);
289 :
290 : typedef BitSetComputer<FeedbackSlotKind, kFeedbackSlotKindBits, kSmiValueSize,
291 : uint32_t>
292 : VectorICComputer;
293 :
294 : DISALLOW_IMPLICIT_CONSTRUCTORS(FeedbackMetadata);
295 : };
296 :
297 : // The shape of the FeedbackVector is an array with:
298 : // 0: feedback metadata
299 : // 1: invocation count
300 : // 2: feedback slot #0
301 : // ...
302 : // 2 + slot_count - 1: feedback slot #(slot_count-1)
303 : //
304 : class FeedbackVector : public FixedArray {
305 : public:
306 : // Casting.
307 : static inline FeedbackVector* cast(Object* obj);
308 :
309 : static const int kSharedFunctionInfoIndex = 0;
310 : static const int kInvocationCountIndex = 1;
311 : static const int kReservedIndexCount = 2;
312 :
313 : inline void ComputeCounts(int* with_type_info, int* generic,
314 : int* vector_ic_count, bool code_is_interpreted);
315 :
316 : inline bool is_empty() const;
317 :
318 : // Returns number of slots in the vector.
319 : inline int slot_count() const;
320 :
321 : inline FeedbackMetadata* metadata() const;
322 : inline SharedFunctionInfo* shared_function_info() const;
323 : inline int invocation_count() const;
324 : inline void clear_invocation_count();
325 :
326 : // Conversion from a slot to an integer index to the underlying array.
327 : static int GetIndex(FeedbackSlot slot) {
328 157711349 : return kReservedIndexCount + slot.ToInt();
329 : }
330 :
331 : // Conversion from an integer index to the underlying array to a slot.
332 : static inline FeedbackSlot ToSlot(int index);
333 : inline Object* Get(FeedbackSlot slot) const;
334 : inline void Set(FeedbackSlot slot, Object* value,
335 : WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
336 :
337 : // Returns slot kind for given slot.
338 : FeedbackSlotKind GetKind(FeedbackSlot slot) const;
339 :
340 : FeedbackSlot GetTypeProfileSlot() const;
341 :
342 : static Handle<FeedbackVector> New(Isolate* isolate,
343 : Handle<SharedFunctionInfo> shared);
344 :
345 : static Handle<FeedbackVector> Copy(Isolate* isolate,
346 : Handle<FeedbackVector> vector);
347 :
348 : #define DEFINE_SLOT_KIND_PREDICATE(Name) \
349 : bool Name(FeedbackSlot slot) const { return Name##Kind(GetKind(slot)); }
350 :
351 : DEFINE_SLOT_KIND_PREDICATE(IsCallIC)
352 : DEFINE_SLOT_KIND_PREDICATE(IsLoadIC)
353 : DEFINE_SLOT_KIND_PREDICATE(IsLoadGlobalIC)
354 : DEFINE_SLOT_KIND_PREDICATE(IsKeyedLoadIC)
355 : DEFINE_SLOT_KIND_PREDICATE(IsStoreIC)
356 64847 : DEFINE_SLOT_KIND_PREDICATE(IsStoreOwnIC)
357 : DEFINE_SLOT_KIND_PREDICATE(IsStoreGlobalIC)
358 75440 : DEFINE_SLOT_KIND_PREDICATE(IsKeyedStoreIC)
359 : DEFINE_SLOT_KIND_PREDICATE(IsTypeProfile)
360 : #undef DEFINE_SLOT_KIND_PREDICATE
361 :
362 : // Returns typeof mode encoded into kind of given slot.
363 : inline TypeofMode GetTypeofMode(FeedbackSlot slot) const {
364 : return GetTypeofModeFromSlotKind(GetKind(slot));
365 : }
366 :
367 : // Returns language mode encoded into kind of given slot.
368 8275572 : inline LanguageMode GetLanguageMode(FeedbackSlot slot) const {
369 16551144 : return GetLanguageModeFromSlotKind(GetKind(slot));
370 : }
371 :
372 : #ifdef OBJECT_PRINT
373 : // For gdb debugging.
374 : void Print();
375 : #endif // OBJECT_PRINT
376 :
377 : DECLARE_PRINTER(FeedbackVector)
378 :
379 : // Clears the vector slots.
380 : void ClearSlots(JSFunction* host_function);
381 :
382 : // The object that indicates an uninitialized cache.
383 : static inline Handle<Symbol> UninitializedSentinel(Isolate* isolate);
384 :
385 : // The object that indicates a megamorphic state.
386 : static inline Handle<Symbol> MegamorphicSentinel(Isolate* isolate);
387 :
388 : // The object that indicates a premonomorphic state.
389 : static inline Handle<Symbol> PremonomorphicSentinel(Isolate* isolate);
390 :
391 : // A raw version of the uninitialized sentinel that's safe to read during
392 : // garbage collection (e.g., for patching the cache).
393 : static inline Symbol* RawUninitializedSentinel(Isolate* isolate);
394 :
395 : private:
396 : static void AddToCodeCoverageList(Isolate* isolate,
397 : Handle<FeedbackVector> vector);
398 :
399 : DISALLOW_IMPLICIT_CONSTRUCTORS(FeedbackVector);
400 : };
401 :
402 : // The following asserts protect an optimization in type feedback vector
403 : // code that looks into the contents of a slot assuming to find a String,
404 : // a Symbol, an AllocationSite, a WeakCell, or a FixedArray.
405 : STATIC_ASSERT(WeakCell::kSize >= 2 * kPointerSize);
406 : STATIC_ASSERT(WeakCell::kValueOffset == AllocationSite::kTransitionInfoOffset);
407 : STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset);
408 : STATIC_ASSERT(WeakCell::kValueOffset == Name::kHashFieldSlot);
409 : // Verify that an empty hash field looks like a tagged object, but can't
410 : // possibly be confused with a pointer.
411 : STATIC_ASSERT((Name::kEmptyHashField & kHeapObjectTag) == kHeapObjectTag);
412 : STATIC_ASSERT(Name::kEmptyHashField == 0x3);
413 : // Verify that a set hash field will not look like a tagged object.
414 : STATIC_ASSERT(Name::kHashNotComputedMask == kHeapObjectTag);
415 :
416 : class FeedbackMetadataIterator {
417 : public:
418 : explicit FeedbackMetadataIterator(Handle<FeedbackMetadata> metadata)
419 : : metadata_handle_(metadata),
420 : next_slot_(FeedbackSlot(0)),
421 : slot_kind_(FeedbackSlotKind::kInvalid) {}
422 :
423 : explicit FeedbackMetadataIterator(FeedbackMetadata* metadata)
424 : : metadata_(metadata),
425 : next_slot_(FeedbackSlot(0)),
426 543158 : slot_kind_(FeedbackSlotKind::kInvalid) {}
427 :
428 : inline bool HasNext() const;
429 :
430 : inline FeedbackSlot Next();
431 :
432 : // Returns slot kind of the last slot returned by Next().
433 : FeedbackSlotKind kind() const {
434 : DCHECK_NE(FeedbackSlotKind::kInvalid, slot_kind_);
435 : DCHECK_NE(FeedbackSlotKind::kKindsNumber, slot_kind_);
436 : return slot_kind_;
437 : }
438 :
439 : // Returns entry size of the last slot returned by Next().
440 : inline int entry_size() const;
441 :
442 : private:
443 : FeedbackMetadata* metadata() const {
444 11361658 : return !metadata_handle_.is_null() ? *metadata_handle_ : metadata_;
445 : }
446 :
447 : // The reason for having a handle and a raw pointer to the meta data is
448 : // to have a single iterator implementation for both "handlified" and raw
449 : // pointer use cases.
450 : Handle<FeedbackMetadata> metadata_handle_;
451 : FeedbackMetadata* metadata_;
452 : FeedbackSlot cur_slot_;
453 : FeedbackSlot next_slot_;
454 : FeedbackSlotKind slot_kind_;
455 : };
456 :
457 : // A FeedbackNexus is the combination of a FeedbackVector and a slot.
458 : // Derived classes customize the update and retrieval of feedback.
459 : class FeedbackNexus {
460 : public:
461 : FeedbackNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
462 21649731 : : vector_handle_(vector), vector_(NULL), slot_(slot) {}
463 : FeedbackNexus(FeedbackVector* vector, FeedbackSlot slot)
464 322862 : : vector_(vector), slot_(slot) {}
465 16353456 : virtual ~FeedbackNexus() {}
466 :
467 : Handle<FeedbackVector> vector_handle() const {
468 : DCHECK(vector_ == NULL);
469 : return vector_handle_;
470 : }
471 : FeedbackVector* vector() const {
472 120885985 : return vector_handle_.is_null() ? vector_ : *vector_handle_;
473 : }
474 : FeedbackSlot slot() const { return slot_; }
475 27513468 : FeedbackSlotKind kind() const { return vector()->GetKind(slot()); }
476 :
477 911380 : InlineCacheState ic_state() const { return StateFromFeedback(); }
478 1232722 : bool IsUninitialized() const { return StateFromFeedback() == UNINITIALIZED; }
479 174318 : Map* FindFirstMap() const {
480 : MapHandleList maps;
481 174318 : ExtractMaps(&maps);
482 348038 : if (maps.length() > 0) return *maps.at(0);
483 : return NULL;
484 : }
485 :
486 : // TODO(mvstanton): remove FindAllMaps, it didn't survive a code review.
487 15782 : void FindAllMaps(MapHandleList* maps) const { ExtractMaps(maps); }
488 :
489 : virtual InlineCacheState StateFromFeedback() const = 0;
490 : virtual int ExtractMaps(MapHandleList* maps) const;
491 : virtual MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const;
492 : virtual bool FindHandlers(List<Handle<Object>>* code_list,
493 : int length = -1) const;
494 0 : virtual Name* FindFirstName() const { return NULL; }
495 :
496 : bool IsCleared() {
497 161333 : InlineCacheState state = StateFromFeedback();
498 161333 : return !FLAG_use_ic || state == UNINITIALIZED || state == PREMONOMORPHIC;
499 : }
500 :
501 23015 : virtual void Clear() { ConfigureUninitialized(); }
502 : virtual void ConfigureUninitialized();
503 : void ConfigurePremonomorphic();
504 : void ConfigureMegamorphic(IcCheckType property_type);
505 :
506 : inline Object* GetFeedback() const;
507 : inline Object* GetFeedbackExtra() const;
508 :
509 : inline Isolate* GetIsolate() const;
510 :
511 : void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
512 : Handle<Object> handler);
513 :
514 : void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps,
515 : List<Handle<Object>>* handlers);
516 :
517 : protected:
518 : inline void SetFeedback(Object* feedback,
519 : WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
520 : inline void SetFeedbackExtra(Object* feedback_extra,
521 : WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
522 :
523 : Handle<FixedArray> EnsureArrayOfSize(int length);
524 : Handle<FixedArray> EnsureExtraArrayOfSize(int length);
525 :
526 : private:
527 : // The reason for having a vector handle and a raw pointer is that we can and
528 : // should use handles during IC miss, but not during GC when we clear ICs. If
529 : // you have a handle to the vector that is better because more operations can
530 : // be done, like allocation.
531 : Handle<FeedbackVector> vector_handle_;
532 : FeedbackVector* vector_;
533 : FeedbackSlot slot_;
534 : };
535 :
536 17456 : class CallICNexus final : public FeedbackNexus {
537 : public:
538 : CallICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
539 1041766 : : FeedbackNexus(vector, slot) {
540 : DCHECK(vector->IsCallIC(slot));
541 : }
542 : CallICNexus(FeedbackVector* vector, FeedbackSlot slot)
543 13602 : : FeedbackNexus(vector, slot) {
544 : DCHECK(vector->IsCallIC(slot));
545 : }
546 :
547 : void ConfigureUninitialized() final;
548 :
549 : InlineCacheState StateFromFeedback() const final;
550 :
551 0 : int ExtractMaps(MapHandleList* maps) const final {
552 : // CallICs don't record map feedback.
553 0 : return 0;
554 : }
555 0 : MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
556 0 : return MaybeHandle<Code>();
557 : }
558 0 : bool FindHandlers(List<Handle<Object>>* code_list,
559 : int length = -1) const final {
560 0 : return length == 0;
561 : }
562 :
563 : int ExtractCallCount();
564 :
565 : // Compute the call frequency based on the call count and the invocation
566 : // count (taken from the type feedback vector).
567 : float ComputeCallFrequency();
568 : };
569 :
570 8760777 : class LoadICNexus : public FeedbackNexus {
571 : public:
572 4359620 : LoadICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
573 5974906 : : FeedbackNexus(vector, slot) {
574 : DCHECK(vector->IsLoadIC(slot));
575 4359620 : }
576 : LoadICNexus(FeedbackVector* vector, FeedbackSlot slot)
577 41537 : : FeedbackNexus(vector, slot) {
578 : DCHECK(vector->IsLoadIC(slot));
579 : }
580 :
581 8137 : void Clear() override { ConfigurePremonomorphic(); }
582 :
583 : InlineCacheState StateFromFeedback() const override;
584 : };
585 :
586 6201614 : class LoadGlobalICNexus : public FeedbackNexus {
587 : public:
588 2094580 : LoadGlobalICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
589 4096211 : : FeedbackNexus(vector, slot) {
590 : DCHECK(vector->IsLoadGlobalIC(slot));
591 2094580 : }
592 : LoadGlobalICNexus(FeedbackVector* vector, FeedbackSlot slot)
593 10823 : : FeedbackNexus(vector, slot) {
594 : DCHECK(vector->IsLoadGlobalIC(slot));
595 : }
596 :
597 0 : int ExtractMaps(MapHandleList* maps) const final {
598 : // LoadGlobalICs don't record map feedback.
599 0 : return 0;
600 : }
601 804 : MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
602 804 : return MaybeHandle<Code>();
603 : }
604 0 : bool FindHandlers(List<Handle<Object>>* code_list,
605 : int length = -1) const final {
606 0 : return length == 0;
607 : }
608 :
609 : void ConfigureUninitialized() override;
610 : void ConfigurePropertyCellMode(Handle<PropertyCell> cell);
611 : void ConfigureHandlerMode(Handle<Object> handler);
612 :
613 : InlineCacheState StateFromFeedback() const override;
614 : };
615 :
616 1495200 : class KeyedLoadICNexus : public FeedbackNexus {
617 : public:
618 704068 : KeyedLoadICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
619 1048744 : : FeedbackNexus(vector, slot) {
620 : DCHECK(vector->IsKeyedLoadIC(slot));
621 704068 : }
622 : KeyedLoadICNexus(FeedbackVector* vector, FeedbackSlot slot)
623 5858 : : FeedbackNexus(vector, slot) {
624 : DCHECK(vector->IsKeyedLoadIC(slot));
625 : }
626 :
627 5308 : void Clear() override { ConfigurePremonomorphic(); }
628 :
629 : IcCheckType GetKeyType() const;
630 : InlineCacheState StateFromFeedback() const override;
631 : Name* FindFirstName() const override;
632 : };
633 :
634 11874816 : class StoreICNexus : public FeedbackNexus {
635 : public:
636 5895933 : StoreICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
637 6195868 : : FeedbackNexus(vector, slot) {
638 : DCHECK(vector->IsStoreIC(slot) || vector->IsStoreOwnIC(slot) ||
639 : vector->IsStoreGlobalIC(slot));
640 5895933 : }
641 : StoreICNexus(FeedbackVector* vector, FeedbackSlot slot)
642 82948 : : FeedbackNexus(vector, slot) {
643 : DCHECK(vector->IsStoreIC(slot) || vector->IsStoreOwnIC(slot) ||
644 : vector->IsStoreGlobalIC(slot));
645 : }
646 :
647 41140 : void Clear() override { ConfigurePremonomorphic(); }
648 :
649 : InlineCacheState StateFromFeedback() const override;
650 : };
651 :
652 : // TODO(ishell): Currently we use StoreOwnIC only for storing properties that
653 : // already exist in the boilerplate therefore we can use StoreIC.
654 : typedef StoreICNexus StoreOwnICNexus;
655 :
656 1424198 : class KeyedStoreICNexus : public FeedbackNexus {
657 : public:
658 702538 : KeyedStoreICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
659 824727 : : FeedbackNexus(vector, slot) {
660 : DCHECK(vector->IsKeyedStoreIC(slot));
661 702538 : }
662 : KeyedStoreICNexus(FeedbackVector* vector, FeedbackSlot slot)
663 6565 : : FeedbackNexus(vector, slot) {
664 : DCHECK(vector->IsKeyedStoreIC(slot));
665 : }
666 :
667 3685 : void Clear() override { ConfigurePremonomorphic(); }
668 :
669 : KeyedAccessStoreMode GetKeyedAccessStoreMode() const;
670 : IcCheckType GetKeyType() const;
671 :
672 : InlineCacheState StateFromFeedback() const override;
673 : Name* FindFirstName() const override;
674 : };
675 :
676 0 : class BinaryOpICNexus final : public FeedbackNexus {
677 : public:
678 : BinaryOpICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
679 1183302 : : FeedbackNexus(vector, slot) {
680 : DCHECK_EQ(FeedbackSlotKind::kBinaryOp, vector->GetKind(slot));
681 : }
682 : BinaryOpICNexus(FeedbackVector* vector, FeedbackSlot slot)
683 : : FeedbackNexus(vector, slot) {
684 : DCHECK_EQ(FeedbackSlotKind::kBinaryOp, vector->GetKind(slot));
685 : }
686 :
687 : InlineCacheState StateFromFeedback() const final;
688 : BinaryOperationHint GetBinaryOperationFeedback() const;
689 :
690 0 : int ExtractMaps(MapHandleList* maps) const final {
691 : // BinaryOpICs don't record map feedback.
692 0 : return 0;
693 : }
694 0 : MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
695 0 : return MaybeHandle<Code>();
696 : }
697 0 : bool FindHandlers(List<Handle<Object>>* code_list,
698 : int length = -1) const final {
699 0 : return length == 0;
700 : }
701 : };
702 :
703 0 : class CompareICNexus final : public FeedbackNexus {
704 : public:
705 : CompareICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
706 903968 : : FeedbackNexus(vector, slot) {
707 : DCHECK_EQ(FeedbackSlotKind::kCompareOp, vector->GetKind(slot));
708 : }
709 : CompareICNexus(FeedbackVector* vector, FeedbackSlot slot)
710 : : FeedbackNexus(vector, slot) {
711 : DCHECK_EQ(FeedbackSlotKind::kCompareOp, vector->GetKind(slot));
712 : }
713 :
714 : InlineCacheState StateFromFeedback() const final;
715 : CompareOperationHint GetCompareOperationFeedback() const;
716 :
717 0 : int ExtractMaps(MapHandleList* maps) const final {
718 : // BinaryOpICs don't record map feedback.
719 0 : return 0;
720 : }
721 0 : MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
722 0 : return MaybeHandle<Code>();
723 : }
724 0 : bool FindHandlers(List<Handle<Object>>* code_list,
725 : int length = -1) const final {
726 0 : return length == 0;
727 : }
728 : };
729 :
730 668438 : class StoreDataPropertyInLiteralICNexus : public FeedbackNexus {
731 : public:
732 334219 : StoreDataPropertyInLiteralICNexus(Handle<FeedbackVector> vector,
733 : FeedbackSlot slot)
734 378421 : : FeedbackNexus(vector, slot) {
735 : DCHECK_EQ(FeedbackSlotKind::kStoreDataPropertyInLiteral,
736 : vector->GetKind(slot));
737 334219 : }
738 : StoreDataPropertyInLiteralICNexus(FeedbackVector* vector, FeedbackSlot slot)
739 0 : : FeedbackNexus(vector, slot) {
740 : DCHECK_EQ(FeedbackSlotKind::kStoreDataPropertyInLiteral,
741 : vector->GetKind(slot));
742 : }
743 :
744 : void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map);
745 :
746 : InlineCacheState StateFromFeedback() const override;
747 : };
748 :
749 : // For each assignment, store the type of the value in the collection of types
750 : // in the feedback vector.
751 3832 : class CollectTypeProfileNexus : public FeedbackNexus {
752 : public:
753 1818 : CollectTypeProfileNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
754 1818 : : FeedbackNexus(vector, slot) {
755 : DCHECK_EQ(FeedbackSlotKind::kTypeProfile, vector->GetKind(slot));
756 1818 : }
757 98 : CollectTypeProfileNexus(FeedbackVector* vector, FeedbackSlot slot)
758 98 : : FeedbackNexus(vector, slot) {
759 : DCHECK_EQ(FeedbackSlotKind::kTypeProfile, vector->GetKind(slot));
760 98 : }
761 :
762 : // Add a type to the list of types for source position <position>.
763 : void Collect(Handle<String> type, int position);
764 : JSObject* GetTypeProfile() const;
765 :
766 : InlineCacheState StateFromFeedback() const override;
767 : };
768 :
769 : inline BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback);
770 : inline CompareOperationHint CompareOperationHintFromFeedback(int type_feedback);
771 :
772 : } // namespace internal
773 : } // namespace v8
774 :
775 : #endif // V8_FEEDBACK_VECTOR_H_
|