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/globals.h"
9 #include "src/type-feedback-vector.h"
10
11 namespace v8 {
12 namespace internal {
13
14
15 template <typename Derived>
AddSlot(FeedbackVectorSlotKind kind)16 FeedbackVectorSlot FeedbackVectorSpecBase<Derived>::AddSlot(
17 FeedbackVectorSlotKind kind) {
18 int slot = This()->slots();
19 int entries_per_slot = TypeFeedbackMetadata::GetSlotSize(kind);
20 This()->append(kind);
21 for (int i = 1; i < entries_per_slot; i++) {
22 This()->append(FeedbackVectorSlotKind::INVALID);
23 }
24 return FeedbackVectorSlot(slot);
25 }
26
27
28 // static
cast(Object * obj)29 TypeFeedbackMetadata* TypeFeedbackMetadata::cast(Object* obj) {
30 DCHECK(obj->IsTypeFeedbackVector());
31 return reinterpret_cast<TypeFeedbackMetadata*>(obj);
32 }
33
is_empty()34 bool TypeFeedbackMetadata::is_empty() const {
35 if (length() == 0) return true;
36 return false;
37 }
38
slot_count()39 int TypeFeedbackMetadata::slot_count() const {
40 if (length() == 0) return 0;
41 DCHECK(length() > kReservedIndexCount);
42 return Smi::cast(get(kSlotsCountIndex))->value();
43 }
44
45
46 // static
cast(Object * obj)47 TypeFeedbackVector* TypeFeedbackVector::cast(Object* obj) {
48 DCHECK(obj->IsTypeFeedbackVector());
49 return reinterpret_cast<TypeFeedbackVector*>(obj);
50 }
51
52
GetSlotSize(FeedbackVectorSlotKind kind)53 int TypeFeedbackMetadata::GetSlotSize(FeedbackVectorSlotKind kind) {
54 DCHECK_NE(FeedbackVectorSlotKind::INVALID, kind);
55 DCHECK_NE(FeedbackVectorSlotKind::KINDS_NUMBER, kind);
56 if (kind == FeedbackVectorSlotKind::GENERAL ||
57 kind == FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC ||
58 kind == FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC) {
59 return 1;
60 }
61
62 return 2;
63 }
64
SlotRequiresName(FeedbackVectorSlotKind kind)65 bool TypeFeedbackMetadata::SlotRequiresName(FeedbackVectorSlotKind kind) {
66 switch (kind) {
67 case FeedbackVectorSlotKind::LOAD_GLOBAL_IC:
68 return true;
69
70 case FeedbackVectorSlotKind::CALL_IC:
71 case FeedbackVectorSlotKind::LOAD_IC:
72 case FeedbackVectorSlotKind::KEYED_LOAD_IC:
73 case FeedbackVectorSlotKind::STORE_IC:
74 case FeedbackVectorSlotKind::KEYED_STORE_IC:
75 case FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC:
76 case FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC:
77 case FeedbackVectorSlotKind::GENERAL:
78 case FeedbackVectorSlotKind::INVALID:
79 return false;
80
81 case FeedbackVectorSlotKind::KINDS_NUMBER:
82 break;
83 }
84 UNREACHABLE();
85 return false;
86 }
87
is_empty()88 bool TypeFeedbackVector::is_empty() const {
89 return length() == kReservedIndexCount;
90 }
91
slot_count()92 int TypeFeedbackVector::slot_count() const {
93 return length() - kReservedIndexCount;
94 }
95
96
metadata()97 TypeFeedbackMetadata* TypeFeedbackVector::metadata() const {
98 return TypeFeedbackMetadata::cast(get(kMetadataIndex));
99 }
100
invocation_count()101 int TypeFeedbackVector::invocation_count() const {
102 return Smi::cast(get(kInvocationCountIndex))->value();
103 }
104
105 // Conversion from an integer index to either a slot or an ic slot.
106 // static
ToSlot(int index)107 FeedbackVectorSlot TypeFeedbackVector::ToSlot(int index) {
108 DCHECK(index >= kReservedIndexCount);
109 return FeedbackVectorSlot(index - kReservedIndexCount);
110 }
111
112
Get(FeedbackVectorSlot slot)113 Object* TypeFeedbackVector::Get(FeedbackVectorSlot slot) const {
114 return get(GetIndex(slot));
115 }
116
117
Set(FeedbackVectorSlot slot,Object * value,WriteBarrierMode mode)118 void TypeFeedbackVector::Set(FeedbackVectorSlot slot, Object* value,
119 WriteBarrierMode mode) {
120 set(GetIndex(slot), value, mode);
121 }
122
123 // Helper function to transform the feedback to BinaryOperationHint.
BinaryOperationHintFromFeedback(int type_feedback)124 BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) {
125 switch (type_feedback) {
126 case BinaryOperationFeedback::kNone:
127 return BinaryOperationHint::kNone;
128 case BinaryOperationFeedback::kSignedSmall:
129 return BinaryOperationHint::kSignedSmall;
130 case BinaryOperationFeedback::kNumber:
131 case BinaryOperationFeedback::kNumberOrOddball:
132 return BinaryOperationHint::kNumberOrOddball;
133 case BinaryOperationFeedback::kString:
134 return BinaryOperationHint::kString;
135 case BinaryOperationFeedback::kAny:
136 default:
137 return BinaryOperationHint::kAny;
138 }
139 UNREACHABLE();
140 return BinaryOperationHint::kNone;
141 }
142
143 // Helper function to transform the feedback to CompareOperationHint.
CompareOperationHintFromFeedback(int type_feedback)144 CompareOperationHint CompareOperationHintFromFeedback(int type_feedback) {
145 switch (type_feedback) {
146 case CompareOperationFeedback::kNone:
147 return CompareOperationHint::kNone;
148 case CompareOperationFeedback::kSignedSmall:
149 return CompareOperationHint::kSignedSmall;
150 case CompareOperationFeedback::kNumber:
151 return CompareOperationHint::kNumber;
152 default:
153 return CompareOperationHint::kAny;
154 }
155 UNREACHABLE();
156 return CompareOperationHint::kNone;
157 }
158
ComputeCounts(int * with_type_info,int * generic,int * vector_ic_count,bool code_is_interpreted)159 void TypeFeedbackVector::ComputeCounts(int* with_type_info, int* generic,
160 int* vector_ic_count,
161 bool code_is_interpreted) {
162 Object* megamorphic_sentinel =
163 *TypeFeedbackVector::MegamorphicSentinel(GetIsolate());
164 int with = 0;
165 int gen = 0;
166 int total = 0;
167 TypeFeedbackMetadataIterator iter(metadata());
168 while (iter.HasNext()) {
169 FeedbackVectorSlot slot = iter.Next();
170 FeedbackVectorSlotKind kind = iter.kind();
171
172 Object* const obj = Get(slot);
173 switch (kind) {
174 case FeedbackVectorSlotKind::CALL_IC:
175 case FeedbackVectorSlotKind::LOAD_IC:
176 case FeedbackVectorSlotKind::LOAD_GLOBAL_IC:
177 case FeedbackVectorSlotKind::KEYED_LOAD_IC:
178 case FeedbackVectorSlotKind::STORE_IC:
179 case FeedbackVectorSlotKind::KEYED_STORE_IC: {
180 if (obj->IsWeakCell() || obj->IsFixedArray() || obj->IsString()) {
181 with++;
182 } else if (obj == megamorphic_sentinel) {
183 gen++;
184 }
185 total++;
186 break;
187 }
188 case FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC:
189 case FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC: {
190 // If we are not running interpreted code, we need to ignore the special
191 // IC slots for binaryop/compare used by the interpreter.
192 // TODO(mvstanton): Remove code_is_interpreted when full code is retired
193 // from service.
194 if (code_is_interpreted) {
195 int const feedback = Smi::cast(obj)->value();
196 if (kind == FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC) {
197 CompareOperationHint hint =
198 CompareOperationHintFromFeedback(feedback);
199 if (hint == CompareOperationHint::kAny) {
200 gen++;
201 } else if (hint != CompareOperationHint::kNone) {
202 with++;
203 }
204 } else {
205 DCHECK_EQ(FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC, kind);
206 BinaryOperationHint hint =
207 BinaryOperationHintFromFeedback(feedback);
208 if (hint == BinaryOperationHint::kAny) {
209 gen++;
210 } else if (hint != BinaryOperationHint::kNone) {
211 with++;
212 }
213 }
214 total++;
215 }
216 break;
217 }
218 case FeedbackVectorSlotKind::GENERAL:
219 break;
220 case FeedbackVectorSlotKind::INVALID:
221 case FeedbackVectorSlotKind::KINDS_NUMBER:
222 UNREACHABLE();
223 break;
224 }
225 }
226
227 *with_type_info = with;
228 *generic = gen;
229 *vector_ic_count = total;
230 }
231
UninitializedSentinel(Isolate * isolate)232 Handle<Symbol> TypeFeedbackVector::UninitializedSentinel(Isolate* isolate) {
233 return isolate->factory()->uninitialized_symbol();
234 }
235
MegamorphicSentinel(Isolate * isolate)236 Handle<Symbol> TypeFeedbackVector::MegamorphicSentinel(Isolate* isolate) {
237 return isolate->factory()->megamorphic_symbol();
238 }
239
PremonomorphicSentinel(Isolate * isolate)240 Handle<Symbol> TypeFeedbackVector::PremonomorphicSentinel(Isolate* isolate) {
241 return isolate->factory()->premonomorphic_symbol();
242 }
243
RawUninitializedSentinel(Isolate * isolate)244 Symbol* TypeFeedbackVector::RawUninitializedSentinel(Isolate* isolate) {
245 return isolate->heap()->uninitialized_symbol();
246 }
247
HasNext()248 bool TypeFeedbackMetadataIterator::HasNext() const {
249 return next_slot_.ToInt() < metadata()->slot_count();
250 }
251
Next()252 FeedbackVectorSlot TypeFeedbackMetadataIterator::Next() {
253 DCHECK(HasNext());
254 cur_slot_ = next_slot_;
255 slot_kind_ = metadata()->GetKind(cur_slot_);
256 next_slot_ = FeedbackVectorSlot(next_slot_.ToInt() + entry_size());
257 return cur_slot_;
258 }
259
entry_size()260 int TypeFeedbackMetadataIterator::entry_size() const {
261 return TypeFeedbackMetadata::GetSlotSize(kind());
262 }
263
GetFeedback()264 Object* FeedbackNexus::GetFeedback() const { return vector()->Get(slot()); }
265
266
GetFeedbackExtra()267 Object* FeedbackNexus::GetFeedbackExtra() const {
268 #ifdef DEBUG
269 FeedbackVectorSlotKind kind = vector()->GetKind(slot());
270 DCHECK_LT(1, TypeFeedbackMetadata::GetSlotSize(kind));
271 #endif
272 int extra_index = vector()->GetIndex(slot()) + 1;
273 return vector()->get(extra_index);
274 }
275
276
SetFeedback(Object * feedback,WriteBarrierMode mode)277 void FeedbackNexus::SetFeedback(Object* feedback, WriteBarrierMode mode) {
278 vector()->Set(slot(), feedback, mode);
279 }
280
281
SetFeedbackExtra(Object * feedback_extra,WriteBarrierMode mode)282 void FeedbackNexus::SetFeedbackExtra(Object* feedback_extra,
283 WriteBarrierMode mode) {
284 #ifdef DEBUG
285 FeedbackVectorSlotKind kind = vector()->GetKind(slot());
286 DCHECK_LT(1, TypeFeedbackMetadata::GetSlotSize(kind));
287 #endif
288 int index = vector()->GetIndex(slot()) + 1;
289 vector()->set(index, feedback_extra, mode);
290 }
291
292
GetIsolate()293 Isolate* FeedbackNexus::GetIsolate() const { return vector()->GetIsolate(); }
294 } // namespace internal
295 } // namespace v8
296
297 #endif // V8_TYPE_FEEDBACK_VECTOR_INL_H_
298