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 7952307 : INT32_ACCESSORS(FeedbackMetadata, slot_count, kSlotCountOffset)
36 :
37 4715598 : INT32_ACCESSORS(FeedbackMetadata, closure_feedback_cell_count,
38 : kFeedbackCellCountOffset)
39 :
40 : int32_t FeedbackMetadata::synchronized_slot_count() const {
41 5361501 : return base::Acquire_Load(reinterpret_cast<const base::Atomic32*>(
42 5361501 : FIELD_ADDR(*this, kSlotCountOffset)));
43 : }
44 :
45 : int32_t FeedbackMetadata::get(int index) const {
46 : DCHECK(index >= 0 && index < length());
47 69959508 : int offset = kHeaderSize + index * kInt32Size;
48 69959928 : 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 25982185 : 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 35711394 : 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 30314617 : return 2;
90 :
91 : case FeedbackSlotKind::kInvalid:
92 : case FeedbackSlotKind::kKindsNumber:
93 0 : UNREACHABLE();
94 : break;
95 : }
96 : return 1;
97 : }
98 :
99 788051 : Handle<FeedbackCell> ClosureFeedbackCellArray::GetFeedbackCell(int index) {
100 788051 : return handle(FeedbackCell::cast(get(index)), GetIsolate());
101 : }
102 :
103 38496293 : ACCESSORS(FeedbackVector, shared_function_info, SharedFunctionInfo,
104 : kSharedFunctionInfoOffset)
105 34799437 : WEAK_ACCESSORS(FeedbackVector, optimized_code_weak_or_smi, kOptimizedCodeOffset)
106 16110368 : ACCESSORS(FeedbackVector, closure_feedback_cell_array, ClosureFeedbackCellArray,
107 : kClosureFeedbackCellArrayOffset)
108 16070297 : INT32_ACCESSORS(FeedbackVector, length, kLengthOffset)
109 3642269 : INT32_ACCESSORS(FeedbackVector, invocation_count, kInvocationCountOffset)
110 7128080 : INT32_ACCESSORS(FeedbackVector, profiler_ticks, kProfilerTicksOffset)
111 3168501 : 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 33206 : if (count < std::numeric_limits<int32_t>::max()) {
124 33206 : 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 7384824 : 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 1515974 : 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 489609 : bool FeedbackVector::has_optimization_marker() const {
147 979217 : return optimization_marker() != OptimizationMarker::kLogFirstExecution &&
148 489609 : 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 25957572 : int offset = kFeedbackSlotsOffset + index * kTaggedSize;
166 25957602 : 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 441931 : ClosureFeedbackCellArray::cast(closure_feedback_cell_array());
173 441931 : return cell_array->GetFeedbackCell(index);
174 : }
175 :
176 : void FeedbackVector::Set(FeedbackSlot slot, MaybeObject value,
177 : WriteBarrierMode mode) {
178 8791969 : set(GetIndex(slot), value, mode);
179 : }
180 :
181 56612253 : void FeedbackVector::set(int index, MaybeObject value, WriteBarrierMode mode) {
182 : DCHECK_GE(index, 0);
183 : DCHECK_LT(index, this->length());
184 56612253 : int offset = kFeedbackSlotsOffset + index * kTaggedSize;
185 56612253 : RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
186 79993647 : CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
187 56612280 : }
188 :
189 : void FeedbackVector::Set(FeedbackSlot slot, Object value,
190 : WriteBarrierMode mode) {
191 261548 : set(GetIndex(slot), MaybeObject::FromObject(value), mode);
192 : }
193 :
194 : void FeedbackVector::set(int index, Object value, WriteBarrierMode mode) {
195 32439954 : 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 : BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) {
204 : switch (type_feedback) {
205 : case BinaryOperationFeedback::kNone:
206 : return BinaryOperationHint::kNone;
207 : case BinaryOperationFeedback::kSignedSmall:
208 : return BinaryOperationHint::kSignedSmall;
209 : case BinaryOperationFeedback::kSignedSmallInputs:
210 : return BinaryOperationHint::kSignedSmallInputs;
211 : case BinaryOperationFeedback::kNumber:
212 : return BinaryOperationHint::kNumber;
213 : case BinaryOperationFeedback::kNumberOrOddball:
214 : return BinaryOperationHint::kNumberOrOddball;
215 : case BinaryOperationFeedback::kString:
216 : return BinaryOperationHint::kString;
217 : case BinaryOperationFeedback::kBigInt:
218 : return BinaryOperationHint::kBigInt;
219 : default:
220 : return BinaryOperationHint::kAny;
221 : }
222 : UNREACHABLE();
223 : }
224 :
225 : // Helper function to transform the feedback to CompareOperationHint.
226 527087 : CompareOperationHint CompareOperationHintFromFeedback(int type_feedback) {
227 527087 : switch (type_feedback) {
228 : case CompareOperationFeedback::kNone:
229 : return CompareOperationHint::kNone;
230 : case CompareOperationFeedback::kSignedSmall:
231 183891 : return CompareOperationHint::kSignedSmall;
232 : case CompareOperationFeedback::kNumber:
233 30509 : return CompareOperationHint::kNumber;
234 : case CompareOperationFeedback::kNumberOrOddball:
235 21 : return CompareOperationHint::kNumberOrOddball;
236 : case CompareOperationFeedback::kInternalizedString:
237 16908 : return CompareOperationHint::kInternalizedString;
238 : case CompareOperationFeedback::kString:
239 27975 : return CompareOperationHint::kString;
240 : case CompareOperationFeedback::kSymbol:
241 117 : return CompareOperationHint::kSymbol;
242 : case CompareOperationFeedback::kBigInt:
243 148 : return CompareOperationHint::kBigInt;
244 : case CompareOperationFeedback::kReceiver:
245 2113 : return CompareOperationHint::kReceiver;
246 : case CompareOperationFeedback::kReceiverOrNullOrUndefined:
247 347 : return CompareOperationHint::kReceiverOrNullOrUndefined;
248 : default:
249 73009 : return CompareOperationHint::kAny;
250 : }
251 : UNREACHABLE();
252 : }
253 :
254 : // Helper function to transform the feedback to ForInHint.
255 : ForInHint ForInHintFromFeedback(int type_feedback) {
256 : switch (type_feedback) {
257 : case ForInFeedback::kNone:
258 : return ForInHint::kNone;
259 : case ForInFeedback::kEnumCacheKeys:
260 : return ForInHint::kEnumCacheKeys;
261 : case ForInFeedback::kEnumCacheKeysAndIndices:
262 : return ForInHint::kEnumCacheKeysAndIndices;
263 : default:
264 : return ForInHint::kAny;
265 : }
266 : UNREACHABLE();
267 : }
268 :
269 : Handle<Symbol> FeedbackVector::UninitializedSentinel(Isolate* isolate) {
270 : return isolate->factory()->uninitialized_symbol();
271 : }
272 :
273 : Handle<Symbol> FeedbackVector::GenericSentinel(Isolate* isolate) {
274 : return isolate->factory()->generic_symbol();
275 : }
276 :
277 : Handle<Symbol> FeedbackVector::MegamorphicSentinel(Isolate* isolate) {
278 : return isolate->factory()->megamorphic_symbol();
279 : }
280 :
281 : Handle<Symbol> FeedbackVector::PremonomorphicSentinel(Isolate* isolate) {
282 : return isolate->factory()->premonomorphic_symbol();
283 : }
284 :
285 : Symbol FeedbackVector::RawUninitializedSentinel(Isolate* isolate) {
286 : return ReadOnlyRoots(isolate).uninitialized_symbol();
287 : }
288 :
289 : bool FeedbackMetadataIterator::HasNext() const {
290 : return next_slot_.ToInt() < metadata()->slot_count();
291 : }
292 :
293 81358 : FeedbackSlot FeedbackMetadataIterator::Next() {
294 : DCHECK(HasNext());
295 81358 : cur_slot_ = next_slot_;
296 81358 : slot_kind_ = metadata()->GetKind(cur_slot_);
297 81358 : next_slot_ = FeedbackSlot(next_slot_.ToInt() + entry_size());
298 81358 : return cur_slot_;
299 : }
300 :
301 : int FeedbackMetadataIterator::entry_size() const {
302 81358 : return FeedbackMetadata::GetSlotSize(kind());
303 : }
304 :
305 17035450 : MaybeObject FeedbackNexus::GetFeedback() const {
306 : MaybeObject feedback = vector()->Get(slot());
307 415730 : FeedbackVector::AssertNoLegacyTypes(feedback);
308 17035450 : return feedback;
309 : }
310 :
311 7272443 : MaybeObject FeedbackNexus::GetFeedbackExtra() const {
312 : #ifdef DEBUG
313 : FeedbackSlotKind kind = vector()->GetKind(slot());
314 : DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
315 : #endif
316 : int extra_index = vector()->GetIndex(slot()) + 1;
317 7272443 : return vector()->get(extra_index);
318 : }
319 :
320 : void FeedbackNexus::SetFeedback(Object feedback, WriteBarrierMode mode) {
321 1011565 : SetFeedback(MaybeObject::FromObject(feedback));
322 : }
323 :
324 8791964 : void FeedbackNexus::SetFeedback(MaybeObject feedback, WriteBarrierMode mode) {
325 : FeedbackVector::AssertNoLegacyTypes(feedback);
326 17583946 : vector()->Set(slot(), feedback, mode);
327 8791982 : }
328 :
329 6132775 : void FeedbackNexus::SetFeedbackExtra(Object feedback_extra,
330 : WriteBarrierMode mode) {
331 : #ifdef DEBUG
332 : FeedbackSlotKind kind = vector()->GetKind(slot());
333 : DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
334 : FeedbackVector::AssertNoLegacyTypes(MaybeObject::FromObject(feedback_extra));
335 : #endif
336 6132775 : int index = vector()->GetIndex(slot()) + 1;
337 6132775 : vector()->set(index, MaybeObject::FromObject(feedback_extra), mode);
338 6132776 : }
339 :
340 2667005 : void FeedbackNexus::SetFeedbackExtra(MaybeObject feedback_extra,
341 : WriteBarrierMode mode) {
342 : #ifdef DEBUG
343 : FeedbackVector::AssertNoLegacyTypes(feedback_extra);
344 : #endif
345 2667005 : int index = vector()->GetIndex(slot()) + 1;
346 2667005 : vector()->set(index, feedback_extra, mode);
347 2666998 : }
348 :
349 : Isolate* FeedbackNexus::GetIsolate() const { return vector()->GetIsolate(); }
350 : } // namespace internal
351 : } // namespace v8
352 :
353 : #include "src/objects/object-macros-undef.h"
354 :
355 : #endif // V8_FEEDBACK_VECTOR_INL_H_
|