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