blob: 38d5695a537dbea157005e9fcef5b3406410374c [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008#include <vector>
9
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010#include "src/base/logging.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011#include "src/elements-kind.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012#include "src/objects.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013#include "src/zone-containers.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014
15namespace v8 {
16namespace internal {
17
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018enum class FeedbackVectorSlotKind {
19 // This kind means that the slot points to the middle of other slot
20 // which occupies more than one feedback vector element.
21 // There must be no such slots in the system.
22 INVALID,
23
24 CALL_IC,
25 LOAD_IC,
Ben Murdoch61f157c2016-09-16 13:49:30 +010026 LOAD_GLOBAL_IC,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000027 KEYED_LOAD_IC,
28 STORE_IC,
29 KEYED_STORE_IC,
30
31 // This is a general purpose slot that occupies one feedback vector element.
32 GENERAL,
33
34 KINDS_NUMBER // Last value indicating number of kinds.
35};
36
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000037std::ostream& operator<<(std::ostream& os, FeedbackVectorSlotKind kind);
38
39
40template <typename Derived>
41class FeedbackVectorSpecBase {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040042 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000043 inline FeedbackVectorSlot AddSlot(FeedbackVectorSlotKind kind);
44
45 FeedbackVectorSlot AddCallICSlot() {
46 return AddSlot(FeedbackVectorSlotKind::CALL_IC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040047 }
48
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000049 FeedbackVectorSlot AddLoadICSlot() {
50 return AddSlot(FeedbackVectorSlotKind::LOAD_IC);
51 }
52
Ben Murdoch61f157c2016-09-16 13:49:30 +010053 FeedbackVectorSlot AddLoadGlobalICSlot(Handle<String> name) {
54 This()->append_name(name);
55 return AddSlot(FeedbackVectorSlotKind::LOAD_GLOBAL_IC);
56 }
57
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000058 FeedbackVectorSlot AddKeyedLoadICSlot() {
59 return AddSlot(FeedbackVectorSlotKind::KEYED_LOAD_IC);
60 }
61
62 FeedbackVectorSlot AddStoreICSlot() {
63 return AddSlot(FeedbackVectorSlotKind::STORE_IC);
64 }
65
66 FeedbackVectorSlot AddKeyedStoreICSlot() {
67 return AddSlot(FeedbackVectorSlotKind::KEYED_STORE_IC);
68 }
69
70 FeedbackVectorSlot AddGeneralSlot() {
71 return AddSlot(FeedbackVectorSlotKind::GENERAL);
72 }
Ben Murdoch61f157c2016-09-16 13:49:30 +010073
74#ifdef OBJECT_PRINT
75 // For gdb debugging.
76 void Print();
77#endif // OBJECT_PRINT
78
79 DECLARE_PRINTER(FeedbackVectorSpec)
80
81 private:
82 Derived* This() { return static_cast<Derived*>(this); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083};
84
85
86class StaticFeedbackVectorSpec
87 : public FeedbackVectorSpecBase<StaticFeedbackVectorSpec> {
88 public:
Ben Murdoch61f157c2016-09-16 13:49:30 +010089 StaticFeedbackVectorSpec() : slot_count_(0), name_count_(0) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000090
Ben Murdoch61f157c2016-09-16 13:49:30 +010091 int slots() const { return slot_count_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040092
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000093 FeedbackVectorSlotKind GetKind(int slot) const {
Ben Murdoch61f157c2016-09-16 13:49:30 +010094 DCHECK(slot >= 0 && slot < slot_count_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000095 return kinds_[slot];
Emily Bernierd0a1eb72015-03-24 16:35:39 -040096 }
97
Ben Murdoch61f157c2016-09-16 13:49:30 +010098 int name_count() const { return name_count_; }
99
100 Handle<String> GetName(int index) const {
101 DCHECK(index >= 0 && index < name_count_);
102 return names_[index];
103 }
104
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400105 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000106 friend class FeedbackVectorSpecBase<StaticFeedbackVectorSpec>;
107
108 void append(FeedbackVectorSlotKind kind) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100109 DCHECK(slot_count_ < kMaxLength);
110 kinds_[slot_count_++] = kind;
111 }
112
113 void append_name(Handle<String> name) {
114 DCHECK(name_count_ < kMaxLength);
115 names_[name_count_++] = name;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000116 }
117
118 static const int kMaxLength = 12;
119
Ben Murdoch61f157c2016-09-16 13:49:30 +0100120 int slot_count_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000121 FeedbackVectorSlotKind kinds_[kMaxLength];
Ben Murdoch61f157c2016-09-16 13:49:30 +0100122 int name_count_;
123 Handle<String> names_[kMaxLength];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000124};
125
126
127class FeedbackVectorSpec : public FeedbackVectorSpecBase<FeedbackVectorSpec> {
128 public:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100129 explicit FeedbackVectorSpec(Zone* zone) : slot_kinds_(zone), names_(zone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000130 slot_kinds_.reserve(16);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100131 names_.reserve(8);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000132 }
133
134 int slots() const { return static_cast<int>(slot_kinds_.size()); }
135
136 FeedbackVectorSlotKind GetKind(int slot) const {
137 return static_cast<FeedbackVectorSlotKind>(slot_kinds_.at(slot));
138 }
139
Ben Murdoch61f157c2016-09-16 13:49:30 +0100140 int name_count() const { return static_cast<int>(names_.size()); }
141
142 Handle<String> GetName(int index) const { return names_.at(index); }
143
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000144 private:
145 friend class FeedbackVectorSpecBase<FeedbackVectorSpec>;
146
147 void append(FeedbackVectorSlotKind kind) {
148 slot_kinds_.push_back(static_cast<unsigned char>(kind));
149 }
150
Ben Murdoch61f157c2016-09-16 13:49:30 +0100151 void append_name(Handle<String> name) { names_.push_back(name); }
152
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000153 ZoneVector<unsigned char> slot_kinds_;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100154 ZoneVector<Handle<String>> names_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000155};
156
157
158// The shape of the TypeFeedbackMetadata is an array with:
159// 0: slot_count
Ben Murdoch61f157c2016-09-16 13:49:30 +0100160// 1: names table
161// 2..N: slot kinds packed into a bit vector
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000162//
163class TypeFeedbackMetadata : public FixedArray {
164 public:
165 // Casting.
166 static inline TypeFeedbackMetadata* cast(Object* obj);
167
168 static const int kSlotsCountIndex = 0;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100169 static const int kNamesTableIndex = 1;
170 static const int kReservedIndexCount = 2;
171
172 static const int kNameTableEntrySize = 2;
173 static const int kNameTableSlotIndex = 0;
174 static const int kNameTableNameIndex = 1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000175
176 // Returns number of feedback vector elements used by given slot kind.
177 static inline int GetSlotSize(FeedbackVectorSlotKind kind);
178
Ben Murdoch61f157c2016-09-16 13:49:30 +0100179 // Defines if slots of given kind require "name".
180 static inline bool SlotRequiresName(FeedbackVectorSlotKind kind);
181
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000182 bool SpecDiffersFrom(const FeedbackVectorSpec* other_spec) const;
183
Ben Murdoch61f157c2016-09-16 13:49:30 +0100184 bool DiffersFrom(const TypeFeedbackMetadata* other_metadata) const;
185
186 inline bool is_empty() const;
187
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000188 // Returns number of slots in the vector.
189 inline int slot_count() const;
190
191 // Returns slot kind for given slot.
192 FeedbackVectorSlotKind GetKind(FeedbackVectorSlot slot) const;
193
Ben Murdoch61f157c2016-09-16 13:49:30 +0100194 // Returns name for given slot.
195 String* GetName(FeedbackVectorSlot slot) const;
196
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000197 template <typename Spec>
198 static Handle<TypeFeedbackMetadata> New(Isolate* isolate, const Spec* spec);
199
200#ifdef OBJECT_PRINT
201 // For gdb debugging.
202 void Print();
203#endif // OBJECT_PRINT
204
205 DECLARE_PRINTER(TypeFeedbackMetadata)
206
207 static const char* Kind2String(FeedbackVectorSlotKind kind);
208
209 private:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100210 static const int kFeedbackVectorSlotKindBits = 4;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211 STATIC_ASSERT(static_cast<int>(FeedbackVectorSlotKind::KINDS_NUMBER) <
212 (1 << kFeedbackVectorSlotKindBits));
213
214 void SetKind(FeedbackVectorSlot slot, FeedbackVectorSlotKind kind);
215
216 typedef BitSetComputer<FeedbackVectorSlotKind, kFeedbackVectorSlotKindBits,
217 kSmiValueSize, uint32_t> VectorICComputer;
218
219 DISALLOW_IMPLICIT_CONSTRUCTORS(TypeFeedbackMetadata);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400220};
221
222
223// The shape of the TypeFeedbackVector is an array with:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000224// 0: feedback metadata
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400225// 1: ics_with_types
226// 2: ics_with_generic_info
Ben Murdoch61f157c2016-09-16 13:49:30 +0100227// 3: feedback slot #0
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400228// ...
Ben Murdoch61f157c2016-09-16 13:49:30 +0100229// 3 + slot_count - 1: feedback slot #(slot_count-1)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400230//
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000231class TypeFeedbackVector : public FixedArray {
232 public:
233 // Casting.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000234 static inline TypeFeedbackVector* cast(Object* obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000235
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000236 static const int kMetadataIndex = 0;
237 static const int kReservedIndexCount = 1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400238
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000239 inline void ComputeCounts(int* with_type_info, int* generic);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400240
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000241 inline bool is_empty() const;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400242
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000243 // Returns number of slots in the vector.
244 inline int slot_count() const;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400245
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000246 inline TypeFeedbackMetadata* metadata() const;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400247
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000248 // Conversion from a slot to an integer index to the underlying array.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100249 static int GetIndex(FeedbackVectorSlot slot) {
250 return kReservedIndexCount + slot.ToInt();
251 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000252 static int GetIndexFromSpec(const FeedbackVectorSpec* spec,
253 FeedbackVectorSlot slot);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400254
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000255 // Conversion from an integer index to the underlying array to a slot.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100256 static inline FeedbackVectorSlot ToSlot(int index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000257 inline Object* Get(FeedbackVectorSlot slot) const;
258 inline void Set(FeedbackVectorSlot slot, Object* value,
259 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400260
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000261 // Returns slot kind for given slot.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100262 FeedbackVectorSlotKind GetKind(FeedbackVectorSlot slot) const;
263 // Returns name corresponding to given slot or an empty string.
264 String* GetName(FeedbackVectorSlot slot) const;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400265
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000266 static Handle<TypeFeedbackVector> New(Isolate* isolate,
267 Handle<TypeFeedbackMetadata> metadata);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400268
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000269 static Handle<TypeFeedbackVector> Copy(Isolate* isolate,
270 Handle<TypeFeedbackVector> vector);
271
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000272#ifdef OBJECT_PRINT
273 // For gdb debugging.
274 void Print();
275#endif // OBJECT_PRINT
276
277 DECLARE_PRINTER(TypeFeedbackVector)
278
279 // Clears the vector slots.
280 void ClearSlots(SharedFunctionInfo* shared) { ClearSlotsImpl(shared, true); }
281
282 void ClearSlotsAtGCTime(SharedFunctionInfo* shared) {
283 ClearSlotsImpl(shared, false);
284 }
285
286 static void ClearAllKeyedStoreICs(Isolate* isolate);
287 void ClearKeyedStoreICs(SharedFunctionInfo* shared);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400288
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000289 // The object that indicates an uninitialized cache.
Ben Murdochda12d292016-06-02 14:46:10 +0100290 static inline Handle<Symbol> UninitializedSentinel(Isolate* isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000291
292 // The object that indicates a megamorphic state.
Ben Murdochda12d292016-06-02 14:46:10 +0100293 static inline Handle<Symbol> MegamorphicSentinel(Isolate* isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000294
295 // The object that indicates a premonomorphic state.
Ben Murdochda12d292016-06-02 14:46:10 +0100296 static inline Handle<Symbol> PremonomorphicSentinel(Isolate* isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000298 // A raw version of the uninitialized sentinel that's safe to read during
299 // garbage collection (e.g., for patching the cache).
Ben Murdochda12d292016-06-02 14:46:10 +0100300 static inline Symbol* RawUninitializedSentinel(Isolate* isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301
302 static const int kDummyLoadICSlot = 0;
303 static const int kDummyKeyedLoadICSlot = 2;
304 static const int kDummyStoreICSlot = 4;
305 static const int kDummyKeyedStoreICSlot = 6;
306
307 static Handle<TypeFeedbackVector> DummyVector(Isolate* isolate);
308 static FeedbackVectorSlot DummySlot(int dummyIndex) {
309 DCHECK(dummyIndex >= 0 && dummyIndex <= kDummyKeyedStoreICSlot);
310 return FeedbackVectorSlot(dummyIndex);
311 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000312
313 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000314 void ClearSlotsImpl(SharedFunctionInfo* shared, bool force_clear);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400315
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000316 DISALLOW_IMPLICIT_CONSTRUCTORS(TypeFeedbackVector);
317};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400318
319
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000320// The following asserts protect an optimization in type feedback vector
321// code that looks into the contents of a slot assuming to find a String,
322// a Symbol, an AllocationSite, a WeakCell, or a FixedArray.
323STATIC_ASSERT(WeakCell::kSize >= 2 * kPointerSize);
324STATIC_ASSERT(WeakCell::kValueOffset == AllocationSite::kTransitionInfoOffset);
325STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset);
326STATIC_ASSERT(WeakCell::kValueOffset == Name::kHashFieldSlot);
327// Verify that an empty hash field looks like a tagged object, but can't
328// possibly be confused with a pointer.
329STATIC_ASSERT((Name::kEmptyHashField & kHeapObjectTag) == kHeapObjectTag);
330STATIC_ASSERT(Name::kEmptyHashField == 0x3);
331// Verify that a set hash field will not look like a tagged object.
332STATIC_ASSERT(Name::kHashNotComputedMask == kHeapObjectTag);
333
334
335class TypeFeedbackMetadataIterator {
336 public:
337 explicit TypeFeedbackMetadataIterator(Handle<TypeFeedbackMetadata> metadata)
338 : metadata_handle_(metadata),
Ben Murdoch61f157c2016-09-16 13:49:30 +0100339 next_slot_(FeedbackVectorSlot(0)),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000340 slot_kind_(FeedbackVectorSlotKind::INVALID) {}
341
342 explicit TypeFeedbackMetadataIterator(TypeFeedbackMetadata* metadata)
343 : metadata_(metadata),
Ben Murdoch61f157c2016-09-16 13:49:30 +0100344 next_slot_(FeedbackVectorSlot(0)),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000345 slot_kind_(FeedbackVectorSlotKind::INVALID) {}
346
Ben Murdoch61f157c2016-09-16 13:49:30 +0100347 inline bool HasNext() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000348
Ben Murdoch61f157c2016-09-16 13:49:30 +0100349 inline FeedbackVectorSlot Next();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000350
351 // Returns slot kind of the last slot returned by Next().
352 FeedbackVectorSlotKind kind() const {
353 DCHECK_NE(FeedbackVectorSlotKind::INVALID, slot_kind_);
354 DCHECK_NE(FeedbackVectorSlotKind::KINDS_NUMBER, slot_kind_);
355 return slot_kind_;
356 }
357
358 // Returns entry size of the last slot returned by Next().
Ben Murdoch61f157c2016-09-16 13:49:30 +0100359 inline int entry_size() const;
360
361 String* name() const {
362 DCHECK(TypeFeedbackMetadata::SlotRequiresName(kind()));
363 return metadata()->GetName(cur_slot_);
364 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000365
366 private:
367 TypeFeedbackMetadata* metadata() const {
368 return !metadata_handle_.is_null() ? *metadata_handle_ : metadata_;
369 }
370
371 // The reason for having a handle and a raw pointer to the meta data is
372 // to have a single iterator implementation for both "handlified" and raw
373 // pointer use cases.
374 Handle<TypeFeedbackMetadata> metadata_handle_;
375 TypeFeedbackMetadata* metadata_;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100376 FeedbackVectorSlot cur_slot_;
377 FeedbackVectorSlot next_slot_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000378 FeedbackVectorSlotKind slot_kind_;
379};
380
381
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400382// A FeedbackNexus is the combination of a TypeFeedbackVector and a slot.
383// Derived classes customize the update and retrieval of feedback.
384class FeedbackNexus {
385 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000386 FeedbackNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400387 : vector_handle_(vector), vector_(NULL), slot_(slot) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000388 FeedbackNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400389 : vector_(vector), slot_(slot) {}
390 virtual ~FeedbackNexus() {}
391
392 Handle<TypeFeedbackVector> vector_handle() const {
393 DCHECK(vector_ == NULL);
394 return vector_handle_;
395 }
396 TypeFeedbackVector* vector() const {
397 return vector_handle_.is_null() ? vector_ : *vector_handle_;
398 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000399 FeedbackVectorSlot slot() const { return slot_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400400
401 InlineCacheState ic_state() const { return StateFromFeedback(); }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100402 bool IsUninitialized() const { return StateFromFeedback() == UNINITIALIZED; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400403 Map* FindFirstMap() const {
404 MapHandleList maps;
405 ExtractMaps(&maps);
406 if (maps.length() > 0) return *maps.at(0);
407 return NULL;
408 }
409
410 // TODO(mvstanton): remove FindAllMaps, it didn't survive a code review.
411 void FindAllMaps(MapHandleList* maps) const { ExtractMaps(maps); }
412
413 virtual InlineCacheState StateFromFeedback() const = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000414 virtual int ExtractMaps(MapHandleList* maps) const;
415 virtual MaybeHandle<Code> FindHandlerForMap(Handle<Map> map) const;
416 virtual bool FindHandlers(CodeHandleList* code_list, int length = -1) const;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400417 virtual Name* FindFirstName() const { return NULL; }
418
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000419 virtual void ConfigureUninitialized();
420 virtual void ConfigurePremonomorphic();
421 virtual void ConfigureMegamorphic();
422
423 inline Object* GetFeedback() const;
424 inline Object* GetFeedbackExtra() const;
425
426 inline Isolate* GetIsolate() const;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400427
428 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000429 inline void SetFeedback(Object* feedback,
430 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
431 inline void SetFeedbackExtra(Object* feedback_extra,
432 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400433
434 Handle<FixedArray> EnsureArrayOfSize(int length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000435 Handle<FixedArray> EnsureExtraArrayOfSize(int length);
436 void InstallHandlers(Handle<FixedArray> array, MapHandleList* maps,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400437 CodeHandleList* handlers);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400438
439 private:
440 // The reason for having a vector handle and a raw pointer is that we can and
441 // should use handles during IC miss, but not during GC when we clear ICs. If
442 // you have a handle to the vector that is better because more operations can
443 // be done, like allocation.
444 Handle<TypeFeedbackVector> vector_handle_;
445 TypeFeedbackVector* vector_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000446 FeedbackVectorSlot slot_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400447};
448
449
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000450class CallICNexus final : public FeedbackNexus {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400451 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000452 CallICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400453 : FeedbackNexus(vector, slot) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000454 DCHECK_EQ(FeedbackVectorSlotKind::CALL_IC, vector->GetKind(slot));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400455 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000456 CallICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400457 : FeedbackNexus(vector, slot) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000458 DCHECK_EQ(FeedbackVectorSlotKind::CALL_IC, vector->GetKind(slot));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400459 }
460
461 void Clear(Code* host);
462
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400463 void ConfigureMonomorphicArray();
464 void ConfigureMonomorphic(Handle<JSFunction> function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000465 void ConfigureMegamorphic() final;
466 void ConfigureMegamorphic(int call_count);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400467
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000468 InlineCacheState StateFromFeedback() const final;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400469
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000470 int ExtractMaps(MapHandleList* maps) const final {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400471 // CallICs don't record map feedback.
472 return 0;
473 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000474 MaybeHandle<Code> FindHandlerForMap(Handle<Map> map) const final {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400475 return MaybeHandle<Code>();
476 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000477 bool FindHandlers(CodeHandleList* code_list, int length = -1) const final {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400478 return length == 0;
479 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000480
481 int ExtractCallCount();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400482};
483
484
485class LoadICNexus : public FeedbackNexus {
486 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000487 LoadICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400488 : FeedbackNexus(vector, slot) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000489 DCHECK_EQ(FeedbackVectorSlotKind::LOAD_IC, vector->GetKind(slot));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400490 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000491 explicit LoadICNexus(Isolate* isolate)
492 : FeedbackNexus(
493 TypeFeedbackVector::DummyVector(isolate),
494 FeedbackVectorSlot(TypeFeedbackVector::kDummyLoadICSlot)) {}
495 LoadICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400496 : FeedbackNexus(vector, slot) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000497 DCHECK_EQ(FeedbackVectorSlotKind::LOAD_IC, vector->GetKind(slot));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400498 }
499
500 void Clear(Code* host);
501
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000502 void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Code> handler);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400503
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000504 void ConfigurePolymorphic(MapHandleList* maps, CodeHandleList* handlers);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400505
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000506 InlineCacheState StateFromFeedback() const override;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400507};
508
Ben Murdoch61f157c2016-09-16 13:49:30 +0100509class LoadGlobalICNexus : public FeedbackNexus {
510 public:
511 LoadGlobalICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
512 : FeedbackNexus(vector, slot) {
513 DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC, vector->GetKind(slot));
514 }
515 LoadGlobalICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
516 : FeedbackNexus(vector, slot) {
517 DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC, vector->GetKind(slot));
518 }
519
520 int ExtractMaps(MapHandleList* maps) const final {
521 // LoadGlobalICs don't record map feedback.
522 return 0;
523 }
524 MaybeHandle<Code> FindHandlerForMap(Handle<Map> map) const final {
525 return MaybeHandle<Code>();
526 }
527 bool FindHandlers(CodeHandleList* code_list, int length = -1) const final {
528 return length == 0;
529 }
530
531 void ConfigureMegamorphic() override { UNREACHABLE(); }
532 void Clear(Code* host);
533
534 void ConfigureUninitialized() override;
535 void ConfigurePropertyCellMode(Handle<PropertyCell> cell);
536 void ConfigureHandlerMode(Handle<Code> handler);
537
538 InlineCacheState StateFromFeedback() const override;
539};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400540
541class KeyedLoadICNexus : public FeedbackNexus {
542 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000543 KeyedLoadICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400544 : FeedbackNexus(vector, slot) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000545 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector->GetKind(slot));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400546 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000547 KeyedLoadICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400548 : FeedbackNexus(vector, slot) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000549 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector->GetKind(slot));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400550 }
551
552 void Clear(Code* host);
553
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400554 // name can be a null handle for element loads.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000555 void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400556 Handle<Code> handler);
557 // name can be null.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000558 void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400559 CodeHandleList* handlers);
560
Ben Murdoch097c5b22016-05-18 11:27:45 +0100561 void ConfigureMegamorphicKeyed(IcCheckType property_type);
562
563 IcCheckType GetKeyType() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000564 InlineCacheState StateFromFeedback() const override;
565 Name* FindFirstName() const override;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400566};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000567
568
569class StoreICNexus : public FeedbackNexus {
570 public:
571 StoreICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
572 : FeedbackNexus(vector, slot) {
573 DCHECK_EQ(FeedbackVectorSlotKind::STORE_IC, vector->GetKind(slot));
574 }
575 explicit StoreICNexus(Isolate* isolate)
576 : FeedbackNexus(
577 TypeFeedbackVector::DummyVector(isolate),
578 FeedbackVectorSlot(TypeFeedbackVector::kDummyStoreICSlot)) {}
579 StoreICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
580 : FeedbackNexus(vector, slot) {
581 DCHECK_EQ(FeedbackVectorSlotKind::STORE_IC, vector->GetKind(slot));
582 }
583
584 void Clear(Code* host);
585
586 void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Code> handler);
587
588 void ConfigurePolymorphic(MapHandleList* maps, CodeHandleList* handlers);
589
590 InlineCacheState StateFromFeedback() const override;
591};
592
593
594class KeyedStoreICNexus : public FeedbackNexus {
595 public:
596 KeyedStoreICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
597 : FeedbackNexus(vector, slot) {
598 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, vector->GetKind(slot));
599 }
600 explicit KeyedStoreICNexus(Isolate* isolate)
601 : FeedbackNexus(
602 TypeFeedbackVector::DummyVector(isolate),
603 FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedStoreICSlot)) {}
604 KeyedStoreICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
605 : FeedbackNexus(vector, slot) {
606 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, vector->GetKind(slot));
607 }
608
609 void Clear(Code* host);
610
611 // name can be a null handle for element loads.
612 void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
613 Handle<Code> handler);
614 // name can be null.
615 void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps,
616 CodeHandleList* handlers);
617 void ConfigurePolymorphic(MapHandleList* maps,
618 MapHandleList* transitioned_maps,
619 CodeHandleList* handlers);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100620 void ConfigureMegamorphicKeyed(IcCheckType property_type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000621
622 KeyedAccessStoreMode GetKeyedAccessStoreMode() const;
623 IcCheckType GetKeyType() const;
624
625 InlineCacheState StateFromFeedback() const override;
626 Name* FindFirstName() const override;
627};
628} // namespace internal
629} // namespace v8
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000630
631#endif // V8_TRANSITIONS_H_