• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   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 
IsCallICKind(FeedbackSlotKind kind)47 inline bool IsCallICKind(FeedbackSlotKind kind) {
48   return kind == FeedbackSlotKind::kCall;
49 }
50 
IsLoadICKind(FeedbackSlotKind kind)51 inline bool IsLoadICKind(FeedbackSlotKind kind) {
52   return kind == FeedbackSlotKind::kLoadProperty;
53 }
54 
IsLoadGlobalICKind(FeedbackSlotKind kind)55 inline bool IsLoadGlobalICKind(FeedbackSlotKind kind) {
56   return kind == FeedbackSlotKind::kLoadGlobalNotInsideTypeof ||
57          kind == FeedbackSlotKind::kLoadGlobalInsideTypeof;
58 }
59 
IsKeyedLoadICKind(FeedbackSlotKind kind)60 inline bool IsKeyedLoadICKind(FeedbackSlotKind kind) {
61   return kind == FeedbackSlotKind::kLoadKeyed;
62 }
63 
IsStoreICKind(FeedbackSlotKind kind)64 inline bool IsStoreICKind(FeedbackSlotKind kind) {
65   return kind == FeedbackSlotKind::kStoreNamedSloppy ||
66          kind == FeedbackSlotKind::kStoreNamedStrict;
67 }
68 
IsStoreOwnICKind(FeedbackSlotKind kind)69 inline bool IsStoreOwnICKind(FeedbackSlotKind kind) {
70   return kind == FeedbackSlotKind::kStoreOwnNamed;
71 }
72 
IsKeyedStoreICKind(FeedbackSlotKind kind)73 inline bool IsKeyedStoreICKind(FeedbackSlotKind kind) {
74   return kind == FeedbackSlotKind::kStoreKeyedSloppy ||
75          kind == FeedbackSlotKind::kStoreKeyedStrict;
76 }
77 
GetTypeofModeFromSlotKind(FeedbackSlotKind kind)78 inline TypeofMode GetTypeofModeFromSlotKind(FeedbackSlotKind kind) {
79   DCHECK(IsLoadGlobalICKind(kind));
80   return (kind == FeedbackSlotKind::kLoadGlobalInsideTypeof)
81              ? INSIDE_TYPEOF
82              : NOT_INSIDE_TYPEOF;
83 }
84 
GetLanguageModeFromSlotKind(FeedbackSlotKind kind)85 inline 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 
94 std::ostream& operator<<(std::ostream& os, FeedbackSlotKind kind);
95 
96 template <typename Derived>
97 class FeedbackVectorSpecBase {
98  public:
AddCallICSlot()99   FeedbackSlot AddCallICSlot() { return AddSlot(FeedbackSlotKind::kCall); }
100 
AddLoadICSlot()101   FeedbackSlot AddLoadICSlot() {
102     return AddSlot(FeedbackSlotKind::kLoadProperty);
103   }
104 
AddLoadGlobalICSlot(TypeofMode typeof_mode)105   FeedbackSlot AddLoadGlobalICSlot(TypeofMode typeof_mode) {
106     return AddSlot(typeof_mode == INSIDE_TYPEOF
107                        ? FeedbackSlotKind::kLoadGlobalInsideTypeof
108                        : FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
109   }
110 
AddCreateClosureSlot()111   FeedbackSlot AddCreateClosureSlot() {
112     return AddSlot(FeedbackSlotKind::kCreateClosure);
113   }
114 
AddKeyedLoadICSlot()115   FeedbackSlot AddKeyedLoadICSlot() {
116     return AddSlot(FeedbackSlotKind::kLoadKeyed);
117   }
118 
AddStoreICSlot(LanguageMode language_mode)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 
AddStoreOwnICSlot()126   FeedbackSlot AddStoreOwnICSlot() {
127     return AddSlot(FeedbackSlotKind::kStoreOwnNamed);
128   }
129 
AddKeyedStoreICSlot(LanguageMode language_mode)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 
AddInterpreterBinaryOpICSlot()137   FeedbackSlot AddInterpreterBinaryOpICSlot() {
138     return AddSlot(FeedbackSlotKind::kBinaryOp);
139   }
140 
AddInterpreterCompareICSlot()141   FeedbackSlot AddInterpreterCompareICSlot() {
142     return AddSlot(FeedbackSlotKind::kCompareOp);
143   }
144 
AddGeneralSlot()145   FeedbackSlot AddGeneralSlot() { return AddSlot(FeedbackSlotKind::kGeneral); }
146 
AddLiteralSlot()147   FeedbackSlot AddLiteralSlot() { return AddSlot(FeedbackSlotKind::kLiteral); }
148 
AddStoreDataPropertyInLiteralICSlot()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 
This()163   Derived* This() { return static_cast<Derived*>(this); }
164 };
165 
166 class StaticFeedbackVectorSpec
167     : public FeedbackVectorSpecBase<StaticFeedbackVectorSpec> {
168  public:
StaticFeedbackVectorSpec()169   StaticFeedbackVectorSpec() : slot_count_(0) {}
170 
slots()171   int slots() const { return slot_count_; }
172 
GetKind(FeedbackSlot slot)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 
append(FeedbackSlotKind kind)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 
192 class FeedbackVectorSpec : public FeedbackVectorSpecBase<FeedbackVectorSpec> {
193  public:
FeedbackVectorSpec(Zone * zone)194   explicit FeedbackVectorSpec(Zone* zone) : slot_kinds_(zone) {
195     slot_kinds_.reserve(16);
196   }
197 
slots()198   int slots() const { return static_cast<int>(slot_kinds_.size()); }
199 
GetKind(FeedbackSlot slot)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 
append(FeedbackSlotKind kind)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 //
220 class 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 //
274 class 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.
GetIndex(FeedbackSlot slot)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)
DEFINE_SLOT_KIND_PREDICATE(IsLoadIC)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.
GetLanguageMode(FeedbackSlot 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.
371 STATIC_ASSERT(WeakCell::kSize >= 2 * kPointerSize);
372 STATIC_ASSERT(WeakCell::kValueOffset == AllocationSite::kTransitionInfoOffset);
373 STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset);
374 STATIC_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.
377 STATIC_ASSERT((Name::kEmptyHashField & kHeapObjectTag) == kHeapObjectTag);
378 STATIC_ASSERT(Name::kEmptyHashField == 0x3);
379 // Verify that a set hash field will not look like a tagged object.
380 STATIC_ASSERT(Name::kHashNotComputedMask == kHeapObjectTag);
381 
382 class FeedbackMetadataIterator {
383  public:
FeedbackMetadataIterator(Handle<FeedbackMetadata> metadata)384   explicit FeedbackMetadataIterator(Handle<FeedbackMetadata> metadata)
385       : metadata_handle_(metadata),
386         next_slot_(FeedbackSlot(0)),
387         slot_kind_(FeedbackSlotKind::kInvalid) {}
388 
FeedbackMetadataIterator(FeedbackMetadata * metadata)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().
kind()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:
metadata()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.
425 class FeedbackNexus {
426  public:
FeedbackNexus(Handle<FeedbackVector> vector,FeedbackSlot slot)427   FeedbackNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
428       : vector_handle_(vector), vector_(NULL), slot_(slot) {}
FeedbackNexus(FeedbackVector * vector,FeedbackSlot slot)429   FeedbackNexus(FeedbackVector* vector, FeedbackSlot slot)
430       : vector_(vector), slot_(slot) {}
~FeedbackNexus()431   virtual ~FeedbackNexus() {}
432 
vector_handle()433   Handle<FeedbackVector> vector_handle() const {
434     DCHECK(vector_ == NULL);
435     return vector_handle_;
436   }
vector()437   FeedbackVector* vector() const {
438     return vector_handle_.is_null() ? vector_ : *vector_handle_;
439   }
slot()440   FeedbackSlot slot() const { return slot_; }
kind()441   FeedbackSlotKind kind() const { return vector()->GetKind(slot()); }
442 
ic_state()443   InlineCacheState ic_state() const { return StateFromFeedback(); }
IsUninitialized()444   bool IsUninitialized() const { return StateFromFeedback() == UNINITIALIZED; }
FindFirstMap()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.
FindAllMaps(MapHandleList * maps)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;
FindFirstName()460   virtual Name* FindFirstName() const { return NULL; }
461 
IsCleared()462   bool IsCleared() {
463     InlineCacheState state = StateFromFeedback();
464     return !FLAG_use_ic || state == UNINITIALIZED || state == PREMONOMORPHIC;
465   }
466 
Clear()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 
498 class CallICNexus final : public FeedbackNexus {
499  public:
CallICNexus(Handle<FeedbackVector> vector,FeedbackSlot slot)500   CallICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
501       : FeedbackNexus(vector, slot) {
502     DCHECK(vector->IsCallIC(slot));
503   }
CallICNexus(FeedbackVector * vector,FeedbackSlot slot)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 
ExtractMaps(MapHandleList * maps)517   int ExtractMaps(MapHandleList* maps) const final {
518     // CallICs don't record map feedback.
519     return 0;
520   }
FindHandlerForMap(Handle<Map> map)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 
536 class LoadICNexus : public FeedbackNexus {
537  public:
LoadICNexus(Handle<FeedbackVector> vector,FeedbackSlot slot)538   LoadICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
539       : FeedbackNexus(vector, slot) {
540     DCHECK(vector->IsLoadIC(slot));
541   }
LoadICNexus(FeedbackVector * vector,FeedbackSlot slot)542   LoadICNexus(FeedbackVector* vector, FeedbackSlot slot)
543       : FeedbackNexus(vector, slot) {
544     DCHECK(vector->IsLoadIC(slot));
545   }
546 
Clear()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 
557 class LoadGlobalICNexus : public FeedbackNexus {
558  public:
LoadGlobalICNexus(Handle<FeedbackVector> vector,FeedbackSlot slot)559   LoadGlobalICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
560       : FeedbackNexus(vector, slot) {
561     DCHECK(vector->IsLoadGlobalIC(slot));
562   }
LoadGlobalICNexus(FeedbackVector * vector,FeedbackSlot slot)563   LoadGlobalICNexus(FeedbackVector* vector, FeedbackSlot slot)
564       : FeedbackNexus(vector, slot) {
565     DCHECK(vector->IsLoadGlobalIC(slot));
566   }
567 
ExtractMaps(MapHandleList * maps)568   int ExtractMaps(MapHandleList* maps) const final {
569     // LoadGlobalICs don't record map feedback.
570     return 0;
571   }
FindHandlerForMap(Handle<Map> map)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 
ConfigureMegamorphic()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 
589 class KeyedLoadICNexus : public FeedbackNexus {
590  public:
KeyedLoadICNexus(Handle<FeedbackVector> vector,FeedbackSlot slot)591   KeyedLoadICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
592       : FeedbackNexus(vector, slot) {
593     DCHECK(vector->IsKeyedLoadIC(slot));
594   }
KeyedLoadICNexus(FeedbackVector * vector,FeedbackSlot slot)595   KeyedLoadICNexus(FeedbackVector* vector, FeedbackSlot slot)
596       : FeedbackNexus(vector, slot) {
597     DCHECK(vector->IsKeyedLoadIC(slot));
598   }
599 
Clear()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 
616 class StoreICNexus : public FeedbackNexus {
617  public:
StoreICNexus(Handle<FeedbackVector> vector,FeedbackSlot slot)618   StoreICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
619       : FeedbackNexus(vector, slot) {
620     DCHECK(vector->IsStoreIC(slot) || vector->IsStoreOwnIC(slot));
621   }
StoreICNexus(FeedbackVector * vector,FeedbackSlot slot)622   StoreICNexus(FeedbackVector* vector, FeedbackSlot slot)
623       : FeedbackNexus(vector, slot) {
624     DCHECK(vector->IsStoreIC(slot) || vector->IsStoreOwnIC(slot));
625   }
626 
Clear()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.
639 typedef StoreICNexus StoreOwnICNexus;
640 
641 class KeyedStoreICNexus : public FeedbackNexus {
642  public:
KeyedStoreICNexus(Handle<FeedbackVector> vector,FeedbackSlot slot)643   KeyedStoreICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
644       : FeedbackNexus(vector, slot) {
645     DCHECK(vector->IsKeyedStoreIC(slot));
646   }
KeyedStoreICNexus(FeedbackVector * vector,FeedbackSlot slot)647   KeyedStoreICNexus(FeedbackVector* vector, FeedbackSlot slot)
648       : FeedbackNexus(vector, slot) {
649     DCHECK(vector->IsKeyedStoreIC(slot));
650   }
651 
Clear()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 
672 class BinaryOpICNexus final : public FeedbackNexus {
673  public:
BinaryOpICNexus(Handle<FeedbackVector> vector,FeedbackSlot slot)674   BinaryOpICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
675       : FeedbackNexus(vector, slot) {
676     DCHECK_EQ(FeedbackSlotKind::kBinaryOp, vector->GetKind(slot));
677   }
BinaryOpICNexus(FeedbackVector * vector,FeedbackSlot slot)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 
ExtractMaps(MapHandleList * maps)686   int ExtractMaps(MapHandleList* maps) const final {
687     // BinaryOpICs don't record map feedback.
688     return 0;
689   }
FindHandlerForMap(Handle<Map> map)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 
699 class CompareICNexus final : public FeedbackNexus {
700  public:
CompareICNexus(Handle<FeedbackVector> vector,FeedbackSlot slot)701   CompareICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
702       : FeedbackNexus(vector, slot) {
703     DCHECK_EQ(FeedbackSlotKind::kCompareOp, vector->GetKind(slot));
704   }
CompareICNexus(FeedbackVector * vector,FeedbackSlot slot)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 
ExtractMaps(MapHandleList * maps)713   int ExtractMaps(MapHandleList* maps) const final {
714     // BinaryOpICs don't record map feedback.
715     return 0;
716   }
FindHandlerForMap(Handle<Map> map)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 
726 class StoreDataPropertyInLiteralICNexus : public FeedbackNexus {
727  public:
StoreDataPropertyInLiteralICNexus(Handle<FeedbackVector> vector,FeedbackSlot slot)728   StoreDataPropertyInLiteralICNexus(Handle<FeedbackVector> vector,
729                                     FeedbackSlot slot)
730       : FeedbackNexus(vector, slot) {
731     DCHECK_EQ(FeedbackSlotKind::kStoreDataPropertyInLiteral,
732               vector->GetKind(slot));
733   }
StoreDataPropertyInLiteralICNexus(FeedbackVector * vector,FeedbackSlot slot)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 
745 inline BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback);
746 inline CompareOperationHint CompareOperationHintFromFeedback(int type_feedback);
747 
748 }  // namespace internal
749 }  // namespace v8
750 
751 #endif  // V8_FEEDBACK_VECTOR_H_
752