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/factory-inl.h"
9 : #include "src/feedback-vector.h"
10 : #include "src/globals.h"
11 : #include "src/heap/heap-inl.h"
12 : #include "src/heap/heap.h"
13 : #include "src/objects/shared-function-info.h"
14 :
15 : // Has to be the last include (doesn't have include guards):
16 : #include "src/objects/object-macros.h"
17 :
18 : namespace v8 {
19 : namespace internal {
20 :
21 : // static
22 : FeedbackMetadata* FeedbackMetadata::cast(Object* obj) {
23 : DCHECK(obj->IsFeedbackMetadata());
24 : return reinterpret_cast<FeedbackMetadata*>(obj);
25 : }
26 :
27 : bool FeedbackMetadata::is_empty() const {
28 400 : if (length() == 0) return true;
29 : return false;
30 : }
31 :
32 17230494 : int FeedbackMetadata::slot_count() const {
33 17230494 : if (length() == 0) return 0;
34 : DCHECK_GT(length(), kReservedIndexCount);
35 8608335 : return Smi::ToInt(get(kSlotsCountIndex));
36 : }
37 :
38 : // static
39 7442042 : FeedbackVector* FeedbackVector::cast(Object* obj) {
40 : DCHECK(obj->IsFeedbackVector());
41 7442042 : return reinterpret_cast<FeedbackVector*>(obj);
42 : }
43 :
44 69311119 : int FeedbackMetadata::GetSlotSize(FeedbackSlotKind kind) {
45 : switch (kind) {
46 : case FeedbackSlotKind::kForIn:
47 : case FeedbackSlotKind::kCompareOp:
48 : case FeedbackSlotKind::kBinaryOp:
49 : case FeedbackSlotKind::kLiteral:
50 : case FeedbackSlotKind::kCreateClosure:
51 : case FeedbackSlotKind::kTypeProfile:
52 : return 1;
53 :
54 : case FeedbackSlotKind::kCall:
55 : case FeedbackSlotKind::kLoadProperty:
56 : case FeedbackSlotKind::kLoadGlobalInsideTypeof:
57 : case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
58 : case FeedbackSlotKind::kLoadKeyed:
59 : case FeedbackSlotKind::kStoreNamedSloppy:
60 : case FeedbackSlotKind::kStoreNamedStrict:
61 : case FeedbackSlotKind::kStoreOwnNamed:
62 : case FeedbackSlotKind::kStoreGlobalSloppy:
63 : case FeedbackSlotKind::kStoreGlobalStrict:
64 : case FeedbackSlotKind::kStoreKeyedSloppy:
65 : case FeedbackSlotKind::kStoreKeyedStrict:
66 : case FeedbackSlotKind::kStoreDataPropertyInLiteral:
67 45339234 : return 2;
68 :
69 : case FeedbackSlotKind::kInvalid:
70 : case FeedbackSlotKind::kKindsNumber:
71 0 : UNREACHABLE();
72 : break;
73 : }
74 : return 1;
75 : }
76 :
77 52795149 : ACCESSORS(FeedbackVector, shared_function_info, SharedFunctionInfo,
78 : kSharedFunctionInfoOffset)
79 53105547 : ACCESSORS(FeedbackVector, optimized_code_cell, Object, kOptimizedCodeOffset)
80 39547817 : INT32_ACCESSORS(FeedbackVector, length, kLengthOffset)
81 6970041 : INT32_ACCESSORS(FeedbackVector, invocation_count, kInvocationCountOffset)
82 12812087 : INT32_ACCESSORS(FeedbackVector, profiler_ticks, kProfilerTicksOffset)
83 6398808 : INT32_ACCESSORS(FeedbackVector, deopt_count, kDeoptCountOffset)
84 :
85 9 : bool FeedbackVector::is_empty() const { return length() == 0; }
86 :
87 0 : FeedbackMetadata* FeedbackVector::metadata() const {
88 0 : return shared_function_info()->feedback_metadata();
89 : }
90 :
91 : void FeedbackVector::clear_invocation_count() { set_invocation_count(0); }
92 :
93 : void FeedbackVector::increment_deopt_count() {
94 : int count = deopt_count();
95 34444 : if (count < std::numeric_limits<int32_t>::max()) {
96 34444 : set_deopt_count(count + 1);
97 : }
98 : }
99 :
100 : Code* FeedbackVector::optimized_code() const {
101 : Object* slot = optimized_code_cell();
102 10934604 : if (slot->IsSmi()) return nullptr;
103 : WeakCell* cell = WeakCell::cast(slot);
104 1051172 : return cell->cleared() ? nullptr : Code::cast(cell->value());
105 : }
106 :
107 : OptimizationMarker FeedbackVector::optimization_marker() const {
108 : Object* slot = optimized_code_cell();
109 712989 : if (!slot->IsSmi()) return OptimizationMarker::kNone;
110 : Smi* value = Smi::cast(slot);
111 : return static_cast<OptimizationMarker>(value->value());
112 : }
113 :
114 : bool FeedbackVector::has_optimized_code() const {
115 : return optimized_code() != nullptr;
116 : }
117 :
118 : bool FeedbackVector::has_optimization_marker() const {
119 : return optimization_marker() != OptimizationMarker::kNone;
120 : }
121 :
122 : // Conversion from an integer index to either a slot or an ic slot.
123 : // static
124 17899423 : FeedbackSlot FeedbackVector::ToSlot(int index) {
125 : DCHECK_GE(index, 0);
126 17899423 : return FeedbackSlot(index);
127 : }
128 :
129 7334287 : Object* FeedbackVector::Get(FeedbackSlot slot) const {
130 7334287 : return get(GetIndex(slot));
131 : }
132 :
133 : Object* FeedbackVector::get(int index) const {
134 : DCHECK_GE(index, 0);
135 : DCHECK_LT(index, this->length());
136 28722807 : int offset = kFeedbackSlotsOffset + index * kPointerSize;
137 57445680 : return RELAXED_READ_FIELD(this, offset);
138 : }
139 :
140 15754 : void FeedbackVector::Set(FeedbackSlot slot, Object* value,
141 : WriteBarrierMode mode) {
142 10160322 : set(GetIndex(slot), value, mode);
143 15754 : }
144 :
145 69945680 : void FeedbackVector::set(int index, Object* value, WriteBarrierMode mode) {
146 : DCHECK_GE(index, 0);
147 : DCHECK_LT(index, this->length());
148 69945680 : int offset = kFeedbackSlotsOffset + index * kPointerSize;
149 69945680 : RELAXED_WRITE_FIELD(this, offset, value);
150 99638277 : CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
151 69945682 : }
152 :
153 : inline Object** FeedbackVector::slots_start() {
154 : return HeapObject::RawField(this, kFeedbackSlotsOffset);
155 : }
156 :
157 : // Helper function to transform the feedback to BinaryOperationHint.
158 : BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) {
159 : switch (type_feedback) {
160 : case BinaryOperationFeedback::kNone:
161 : return BinaryOperationHint::kNone;
162 : case BinaryOperationFeedback::kSignedSmall:
163 : return BinaryOperationHint::kSignedSmall;
164 : case BinaryOperationFeedback::kSignedSmallInputs:
165 : return BinaryOperationHint::kSignedSmallInputs;
166 : case BinaryOperationFeedback::kNumber:
167 : return BinaryOperationHint::kNumber;
168 : case BinaryOperationFeedback::kNumberOrOddball:
169 : return BinaryOperationHint::kNumberOrOddball;
170 : case BinaryOperationFeedback::kString:
171 : return BinaryOperationHint::kString;
172 : case BinaryOperationFeedback::kBigInt:
173 : // TODO(jarin/jkummerow/neis): Support BigInts in TF.
174 : // Fall through for now.
175 : case BinaryOperationFeedback::kAny:
176 : default:
177 : return BinaryOperationHint::kAny;
178 : }
179 : UNREACHABLE();
180 : }
181 :
182 : // Helper function to transform the feedback to CompareOperationHint.
183 : CompareOperationHint CompareOperationHintFromFeedback(int type_feedback) {
184 : switch (type_feedback) {
185 : case CompareOperationFeedback::kNone:
186 : return CompareOperationHint::kNone;
187 : case CompareOperationFeedback::kSignedSmall:
188 : return CompareOperationHint::kSignedSmall;
189 : case CompareOperationFeedback::kNumber:
190 : return CompareOperationHint::kNumber;
191 : case CompareOperationFeedback::kNumberOrOddball:
192 : return CompareOperationHint::kNumberOrOddball;
193 : case CompareOperationFeedback::kInternalizedString:
194 : return CompareOperationHint::kInternalizedString;
195 : case CompareOperationFeedback::kString:
196 : return CompareOperationHint::kString;
197 : case CompareOperationFeedback::kSymbol:
198 : return CompareOperationHint::kSymbol;
199 : case CompareOperationFeedback::kReceiver:
200 : return CompareOperationHint::kReceiver;
201 : default:
202 : return CompareOperationHint::kAny;
203 : }
204 : UNREACHABLE();
205 : }
206 :
207 : // Helper function to transform the feedback to ForInHint.
208 : ForInHint ForInHintFromFeedback(int type_feedback) {
209 : switch (type_feedback) {
210 : case ForInFeedback::kNone:
211 : return ForInHint::kNone;
212 : case ForInFeedback::kEnumCacheKeys:
213 : return ForInHint::kEnumCacheKeys;
214 : case ForInFeedback::kEnumCacheKeysAndIndices:
215 : return ForInHint::kEnumCacheKeysAndIndices;
216 : default:
217 : return ForInHint::kAny;
218 : }
219 : UNREACHABLE();
220 : }
221 :
222 0 : void FeedbackVector::ComputeCounts(int* with_type_info, int* generic,
223 : int* vector_ic_count) {
224 : Object* megamorphic_sentinel =
225 : *FeedbackVector::MegamorphicSentinel(GetIsolate());
226 : int with = 0;
227 : int gen = 0;
228 : int total = 0;
229 : FeedbackMetadataIterator iter(metadata());
230 0 : while (iter.HasNext()) {
231 0 : FeedbackSlot slot = iter.Next();
232 0 : FeedbackSlotKind kind = iter.kind();
233 :
234 : Object* const obj = Get(slot);
235 0 : switch (kind) {
236 : case FeedbackSlotKind::kCall:
237 : case FeedbackSlotKind::kLoadProperty:
238 : case FeedbackSlotKind::kLoadGlobalInsideTypeof:
239 : case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
240 : case FeedbackSlotKind::kLoadKeyed:
241 : case FeedbackSlotKind::kStoreNamedSloppy:
242 : case FeedbackSlotKind::kStoreNamedStrict:
243 : case FeedbackSlotKind::kStoreOwnNamed:
244 : case FeedbackSlotKind::kStoreGlobalSloppy:
245 : case FeedbackSlotKind::kStoreGlobalStrict:
246 : case FeedbackSlotKind::kStoreKeyedSloppy:
247 : case FeedbackSlotKind::kStoreKeyedStrict:
248 : case FeedbackSlotKind::kStoreDataPropertyInLiteral:
249 : case FeedbackSlotKind::kTypeProfile: {
250 0 : if (obj->IsWeakCell() || obj->IsFixedArray() || obj->IsString()) {
251 0 : with++;
252 0 : } else if (obj == megamorphic_sentinel) {
253 0 : gen++;
254 0 : with++;
255 : }
256 0 : total++;
257 0 : break;
258 : }
259 : case FeedbackSlotKind::kBinaryOp: {
260 : int const feedback = Smi::ToInt(obj);
261 : BinaryOperationHint hint = BinaryOperationHintFromFeedback(feedback);
262 0 : if (hint == BinaryOperationHint::kAny) {
263 0 : gen++;
264 : }
265 0 : if (hint != BinaryOperationHint::kNone) {
266 0 : with++;
267 : }
268 0 : total++;
269 0 : break;
270 : }
271 : case FeedbackSlotKind::kCompareOp: {
272 : int const feedback = Smi::ToInt(obj);
273 : CompareOperationHint hint =
274 : CompareOperationHintFromFeedback(feedback);
275 0 : if (hint == CompareOperationHint::kAny) {
276 0 : gen++;
277 : }
278 0 : if (hint != CompareOperationHint::kNone) {
279 0 : with++;
280 : }
281 0 : total++;
282 0 : break;
283 : }
284 : case FeedbackSlotKind::kForIn: {
285 : int const feedback = Smi::ToInt(obj);
286 : ForInHint hint = ForInHintFromFeedback(feedback);
287 0 : if (hint == ForInHint::kAny) {
288 0 : gen++;
289 : }
290 0 : if (hint != ForInHint::kNone) {
291 0 : with++;
292 : }
293 0 : total++;
294 0 : break;
295 : }
296 : case FeedbackSlotKind::kCreateClosure:
297 : case FeedbackSlotKind::kLiteral:
298 : break;
299 : case FeedbackSlotKind::kInvalid:
300 : case FeedbackSlotKind::kKindsNumber:
301 0 : UNREACHABLE();
302 : break;
303 : }
304 : }
305 :
306 0 : *with_type_info = with;
307 0 : *generic = gen;
308 0 : *vector_ic_count = total;
309 0 : }
310 :
311 : Handle<Symbol> FeedbackVector::UninitializedSentinel(Isolate* isolate) {
312 : return isolate->factory()->uninitialized_symbol();
313 : }
314 :
315 : Handle<Symbol> FeedbackVector::GenericSentinel(Isolate* isolate) {
316 : return isolate->factory()->generic_symbol();
317 : }
318 :
319 : Handle<Symbol> FeedbackVector::MegamorphicSentinel(Isolate* isolate) {
320 : return isolate->factory()->megamorphic_symbol();
321 : }
322 :
323 : Handle<Symbol> FeedbackVector::PremonomorphicSentinel(Isolate* isolate) {
324 : return isolate->factory()->premonomorphic_symbol();
325 : }
326 :
327 : Symbol* FeedbackVector::RawUninitializedSentinel(Isolate* isolate) {
328 67308 : return isolate->heap()->uninitialized_symbol();
329 : }
330 :
331 301066 : bool FeedbackMetadataIterator::HasNext() const {
332 301066 : return next_slot_.ToInt() < metadata()->slot_count();
333 : }
334 :
335 233655 : FeedbackSlot FeedbackMetadataIterator::Next() {
336 : DCHECK(HasNext());
337 233655 : cur_slot_ = next_slot_;
338 233655 : slot_kind_ = metadata()->GetKind(cur_slot_);
339 233655 : next_slot_ = FeedbackSlot(next_slot_.ToInt() + entry_size());
340 233655 : return cur_slot_;
341 : }
342 :
343 : int FeedbackMetadataIterator::entry_size() const {
344 233655 : return FeedbackMetadata::GetSlotSize(kind());
345 : }
346 :
347 31697392 : Object* FeedbackNexus::GetFeedback() const { return vector()->Get(slot()); }
348 :
349 2988609 : Object* FeedbackNexus::GetFeedbackExtra() const {
350 : #ifdef DEBUG
351 : FeedbackSlotKind kind = vector()->GetKind(slot());
352 : DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
353 : #endif
354 : int extra_index = vector()->GetIndex(slot()) + 1;
355 2988609 : return vector()->get(extra_index);
356 : }
357 :
358 9535376 : void FeedbackNexus::SetFeedback(Object* feedback, WriteBarrierMode mode) {
359 : vector()->Set(slot(), feedback, mode);
360 9535379 : }
361 :
362 9539671 : void FeedbackNexus::SetFeedbackExtra(Object* feedback_extra,
363 : WriteBarrierMode mode) {
364 : #ifdef DEBUG
365 : FeedbackSlotKind kind = vector()->GetKind(slot());
366 : DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
367 : #endif
368 9539671 : int index = vector()->GetIndex(slot()) + 1;
369 9539671 : vector()->set(index, feedback_extra, mode);
370 9539670 : }
371 :
372 : Isolate* FeedbackNexus::GetIsolate() const { return vector()->GetIsolate(); }
373 : } // namespace internal
374 : } // namespace v8
375 :
376 : #include "src/objects/object-macros-undef.h"
377 :
378 : #endif // V8_FEEDBACK_VECTOR_INL_H_
|