• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "src/globals.h"
10 #include "src/heap/factory-inl.h"
11 #include "src/heap/heap-inl.h"
12 #include "src/objects/maybe-object-inl.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 
INT32_ACCESSORS(FeedbackMetadata,slot_count,kSlotCountOffset)21 INT32_ACCESSORS(FeedbackMetadata, slot_count, kSlotCountOffset)
22 
23 int32_t FeedbackMetadata::synchronized_slot_count() const {
24   return base::Acquire_Load(reinterpret_cast<const base::Atomic32*>(
25       FIELD_ADDR(this, kSlotCountOffset)));
26 }
27 
28 // static
cast(Object * obj)29 FeedbackMetadata* FeedbackMetadata::cast(Object* obj) {
30   DCHECK(obj->IsFeedbackMetadata());
31   return reinterpret_cast<FeedbackMetadata*>(obj);
32 }
33 
get(int index)34 int32_t FeedbackMetadata::get(int index) const {
35   DCHECK(index >= 0 && index < length());
36   int offset = kHeaderSize + index * kInt32Size;
37   return READ_INT32_FIELD(this, offset);
38 }
39 
set(int index,int32_t value)40 void FeedbackMetadata::set(int index, int32_t value) {
41   DCHECK(index >= 0 && index < length());
42   int offset = kHeaderSize + index * kInt32Size;
43   WRITE_INT32_FIELD(this, offset, value);
44 }
45 
is_empty()46 bool FeedbackMetadata::is_empty() const { return slot_count() == 0; }
47 
length()48 int FeedbackMetadata::length() const {
49   return FeedbackMetadata::length(slot_count());
50 }
51 
52 // static
cast(Object * obj)53 FeedbackVector* FeedbackVector::cast(Object* obj) {
54   DCHECK(obj->IsFeedbackVector());
55   return reinterpret_cast<FeedbackVector*>(obj);
56 }
57 
GetSlotSize(FeedbackSlotKind kind)58 int FeedbackMetadata::GetSlotSize(FeedbackSlotKind kind) {
59   switch (kind) {
60     case FeedbackSlotKind::kForIn:
61     case FeedbackSlotKind::kInstanceOf:
62     case FeedbackSlotKind::kCompareOp:
63     case FeedbackSlotKind::kBinaryOp:
64     case FeedbackSlotKind::kLiteral:
65     case FeedbackSlotKind::kCreateClosure:
66     case FeedbackSlotKind::kTypeProfile:
67       return 1;
68 
69     case FeedbackSlotKind::kCall:
70     case FeedbackSlotKind::kCloneObject:
71     case FeedbackSlotKind::kLoadProperty:
72     case FeedbackSlotKind::kLoadGlobalInsideTypeof:
73     case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
74     case FeedbackSlotKind::kLoadKeyed:
75     case FeedbackSlotKind::kStoreNamedSloppy:
76     case FeedbackSlotKind::kStoreNamedStrict:
77     case FeedbackSlotKind::kStoreOwnNamed:
78     case FeedbackSlotKind::kStoreGlobalSloppy:
79     case FeedbackSlotKind::kStoreGlobalStrict:
80     case FeedbackSlotKind::kStoreKeyedSloppy:
81     case FeedbackSlotKind::kStoreKeyedStrict:
82     case FeedbackSlotKind::kStoreInArrayLiteral:
83     case FeedbackSlotKind::kStoreDataPropertyInLiteral:
84       return 2;
85 
86     case FeedbackSlotKind::kInvalid:
87     case FeedbackSlotKind::kKindsNumber:
88       UNREACHABLE();
89       break;
90   }
91   return 1;
92 }
93 
ACCESSORS(FeedbackVector,shared_function_info,SharedFunctionInfo,kSharedFunctionInfoOffset)94 ACCESSORS(FeedbackVector, shared_function_info, SharedFunctionInfo,
95           kSharedFunctionInfoOffset)
96 WEAK_ACCESSORS(FeedbackVector, optimized_code_weak_or_smi, kOptimizedCodeOffset)
97 INT32_ACCESSORS(FeedbackVector, length, kLengthOffset)
98 INT32_ACCESSORS(FeedbackVector, invocation_count, kInvocationCountOffset)
99 INT32_ACCESSORS(FeedbackVector, profiler_ticks, kProfilerTicksOffset)
100 INT32_ACCESSORS(FeedbackVector, deopt_count, kDeoptCountOffset)
101 
102 bool FeedbackVector::is_empty() const { return length() == 0; }
103 
metadata()104 FeedbackMetadata* FeedbackVector::metadata() const {
105   return shared_function_info()->feedback_metadata();
106 }
107 
clear_invocation_count()108 void FeedbackVector::clear_invocation_count() { set_invocation_count(0); }
109 
increment_deopt_count()110 void FeedbackVector::increment_deopt_count() {
111   int count = deopt_count();
112   if (count < std::numeric_limits<int32_t>::max()) {
113     set_deopt_count(count + 1);
114   }
115 }
116 
optimized_code()117 Code* FeedbackVector::optimized_code() const {
118   MaybeObject* slot = optimized_code_weak_or_smi();
119   DCHECK(slot->IsSmi() || slot->IsClearedWeakHeapObject() ||
120          slot->IsWeakHeapObject());
121   HeapObject* heap_object;
122   return slot->ToStrongOrWeakHeapObject(&heap_object) ? Code::cast(heap_object)
123                                                       : nullptr;
124 }
125 
optimization_marker()126 OptimizationMarker FeedbackVector::optimization_marker() const {
127   MaybeObject* slot = optimized_code_weak_or_smi();
128   Smi* value;
129   if (!slot->ToSmi(&value)) return OptimizationMarker::kNone;
130   return static_cast<OptimizationMarker>(value->value());
131 }
132 
has_optimized_code()133 bool FeedbackVector::has_optimized_code() const {
134   return optimized_code() != nullptr;
135 }
136 
has_optimization_marker()137 bool FeedbackVector::has_optimization_marker() const {
138   return optimization_marker() != OptimizationMarker::kLogFirstExecution &&
139          optimization_marker() != OptimizationMarker::kNone;
140 }
141 
142 // Conversion from an integer index to either a slot or an ic slot.
143 // static
ToSlot(int index)144 FeedbackSlot FeedbackVector::ToSlot(int index) {
145   DCHECK_GE(index, 0);
146   return FeedbackSlot(index);
147 }
148 
Get(FeedbackSlot slot)149 MaybeObject* FeedbackVector::Get(FeedbackSlot slot) const {
150   return get(GetIndex(slot));
151 }
152 
get(int index)153 MaybeObject* FeedbackVector::get(int index) const {
154   DCHECK_GE(index, 0);
155   DCHECK_LT(index, this->length());
156   int offset = kFeedbackSlotsOffset + index * kPointerSize;
157   return RELAXED_READ_WEAK_FIELD(this, offset);
158 }
159 
Set(FeedbackSlot slot,MaybeObject * value,WriteBarrierMode mode)160 void FeedbackVector::Set(FeedbackSlot slot, MaybeObject* value,
161                          WriteBarrierMode mode) {
162   set(GetIndex(slot), value, mode);
163 }
164 
set(int index,MaybeObject * value,WriteBarrierMode mode)165 void FeedbackVector::set(int index, MaybeObject* value, WriteBarrierMode mode) {
166   DCHECK_GE(index, 0);
167   DCHECK_LT(index, this->length());
168   int offset = kFeedbackSlotsOffset + index * kPointerSize;
169   RELAXED_WRITE_FIELD(this, offset, value);
170   CONDITIONAL_WEAK_WRITE_BARRIER(this, offset, value, mode);
171 }
172 
Set(FeedbackSlot slot,Object * value,WriteBarrierMode mode)173 void FeedbackVector::Set(FeedbackSlot slot, Object* value,
174                          WriteBarrierMode mode) {
175   set(GetIndex(slot), MaybeObject::FromObject(value), mode);
176 }
177 
set(int index,Object * value,WriteBarrierMode mode)178 void FeedbackVector::set(int index, Object* value, WriteBarrierMode mode) {
179   set(index, MaybeObject::FromObject(value), mode);
180 }
181 
slots_start()182 inline MaybeObject** FeedbackVector::slots_start() {
183   return HeapObject::RawMaybeWeakField(this, kFeedbackSlotsOffset);
184 }
185 
186 // Helper function to transform the feedback to BinaryOperationHint.
BinaryOperationHintFromFeedback(int type_feedback)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;
203     default:
204       return BinaryOperationHint::kAny;
205   }
206   UNREACHABLE();
207 }
208 
209 // Helper function to transform the feedback to CompareOperationHint.
CompareOperationHintFromFeedback(int type_feedback)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     default:
231       return CompareOperationHint::kAny;
232   }
233   UNREACHABLE();
234 }
235 
236 // Helper function to transform the feedback to ForInHint.
ForInHintFromFeedback(int type_feedback)237 ForInHint ForInHintFromFeedback(int type_feedback) {
238   switch (type_feedback) {
239     case ForInFeedback::kNone:
240       return ForInHint::kNone;
241     case ForInFeedback::kEnumCacheKeys:
242       return ForInHint::kEnumCacheKeys;
243     case ForInFeedback::kEnumCacheKeysAndIndices:
244       return ForInHint::kEnumCacheKeysAndIndices;
245     default:
246       return ForInHint::kAny;
247   }
248   UNREACHABLE();
249 }
250 
ComputeCounts(int * with_type_info,int * generic,int * vector_ic_count)251 void FeedbackVector::ComputeCounts(int* with_type_info, int* generic,
252                                    int* vector_ic_count) {
253   MaybeObject* megamorphic_sentinel = MaybeObject::FromObject(
254       *FeedbackVector::MegamorphicSentinel(GetIsolate()));
255   int with = 0;
256   int gen = 0;
257   int total = 0;
258   FeedbackMetadataIterator iter(metadata());
259   while (iter.HasNext()) {
260     FeedbackSlot slot = iter.Next();
261     FeedbackSlotKind kind = iter.kind();
262 
263     MaybeObject* const obj = Get(slot);
264     AssertNoLegacyTypes(obj);
265     switch (kind) {
266       case FeedbackSlotKind::kCall:
267       case FeedbackSlotKind::kLoadProperty:
268       case FeedbackSlotKind::kLoadGlobalInsideTypeof:
269       case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
270       case FeedbackSlotKind::kLoadKeyed:
271       case FeedbackSlotKind::kStoreNamedSloppy:
272       case FeedbackSlotKind::kStoreNamedStrict:
273       case FeedbackSlotKind::kStoreOwnNamed:
274       case FeedbackSlotKind::kStoreGlobalSloppy:
275       case FeedbackSlotKind::kStoreGlobalStrict:
276       case FeedbackSlotKind::kStoreKeyedSloppy:
277       case FeedbackSlotKind::kStoreKeyedStrict:
278       case FeedbackSlotKind::kStoreInArrayLiteral:
279       case FeedbackSlotKind::kStoreDataPropertyInLiteral:
280       case FeedbackSlotKind::kTypeProfile: {
281         HeapObject* heap_object;
282         if (obj->IsWeakOrClearedHeapObject() ||
283             (obj->ToStrongHeapObject(&heap_object) &&
284              (heap_object->IsWeakFixedArray() || heap_object->IsString()))) {
285           with++;
286         } else if (obj == megamorphic_sentinel) {
287           gen++;
288           with++;
289         }
290         total++;
291         break;
292       }
293       case FeedbackSlotKind::kBinaryOp: {
294         int const feedback = Smi::ToInt(obj->ToSmi());
295         BinaryOperationHint hint = BinaryOperationHintFromFeedback(feedback);
296         if (hint == BinaryOperationHint::kAny) {
297           gen++;
298         }
299         if (hint != BinaryOperationHint::kNone) {
300           with++;
301         }
302         total++;
303         break;
304       }
305       case FeedbackSlotKind::kCompareOp: {
306         int const feedback = Smi::ToInt(obj->ToSmi());
307         CompareOperationHint hint = CompareOperationHintFromFeedback(feedback);
308         if (hint == CompareOperationHint::kAny) {
309           gen++;
310         }
311         if (hint != CompareOperationHint::kNone) {
312           with++;
313         }
314         total++;
315         break;
316       }
317       case FeedbackSlotKind::kForIn: {
318         int const feedback = Smi::ToInt(obj->ToSmi());
319         ForInHint hint = ForInHintFromFeedback(feedback);
320         if (hint == ForInHint::kAny) {
321           gen++;
322         }
323         if (hint != ForInHint::kNone) {
324           with++;
325         }
326         total++;
327         break;
328       }
329       case FeedbackSlotKind::kInstanceOf: {
330         if (obj->IsWeakOrClearedHeapObject()) {
331           with++;
332         } else if (obj == megamorphic_sentinel) {
333           gen++;
334           with++;
335         }
336         total++;
337         break;
338       }
339       case FeedbackSlotKind::kCreateClosure:
340       case FeedbackSlotKind::kLiteral:
341       case FeedbackSlotKind::kCloneObject:
342         break;
343       case FeedbackSlotKind::kInvalid:
344       case FeedbackSlotKind::kKindsNumber:
345         UNREACHABLE();
346         break;
347     }
348   }
349 
350   *with_type_info = with;
351   *generic = gen;
352   *vector_ic_count = total;
353 }
354 
UninitializedSentinel(Isolate * isolate)355 Handle<Symbol> FeedbackVector::UninitializedSentinel(Isolate* isolate) {
356   return isolate->factory()->uninitialized_symbol();
357 }
358 
GenericSentinel(Isolate * isolate)359 Handle<Symbol> FeedbackVector::GenericSentinel(Isolate* isolate) {
360   return isolate->factory()->generic_symbol();
361 }
362 
MegamorphicSentinel(Isolate * isolate)363 Handle<Symbol> FeedbackVector::MegamorphicSentinel(Isolate* isolate) {
364   return isolate->factory()->megamorphic_symbol();
365 }
366 
PremonomorphicSentinel(Isolate * isolate)367 Handle<Symbol> FeedbackVector::PremonomorphicSentinel(Isolate* isolate) {
368   return isolate->factory()->premonomorphic_symbol();
369 }
370 
RawUninitializedSentinel(Isolate * isolate)371 Symbol* FeedbackVector::RawUninitializedSentinel(Isolate* isolate) {
372   return ReadOnlyRoots(isolate).uninitialized_symbol();
373 }
374 
HasNext()375 bool FeedbackMetadataIterator::HasNext() const {
376   return next_slot_.ToInt() < metadata()->slot_count();
377 }
378 
Next()379 FeedbackSlot FeedbackMetadataIterator::Next() {
380   DCHECK(HasNext());
381   cur_slot_ = next_slot_;
382   slot_kind_ = metadata()->GetKind(cur_slot_);
383   next_slot_ = FeedbackSlot(next_slot_.ToInt() + entry_size());
384   return cur_slot_;
385 }
386 
entry_size()387 int FeedbackMetadataIterator::entry_size() const {
388   return FeedbackMetadata::GetSlotSize(kind());
389 }
390 
GetFeedback()391 MaybeObject* FeedbackNexus::GetFeedback() const {
392   MaybeObject* feedback = vector()->Get(slot());
393   FeedbackVector::AssertNoLegacyTypes(feedback);
394   return feedback;
395 }
396 
GetFeedbackExtra()397 MaybeObject* FeedbackNexus::GetFeedbackExtra() const {
398 #ifdef DEBUG
399   FeedbackSlotKind kind = vector()->GetKind(slot());
400   DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
401 #endif
402   int extra_index = vector()->GetIndex(slot()) + 1;
403   return vector()->get(extra_index);
404 }
405 
SetFeedback(Object * feedback,WriteBarrierMode mode)406 void FeedbackNexus::SetFeedback(Object* feedback, WriteBarrierMode mode) {
407   SetFeedback(MaybeObject::FromObject(feedback));
408 }
409 
SetFeedback(MaybeObject * feedback,WriteBarrierMode mode)410 void FeedbackNexus::SetFeedback(MaybeObject* feedback, WriteBarrierMode mode) {
411   FeedbackVector::AssertNoLegacyTypes(feedback);
412   vector()->Set(slot(), feedback, mode);
413 }
414 
SetFeedbackExtra(Object * feedback_extra,WriteBarrierMode mode)415 void FeedbackNexus::SetFeedbackExtra(Object* feedback_extra,
416                                      WriteBarrierMode mode) {
417 #ifdef DEBUG
418   FeedbackSlotKind kind = vector()->GetKind(slot());
419   DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
420   FeedbackVector::AssertNoLegacyTypes(MaybeObject::FromObject(feedback_extra));
421 #endif
422   int index = vector()->GetIndex(slot()) + 1;
423   vector()->set(index, MaybeObject::FromObject(feedback_extra), mode);
424 }
425 
SetFeedbackExtra(MaybeObject * feedback_extra,WriteBarrierMode mode)426 void FeedbackNexus::SetFeedbackExtra(MaybeObject* feedback_extra,
427                                      WriteBarrierMode mode) {
428 #ifdef DEBUG
429   FeedbackVector::AssertNoLegacyTypes(feedback_extra);
430 #endif
431   int index = vector()->GetIndex(slot()) + 1;
432   vector()->set(index, feedback_extra, mode);
433 }
434 
GetIsolate()435 Isolate* FeedbackNexus::GetIsolate() const { return vector()->GetIsolate(); }
436 }  // namespace internal
437 }  // namespace v8
438 
439 #include "src/objects/object-macros-undef.h"
440 
441 #endif  // V8_FEEDBACK_VECTOR_INL_H_
442