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 : OBJECT_CONSTRUCTORS_IMPL(ClosureFeedbackCellArray, FixedArray)
27 :
28 : NEVER_READ_ONLY_SPACE_IMPL(FeedbackVector)
29 : NEVER_READ_ONLY_SPACE_IMPL(ClosureFeedbackCellArray)
30 :
31 : CAST_ACCESSOR(FeedbackVector)
32 : CAST_ACCESSOR(FeedbackMetadata)
33 : CAST_ACCESSOR(ClosureFeedbackCellArray)
34 :
35 7948921 : INT32_ACCESSORS(FeedbackMetadata, slot_count, kSlotCountOffset)
36 :
37 4714486 : INT32_ACCESSORS(FeedbackMetadata, closure_feedback_cell_count,
38 : kFeedbackCellCountOffset)
39 :
40 : int32_t FeedbackMetadata::synchronized_slot_count() const {
41 5628074 : return base::Acquire_Load(reinterpret_cast<const base::Atomic32*>(
42 5628074 : FIELD_ADDR(*this, kSlotCountOffset)));
43 : }
44 :
45 : int32_t FeedbackMetadata::get(int index) const {
46 : DCHECK(index >= 0 && index < length());
47 70098832 : int offset = kHeaderSize + index * kInt32Size;
48 70099252 : return READ_INT32_FIELD(*this, offset);
49 : }
50 :
51 : void FeedbackMetadata::set(int index, int32_t value) {
52 : DCHECK(index >= 0 && index < length());
53 : int offset = kHeaderSize + index * kInt32Size;
54 26069343 : WRITE_INT32_FIELD(*this, offset, value);
55 : }
56 :
57 : bool FeedbackMetadata::is_empty() const { return slot_count() == 0; }
58 :
59 : int FeedbackMetadata::length() const {
60 : return FeedbackMetadata::length(slot_count());
61 : }
62 :
63 35772261 : int FeedbackMetadata::GetSlotSize(FeedbackSlotKind kind) {
64 : switch (kind) {
65 : case FeedbackSlotKind::kForIn:
66 : case FeedbackSlotKind::kInstanceOf:
67 : case FeedbackSlotKind::kCompareOp:
68 : case FeedbackSlotKind::kBinaryOp:
69 : case FeedbackSlotKind::kLiteral:
70 : case FeedbackSlotKind::kTypeProfile:
71 : return 1;
72 :
73 : case FeedbackSlotKind::kCall:
74 : case FeedbackSlotKind::kCloneObject:
75 : case FeedbackSlotKind::kLoadProperty:
76 : case FeedbackSlotKind::kLoadGlobalInsideTypeof:
77 : case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
78 : case FeedbackSlotKind::kLoadKeyed:
79 : case FeedbackSlotKind::kHasKeyed:
80 : case FeedbackSlotKind::kStoreNamedSloppy:
81 : case FeedbackSlotKind::kStoreNamedStrict:
82 : case FeedbackSlotKind::kStoreOwnNamed:
83 : case FeedbackSlotKind::kStoreGlobalSloppy:
84 : case FeedbackSlotKind::kStoreGlobalStrict:
85 : case FeedbackSlotKind::kStoreKeyedSloppy:
86 : case FeedbackSlotKind::kStoreKeyedStrict:
87 : case FeedbackSlotKind::kStoreInArrayLiteral:
88 : case FeedbackSlotKind::kStoreDataPropertyInLiteral:
89 30365560 : return 2;
90 :
91 : case FeedbackSlotKind::kInvalid:
92 : case FeedbackSlotKind::kKindsNumber:
93 0 : UNREACHABLE();
94 : break;
95 : }
96 : return 1;
97 : }
98 :
99 787792 : Handle<FeedbackCell> ClosureFeedbackCellArray::GetFeedbackCell(int index) {
100 787792 : return handle(FeedbackCell::cast(get(index)), GetIsolate());
101 : }
102 :
103 38523151 : ACCESSORS(FeedbackVector, shared_function_info, SharedFunctionInfo,
104 : kSharedFunctionInfoOffset)
105 34813709 : WEAK_ACCESSORS(FeedbackVector, optimized_code_weak_or_smi, kOptimizedCodeOffset)
106 16098830 : ACCESSORS(FeedbackVector, closure_feedback_cell_array, ClosureFeedbackCellArray,
107 : kClosureFeedbackCellArrayOffset)
108 24378508 : INT32_ACCESSORS(FeedbackVector, length, kLengthOffset)
109 3641095 : INT32_ACCESSORS(FeedbackVector, invocation_count, kInvocationCountOffset)
110 7139468 : INT32_ACCESSORS(FeedbackVector, profiler_ticks, kProfilerTicksOffset)
111 3165931 : INT32_ACCESSORS(FeedbackVector, deopt_count, kDeoptCountOffset)
112 :
113 7 : bool FeedbackVector::is_empty() const { return length() == 0; }
114 :
115 : FeedbackMetadata FeedbackVector::metadata() const {
116 : return shared_function_info()->feedback_metadata();
117 : }
118 :
119 : void FeedbackVector::clear_invocation_count() { set_invocation_count(0); }
120 :
121 : void FeedbackVector::increment_deopt_count() {
122 : int count = deopt_count();
123 33061 : if (count < std::numeric_limits<int32_t>::max()) {
124 33061 : set_deopt_count(count + 1);
125 : }
126 : }
127 :
128 : Code FeedbackVector::optimized_code() const {
129 : MaybeObject slot = optimized_code_weak_or_smi();
130 : DCHECK(slot->IsSmi() || slot->IsWeakOrCleared());
131 : HeapObject heap_object;
132 7389885 : return slot->GetHeapObject(&heap_object) ? Code::cast(heap_object) : Code();
133 : }
134 :
135 : OptimizationMarker FeedbackVector::optimization_marker() const {
136 : MaybeObject slot = optimized_code_weak_or_smi();
137 : Smi value;
138 1516095 : if (!slot->ToSmi(&value)) return OptimizationMarker::kNone;
139 : return static_cast<OptimizationMarker>(value->value());
140 : }
141 :
142 : bool FeedbackVector::has_optimized_code() const {
143 : return !optimized_code().is_null();
144 : }
145 :
146 489391 : bool FeedbackVector::has_optimization_marker() const {
147 978781 : return optimization_marker() != OptimizationMarker::kLogFirstExecution &&
148 489391 : optimization_marker() != OptimizationMarker::kNone;
149 : }
150 :
151 : // Conversion from an integer index to either a slot or an ic slot.
152 : // static
153 : FeedbackSlot FeedbackVector::ToSlot(int index) {
154 : DCHECK_GE(index, 0);
155 : return FeedbackSlot(index);
156 : }
157 :
158 : MaybeObject FeedbackVector::Get(FeedbackSlot slot) const {
159 : return get(GetIndex(slot));
160 : }
161 :
162 : MaybeObject FeedbackVector::get(int index) const {
163 : DCHECK_GE(index, 0);
164 : DCHECK_LT(index, this->length());
165 26020272 : int offset = kFeedbackSlotsOffset + index * kTaggedSize;
166 26020302 : return RELAXED_READ_WEAK_FIELD(*this, offset);
167 : }
168 :
169 : Handle<FeedbackCell> FeedbackVector::GetClosureFeedbackCell(int index) const {
170 : DCHECK_GE(index, 0);
171 : ClosureFeedbackCellArray cell_array =
172 441820 : ClosureFeedbackCellArray::cast(closure_feedback_cell_array());
173 441820 : return cell_array->GetFeedbackCell(index);
174 : }
175 :
176 : void FeedbackVector::Set(FeedbackSlot slot, MaybeObject value,
177 : WriteBarrierMode mode) {
178 8804944 : set(GetIndex(slot), value, mode);
179 : }
180 :
181 56663742 : void FeedbackVector::set(int index, MaybeObject value, WriteBarrierMode mode) {
182 : DCHECK_GE(index, 0);
183 : DCHECK_LT(index, this->length());
184 56663742 : int offset = kFeedbackSlotsOffset + index * kTaggedSize;
185 56663742 : RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
186 80095370 : CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
187 56663745 : }
188 :
189 : void FeedbackVector::Set(FeedbackSlot slot, Object value,
190 : WriteBarrierMode mode) {
191 261827 : set(GetIndex(slot), MaybeObject::FromObject(value), mode);
192 : }
193 :
194 : void FeedbackVector::set(int index, Object value, WriteBarrierMode mode) {
195 32464798 : set(index, MaybeObject::FromObject(value), mode);
196 : }
197 :
198 : inline MaybeObjectSlot FeedbackVector::slots_start() {
199 : return RawMaybeWeakField(kFeedbackSlotsOffset);
200 : }
201 :
202 : // Helper function to transform the feedback to BinaryOperationHint.
203 945973 : BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) {
204 945973 : switch (type_feedback) {
205 : case BinaryOperationFeedback::kNone:
206 : return BinaryOperationHint::kNone;
207 : case BinaryOperationFeedback::kSignedSmall:
208 415290 : return BinaryOperationHint::kSignedSmall;
209 : case BinaryOperationFeedback::kSignedSmallInputs:
210 28039 : return BinaryOperationHint::kSignedSmallInputs;
211 : case BinaryOperationFeedback::kNumber:
212 204261 : return BinaryOperationHint::kNumber;
213 : case BinaryOperationFeedback::kNumberOrOddball:
214 6564 : return BinaryOperationHint::kNumberOrOddball;
215 : case BinaryOperationFeedback::kConsOneByteString:
216 6083 : return BinaryOperationHint::kConsOneByteString;
217 : case BinaryOperationFeedback::kConsTwoByteString:
218 518 : return BinaryOperationHint::kConsTwoByteString;
219 : case BinaryOperationFeedback::kConsString:
220 54 : return BinaryOperationHint::kConsString;
221 : case BinaryOperationFeedback::kString:
222 13174 : return BinaryOperationHint::kString;
223 : case BinaryOperationFeedback::kBigInt:
224 917 : return BinaryOperationHint::kBigInt;
225 : default:
226 10166 : return BinaryOperationHint::kAny;
227 : }
228 : UNREACHABLE();
229 : }
230 :
231 : // Helper function to transform the feedback to CompareOperationHint.
232 526602 : CompareOperationHint CompareOperationHintFromFeedback(int type_feedback) {
233 526602 : switch (type_feedback) {
234 : case CompareOperationFeedback::kNone:
235 : return CompareOperationHint::kNone;
236 : case CompareOperationFeedback::kSignedSmall:
237 183030 : return CompareOperationHint::kSignedSmall;
238 : case CompareOperationFeedback::kNumber:
239 30544 : return CompareOperationHint::kNumber;
240 : case CompareOperationFeedback::kNumberOrOddball:
241 21 : return CompareOperationHint::kNumberOrOddball;
242 : case CompareOperationFeedback::kInternalizedString:
243 16985 : return CompareOperationHint::kInternalizedString;
244 : case CompareOperationFeedback::kString:
245 28050 : return CompareOperationHint::kString;
246 : case CompareOperationFeedback::kSymbol:
247 117 : return CompareOperationHint::kSymbol;
248 : case CompareOperationFeedback::kBigInt:
249 148 : return CompareOperationHint::kBigInt;
250 : case CompareOperationFeedback::kReceiver:
251 2103 : return CompareOperationHint::kReceiver;
252 : case CompareOperationFeedback::kReceiverOrNullOrUndefined:
253 347 : return CompareOperationHint::kReceiverOrNullOrUndefined;
254 : default:
255 73126 : return CompareOperationHint::kAny;
256 : }
257 : UNREACHABLE();
258 : }
259 :
260 : // Helper function to transform the feedback to ForInHint.
261 : ForInHint ForInHintFromFeedback(int type_feedback) {
262 : switch (type_feedback) {
263 : case ForInFeedback::kNone:
264 : return ForInHint::kNone;
265 : case ForInFeedback::kEnumCacheKeys:
266 : return ForInHint::kEnumCacheKeys;
267 : case ForInFeedback::kEnumCacheKeysAndIndices:
268 : return ForInHint::kEnumCacheKeysAndIndices;
269 : default:
270 : return ForInHint::kAny;
271 : }
272 : UNREACHABLE();
273 : }
274 :
275 : Handle<Symbol> FeedbackVector::UninitializedSentinel(Isolate* isolate) {
276 : return isolate->factory()->uninitialized_symbol();
277 : }
278 :
279 : Handle<Symbol> FeedbackVector::GenericSentinel(Isolate* isolate) {
280 : return isolate->factory()->generic_symbol();
281 : }
282 :
283 : Handle<Symbol> FeedbackVector::MegamorphicSentinel(Isolate* isolate) {
284 : return isolate->factory()->megamorphic_symbol();
285 : }
286 :
287 : Handle<Symbol> FeedbackVector::PremonomorphicSentinel(Isolate* isolate) {
288 : return isolate->factory()->premonomorphic_symbol();
289 : }
290 :
291 : Symbol FeedbackVector::RawUninitializedSentinel(Isolate* isolate) {
292 : return ReadOnlyRoots(isolate).uninitialized_symbol();
293 : }
294 :
295 : bool FeedbackMetadataIterator::HasNext() const {
296 : return next_slot_.ToInt() < metadata()->slot_count();
297 : }
298 :
299 81358 : FeedbackSlot FeedbackMetadataIterator::Next() {
300 : DCHECK(HasNext());
301 81358 : cur_slot_ = next_slot_;
302 81358 : slot_kind_ = metadata()->GetKind(cur_slot_);
303 81358 : next_slot_ = FeedbackSlot(next_slot_.ToInt() + entry_size());
304 81358 : return cur_slot_;
305 : }
306 :
307 : int FeedbackMetadataIterator::entry_size() const {
308 81358 : return FeedbackMetadata::GetSlotSize(kind());
309 : }
310 :
311 17089398 : MaybeObject FeedbackNexus::GetFeedback() const {
312 : MaybeObject feedback = vector()->Get(slot());
313 418147 : FeedbackVector::AssertNoLegacyTypes(feedback);
314 17089398 : return feedback;
315 : }
316 :
317 7277347 : MaybeObject FeedbackNexus::GetFeedbackExtra() const {
318 : #ifdef DEBUG
319 : FeedbackSlotKind kind = vector()->GetKind(slot());
320 : DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
321 : #endif
322 : int extra_index = vector()->GetIndex(slot()) + 1;
323 7277347 : return vector()->get(extra_index);
324 : }
325 :
326 : void FeedbackNexus::SetFeedback(Object feedback, WriteBarrierMode mode) {
327 1013043 : SetFeedback(MaybeObject::FromObject(feedback));
328 : }
329 :
330 8804939 : void FeedbackNexus::SetFeedback(MaybeObject feedback, WriteBarrierMode mode) {
331 : FeedbackVector::AssertNoLegacyTypes(feedback);
332 17609885 : vector()->Set(slot(), feedback, mode);
333 8804946 : }
334 :
335 6133705 : void FeedbackNexus::SetFeedbackExtra(Object feedback_extra,
336 : WriteBarrierMode mode) {
337 : #ifdef DEBUG
338 : FeedbackSlotKind kind = vector()->GetKind(slot());
339 : DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
340 : FeedbackVector::AssertNoLegacyTypes(MaybeObject::FromObject(feedback_extra));
341 : #endif
342 6133705 : int index = vector()->GetIndex(slot()) + 1;
343 6133705 : vector()->set(index, MaybeObject::FromObject(feedback_extra), mode);
344 6133708 : }
345 :
346 2679047 : void FeedbackNexus::SetFeedbackExtra(MaybeObject feedback_extra,
347 : WriteBarrierMode mode) {
348 : #ifdef DEBUG
349 : FeedbackVector::AssertNoLegacyTypes(feedback_extra);
350 : #endif
351 2679047 : int index = vector()->GetIndex(slot()) + 1;
352 2679047 : vector()->set(index, feedback_extra, mode);
353 2679022 : }
354 :
355 : Isolate* FeedbackNexus::GetIsolate() const { return vector()->GetIsolate(); }
356 : } // namespace internal
357 : } // namespace v8
358 :
359 : #include "src/objects/object-macros-undef.h"
360 :
361 : #endif // V8_FEEDBACK_VECTOR_INL_H_
|