• 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/factory.h"
9 #include "src/feedback-vector.h"
10 #include "src/globals.h"
11 
12 namespace v8 {
13 namespace internal {
14 
15 template <typename Derived>
AddSlot(FeedbackSlotKind kind)16 FeedbackSlot FeedbackVectorSpecBase<Derived>::AddSlot(FeedbackSlotKind kind) {
17   int slot = This()->slots();
18   int entries_per_slot = FeedbackMetadata::GetSlotSize(kind);
19   This()->append(kind);
20   for (int i = 1; i < entries_per_slot; i++) {
21     This()->append(FeedbackSlotKind::kInvalid);
22   }
23   return FeedbackSlot(slot);
24 }
25 
26 // static
cast(Object * obj)27 FeedbackMetadata* FeedbackMetadata::cast(Object* obj) {
28   DCHECK(obj->IsFeedbackMetadata());
29   return reinterpret_cast<FeedbackMetadata*>(obj);
30 }
31 
is_empty()32 bool FeedbackMetadata::is_empty() const {
33   if (length() == 0) return true;
34   return false;
35 }
36 
slot_count()37 int FeedbackMetadata::slot_count() const {
38   if (length() == 0) return 0;
39   DCHECK(length() > kReservedIndexCount);
40   return Smi::cast(get(kSlotsCountIndex))->value();
41 }
42 
43 // static
cast(Object * obj)44 FeedbackVector* FeedbackVector::cast(Object* obj) {
45   DCHECK(obj->IsFeedbackVector());
46   return reinterpret_cast<FeedbackVector*>(obj);
47 }
48 
GetSlotSize(FeedbackSlotKind kind)49 int FeedbackMetadata::GetSlotSize(FeedbackSlotKind kind) {
50   switch (kind) {
51     case FeedbackSlotKind::kGeneral:
52     case FeedbackSlotKind::kCompareOp:
53     case FeedbackSlotKind::kBinaryOp:
54     case FeedbackSlotKind::kToBoolean:
55     case FeedbackSlotKind::kLiteral:
56     case FeedbackSlotKind::kCreateClosure:
57       return 1;
58 
59     case FeedbackSlotKind::kCall:
60     case FeedbackSlotKind::kLoadProperty:
61     case FeedbackSlotKind::kLoadGlobalInsideTypeof:
62     case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
63     case FeedbackSlotKind::kLoadKeyed:
64     case FeedbackSlotKind::kStoreNamedSloppy:
65     case FeedbackSlotKind::kStoreNamedStrict:
66     case FeedbackSlotKind::kStoreOwnNamed:
67     case FeedbackSlotKind::kStoreKeyedSloppy:
68     case FeedbackSlotKind::kStoreKeyedStrict:
69     case FeedbackSlotKind::kStoreDataPropertyInLiteral:
70       return 2;
71 
72     case FeedbackSlotKind::kInvalid:
73     case FeedbackSlotKind::kKindsNumber:
74       UNREACHABLE();
75       break;
76   }
77   return 1;
78 }
79 
is_empty()80 bool FeedbackVector::is_empty() const {
81   return length() == kReservedIndexCount;
82 }
83 
slot_count()84 int FeedbackVector::slot_count() const {
85   return length() - kReservedIndexCount;
86 }
87 
metadata()88 FeedbackMetadata* FeedbackVector::metadata() const {
89   return shared_function_info()->feedback_metadata();
90 }
91 
shared_function_info()92 SharedFunctionInfo* FeedbackVector::shared_function_info() const {
93   return SharedFunctionInfo::cast(get(kSharedFunctionInfoIndex));
94 }
95 
invocation_count()96 int FeedbackVector::invocation_count() const {
97   return Smi::cast(get(kInvocationCountIndex))->value();
98 }
99 
clear_invocation_count()100 void FeedbackVector::clear_invocation_count() {
101   set(kInvocationCountIndex, Smi::kZero);
102 }
103 
104 // Conversion from an integer index to either a slot or an ic slot.
105 // static
ToSlot(int index)106 FeedbackSlot FeedbackVector::ToSlot(int index) {
107   DCHECK_GE(index, kReservedIndexCount);
108   return FeedbackSlot(index - kReservedIndexCount);
109 }
110 
Get(FeedbackSlot slot)111 Object* FeedbackVector::Get(FeedbackSlot slot) const {
112   return get(GetIndex(slot));
113 }
114 
Set(FeedbackSlot slot,Object * value,WriteBarrierMode mode)115 void FeedbackVector::Set(FeedbackSlot slot, Object* value,
116                          WriteBarrierMode mode) {
117   set(GetIndex(slot), value, mode);
118 }
119 
120 // Helper function to transform the feedback to BinaryOperationHint.
BinaryOperationHintFromFeedback(int type_feedback)121 BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) {
122   switch (type_feedback) {
123     case BinaryOperationFeedback::kNone:
124       return BinaryOperationHint::kNone;
125     case BinaryOperationFeedback::kSignedSmall:
126       return BinaryOperationHint::kSignedSmall;
127     case BinaryOperationFeedback::kNumber:
128     case BinaryOperationFeedback::kNumberOrOddball:
129       return BinaryOperationHint::kNumberOrOddball;
130     case BinaryOperationFeedback::kString:
131       return BinaryOperationHint::kString;
132     case BinaryOperationFeedback::kAny:
133     default:
134       return BinaryOperationHint::kAny;
135   }
136   UNREACHABLE();
137   return BinaryOperationHint::kNone;
138 }
139 
140 // Helper function to transform the feedback to CompareOperationHint.
CompareOperationHintFromFeedback(int type_feedback)141 CompareOperationHint CompareOperationHintFromFeedback(int type_feedback) {
142   switch (type_feedback) {
143     case CompareOperationFeedback::kNone:
144       return CompareOperationHint::kNone;
145     case CompareOperationFeedback::kSignedSmall:
146       return CompareOperationHint::kSignedSmall;
147     case CompareOperationFeedback::kNumber:
148       return CompareOperationHint::kNumber;
149     case CompareOperationFeedback::kNumberOrOddball:
150       return CompareOperationHint::kNumberOrOddball;
151     case CompareOperationFeedback::kInternalizedString:
152       return CompareOperationHint::kInternalizedString;
153     case CompareOperationFeedback::kString:
154       return CompareOperationHint::kString;
155     case CompareOperationFeedback::kReceiver:
156       return CompareOperationHint::kReceiver;
157     default:
158       return CompareOperationHint::kAny;
159   }
160   UNREACHABLE();
161   return CompareOperationHint::kNone;
162 }
163 
ComputeCounts(int * with_type_info,int * generic,int * vector_ic_count,bool code_is_interpreted)164 void FeedbackVector::ComputeCounts(int* with_type_info, int* generic,
165                                    int* vector_ic_count,
166                                    bool code_is_interpreted) {
167   Object* megamorphic_sentinel =
168       *FeedbackVector::MegamorphicSentinel(GetIsolate());
169   int with = 0;
170   int gen = 0;
171   int total = 0;
172   FeedbackMetadataIterator iter(metadata());
173   while (iter.HasNext()) {
174     FeedbackSlot slot = iter.Next();
175     FeedbackSlotKind kind = iter.kind();
176 
177     Object* const obj = Get(slot);
178     switch (kind) {
179       case FeedbackSlotKind::kCall:
180       case FeedbackSlotKind::kLoadProperty:
181       case FeedbackSlotKind::kLoadGlobalInsideTypeof:
182       case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
183       case FeedbackSlotKind::kLoadKeyed:
184       case FeedbackSlotKind::kStoreNamedSloppy:
185       case FeedbackSlotKind::kStoreNamedStrict:
186       case FeedbackSlotKind::kStoreOwnNamed:
187       case FeedbackSlotKind::kStoreKeyedSloppy:
188       case FeedbackSlotKind::kStoreKeyedStrict:
189       case FeedbackSlotKind::kStoreDataPropertyInLiteral: {
190         if (obj->IsWeakCell() || obj->IsFixedArray() || obj->IsString()) {
191           with++;
192         } else if (obj == megamorphic_sentinel) {
193           gen++;
194           if (code_is_interpreted) with++;
195         }
196         total++;
197         break;
198       }
199       case FeedbackSlotKind::kBinaryOp:
200         // If we are not running interpreted code, we need to ignore the special
201         // IC slots for binaryop/compare used by the interpreter.
202         // TODO(mvstanton): Remove code_is_interpreted when full code is retired
203         // from service.
204         if (code_is_interpreted) {
205           int const feedback = Smi::cast(obj)->value();
206           BinaryOperationHint hint = BinaryOperationHintFromFeedback(feedback);
207           if (hint == BinaryOperationHint::kAny) {
208             gen++;
209           }
210           if (hint != BinaryOperationHint::kNone) {
211             with++;
212           }
213           total++;
214         }
215         break;
216       case FeedbackSlotKind::kCompareOp: {
217         // If we are not running interpreted code, we need to ignore the special
218         // IC slots for binaryop/compare used by the interpreter.
219         // TODO(mvstanton): Remove code_is_interpreted when full code is retired
220         // from service.
221         if (code_is_interpreted) {
222           int const feedback = Smi::cast(obj)->value();
223           CompareOperationHint hint =
224               CompareOperationHintFromFeedback(feedback);
225           if (hint == CompareOperationHint::kAny) {
226             gen++;
227           }
228           if (hint != CompareOperationHint::kNone) {
229             with++;
230           }
231           total++;
232         }
233         break;
234       }
235       case FeedbackSlotKind::kToBoolean:
236       case FeedbackSlotKind::kCreateClosure:
237       case FeedbackSlotKind::kGeneral:
238       case FeedbackSlotKind::kLiteral:
239         break;
240       case FeedbackSlotKind::kInvalid:
241       case FeedbackSlotKind::kKindsNumber:
242         UNREACHABLE();
243         break;
244     }
245   }
246 
247   *with_type_info = with;
248   *generic = gen;
249   *vector_ic_count = total;
250 }
251 
UninitializedSentinel(Isolate * isolate)252 Handle<Symbol> FeedbackVector::UninitializedSentinel(Isolate* isolate) {
253   return isolate->factory()->uninitialized_symbol();
254 }
255 
MegamorphicSentinel(Isolate * isolate)256 Handle<Symbol> FeedbackVector::MegamorphicSentinel(Isolate* isolate) {
257   return isolate->factory()->megamorphic_symbol();
258 }
259 
PremonomorphicSentinel(Isolate * isolate)260 Handle<Symbol> FeedbackVector::PremonomorphicSentinel(Isolate* isolate) {
261   return isolate->factory()->premonomorphic_symbol();
262 }
263 
RawUninitializedSentinel(Isolate * isolate)264 Symbol* FeedbackVector::RawUninitializedSentinel(Isolate* isolate) {
265   return isolate->heap()->uninitialized_symbol();
266 }
267 
HasNext()268 bool FeedbackMetadataIterator::HasNext() const {
269   return next_slot_.ToInt() < metadata()->slot_count();
270 }
271 
Next()272 FeedbackSlot FeedbackMetadataIterator::Next() {
273   DCHECK(HasNext());
274   cur_slot_ = next_slot_;
275   slot_kind_ = metadata()->GetKind(cur_slot_);
276   next_slot_ = FeedbackSlot(next_slot_.ToInt() + entry_size());
277   return cur_slot_;
278 }
279 
entry_size()280 int FeedbackMetadataIterator::entry_size() const {
281   return FeedbackMetadata::GetSlotSize(kind());
282 }
283 
GetFeedback()284 Object* FeedbackNexus::GetFeedback() const { return vector()->Get(slot()); }
285 
GetFeedbackExtra()286 Object* FeedbackNexus::GetFeedbackExtra() const {
287 #ifdef DEBUG
288   FeedbackSlotKind kind = vector()->GetKind(slot());
289   DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
290 #endif
291   int extra_index = vector()->GetIndex(slot()) + 1;
292   return vector()->get(extra_index);
293 }
294 
SetFeedback(Object * feedback,WriteBarrierMode mode)295 void FeedbackNexus::SetFeedback(Object* feedback, WriteBarrierMode mode) {
296   vector()->Set(slot(), feedback, mode);
297 }
298 
SetFeedbackExtra(Object * feedback_extra,WriteBarrierMode mode)299 void FeedbackNexus::SetFeedbackExtra(Object* feedback_extra,
300                                      WriteBarrierMode mode) {
301 #ifdef DEBUG
302   FeedbackSlotKind kind = vector()->GetKind(slot());
303   DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
304 #endif
305   int index = vector()->GetIndex(slot()) + 1;
306   vector()->set(index, feedback_extra, mode);
307 }
308 
GetIsolate()309 Isolate* FeedbackNexus::GetIsolate() const { return vector()->GetIsolate(); }
310 }  // namespace internal
311 }  // namespace v8
312 
313 #endif  // V8_FEEDBACK_VECTOR_INL_H_
314