Line data Source code
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_FEEDBACK_VECTOR_INL_H_
6 : #define V8_FEEDBACK_VECTOR_INL_H_
7 :
8 : #include "src/factory.h"
9 : #include "src/feedback-vector.h"
10 : #include "src/globals.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 :
15 : template <typename Derived>
16 31521086 : FeedbackSlot FeedbackVectorSpecBase<Derived>::AddSlot(FeedbackSlotKind kind) {
17 : int slot = This()->slots();
18 31521086 : int entries_per_slot = FeedbackMetadata::GetSlotSize(kind);
19 : This()->append(kind);
20 50868480 : for (int i = 1; i < entries_per_slot; i++) {
21 : This()->append(FeedbackSlotKind::kInvalid);
22 : }
23 31521097 : return FeedbackSlot(slot);
24 : }
25 :
26 : template <typename Derived>
27 102 : FeedbackSlot FeedbackVectorSpecBase<Derived>::AddTypeProfileSlot() {
28 : DCHECK(FLAG_type_profile);
29 102 : FeedbackSlot slot = AddSlot(FeedbackSlotKind::kTypeProfile);
30 102 : CHECK_EQ(FeedbackVectorSpec::kTypeProfileSlotIndex,
31 : FeedbackVector::GetIndex(slot));
32 102 : return slot;
33 : }
34 :
35 : // static
36 : FeedbackMetadata* FeedbackMetadata::cast(Object* obj) {
37 : DCHECK(obj->IsFeedbackMetadata());
38 : return reinterpret_cast<FeedbackMetadata*>(obj);
39 : }
40 :
41 : bool FeedbackMetadata::is_empty() const {
42 0 : if (length() == 0) return true;
43 : return false;
44 : }
45 :
46 19263790 : int FeedbackMetadata::slot_count() const {
47 19263790 : if (length() == 0) return 0;
48 : DCHECK(length() > kReservedIndexCount);
49 12887915 : return Smi::cast(get(kSlotsCountIndex))->value();
50 : }
51 :
52 : // static
53 : FeedbackVector* FeedbackVector::cast(Object* obj) {
54 : DCHECK(obj->IsFeedbackVector());
55 : return reinterpret_cast<FeedbackVector*>(obj);
56 : }
57 :
58 107864780 : int FeedbackMetadata::GetSlotSize(FeedbackSlotKind kind) {
59 : switch (kind) {
60 : case FeedbackSlotKind::kGeneral:
61 : case FeedbackSlotKind::kCompareOp:
62 : case FeedbackSlotKind::kBinaryOp:
63 : case FeedbackSlotKind::kToBoolean:
64 : case FeedbackSlotKind::kLiteral:
65 : case FeedbackSlotKind::kCreateClosure:
66 : case FeedbackSlotKind::kTypeProfile:
67 : return 1;
68 :
69 : case FeedbackSlotKind::kCall:
70 : case FeedbackSlotKind::kLoadProperty:
71 : case FeedbackSlotKind::kLoadGlobalInsideTypeof:
72 : case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
73 : case FeedbackSlotKind::kLoadKeyed:
74 : case FeedbackSlotKind::kStoreNamedSloppy:
75 : case FeedbackSlotKind::kStoreNamedStrict:
76 : case FeedbackSlotKind::kStoreOwnNamed:
77 : case FeedbackSlotKind::kStoreGlobalSloppy:
78 : case FeedbackSlotKind::kStoreGlobalStrict:
79 : case FeedbackSlotKind::kStoreKeyedSloppy:
80 : case FeedbackSlotKind::kStoreKeyedStrict:
81 : case FeedbackSlotKind::kStoreDataPropertyInLiteral:
82 66919611 : return 2;
83 :
84 : case FeedbackSlotKind::kInvalid:
85 : case FeedbackSlotKind::kKindsNumber:
86 0 : UNREACHABLE();
87 : break;
88 : }
89 : return 1;
90 : }
91 :
92 : bool FeedbackVector::is_empty() const {
93 : return length() == kReservedIndexCount;
94 : }
95 :
96 5419817 : int FeedbackVector::slot_count() const {
97 7345739 : return length() - kReservedIndexCount;
98 : }
99 :
100 98 : FeedbackMetadata* FeedbackVector::metadata() const {
101 98 : return shared_function_info()->feedback_metadata();
102 : }
103 :
104 : SharedFunctionInfo* FeedbackVector::shared_function_info() const {
105 : return SharedFunctionInfo::cast(get(kSharedFunctionInfoIndex));
106 : }
107 :
108 : int FeedbackVector::invocation_count() const {
109 : return Smi::cast(get(kInvocationCountIndex))->value();
110 : }
111 :
112 : void FeedbackVector::clear_invocation_count() {
113 : set(kInvocationCountIndex, Smi::kZero);
114 : }
115 :
116 : // Conversion from an integer index to either a slot or an ic slot.
117 : // static
118 39098874 : FeedbackSlot FeedbackVector::ToSlot(int index) {
119 : DCHECK_GE(index, kReservedIndexCount);
120 47225053 : return FeedbackSlot(index - kReservedIndexCount);
121 : }
122 :
123 21417549 : Object* FeedbackVector::Get(FeedbackSlot slot) const {
124 21417549 : return get(GetIndex(slot));
125 : }
126 :
127 727267 : void FeedbackVector::Set(FeedbackSlot slot, Object* value,
128 : WriteBarrierMode mode) {
129 15641528 : set(GetIndex(slot), value, mode);
130 727267 : }
131 :
132 : // Helper function to transform the feedback to BinaryOperationHint.
133 : BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) {
134 : switch (type_feedback) {
135 : case BinaryOperationFeedback::kNone:
136 : return BinaryOperationHint::kNone;
137 : case BinaryOperationFeedback::kSignedSmall:
138 : return BinaryOperationHint::kSignedSmall;
139 : case BinaryOperationFeedback::kNumber:
140 : case BinaryOperationFeedback::kNumberOrOddball:
141 : return BinaryOperationHint::kNumberOrOddball;
142 : case BinaryOperationFeedback::kString:
143 : return BinaryOperationHint::kString;
144 : case BinaryOperationFeedback::kAny:
145 : default:
146 : return BinaryOperationHint::kAny;
147 : }
148 : UNREACHABLE();
149 : return BinaryOperationHint::kNone;
150 : }
151 :
152 : // Helper function to transform the feedback to CompareOperationHint.
153 : CompareOperationHint CompareOperationHintFromFeedback(int type_feedback) {
154 : switch (type_feedback) {
155 : case CompareOperationFeedback::kNone:
156 : return CompareOperationHint::kNone;
157 : case CompareOperationFeedback::kSignedSmall:
158 : return CompareOperationHint::kSignedSmall;
159 : case CompareOperationFeedback::kNumber:
160 : return CompareOperationHint::kNumber;
161 : case CompareOperationFeedback::kNumberOrOddball:
162 : return CompareOperationHint::kNumberOrOddball;
163 : case CompareOperationFeedback::kInternalizedString:
164 : return CompareOperationHint::kInternalizedString;
165 : case CompareOperationFeedback::kString:
166 : return CompareOperationHint::kString;
167 : case CompareOperationFeedback::kReceiver:
168 : return CompareOperationHint::kReceiver;
169 : default:
170 : return CompareOperationHint::kAny;
171 : }
172 : UNREACHABLE();
173 : return CompareOperationHint::kNone;
174 : }
175 :
176 179274 : void FeedbackVector::ComputeCounts(int* with_type_info, int* generic,
177 : int* vector_ic_count,
178 : bool code_is_interpreted) {
179 : Object* megamorphic_sentinel =
180 : *FeedbackVector::MegamorphicSentinel(GetIsolate());
181 : int with = 0;
182 : int gen = 0;
183 : int total = 0;
184 : FeedbackMetadataIterator iter(metadata());
185 2604395 : while (iter.HasNext()) {
186 2425121 : FeedbackSlot slot = iter.Next();
187 2425121 : FeedbackSlotKind kind = iter.kind();
188 :
189 : Object* const obj = Get(slot);
190 2425121 : switch (kind) {
191 : case FeedbackSlotKind::kCall:
192 : case FeedbackSlotKind::kLoadProperty:
193 : case FeedbackSlotKind::kLoadGlobalInsideTypeof:
194 : case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
195 : case FeedbackSlotKind::kLoadKeyed:
196 : case FeedbackSlotKind::kStoreNamedSloppy:
197 : case FeedbackSlotKind::kStoreNamedStrict:
198 : case FeedbackSlotKind::kStoreOwnNamed:
199 : case FeedbackSlotKind::kStoreGlobalSloppy:
200 : case FeedbackSlotKind::kStoreGlobalStrict:
201 : case FeedbackSlotKind::kStoreKeyedSloppy:
202 : case FeedbackSlotKind::kStoreKeyedStrict:
203 : case FeedbackSlotKind::kStoreDataPropertyInLiteral:
204 : case FeedbackSlotKind::kTypeProfile: {
205 2394893 : if (obj->IsWeakCell() || obj->IsFixedArray() || obj->IsString()) {
206 598629 : with++;
207 583297 : } else if (obj == megamorphic_sentinel) {
208 70825 : gen++;
209 70825 : if (code_is_interpreted) with++;
210 : }
211 1181926 : total++;
212 1181926 : break;
213 : }
214 : case FeedbackSlotKind::kBinaryOp:
215 : // If we are not running interpreted code, we need to ignore the special
216 : // IC slots for binaryop/compare used by the interpreter.
217 : // TODO(mvstanton): Remove code_is_interpreted when full code is retired
218 : // from service.
219 816818 : if (code_is_interpreted) {
220 : int const feedback = Smi::cast(obj)->value();
221 : BinaryOperationHint hint = BinaryOperationHintFromFeedback(feedback);
222 181915 : if (hint == BinaryOperationHint::kAny) {
223 1559 : gen++;
224 : }
225 181915 : if (hint != BinaryOperationHint::kNone) {
226 138781 : with++;
227 : }
228 181915 : total++;
229 : }
230 : break;
231 : case FeedbackSlotKind::kCompareOp: {
232 : // If we are not running interpreted code, we need to ignore the special
233 : // IC slots for binaryop/compare used by the interpreter.
234 : // TODO(mvstanton): Remove code_is_interpreted when full code is retired
235 : // from service.
236 374723 : if (code_is_interpreted) {
237 : int const feedback = Smi::cast(obj)->value();
238 : CompareOperationHint hint =
239 : CompareOperationHintFromFeedback(feedback);
240 87275 : if (hint == CompareOperationHint::kAny) {
241 7681 : gen++;
242 : }
243 87275 : if (hint != CompareOperationHint::kNone) {
244 55581 : with++;
245 : }
246 87275 : total++;
247 : }
248 : break;
249 : }
250 : case FeedbackSlotKind::kToBoolean:
251 : case FeedbackSlotKind::kCreateClosure:
252 : case FeedbackSlotKind::kGeneral:
253 : case FeedbackSlotKind::kLiteral:
254 : break;
255 : case FeedbackSlotKind::kInvalid:
256 : case FeedbackSlotKind::kKindsNumber:
257 0 : UNREACHABLE();
258 : break;
259 : }
260 : }
261 :
262 179274 : *with_type_info = with;
263 179274 : *generic = gen;
264 179274 : *vector_ic_count = total;
265 179274 : }
266 :
267 : Handle<Symbol> FeedbackVector::UninitializedSentinel(Isolate* isolate) {
268 : return isolate->factory()->uninitialized_symbol();
269 : }
270 :
271 : Handle<Symbol> FeedbackVector::MegamorphicSentinel(Isolate* isolate) {
272 : return isolate->factory()->megamorphic_symbol();
273 : }
274 :
275 : Handle<Symbol> FeedbackVector::PremonomorphicSentinel(Isolate* isolate) {
276 : return isolate->factory()->premonomorphic_symbol();
277 : }
278 :
279 : Symbol* FeedbackVector::RawUninitializedSentinel(Isolate* isolate) {
280 92305 : return isolate->heap()->uninitialized_symbol();
281 : }
282 :
283 2976204 : bool FeedbackMetadataIterator::HasNext() const {
284 2976204 : return next_slot_.ToInt() < metadata()->slot_count();
285 : }
286 :
287 2704625 : FeedbackSlot FeedbackMetadataIterator::Next() {
288 : DCHECK(HasNext());
289 2704625 : cur_slot_ = next_slot_;
290 2704625 : slot_kind_ = metadata()->GetKind(cur_slot_);
291 2704625 : next_slot_ = FeedbackSlot(next_slot_.ToInt() + entry_size());
292 2704625 : return cur_slot_;
293 : }
294 :
295 : int FeedbackMetadataIterator::entry_size() const {
296 2704625 : return FeedbackMetadata::GetSlotSize(kind());
297 : }
298 :
299 54696672 : Object* FeedbackNexus::GetFeedback() const { return vector()->Get(slot()); }
300 :
301 3529351 : Object* FeedbackNexus::GetFeedbackExtra() const {
302 : #ifdef DEBUG
303 : FeedbackSlotKind kind = vector()->GetKind(slot());
304 : DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
305 : #endif
306 3529351 : int extra_index = vector()->GetIndex(slot()) + 1;
307 3529351 : return vector()->get(extra_index);
308 : }
309 :
310 14598800 : void FeedbackNexus::SetFeedback(Object* feedback, WriteBarrierMode mode) {
311 : vector()->Set(slot(), feedback, mode);
312 14598804 : }
313 :
314 14635804 : void FeedbackNexus::SetFeedbackExtra(Object* feedback_extra,
315 : WriteBarrierMode mode) {
316 : #ifdef DEBUG
317 : FeedbackSlotKind kind = vector()->GetKind(slot());
318 : DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
319 : #endif
320 14635804 : int index = vector()->GetIndex(slot()) + 1;
321 14635804 : vector()->set(index, feedback_extra, mode);
322 14635801 : }
323 :
324 : Isolate* FeedbackNexus::GetIsolate() const { return vector()->GetIsolate(); }
325 : } // namespace internal
326 : } // namespace v8
327 :
328 : #endif // V8_FEEDBACK_VECTOR_INL_H_
|