1 // Copyright 2012 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_INL_H_
6 #define V8_TYPE_FEEDBACK_VECTOR_INL_H_
7
8 #include "src/type-feedback-vector.h"
9
10 namespace v8 {
11 namespace internal {
12
13
14 template <typename Derived>
AddSlot(FeedbackVectorSlotKind kind)15 FeedbackVectorSlot FeedbackVectorSpecBase<Derived>::AddSlot(
16 FeedbackVectorSlotKind kind) {
17 int slot = This()->slots();
18 int entries_per_slot = TypeFeedbackMetadata::GetSlotSize(kind);
19 This()->append(kind);
20 for (int i = 1; i < entries_per_slot; i++) {
21 This()->append(FeedbackVectorSlotKind::INVALID);
22 }
23 return FeedbackVectorSlot(slot);
24 }
25
26
27 // static
cast(Object * obj)28 TypeFeedbackMetadata* TypeFeedbackMetadata::cast(Object* obj) {
29 DCHECK(obj->IsTypeFeedbackVector());
30 return reinterpret_cast<TypeFeedbackMetadata*>(obj);
31 }
32
is_empty()33 bool TypeFeedbackMetadata::is_empty() const {
34 if (length() == 0) return true;
35 return false;
36 }
37
slot_count()38 int TypeFeedbackMetadata::slot_count() const {
39 if (length() == 0) return 0;
40 DCHECK(length() > kReservedIndexCount);
41 return Smi::cast(get(kSlotsCountIndex))->value();
42 }
43
44
45 // static
cast(Object * obj)46 TypeFeedbackVector* TypeFeedbackVector::cast(Object* obj) {
47 DCHECK(obj->IsTypeFeedbackVector());
48 return reinterpret_cast<TypeFeedbackVector*>(obj);
49 }
50
51
GetSlotSize(FeedbackVectorSlotKind kind)52 int TypeFeedbackMetadata::GetSlotSize(FeedbackVectorSlotKind kind) {
53 DCHECK_NE(FeedbackVectorSlotKind::INVALID, kind);
54 DCHECK_NE(FeedbackVectorSlotKind::KINDS_NUMBER, kind);
55 return kind == FeedbackVectorSlotKind::GENERAL ? 1 : 2;
56 }
57
SlotRequiresName(FeedbackVectorSlotKind kind)58 bool TypeFeedbackMetadata::SlotRequiresName(FeedbackVectorSlotKind kind) {
59 switch (kind) {
60 case FeedbackVectorSlotKind::LOAD_GLOBAL_IC:
61 return true;
62
63 case FeedbackVectorSlotKind::CALL_IC:
64 case FeedbackVectorSlotKind::LOAD_IC:
65 case FeedbackVectorSlotKind::KEYED_LOAD_IC:
66 case FeedbackVectorSlotKind::STORE_IC:
67 case FeedbackVectorSlotKind::KEYED_STORE_IC:
68 case FeedbackVectorSlotKind::GENERAL:
69 case FeedbackVectorSlotKind::INVALID:
70 return false;
71
72 case FeedbackVectorSlotKind::KINDS_NUMBER:
73 break;
74 }
75 UNREACHABLE();
76 return false;
77 }
78
is_empty()79 bool TypeFeedbackVector::is_empty() const {
80 if (length() == 0) return true;
81 DCHECK(length() > kReservedIndexCount);
82 return false;
83 }
84
85
slot_count()86 int TypeFeedbackVector::slot_count() const {
87 if (length() == 0) return 0;
88 DCHECK(length() > kReservedIndexCount);
89 return length() - kReservedIndexCount;
90 }
91
92
metadata()93 TypeFeedbackMetadata* TypeFeedbackVector::metadata() const {
94 return is_empty() ? TypeFeedbackMetadata::cast(GetHeap()->empty_fixed_array())
95 : TypeFeedbackMetadata::cast(get(kMetadataIndex));
96 }
97
98 // Conversion from an integer index to either a slot or an ic slot.
99 // static
ToSlot(int index)100 FeedbackVectorSlot TypeFeedbackVector::ToSlot(int index) {
101 DCHECK(index >= kReservedIndexCount);
102 return FeedbackVectorSlot(index - kReservedIndexCount);
103 }
104
105
Get(FeedbackVectorSlot slot)106 Object* TypeFeedbackVector::Get(FeedbackVectorSlot slot) const {
107 return get(GetIndex(slot));
108 }
109
110
Set(FeedbackVectorSlot slot,Object * value,WriteBarrierMode mode)111 void TypeFeedbackVector::Set(FeedbackVectorSlot slot, Object* value,
112 WriteBarrierMode mode) {
113 set(GetIndex(slot), value, mode);
114 }
115
116
ComputeCounts(int * with_type_info,int * generic)117 void TypeFeedbackVector::ComputeCounts(int* with_type_info, int* generic) {
118 Object* uninitialized_sentinel =
119 TypeFeedbackVector::RawUninitializedSentinel(GetIsolate());
120 Object* megamorphic_sentinel =
121 *TypeFeedbackVector::MegamorphicSentinel(GetIsolate());
122 int with = 0;
123 int gen = 0;
124 TypeFeedbackMetadataIterator iter(metadata());
125 while (iter.HasNext()) {
126 FeedbackVectorSlot slot = iter.Next();
127 FeedbackVectorSlotKind kind = iter.kind();
128
129 Object* obj = Get(slot);
130 if (obj != uninitialized_sentinel &&
131 kind != FeedbackVectorSlotKind::GENERAL) {
132 if (obj->IsWeakCell() || obj->IsFixedArray() || obj->IsString()) {
133 with++;
134 } else if (obj == megamorphic_sentinel) {
135 gen++;
136 }
137 }
138 }
139
140 *with_type_info = with;
141 *generic = gen;
142 }
143
UninitializedSentinel(Isolate * isolate)144 Handle<Symbol> TypeFeedbackVector::UninitializedSentinel(Isolate* isolate) {
145 return isolate->factory()->uninitialized_symbol();
146 }
147
MegamorphicSentinel(Isolate * isolate)148 Handle<Symbol> TypeFeedbackVector::MegamorphicSentinel(Isolate* isolate) {
149 return isolate->factory()->megamorphic_symbol();
150 }
151
PremonomorphicSentinel(Isolate * isolate)152 Handle<Symbol> TypeFeedbackVector::PremonomorphicSentinel(Isolate* isolate) {
153 return isolate->factory()->premonomorphic_symbol();
154 }
155
RawUninitializedSentinel(Isolate * isolate)156 Symbol* TypeFeedbackVector::RawUninitializedSentinel(Isolate* isolate) {
157 return isolate->heap()->uninitialized_symbol();
158 }
159
HasNext()160 bool TypeFeedbackMetadataIterator::HasNext() const {
161 return next_slot_.ToInt() < metadata()->slot_count();
162 }
163
Next()164 FeedbackVectorSlot TypeFeedbackMetadataIterator::Next() {
165 DCHECK(HasNext());
166 cur_slot_ = next_slot_;
167 slot_kind_ = metadata()->GetKind(cur_slot_);
168 next_slot_ = FeedbackVectorSlot(next_slot_.ToInt() + entry_size());
169 return cur_slot_;
170 }
171
entry_size()172 int TypeFeedbackMetadataIterator::entry_size() const {
173 return TypeFeedbackMetadata::GetSlotSize(kind());
174 }
175
GetFeedback()176 Object* FeedbackNexus::GetFeedback() const { return vector()->Get(slot()); }
177
178
GetFeedbackExtra()179 Object* FeedbackNexus::GetFeedbackExtra() const {
180 #ifdef DEBUG
181 FeedbackVectorSlotKind kind = vector()->GetKind(slot());
182 DCHECK_LT(1, TypeFeedbackMetadata::GetSlotSize(kind));
183 #endif
184 int extra_index = vector()->GetIndex(slot()) + 1;
185 return vector()->get(extra_index);
186 }
187
188
SetFeedback(Object * feedback,WriteBarrierMode mode)189 void FeedbackNexus::SetFeedback(Object* feedback, WriteBarrierMode mode) {
190 vector()->Set(slot(), feedback, mode);
191 }
192
193
SetFeedbackExtra(Object * feedback_extra,WriteBarrierMode mode)194 void FeedbackNexus::SetFeedbackExtra(Object* feedback_extra,
195 WriteBarrierMode mode) {
196 #ifdef DEBUG
197 FeedbackVectorSlotKind kind = vector()->GetKind(slot());
198 DCHECK_LT(1, TypeFeedbackMetadata::GetSlotSize(kind));
199 #endif
200 int index = vector()->GetIndex(slot()) + 1;
201 vector()->set(index, feedback_extra, mode);
202 }
203
204
GetIsolate()205 Isolate* FeedbackNexus::GetIsolate() const { return vector()->GetIsolate(); }
206 } // namespace internal
207 } // namespace v8
208
209 #endif // V8_TYPE_FEEDBACK_VECTOR_INL_H_
210