5 #ifndef V8_FEEDBACK_VECTOR_INL_H_ 6 #define V8_FEEDBACK_VECTOR_INL_H_ 8 #include "src/feedback-vector.h" 9 #include "src/globals.h" 10 #include "src/heap/factory-inl.h" 11 #include "src/heap/heap-inl.h" 12 #include "src/heap/heap-write-barrier.h" 13 #include "src/objects/maybe-object-inl.h" 14 #include "src/objects/shared-function-info.h" 15 #include "src/objects/smi.h" 18 #include "src/objects/object-macros.h" 23 INT32_ACCESSORS(FeedbackMetadata, slot_count, kSlotCountOffset)
25 int32_t FeedbackMetadata::synchronized_slot_count()
const {
26 return base::Acquire_Load(reinterpret_cast<const base::Atomic32*>(
27 FIELD_ADDR(
this, kSlotCountOffset)));
31 FeedbackMetadata* FeedbackMetadata::cast(Object* obj) {
32 DCHECK(obj->IsFeedbackMetadata());
33 return reinterpret_cast<FeedbackMetadata*
>(obj);
36 int32_t FeedbackMetadata::get(
int index)
const {
37 DCHECK(index >= 0 && index < length());
38 int offset = kHeaderSize + index * kInt32Size;
39 return READ_INT32_FIELD(
this, offset);
42 void FeedbackMetadata::set(
int index, int32_t value) {
43 DCHECK(index >= 0 && index < length());
44 int offset = kHeaderSize + index * kInt32Size;
45 WRITE_INT32_FIELD(
this, offset, value);
48 bool FeedbackMetadata::is_empty()
const {
return slot_count() == 0; }
50 int FeedbackMetadata::length()
const {
51 return FeedbackMetadata::length(slot_count());
55 FeedbackVector* FeedbackVector::cast(Object* obj) {
56 DCHECK(obj->IsFeedbackVector());
57 return reinterpret_cast<FeedbackVector*
>(obj);
60 int FeedbackMetadata::GetSlotSize(FeedbackSlotKind kind) {
62 case FeedbackSlotKind::kForIn:
63 case FeedbackSlotKind::kInstanceOf:
64 case FeedbackSlotKind::kCompareOp:
65 case FeedbackSlotKind::kBinaryOp:
66 case FeedbackSlotKind::kLiteral:
67 case FeedbackSlotKind::kCreateClosure:
68 case FeedbackSlotKind::kTypeProfile:
71 case FeedbackSlotKind::kCall:
72 case FeedbackSlotKind::kCloneObject:
73 case FeedbackSlotKind::kLoadProperty:
74 case FeedbackSlotKind::kLoadGlobalInsideTypeof:
75 case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
76 case FeedbackSlotKind::kLoadKeyed:
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:
88 case FeedbackSlotKind::kInvalid:
89 case FeedbackSlotKind::kKindsNumber:
96 ACCESSORS(FeedbackVector, shared_function_info, SharedFunctionInfo,
97 kSharedFunctionInfoOffset)
98 WEAK_ACCESSORS(FeedbackVector, optimized_code_weak_or_smi, kOptimizedCodeOffset)
99 INT32_ACCESSORS(FeedbackVector, length, kLengthOffset)
100 INT32_ACCESSORS(FeedbackVector, invocation_count, kInvocationCountOffset)
101 INT32_ACCESSORS(FeedbackVector, profiler_ticks, kProfilerTicksOffset)
102 INT32_ACCESSORS(FeedbackVector, deopt_count, kDeoptCountOffset)
104 bool FeedbackVector::is_empty()
const {
return length() == 0; }
106 FeedbackMetadata* FeedbackVector::metadata()
const {
107 return shared_function_info()->feedback_metadata();
110 void FeedbackVector::clear_invocation_count() { set_invocation_count(0); }
112 void FeedbackVector::increment_deopt_count() {
113 int count = deopt_count();
114 if (count < std::numeric_limits<int32_t>::max()) {
115 set_deopt_count(count + 1);
119 Code FeedbackVector::optimized_code()
const {
120 MaybeObject slot = optimized_code_weak_or_smi();
121 DCHECK(slot->IsSmi() || slot->IsWeakOrCleared());
122 HeapObject* heap_object;
123 return slot->GetHeapObject(&heap_object) ? Code::cast(heap_object) : Code();
126 OptimizationMarker FeedbackVector::optimization_marker()
const {
127 MaybeObject slot = optimized_code_weak_or_smi();
129 if (!slot->ToSmi(&value))
return OptimizationMarker::kNone;
130 return static_cast<OptimizationMarker
>(value->value());
133 bool FeedbackVector::has_optimized_code()
const {
134 return !optimized_code().is_null();
137 bool FeedbackVector::has_optimization_marker()
const {
138 return optimization_marker() != OptimizationMarker::kLogFirstExecution &&
139 optimization_marker() != OptimizationMarker::kNone;
144 FeedbackSlot FeedbackVector::ToSlot(
int index) {
146 return FeedbackSlot(index);
149 MaybeObject FeedbackVector::Get(FeedbackSlot slot)
const {
150 return get(GetIndex(slot));
153 MaybeObject FeedbackVector::get(
int index)
const {
155 DCHECK_LT(index, this->length());
156 int offset = kFeedbackSlotsOffset + index * kPointerSize;
157 return RELAXED_READ_WEAK_FIELD(
this, offset);
160 void FeedbackVector::Set(FeedbackSlot slot, MaybeObject value,
161 WriteBarrierMode mode) {
162 set(GetIndex(slot), value, mode);
165 void FeedbackVector::set(
int index, MaybeObject value, WriteBarrierMode mode) {
167 DCHECK_LT(index, this->length());
168 int offset = kFeedbackSlotsOffset + index * kPointerSize;
169 RELAXED_WRITE_WEAK_FIELD(
this, offset, value);
170 CONDITIONAL_WEAK_WRITE_BARRIER(
this, offset, value, mode);
173 void FeedbackVector::Set(FeedbackSlot slot, Object* value,
174 WriteBarrierMode mode) {
175 set(GetIndex(slot), MaybeObject::FromObject(value), mode);
178 void FeedbackVector::set(
int index, Object* value, WriteBarrierMode mode) {
179 set(index, MaybeObject::FromObject(value), mode);
182 inline MaybeObjectSlot FeedbackVector::slots_start() {
183 return HeapObject::RawMaybeWeakField(
this, kFeedbackSlotsOffset);
187 BinaryOperationHint BinaryOperationHintFromFeedback(
int type_feedback) {
188 switch (type_feedback) {
189 case BinaryOperationFeedback::kNone:
190 return BinaryOperationHint::kNone;
191 case BinaryOperationFeedback::kSignedSmall:
192 return BinaryOperationHint::kSignedSmall;
193 case BinaryOperationFeedback::kSignedSmallInputs:
194 return BinaryOperationHint::kSignedSmallInputs;
195 case BinaryOperationFeedback::kNumber:
196 return BinaryOperationHint::kNumber;
197 case BinaryOperationFeedback::kNumberOrOddball:
198 return BinaryOperationHint::kNumberOrOddball;
199 case BinaryOperationFeedback::kString:
200 return BinaryOperationHint::kString;
201 case BinaryOperationFeedback::kBigInt:
202 return BinaryOperationHint::kBigInt;
204 return BinaryOperationHint::kAny;
210 CompareOperationHint CompareOperationHintFromFeedback(
int type_feedback) {
211 switch (type_feedback) {
212 case CompareOperationFeedback::kNone:
213 return CompareOperationHint::kNone;
214 case CompareOperationFeedback::kSignedSmall:
215 return CompareOperationHint::kSignedSmall;
216 case CompareOperationFeedback::kNumber:
217 return CompareOperationHint::kNumber;
218 case CompareOperationFeedback::kNumberOrOddball:
219 return CompareOperationHint::kNumberOrOddball;
220 case CompareOperationFeedback::kInternalizedString:
221 return CompareOperationHint::kInternalizedString;
222 case CompareOperationFeedback::kString:
223 return CompareOperationHint::kString;
224 case CompareOperationFeedback::kSymbol:
225 return CompareOperationHint::kSymbol;
226 case CompareOperationFeedback::kBigInt:
227 return CompareOperationHint::kBigInt;
228 case CompareOperationFeedback::kReceiver:
229 return CompareOperationHint::kReceiver;
230 case CompareOperationFeedback::kReceiverOrNullOrUndefined:
231 return CompareOperationHint::kReceiverOrNullOrUndefined;
233 return CompareOperationHint::kAny;
239 ForInHint ForInHintFromFeedback(
int type_feedback) {
240 switch (type_feedback) {
241 case ForInFeedback::kNone:
242 return ForInHint::kNone;
243 case ForInFeedback::kEnumCacheKeys:
244 return ForInHint::kEnumCacheKeys;
245 case ForInFeedback::kEnumCacheKeysAndIndices:
246 return ForInHint::kEnumCacheKeysAndIndices;
248 return ForInHint::kAny;
253 void FeedbackVector::ComputeCounts(
int* with_type_info,
int*
generic,
254 int* vector_ic_count) {
255 MaybeObject megamorphic_sentinel = MaybeObject::FromObject(
256 *FeedbackVector::MegamorphicSentinel(GetIsolate()));
260 FeedbackMetadataIterator iter(metadata());
261 while (iter.HasNext()) {
262 FeedbackSlot slot = iter.Next();
263 FeedbackSlotKind kind = iter.kind();
265 MaybeObject
const obj = Get(slot);
266 AssertNoLegacyTypes(obj);
268 case FeedbackSlotKind::kCall:
269 case FeedbackSlotKind::kLoadProperty:
270 case FeedbackSlotKind::kLoadGlobalInsideTypeof:
271 case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
272 case FeedbackSlotKind::kLoadKeyed:
273 case FeedbackSlotKind::kStoreNamedSloppy:
274 case FeedbackSlotKind::kStoreNamedStrict:
275 case FeedbackSlotKind::kStoreOwnNamed:
276 case FeedbackSlotKind::kStoreGlobalSloppy:
277 case FeedbackSlotKind::kStoreGlobalStrict:
278 case FeedbackSlotKind::kStoreKeyedSloppy:
279 case FeedbackSlotKind::kStoreKeyedStrict:
280 case FeedbackSlotKind::kStoreInArrayLiteral:
281 case FeedbackSlotKind::kStoreDataPropertyInLiteral:
282 case FeedbackSlotKind::kTypeProfile: {
283 HeapObject* heap_object;
284 if (obj->IsWeakOrCleared() ||
285 (obj->GetHeapObjectIfStrong(&heap_object) &&
286 (heap_object->IsWeakFixedArray() || heap_object->IsString()))) {
288 }
else if (obj == megamorphic_sentinel) {
295 case FeedbackSlotKind::kBinaryOp: {
296 int const feedback = obj.ToSmi().value();
297 BinaryOperationHint hint = BinaryOperationHintFromFeedback(feedback);
298 if (hint == BinaryOperationHint::kAny) {
301 if (hint != BinaryOperationHint::kNone) {
307 case FeedbackSlotKind::kCompareOp: {
308 int const feedback = obj.ToSmi().value();
309 CompareOperationHint hint = CompareOperationHintFromFeedback(feedback);
310 if (hint == CompareOperationHint::kAny) {
313 if (hint != CompareOperationHint::kNone) {
319 case FeedbackSlotKind::kForIn: {
320 int const feedback = obj.ToSmi().value();
321 ForInHint hint = ForInHintFromFeedback(feedback);
322 if (hint == ForInHint::kAny) {
325 if (hint != ForInHint::kNone) {
331 case FeedbackSlotKind::kInstanceOf: {
332 if (obj->IsWeakOrCleared()) {
334 }
else if (obj == megamorphic_sentinel) {
341 case FeedbackSlotKind::kCreateClosure:
342 case FeedbackSlotKind::kLiteral:
343 case FeedbackSlotKind::kCloneObject:
345 case FeedbackSlotKind::kInvalid:
346 case FeedbackSlotKind::kKindsNumber:
352 *with_type_info = with;
354 *vector_ic_count = total;
357 Handle<Symbol> FeedbackVector::UninitializedSentinel(Isolate* isolate) {
358 return isolate->factory()->uninitialized_symbol();
361 Handle<Symbol> FeedbackVector::GenericSentinel(Isolate* isolate) {
362 return isolate->factory()->generic_symbol();
365 Handle<Symbol> FeedbackVector::MegamorphicSentinel(Isolate* isolate) {
366 return isolate->factory()->megamorphic_symbol();
369 Handle<Symbol> FeedbackVector::PremonomorphicSentinel(Isolate* isolate) {
370 return isolate->factory()->premonomorphic_symbol();
373 Symbol FeedbackVector::RawUninitializedSentinel(Isolate* isolate) {
374 return ReadOnlyRoots(isolate).uninitialized_symbol();
377 bool FeedbackMetadataIterator::HasNext()
const {
378 return next_slot_.ToInt() < metadata()->slot_count();
381 FeedbackSlot FeedbackMetadataIterator::Next() {
383 cur_slot_ = next_slot_;
384 slot_kind_ = metadata()->GetKind(cur_slot_);
385 next_slot_ = FeedbackSlot(next_slot_.ToInt() + entry_size());
389 int FeedbackMetadataIterator::entry_size()
const {
390 return FeedbackMetadata::GetSlotSize(kind());
393 MaybeObject FeedbackNexus::GetFeedback()
const {
394 MaybeObject feedback = vector()->Get(slot());
395 FeedbackVector::AssertNoLegacyTypes(feedback);
399 MaybeObject FeedbackNexus::GetFeedbackExtra()
const {
401 FeedbackSlotKind kind = vector()->GetKind(slot());
402 DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
404 int extra_index = vector()->GetIndex(slot()) + 1;
405 return vector()->get(extra_index);
408 void FeedbackNexus::SetFeedback(Object* feedback, WriteBarrierMode mode) {
409 SetFeedback(MaybeObject::FromObject(feedback));
412 void FeedbackNexus::SetFeedback(MaybeObject feedback, WriteBarrierMode mode) {
413 FeedbackVector::AssertNoLegacyTypes(feedback);
414 vector()->Set(slot(), feedback, mode);
417 void FeedbackNexus::SetFeedbackExtra(Object* feedback_extra,
418 WriteBarrierMode mode) {
420 FeedbackSlotKind kind = vector()->GetKind(slot());
421 DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
422 FeedbackVector::AssertNoLegacyTypes(MaybeObject::FromObject(feedback_extra));
424 int index = vector()->GetIndex(slot()) + 1;
425 vector()->set(index, MaybeObject::FromObject(feedback_extra), mode);
428 void FeedbackNexus::SetFeedbackExtra(MaybeObject feedback_extra,
429 WriteBarrierMode mode) {
431 FeedbackVector::AssertNoLegacyTypes(feedback_extra);
433 int index = vector()->GetIndex(slot()) + 1;
434 vector()->set(index, feedback_extra, mode);
437 Isolate* FeedbackNexus::GetIsolate()
const {
return vector()->GetIsolate(); }
441 #include "src/objects/object-macros-undef.h" 443 #endif // V8_FEEDBACK_VECTOR_INL_H_