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/feedback-vector.h"
9 : #include "src/globals.h"
10 : #include "src/heap/factory-inl.h"
11 : #include "src/heap/heap-inl.h"
12 : #include "src/heap/heap-write-barrier.h"
13 : #include "src/objects/maybe-object-inl.h"
14 : #include "src/objects/shared-function-info.h"
15 : #include "src/objects/smi.h"
16 :
17 : // Has to be the last include (doesn't have include guards):
18 : #include "src/objects/object-macros.h"
19 :
20 : namespace v8 {
21 : namespace internal {
22 :
23 79862410 : OBJECT_CONSTRUCTORS_IMPL(FeedbackVector, HeapObject)
24 100463966 : OBJECT_CONSTRUCTORS_IMPL(FeedbackMetadata, HeapObject)
25 :
26 : NEVER_READ_ONLY_SPACE_IMPL(FeedbackVector)
27 :
28 39956970 : CAST_ACCESSOR(FeedbackVector)
29 50232018 : CAST_ACCESSOR(FeedbackMetadata)
30 :
31 7896268 : INT32_ACCESSORS(FeedbackMetadata, slot_count, kSlotCountOffset)
32 :
33 : int32_t FeedbackMetadata::synchronized_slot_count() const {
34 : return base::Acquire_Load(reinterpret_cast<const base::Atomic32*>(
35 15662030 : FIELD_ADDR(this, kSlotCountOffset)));
36 : }
37 :
38 : int32_t FeedbackMetadata::get(int index) const {
39 : DCHECK(index >= 0 && index < length());
40 66586121 : int offset = kHeaderSize + index * kInt32Size;
41 66586646 : return READ_INT32_FIELD(this, offset);
42 : }
43 :
44 : void FeedbackMetadata::set(int index, int32_t value) {
45 : DCHECK(index >= 0 && index < length());
46 : int offset = kHeaderSize + index * kInt32Size;
47 24090465 : WRITE_INT32_FIELD(this, offset, value);
48 : }
49 :
50 : bool FeedbackMetadata::is_empty() const { return slot_count() == 0; }
51 :
52 : int FeedbackMetadata::length() const {
53 : return FeedbackMetadata::length(slot_count());
54 : }
55 :
56 36752758 : int FeedbackMetadata::GetSlotSize(FeedbackSlotKind kind) {
57 : switch (kind) {
58 : case FeedbackSlotKind::kForIn:
59 : case FeedbackSlotKind::kInstanceOf:
60 : case FeedbackSlotKind::kCompareOp:
61 : case FeedbackSlotKind::kBinaryOp:
62 : case FeedbackSlotKind::kLiteral:
63 : case FeedbackSlotKind::kCreateClosure:
64 : case FeedbackSlotKind::kTypeProfile:
65 : return 1;
66 :
67 : case FeedbackSlotKind::kCall:
68 : case FeedbackSlotKind::kCloneObject:
69 : case FeedbackSlotKind::kLoadProperty:
70 : case FeedbackSlotKind::kLoadGlobalInsideTypeof:
71 : case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
72 : case FeedbackSlotKind::kLoadKeyed:
73 : case FeedbackSlotKind::kStoreNamedSloppy:
74 : case FeedbackSlotKind::kStoreNamedStrict:
75 : case FeedbackSlotKind::kStoreOwnNamed:
76 : case FeedbackSlotKind::kStoreGlobalSloppy:
77 : case FeedbackSlotKind::kStoreGlobalStrict:
78 : case FeedbackSlotKind::kStoreKeyedSloppy:
79 : case FeedbackSlotKind::kStoreKeyedStrict:
80 : case FeedbackSlotKind::kStoreInArrayLiteral:
81 : case FeedbackSlotKind::kStoreDataPropertyInLiteral:
82 24785928 : return 2;
83 :
84 : case FeedbackSlotKind::kInvalid:
85 : case FeedbackSlotKind::kKindsNumber:
86 0 : UNREACHABLE();
87 : break;
88 : }
89 : return 1;
90 : }
91 :
92 90370605 : ACCESSORS(FeedbackVector, shared_function_info, SharedFunctionInfo,
93 : kSharedFunctionInfoOffset)
94 34928759 : WEAK_ACCESSORS(FeedbackVector, optimized_code_weak_or_smi, kOptimizedCodeOffset)
95 26722992 : INT32_ACCESSORS(FeedbackVector, length, kLengthOffset)
96 3604272 : INT32_ACCESSORS(FeedbackVector, invocation_count, kInvocationCountOffset)
97 6552635 : INT32_ACCESSORS(FeedbackVector, profiler_ticks, kProfilerTicksOffset)
98 3143843 : INT32_ACCESSORS(FeedbackVector, deopt_count, kDeoptCountOffset)
99 :
100 7 : bool FeedbackVector::is_empty() const { return length() == 0; }
101 :
102 : FeedbackMetadata FeedbackVector::metadata() const {
103 21003324 : return shared_function_info()->feedback_metadata();
104 : }
105 :
106 : void FeedbackVector::clear_invocation_count() { set_invocation_count(0); }
107 :
108 : void FeedbackVector::increment_deopt_count() {
109 : int count = deopt_count();
110 34902 : if (count < std::numeric_limits<int32_t>::max()) {
111 34902 : set_deopt_count(count + 1);
112 : }
113 : }
114 :
115 7305855 : Code FeedbackVector::optimized_code() const {
116 7305855 : MaybeObject slot = optimized_code_weak_or_smi();
117 : DCHECK(slot->IsSmi() || slot->IsWeakOrCleared());
118 7305855 : HeapObject heap_object;
119 15069210 : return slot->GetHeapObject(&heap_object) ? Code::cast(heap_object) : Code();
120 : }
121 :
122 1468292 : OptimizationMarker FeedbackVector::optimization_marker() const {
123 1468292 : MaybeObject slot = optimized_code_weak_or_smi();
124 1468292 : Smi value;
125 1468292 : if (!slot->ToSmi(&value)) return OptimizationMarker::kNone;
126 1462704 : return static_cast<OptimizationMarker>(value->value());
127 : }
128 :
129 : bool FeedbackVector::has_optimized_code() const {
130 1153647 : return !optimized_code().is_null();
131 : }
132 :
133 479852 : bool FeedbackVector::has_optimization_marker() const {
134 959708 : return optimization_marker() != OptimizationMarker::kLogFirstExecution &&
135 959709 : optimization_marker() != OptimizationMarker::kNone;
136 : }
137 :
138 : // Conversion from an integer index to either a slot or an ic slot.
139 : // static
140 7617586 : FeedbackSlot FeedbackVector::ToSlot(int index) {
141 : DCHECK_GE(index, 0);
142 7617586 : return FeedbackSlot(index);
143 : }
144 :
145 81905 : MaybeObject FeedbackVector::Get(FeedbackSlot slot) const {
146 16749365 : return get(GetIndex(slot));
147 : }
148 :
149 23727815 : MaybeObject FeedbackVector::get(int index) const {
150 : DCHECK_GE(index, 0);
151 : DCHECK_LT(index, this->length());
152 23727815 : int offset = kFeedbackSlotsOffset + index * kTaggedSize;
153 47455630 : return RELAXED_READ_WEAK_FIELD(*this, offset);
154 : }
155 :
156 : void FeedbackVector::Set(FeedbackSlot slot, MaybeObject value,
157 : WriteBarrierMode mode) {
158 7918085 : set(GetIndex(slot), value, mode);
159 : }
160 :
161 52044047 : void FeedbackVector::set(int index, MaybeObject value, WriteBarrierMode mode) {
162 : DCHECK_GE(index, 0);
163 : DCHECK_LT(index, this->length());
164 52044047 : int offset = kFeedbackSlotsOffset + index * kTaggedSize;
165 52044047 : RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
166 80535465 : CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
167 52044072 : }
168 :
169 18621 : void FeedbackVector::Set(FeedbackSlot slot, Object value,
170 : WriteBarrierMode mode) {
171 259608 : set(GetIndex(slot), MaybeObject::FromObject(value), mode);
172 18621 : }
173 :
174 : void FeedbackVector::set(int index, Object value, WriteBarrierMode mode) {
175 29729321 : set(index, MaybeObject::FromObject(value), mode);
176 : }
177 :
178 : inline MaybeObjectSlot FeedbackVector::slots_start() {
179 : return RawMaybeWeakField(kFeedbackSlotsOffset);
180 : }
181 :
182 : // Helper function to transform the feedback to BinaryOperationHint.
183 : BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) {
184 : switch (type_feedback) {
185 : case BinaryOperationFeedback::kNone:
186 : return BinaryOperationHint::kNone;
187 : case BinaryOperationFeedback::kSignedSmall:
188 : return BinaryOperationHint::kSignedSmall;
189 : case BinaryOperationFeedback::kSignedSmallInputs:
190 : return BinaryOperationHint::kSignedSmallInputs;
191 : case BinaryOperationFeedback::kNumber:
192 : return BinaryOperationHint::kNumber;
193 : case BinaryOperationFeedback::kNumberOrOddball:
194 : return BinaryOperationHint::kNumberOrOddball;
195 : case BinaryOperationFeedback::kString:
196 : return BinaryOperationHint::kString;
197 : case BinaryOperationFeedback::kBigInt:
198 : return BinaryOperationHint::kBigInt;
199 : default:
200 : return BinaryOperationHint::kAny;
201 : }
202 : UNREACHABLE();
203 : }
204 :
205 : // Helper function to transform the feedback to CompareOperationHint.
206 527494 : CompareOperationHint CompareOperationHintFromFeedback(int type_feedback) {
207 527494 : switch (type_feedback) {
208 : case CompareOperationFeedback::kNone:
209 : return CompareOperationHint::kNone;
210 : case CompareOperationFeedback::kSignedSmall:
211 188647 : return CompareOperationHint::kSignedSmall;
212 : case CompareOperationFeedback::kNumber:
213 33666 : return CompareOperationHint::kNumber;
214 : case CompareOperationFeedback::kNumberOrOddball:
215 21 : return CompareOperationHint::kNumberOrOddball;
216 : case CompareOperationFeedback::kInternalizedString:
217 17033 : return CompareOperationHint::kInternalizedString;
218 : case CompareOperationFeedback::kString:
219 27404 : return CompareOperationHint::kString;
220 : case CompareOperationFeedback::kSymbol:
221 132 : return CompareOperationHint::kSymbol;
222 : case CompareOperationFeedback::kBigInt:
223 148 : return CompareOperationHint::kBigInt;
224 : case CompareOperationFeedback::kReceiver:
225 2154 : return CompareOperationHint::kReceiver;
226 : case CompareOperationFeedback::kReceiverOrNullOrUndefined:
227 409 : return CompareOperationHint::kReceiverOrNullOrUndefined;
228 : default:
229 73033 : return CompareOperationHint::kAny;
230 : }
231 : UNREACHABLE();
232 : }
233 :
234 : // Helper function to transform the feedback to ForInHint.
235 : ForInHint ForInHintFromFeedback(int type_feedback) {
236 : switch (type_feedback) {
237 : case ForInFeedback::kNone:
238 : return ForInHint::kNone;
239 : case ForInFeedback::kEnumCacheKeys:
240 : return ForInHint::kEnumCacheKeys;
241 : case ForInFeedback::kEnumCacheKeysAndIndices:
242 : return ForInHint::kEnumCacheKeysAndIndices;
243 : default:
244 : return ForInHint::kAny;
245 : }
246 : UNREACHABLE();
247 : }
248 :
249 0 : void FeedbackVector::ComputeCounts(int* with_type_info, int* generic,
250 : int* vector_ic_count) {
251 : MaybeObject megamorphic_sentinel = MaybeObject::FromObject(
252 : *FeedbackVector::MegamorphicSentinel(GetIsolate()));
253 : int with = 0;
254 : int gen = 0;
255 : int total = 0;
256 : FeedbackMetadataIterator iter(metadata());
257 0 : while (iter.HasNext()) {
258 0 : FeedbackSlot slot = iter.Next();
259 0 : FeedbackSlotKind kind = iter.kind();
260 :
261 0 : MaybeObject const obj = Get(slot);
262 0 : AssertNoLegacyTypes(obj);
263 0 : switch (kind) {
264 : case FeedbackSlotKind::kCall:
265 : case FeedbackSlotKind::kLoadProperty:
266 : case FeedbackSlotKind::kLoadGlobalInsideTypeof:
267 : case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
268 : case FeedbackSlotKind::kLoadKeyed:
269 : case FeedbackSlotKind::kStoreNamedSloppy:
270 : case FeedbackSlotKind::kStoreNamedStrict:
271 : case FeedbackSlotKind::kStoreOwnNamed:
272 : case FeedbackSlotKind::kStoreGlobalSloppy:
273 : case FeedbackSlotKind::kStoreGlobalStrict:
274 : case FeedbackSlotKind::kStoreKeyedSloppy:
275 : case FeedbackSlotKind::kStoreKeyedStrict:
276 : case FeedbackSlotKind::kStoreInArrayLiteral:
277 : case FeedbackSlotKind::kStoreDataPropertyInLiteral:
278 : case FeedbackSlotKind::kTypeProfile: {
279 0 : HeapObject heap_object;
280 0 : if (obj->IsWeakOrCleared() ||
281 0 : (obj->GetHeapObjectIfStrong(&heap_object) &&
282 0 : (heap_object->IsWeakFixedArray() || heap_object->IsString()))) {
283 0 : with++;
284 0 : } else if (obj == megamorphic_sentinel) {
285 0 : gen++;
286 0 : with++;
287 : }
288 0 : total++;
289 : break;
290 : }
291 : case FeedbackSlotKind::kBinaryOp: {
292 0 : int const feedback = obj.ToSmi().value();
293 : BinaryOperationHint hint = BinaryOperationHintFromFeedback(feedback);
294 0 : if (hint == BinaryOperationHint::kAny) {
295 0 : gen++;
296 : }
297 0 : if (hint != BinaryOperationHint::kNone) {
298 0 : with++;
299 : }
300 0 : total++;
301 0 : break;
302 : }
303 : case FeedbackSlotKind::kCompareOp: {
304 0 : int const feedback = obj.ToSmi().value();
305 0 : CompareOperationHint hint = CompareOperationHintFromFeedback(feedback);
306 0 : if (hint == CompareOperationHint::kAny) {
307 0 : gen++;
308 : }
309 0 : if (hint != CompareOperationHint::kNone) {
310 0 : with++;
311 : }
312 0 : total++;
313 0 : break;
314 : }
315 : case FeedbackSlotKind::kForIn: {
316 0 : int const feedback = obj.ToSmi().value();
317 : ForInHint hint = ForInHintFromFeedback(feedback);
318 0 : if (hint == ForInHint::kAny) {
319 0 : gen++;
320 : }
321 0 : if (hint != ForInHint::kNone) {
322 0 : with++;
323 : }
324 0 : total++;
325 0 : break;
326 : }
327 : case FeedbackSlotKind::kInstanceOf: {
328 0 : if (obj->IsWeakOrCleared()) {
329 0 : with++;
330 0 : } else if (obj == megamorphic_sentinel) {
331 0 : gen++;
332 0 : with++;
333 : }
334 0 : total++;
335 0 : break;
336 : }
337 : case FeedbackSlotKind::kCreateClosure:
338 : case FeedbackSlotKind::kLiteral:
339 : case FeedbackSlotKind::kCloneObject:
340 : break;
341 : case FeedbackSlotKind::kInvalid:
342 : case FeedbackSlotKind::kKindsNumber:
343 0 : UNREACHABLE();
344 : break;
345 : }
346 : }
347 :
348 0 : *with_type_info = with;
349 0 : *generic = gen;
350 0 : *vector_ic_count = total;
351 0 : }
352 :
353 : Handle<Symbol> FeedbackVector::UninitializedSentinel(Isolate* isolate) {
354 : return isolate->factory()->uninitialized_symbol();
355 : }
356 :
357 : Handle<Symbol> FeedbackVector::GenericSentinel(Isolate* isolate) {
358 : return isolate->factory()->generic_symbol();
359 : }
360 :
361 : Handle<Symbol> FeedbackVector::MegamorphicSentinel(Isolate* isolate) {
362 : return isolate->factory()->megamorphic_symbol();
363 : }
364 :
365 : Handle<Symbol> FeedbackVector::PremonomorphicSentinel(Isolate* isolate) {
366 : return isolate->factory()->premonomorphic_symbol();
367 : }
368 :
369 52533 : Symbol FeedbackVector::RawUninitializedSentinel(Isolate* isolate) {
370 52533 : return ReadOnlyRoots(isolate).uninitialized_symbol();
371 : }
372 :
373 : bool FeedbackMetadataIterator::HasNext() const {
374 268148 : return next_slot_.ToInt() < metadata()->slot_count();
375 : }
376 :
377 81452 : FeedbackSlot FeedbackMetadataIterator::Next() {
378 : DCHECK(HasNext());
379 81452 : cur_slot_ = next_slot_;
380 162495 : slot_kind_ = metadata()->GetKind(cur_slot_);
381 81452 : next_slot_ = FeedbackSlot(next_slot_.ToInt() + entry_size());
382 81452 : return cur_slot_;
383 : }
384 :
385 0 : int FeedbackMetadataIterator::entry_size() const {
386 81452 : return FeedbackMetadata::GetSlotSize(kind());
387 : }
388 :
389 15329909 : MaybeObject FeedbackNexus::GetFeedback() const {
390 30659858 : MaybeObject feedback = vector()->Get(slot());
391 26116 : FeedbackVector::AssertNoLegacyTypes(feedback);
392 15329949 : return feedback;
393 : }
394 :
395 6315717 : MaybeObject FeedbackNexus::GetFeedbackExtra() const {
396 : #ifdef DEBUG
397 : FeedbackSlotKind kind = vector()->GetKind(slot());
398 : DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
399 : #endif
400 6315717 : int extra_index = vector()->GetIndex(slot()) + 1;
401 6315721 : return vector()->get(extra_index);
402 : }
403 :
404 : void FeedbackNexus::SetFeedback(Object feedback, WriteBarrierMode mode) {
405 909546 : SetFeedback(MaybeObject::FromObject(feedback));
406 : }
407 :
408 7918071 : void FeedbackNexus::SetFeedback(MaybeObject feedback, WriteBarrierMode mode) {
409 : FeedbackVector::AssertNoLegacyTypes(feedback);
410 15836174 : vector()->Set(slot(), feedback, mode);
411 7918103 : }
412 :
413 5766948 : void FeedbackNexus::SetFeedbackExtra(Object feedback_extra,
414 : WriteBarrierMode mode) {
415 : #ifdef DEBUG
416 : FeedbackSlotKind kind = vector()->GetKind(slot());
417 : DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
418 : FeedbackVector::AssertNoLegacyTypes(MaybeObject::FromObject(feedback_extra));
419 : #endif
420 5766948 : int index = vector()->GetIndex(slot()) + 1;
421 5766949 : vector()->set(index, MaybeObject::FromObject(feedback_extra), mode);
422 5766949 : }
423 :
424 2158596 : void FeedbackNexus::SetFeedbackExtra(MaybeObject feedback_extra,
425 : WriteBarrierMode mode) {
426 : #ifdef DEBUG
427 : FeedbackVector::AssertNoLegacyTypes(feedback_extra);
428 : #endif
429 2158596 : int index = vector()->GetIndex(slot()) + 1;
430 2158601 : vector()->set(index, feedback_extra, mode);
431 2158609 : }
432 :
433 39353373 : Isolate* FeedbackNexus::GetIsolate() const { return vector()->GetIsolate(); }
434 : } // namespace internal
435 : } // namespace v8
436 :
437 : #include "src/objects/object-macros-undef.h"
438 :
439 : #endif // V8_FEEDBACK_VECTOR_INL_H_
|