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