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 : OBJECT_CONSTRUCTORS_IMPL(FeedbackVector, HeapObject)
25 : OBJECT_CONSTRUCTORS_IMPL(FeedbackMetadata, HeapObject)
26 :
27 : NEVER_READ_ONLY_SPACE_IMPL(FeedbackVector)
28 :
29 : CAST_ACCESSOR(FeedbackVector)
30 : CAST_ACCESSOR(FeedbackMetadata)
31 :
32 7897326 : INT32_ACCESSORS(FeedbackMetadata, slot_count, kSlotCountOffset)
33 :
34 4680022 : INT32_ACCESSORS(FeedbackMetadata, closure_feedback_cell_count,
35 : kFeedbackCellCountOffset)
36 :
37 : int32_t FeedbackMetadata::synchronized_slot_count() const {
38 5301966 : return base::Acquire_Load(reinterpret_cast<const base::Atomic32*>(
39 5301966 : FIELD_ADDR(*this, kSlotCountOffset)));
40 : }
41 :
42 : int32_t FeedbackMetadata::get(int index) const {
43 : DCHECK(index >= 0 && index < length());
44 70154102 : int offset = kHeaderSize + index * kInt32Size;
45 70154522 : return READ_INT32_FIELD(*this, offset);
46 : }
47 :
48 : void FeedbackMetadata::set(int index, int32_t value) {
49 : DCHECK(index >= 0 && index < length());
50 : int offset = kHeaderSize + index * kInt32Size;
51 25902969 : WRITE_INT32_FIELD(*this, offset, value);
52 : }
53 :
54 : bool FeedbackMetadata::is_empty() const { return slot_count() == 0; }
55 :
56 : int FeedbackMetadata::length() const {
57 : return FeedbackMetadata::length(slot_count());
58 : }
59 :
60 35486534 : int FeedbackMetadata::GetSlotSize(FeedbackSlotKind kind) {
61 : switch (kind) {
62 : case FeedbackSlotKind::kForIn:
63 : case FeedbackSlotKind::kInstanceOf:
64 : case FeedbackSlotKind::kCompareOp:
65 : case FeedbackSlotKind::kBinaryOp:
66 : case FeedbackSlotKind::kLiteral:
67 : case FeedbackSlotKind::kTypeProfile:
68 : return 1;
69 :
70 : case FeedbackSlotKind::kCall:
71 : case FeedbackSlotKind::kCloneObject:
72 : case FeedbackSlotKind::kLoadProperty:
73 : case FeedbackSlotKind::kLoadGlobalInsideTypeof:
74 : case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
75 : case FeedbackSlotKind::kLoadKeyed:
76 : case FeedbackSlotKind::kHasKeyed:
77 : case FeedbackSlotKind::kStoreNamedSloppy:
78 : case FeedbackSlotKind::kStoreNamedStrict:
79 : case FeedbackSlotKind::kStoreOwnNamed:
80 : case FeedbackSlotKind::kStoreGlobalSloppy:
81 : case FeedbackSlotKind::kStoreGlobalStrict:
82 : case FeedbackSlotKind::kStoreKeyedSloppy:
83 : case FeedbackSlotKind::kStoreKeyedStrict:
84 : case FeedbackSlotKind::kStoreInArrayLiteral:
85 : case FeedbackSlotKind::kStoreDataPropertyInLiteral:
86 30122373 : return 2;
87 :
88 : case FeedbackSlotKind::kInvalid:
89 : case FeedbackSlotKind::kKindsNumber:
90 0 : UNREACHABLE();
91 : break;
92 : }
93 : return 1;
94 : }
95 :
96 38844020 : ACCESSORS(FeedbackVector, shared_function_info, SharedFunctionInfo,
97 : kSharedFunctionInfoOffset)
98 34661139 : WEAK_ACCESSORS(FeedbackVector, optimized_code_weak_or_smi, kOptimizedCodeOffset)
99 31428809 : ACCESSORS(FeedbackVector, closure_feedback_cell_array, FixedArray,
100 : kClosureFeedbackCellArrayOffset)
101 23800468 : INT32_ACCESSORS(FeedbackVector, length, kLengthOffset)
102 3618675 : INT32_ACCESSORS(FeedbackVector, invocation_count, kInvocationCountOffset)
103 7068695 : INT32_ACCESSORS(FeedbackVector, profiler_ticks, kProfilerTicksOffset)
104 3156250 : INT32_ACCESSORS(FeedbackVector, deopt_count, kDeoptCountOffset)
105 :
106 7 : bool FeedbackVector::is_empty() const { return length() == 0; }
107 :
108 23412762 : FeedbackMetadata FeedbackVector::metadata() const {
109 23412762 : return shared_function_info()->feedback_metadata();
110 : }
111 :
112 : void FeedbackVector::clear_invocation_count() { set_invocation_count(0); }
113 :
114 : void FeedbackVector::increment_deopt_count() {
115 : int count = deopt_count();
116 36812 : if (count < std::numeric_limits<int32_t>::max()) {
117 36812 : set_deopt_count(count + 1);
118 : }
119 : }
120 :
121 7367277 : Code FeedbackVector::optimized_code() const {
122 : MaybeObject slot = optimized_code_weak_or_smi();
123 : DCHECK(slot->IsSmi() || slot->IsWeakOrCleared());
124 : HeapObject heap_object;
125 14734554 : return slot->GetHeapObject(&heap_object) ? Code::cast(heap_object) : Code();
126 : }
127 :
128 : OptimizationMarker FeedbackVector::optimization_marker() const {
129 : MaybeObject slot = optimized_code_weak_or_smi();
130 : Smi value;
131 1486297 : if (!slot->ToSmi(&value)) return OptimizationMarker::kNone;
132 : return static_cast<OptimizationMarker>(value->value());
133 : }
134 :
135 : bool FeedbackVector::has_optimized_code() const {
136 1245078 : return !optimized_code().is_null();
137 : }
138 :
139 488811 : bool FeedbackVector::has_optimization_marker() const {
140 977620 : return optimization_marker() != OptimizationMarker::kLogFirstExecution &&
141 488811 : optimization_marker() != OptimizationMarker::kNone;
142 : }
143 :
144 : // Conversion from an integer index to either a slot or an ic slot.
145 : // static
146 : FeedbackSlot FeedbackVector::ToSlot(int index) {
147 : DCHECK_GE(index, 0);
148 : return FeedbackSlot(index);
149 : }
150 :
151 : MaybeObject FeedbackVector::Get(FeedbackSlot slot) const {
152 : return get(GetIndex(slot));
153 : }
154 :
155 : MaybeObject FeedbackVector::get(int index) const {
156 : DCHECK_GE(index, 0);
157 : DCHECK_LT(index, this->length());
158 26912800 : int offset = kFeedbackSlotsOffset + index * kTaggedSize;
159 53825660 : return RELAXED_READ_WEAK_FIELD(*this, offset);
160 : }
161 :
162 446200 : Handle<FeedbackCell> FeedbackVector::GetClosureFeedbackCell(int index) const {
163 : DCHECK_GE(index, 0);
164 : FixedArray cell_array = closure_feedback_cell_array();
165 446200 : return handle(FeedbackCell::cast(cell_array.get(index)), GetIsolate());
166 : }
167 :
168 : void FeedbackVector::Set(FeedbackSlot slot, MaybeObject value,
169 : WriteBarrierMode mode) {
170 8718033 : set(GetIndex(slot), value, mode);
171 : }
172 :
173 56142159 : void FeedbackVector::set(int index, MaybeObject value, WriteBarrierMode mode) {
174 : DCHECK_GE(index, 0);
175 : DCHECK_LT(index, this->length());
176 56142159 : int offset = kFeedbackSlotsOffset + index * kTaggedSize;
177 56142159 : RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
178 79348886 : CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
179 56142176 : }
180 :
181 : void FeedbackVector::Set(FeedbackSlot slot, Object value,
182 : WriteBarrierMode mode) {
183 259704 : set(GetIndex(slot), MaybeObject::FromObject(value), mode);
184 : }
185 :
186 : void FeedbackVector::set(int index, Object value, WriteBarrierMode mode) {
187 32186490 : set(index, MaybeObject::FromObject(value), mode);
188 : }
189 :
190 : inline MaybeObjectSlot FeedbackVector::slots_start() {
191 : return RawMaybeWeakField(kFeedbackSlotsOffset);
192 : }
193 :
194 : // Helper function to transform the feedback to BinaryOperationHint.
195 967534 : BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) {
196 967534 : switch (type_feedback) {
197 : case BinaryOperationFeedback::kNone:
198 : return BinaryOperationHint::kNone;
199 : case BinaryOperationFeedback::kSignedSmall:
200 401759 : return BinaryOperationHint::kSignedSmall;
201 : case BinaryOperationFeedback::kSignedSmallInputs:
202 27367 : return BinaryOperationHint::kSignedSmallInputs;
203 : case BinaryOperationFeedback::kNumber:
204 224212 : return BinaryOperationHint::kNumber;
205 : case BinaryOperationFeedback::kNumberOrOddball:
206 6603 : return BinaryOperationHint::kNumberOrOddball;
207 : case BinaryOperationFeedback::kConsOneByteString:
208 6212 : return BinaryOperationHint::kConsOneByteString;
209 : case BinaryOperationFeedback::kConsTwoByteString:
210 494 : return BinaryOperationHint::kConsTwoByteString;
211 : case BinaryOperationFeedback::kConsString:
212 0 : return BinaryOperationHint::kConsString;
213 : case BinaryOperationFeedback::kString:
214 13432 : return BinaryOperationHint::kString;
215 : case BinaryOperationFeedback::kBigInt:
216 938 : return BinaryOperationHint::kBigInt;
217 : default:
218 10181 : return BinaryOperationHint::kAny;
219 : }
220 : UNREACHABLE();
221 : }
222 :
223 : // Helper function to transform the feedback to CompareOperationHint.
224 526601 : CompareOperationHint CompareOperationHintFromFeedback(int type_feedback) {
225 526601 : switch (type_feedback) {
226 : case CompareOperationFeedback::kNone:
227 : return CompareOperationHint::kNone;
228 : case CompareOperationFeedback::kSignedSmall:
229 183609 : return CompareOperationHint::kSignedSmall;
230 : case CompareOperationFeedback::kNumber:
231 31641 : return CompareOperationHint::kNumber;
232 : case CompareOperationFeedback::kNumberOrOddball:
233 21 : return CompareOperationHint::kNumberOrOddball;
234 : case CompareOperationFeedback::kInternalizedString:
235 17032 : return CompareOperationHint::kInternalizedString;
236 : case CompareOperationFeedback::kString:
237 28065 : return CompareOperationHint::kString;
238 : case CompareOperationFeedback::kSymbol:
239 117 : return CompareOperationHint::kSymbol;
240 : case CompareOperationFeedback::kBigInt:
241 148 : return CompareOperationHint::kBigInt;
242 : case CompareOperationFeedback::kReceiver:
243 2109 : return CompareOperationHint::kReceiver;
244 : case CompareOperationFeedback::kReceiverOrNullOrUndefined:
245 347 : return CompareOperationHint::kReceiverOrNullOrUndefined;
246 : default:
247 73277 : return CompareOperationHint::kAny;
248 : }
249 : UNREACHABLE();
250 : }
251 :
252 : // Helper function to transform the feedback to ForInHint.
253 : ForInHint ForInHintFromFeedback(int type_feedback) {
254 : switch (type_feedback) {
255 : case ForInFeedback::kNone:
256 : return ForInHint::kNone;
257 : case ForInFeedback::kEnumCacheKeys:
258 : return ForInHint::kEnumCacheKeys;
259 : case ForInFeedback::kEnumCacheKeysAndIndices:
260 : return ForInHint::kEnumCacheKeysAndIndices;
261 : default:
262 : return ForInHint::kAny;
263 : }
264 : UNREACHABLE();
265 : }
266 :
267 0 : void FeedbackVector::ComputeCounts(int* with_type_info, int* generic,
268 : int* vector_ic_count) {
269 : MaybeObject megamorphic_sentinel = MaybeObject::FromObject(
270 : *FeedbackVector::MegamorphicSentinel(GetIsolate()));
271 : int with = 0;
272 : int gen = 0;
273 : int total = 0;
274 0 : FeedbackMetadataIterator iter(metadata());
275 0 : while (iter.HasNext()) {
276 0 : FeedbackSlot slot = iter.Next();
277 : FeedbackSlotKind kind = iter.kind();
278 :
279 : MaybeObject const obj = Get(slot);
280 0 : AssertNoLegacyTypes(obj);
281 0 : switch (kind) {
282 : case FeedbackSlotKind::kCall:
283 : case FeedbackSlotKind::kLoadProperty:
284 : case FeedbackSlotKind::kLoadGlobalInsideTypeof:
285 : case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
286 : case FeedbackSlotKind::kLoadKeyed:
287 : case FeedbackSlotKind::kHasKeyed:
288 : case FeedbackSlotKind::kStoreNamedSloppy:
289 : case FeedbackSlotKind::kStoreNamedStrict:
290 : case FeedbackSlotKind::kStoreOwnNamed:
291 : case FeedbackSlotKind::kStoreGlobalSloppy:
292 : case FeedbackSlotKind::kStoreGlobalStrict:
293 : case FeedbackSlotKind::kStoreKeyedSloppy:
294 : case FeedbackSlotKind::kStoreKeyedStrict:
295 : case FeedbackSlotKind::kStoreInArrayLiteral:
296 : case FeedbackSlotKind::kStoreDataPropertyInLiteral:
297 : case FeedbackSlotKind::kTypeProfile: {
298 0 : HeapObject heap_object;
299 0 : if (obj->IsWeakOrCleared() ||
300 0 : (obj->GetHeapObjectIfStrong(&heap_object) &&
301 0 : (heap_object->IsWeakFixedArray() || heap_object->IsString()))) {
302 0 : with++;
303 0 : } else if (obj == megamorphic_sentinel) {
304 0 : gen++;
305 0 : with++;
306 : }
307 0 : total++;
308 : break;
309 : }
310 : case FeedbackSlotKind::kBinaryOp: {
311 : int const feedback = obj.ToSmi().value();
312 0 : BinaryOperationHint hint = BinaryOperationHintFromFeedback(feedback);
313 0 : if (hint == BinaryOperationHint::kAny) {
314 0 : gen++;
315 : }
316 0 : if (hint != BinaryOperationHint::kNone) {
317 0 : with++;
318 : }
319 0 : total++;
320 0 : break;
321 : }
322 : case FeedbackSlotKind::kCompareOp: {
323 : int const feedback = obj.ToSmi().value();
324 0 : CompareOperationHint hint = CompareOperationHintFromFeedback(feedback);
325 0 : if (hint == CompareOperationHint::kAny) {
326 0 : gen++;
327 : }
328 0 : if (hint != CompareOperationHint::kNone) {
329 0 : with++;
330 : }
331 0 : total++;
332 0 : break;
333 : }
334 : case FeedbackSlotKind::kForIn: {
335 : int const feedback = obj.ToSmi().value();
336 : ForInHint hint = ForInHintFromFeedback(feedback);
337 0 : if (hint == ForInHint::kAny) {
338 0 : gen++;
339 : }
340 0 : if (hint != ForInHint::kNone) {
341 0 : with++;
342 : }
343 0 : total++;
344 0 : break;
345 : }
346 : case FeedbackSlotKind::kInstanceOf: {
347 0 : if (obj->IsWeakOrCleared()) {
348 0 : with++;
349 0 : } else if (obj == megamorphic_sentinel) {
350 0 : gen++;
351 0 : with++;
352 : }
353 0 : total++;
354 0 : break;
355 : }
356 : case FeedbackSlotKind::kLiteral:
357 : case FeedbackSlotKind::kCloneObject:
358 : break;
359 : case FeedbackSlotKind::kInvalid:
360 : case FeedbackSlotKind::kKindsNumber:
361 0 : UNREACHABLE();
362 : break;
363 : }
364 : }
365 :
366 0 : *with_type_info = with;
367 0 : *generic = gen;
368 0 : *vector_ic_count = total;
369 0 : }
370 :
371 1848 : Handle<Symbol> FeedbackVector::UninitializedSentinel(Isolate* isolate) {
372 1848 : return isolate->factory()->uninitialized_symbol();
373 : }
374 :
375 : Handle<Symbol> FeedbackVector::GenericSentinel(Isolate* isolate) {
376 : return isolate->factory()->generic_symbol();
377 : }
378 :
379 4368 : Handle<Symbol> FeedbackVector::MegamorphicSentinel(Isolate* isolate) {
380 4368 : return isolate->factory()->megamorphic_symbol();
381 : }
382 :
383 : Handle<Symbol> FeedbackVector::PremonomorphicSentinel(Isolate* isolate) {
384 : return isolate->factory()->premonomorphic_symbol();
385 : }
386 :
387 : Symbol FeedbackVector::RawUninitializedSentinel(Isolate* isolate) {
388 : return ReadOnlyRoots(isolate).uninitialized_symbol();
389 : }
390 :
391 : bool FeedbackMetadataIterator::HasNext() const {
392 : return next_slot_.ToInt() < metadata()->slot_count();
393 : }
394 :
395 81361 : FeedbackSlot FeedbackMetadataIterator::Next() {
396 : DCHECK(HasNext());
397 81361 : cur_slot_ = next_slot_;
398 81361 : slot_kind_ = metadata()->GetKind(cur_slot_);
399 81361 : next_slot_ = FeedbackSlot(next_slot_.ToInt() + entry_size());
400 81361 : return cur_slot_;
401 : }
402 :
403 : int FeedbackMetadataIterator::entry_size() const {
404 81361 : return FeedbackMetadata::GetSlotSize(kind());
405 : }
406 :
407 17497485 : MaybeObject FeedbackNexus::GetFeedback() const {
408 : MaybeObject feedback = vector()->Get(slot());
409 413684 : FeedbackVector::AssertNoLegacyTypes(feedback);
410 17497492 : return feedback;
411 : }
412 :
413 7768770 : MaybeObject FeedbackNexus::GetFeedbackExtra() const {
414 : #ifdef DEBUG
415 : FeedbackSlotKind kind = vector()->GetKind(slot());
416 : DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
417 : #endif
418 : int extra_index = vector()->GetIndex(slot()) + 1;
419 7768770 : return vector()->get(extra_index);
420 : }
421 :
422 : void FeedbackNexus::SetFeedback(Object feedback, WriteBarrierMode mode) {
423 1015473 : SetFeedback(MaybeObject::FromObject(feedback));
424 : }
425 :
426 8718028 : void FeedbackNexus::SetFeedback(MaybeObject feedback, WriteBarrierMode mode) {
427 : FeedbackVector::AssertNoLegacyTypes(feedback);
428 17436064 : vector()->Set(slot(), feedback, mode);
429 8718036 : }
430 :
431 6069672 : void FeedbackNexus::SetFeedbackExtra(Object feedback_extra,
432 : WriteBarrierMode mode) {
433 : #ifdef DEBUG
434 : FeedbackSlotKind kind = vector()->GetKind(slot());
435 : DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
436 : FeedbackVector::AssertNoLegacyTypes(MaybeObject::FromObject(feedback_extra));
437 : #endif
438 6069672 : int index = vector()->GetIndex(slot()) + 1;
439 6069672 : vector()->set(index, MaybeObject::FromObject(feedback_extra), mode);
440 6069670 : }
441 :
442 2655954 : void FeedbackNexus::SetFeedbackExtra(MaybeObject feedback_extra,
443 : WriteBarrierMode mode) {
444 : #ifdef DEBUG
445 : FeedbackVector::AssertNoLegacyTypes(feedback_extra);
446 : #endif
447 2655954 : int index = vector()->GetIndex(slot()) + 1;
448 2655954 : vector()->set(index, feedback_extra, mode);
449 2655953 : }
450 :
451 : Isolate* FeedbackNexus::GetIsolate() const { return vector()->GetIsolate(); }
452 : } // namespace internal
453 : } // namespace v8
454 :
455 : #include "src/objects/object-macros-undef.h"
456 :
457 : #endif // V8_FEEDBACK_VECTOR_INL_H_
|