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