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
21namespace v8 {
22namespace internal {
23
24OBJECT_CONSTRUCTORS_IMPL(FeedbackVector, HeapObject)
25OBJECT_CONSTRUCTORS_IMPL(FeedbackMetadata, HeapObject)
26OBJECT_CONSTRUCTORS_IMPL(ClosureFeedbackCellArray, FixedArray)
27
28NEVER_READ_ONLY_SPACE_IMPL(FeedbackVector)
29NEVER_READ_ONLY_SPACE_IMPL(ClosureFeedbackCellArray)
30
31CAST_ACCESSOR(FeedbackVector)
32CAST_ACCESSOR(FeedbackMetadata)
33CAST_ACCESSOR(ClosureFeedbackCellArray)
34
35INT32_ACCESSORS(FeedbackMetadata, slot_count, kSlotCountOffset)
36
37INT32_ACCESSORS(FeedbackMetadata, closure_feedback_cell_count,
38 kFeedbackCellCountOffset)
39
40int32_t FeedbackMetadata::synchronized_slot_count() const {
41 return base::Acquire_Load(reinterpret_cast<const base::Atomic32*>(
42 FIELD_ADDR(*this, kSlotCountOffset)));
43}
44
45int32_t FeedbackMetadata::get(int index) const {
46 DCHECK(index >= 0 && index < length());
47 int offset = kHeaderSize + index * kInt32Size;
48 return READ_INT32_FIELD(*this, offset);
49}
50
51void FeedbackMetadata::set(int index, int32_t value) {
52 DCHECK(index >= 0 && index < length());
53 int offset = kHeaderSize + index * kInt32Size;
54 WRITE_INT32_FIELD(*this, offset, value);
55}
56
57bool FeedbackMetadata::is_empty() const { return slot_count() == 0; }
58
59int FeedbackMetadata::length() const {
60 return FeedbackMetadata::length(slot_count());
61}
62
63int 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 return 2;
90
91 case FeedbackSlotKind::kInvalid:
92 case FeedbackSlotKind::kKindsNumber:
93 UNREACHABLE();
94 break;
95 }
96 return 1;
97}
98
99Handle<FeedbackCell> ClosureFeedbackCellArray::GetFeedbackCell(int index) {
100 return handle(FeedbackCell::cast(get(index)), GetIsolate());
101}
102
103ACCESSORS(FeedbackVector, shared_function_info, SharedFunctionInfo,
104 kSharedFunctionInfoOffset)
105WEAK_ACCESSORS(FeedbackVector, optimized_code_weak_or_smi, kOptimizedCodeOffset)
106ACCESSORS(FeedbackVector, closure_feedback_cell_array, ClosureFeedbackCellArray,
107 kClosureFeedbackCellArrayOffset)
108INT32_ACCESSORS(FeedbackVector, length, kLengthOffset)
109INT32_ACCESSORS(FeedbackVector, invocation_count, kInvocationCountOffset)
110INT32_ACCESSORS(FeedbackVector, profiler_ticks, kProfilerTicksOffset)
111INT32_ACCESSORS(FeedbackVector, deopt_count, kDeoptCountOffset)
112
113bool FeedbackVector::is_empty() const { return length() == 0; }
114
115FeedbackMetadata FeedbackVector::metadata() const {
116 return shared_function_info()->feedback_metadata();
117}
118
119void FeedbackVector::clear_invocation_count() { set_invocation_count(0); }
120
121void FeedbackVector::increment_deopt_count() {
122 int count = deopt_count();
123 if (count < std::numeric_limits<int32_t>::max()) {
124 set_deopt_count(count + 1);
125 }
126}
127
128Code FeedbackVector::optimized_code() const {
129 MaybeObject slot = optimized_code_weak_or_smi();
130 DCHECK(slot->IsSmi() || slot->IsWeakOrCleared());
131 HeapObject heap_object;
132 return slot->GetHeapObject(&heap_object) ? Code::cast(heap_object) : Code();
133}
134
135OptimizationMarker FeedbackVector::optimization_marker() const {
136 MaybeObject slot = optimized_code_weak_or_smi();
137 Smi value;
138 if (!slot->ToSmi(&value)) return OptimizationMarker::kNone;
139 return static_cast<OptimizationMarker>(value->value());
140}
141
142bool FeedbackVector::has_optimized_code() const {
143 return !optimized_code().is_null();
144}
145
146bool FeedbackVector::has_optimization_marker() const {
147 return optimization_marker() != OptimizationMarker::kLogFirstExecution &&
148 optimization_marker() != OptimizationMarker::kNone;
149}
150
151// Conversion from an integer index to either a slot or an ic slot.
152// static
153FeedbackSlot FeedbackVector::ToSlot(int index) {
154 DCHECK_GE(index, 0);
155 return FeedbackSlot(index);
156}
157
158MaybeObject FeedbackVector::Get(FeedbackSlot slot) const {
159 return get(GetIndex(slot));
160}
161
162MaybeObject FeedbackVector::get(int index) const {
163 DCHECK_GE(index, 0);
164 DCHECK_LT(index, this->length());
165 int offset = kFeedbackSlotsOffset + index * kTaggedSize;
166 return RELAXED_READ_WEAK_FIELD(*this, offset);
167}
168
169Handle<FeedbackCell> FeedbackVector::GetClosureFeedbackCell(int index) const {
170 DCHECK_GE(index, 0);
171 ClosureFeedbackCellArray cell_array =
172 ClosureFeedbackCellArray::cast(closure_feedback_cell_array());
173 return cell_array->GetFeedbackCell(index);
174}
175
176void FeedbackVector::Set(FeedbackSlot slot, MaybeObject value,
177 WriteBarrierMode mode) {
178 set(GetIndex(slot), value, mode);
179}
180
181void FeedbackVector::set(int index, MaybeObject value, WriteBarrierMode mode) {
182 DCHECK_GE(index, 0);
183 DCHECK_LT(index, this->length());
184 int offset = kFeedbackSlotsOffset + index * kTaggedSize;
185 RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
186 CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
187}
188
189void FeedbackVector::Set(FeedbackSlot slot, Object value,
190 WriteBarrierMode mode) {
191 set(GetIndex(slot), MaybeObject::FromObject(value), mode);
192}
193
194void FeedbackVector::set(int index, Object value, WriteBarrierMode mode) {
195 set(index, MaybeObject::FromObject(value), mode);
196}
197
198inline MaybeObjectSlot FeedbackVector::slots_start() {
199 return RawMaybeWeakField(kFeedbackSlotsOffset);
200}
201
202// Helper function to transform the feedback to BinaryOperationHint.
203BinaryOperationHint 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::kConsOneByteString:
216 return BinaryOperationHint::kConsOneByteString;
217 case BinaryOperationFeedback::kConsTwoByteString:
218 return BinaryOperationHint::kConsTwoByteString;
219 case BinaryOperationFeedback::kConsString:
220 return BinaryOperationHint::kConsString;
221 case BinaryOperationFeedback::kString:
222 return BinaryOperationHint::kString;
223 case BinaryOperationFeedback::kBigInt:
224 return BinaryOperationHint::kBigInt;
225 default:
226 return BinaryOperationHint::kAny;
227 }
228 UNREACHABLE();
229}
230
231// Helper function to transform the feedback to CompareOperationHint.
232CompareOperationHint CompareOperationHintFromFeedback(int type_feedback) {
233 switch (type_feedback) {
234 case CompareOperationFeedback::kNone:
235 return CompareOperationHint::kNone;
236 case CompareOperationFeedback::kSignedSmall:
237 return CompareOperationHint::kSignedSmall;
238 case CompareOperationFeedback::kNumber:
239 return CompareOperationHint::kNumber;
240 case CompareOperationFeedback::kNumberOrOddball:
241 return CompareOperationHint::kNumberOrOddball;
242 case CompareOperationFeedback::kInternalizedString:
243 return CompareOperationHint::kInternalizedString;
244 case CompareOperationFeedback::kString:
245 return CompareOperationHint::kString;
246 case CompareOperationFeedback::kSymbol:
247 return CompareOperationHint::kSymbol;
248 case CompareOperationFeedback::kBigInt:
249 return CompareOperationHint::kBigInt;
250 case CompareOperationFeedback::kReceiver:
251 return CompareOperationHint::kReceiver;
252 case CompareOperationFeedback::kReceiverOrNullOrUndefined:
253 return CompareOperationHint::kReceiverOrNullOrUndefined;
254 default:
255 return CompareOperationHint::kAny;
256 }
257 UNREACHABLE();
258}
259
260// Helper function to transform the feedback to ForInHint.
261ForInHint 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
275Handle<Symbol> FeedbackVector::UninitializedSentinel(Isolate* isolate) {
276 return isolate->factory()->uninitialized_symbol();
277}
278
279Handle<Symbol> FeedbackVector::GenericSentinel(Isolate* isolate) {
280 return isolate->factory()->generic_symbol();
281}
282
283Handle<Symbol> FeedbackVector::MegamorphicSentinel(Isolate* isolate) {
284 return isolate->factory()->megamorphic_symbol();
285}
286
287Handle<Symbol> FeedbackVector::PremonomorphicSentinel(Isolate* isolate) {
288 return isolate->factory()->premonomorphic_symbol();
289}
290
291Symbol FeedbackVector::RawUninitializedSentinel(Isolate* isolate) {
292 return ReadOnlyRoots(isolate).uninitialized_symbol();
293}
294
295bool FeedbackMetadataIterator::HasNext() const {
296 return next_slot_.ToInt() < metadata()->slot_count();
297}
298
299FeedbackSlot FeedbackMetadataIterator::Next() {
300 DCHECK(HasNext());
301 cur_slot_ = next_slot_;
302 slot_kind_ = metadata()->GetKind(cur_slot_);
303 next_slot_ = FeedbackSlot(next_slot_.ToInt() + entry_size());
304 return cur_slot_;
305}
306
307int FeedbackMetadataIterator::entry_size() const {
308 return FeedbackMetadata::GetSlotSize(kind());
309}
310
311MaybeObject FeedbackNexus::GetFeedback() const {
312 MaybeObject feedback = vector()->Get(slot());
313 FeedbackVector::AssertNoLegacyTypes(feedback);
314 return feedback;
315}
316
317MaybeObject 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 return vector()->get(extra_index);
324}
325
326void FeedbackNexus::SetFeedback(Object feedback, WriteBarrierMode mode) {
327 SetFeedback(MaybeObject::FromObject(feedback));
328}
329
330void FeedbackNexus::SetFeedback(MaybeObject feedback, WriteBarrierMode mode) {
331 FeedbackVector::AssertNoLegacyTypes(feedback);
332 vector()->Set(slot(), feedback, mode);
333}
334
335void 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 int index = vector()->GetIndex(slot()) + 1;
343 vector()->set(index, MaybeObject::FromObject(feedback_extra), mode);
344}
345
346void FeedbackNexus::SetFeedbackExtra(MaybeObject feedback_extra,
347 WriteBarrierMode mode) {
348#ifdef DEBUG
349 FeedbackVector::AssertNoLegacyTypes(feedback_extra);
350#endif
351 int index = vector()->GetIndex(slot()) + 1;
352 vector()->set(index, feedback_extra, mode);
353}
354
355Isolate* 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_
362