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