• 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_TYPE_FEEDBACK_VECTOR_INL_H_
6 #define V8_TYPE_FEEDBACK_VECTOR_INL_H_
7 
8 #include "src/type-feedback-vector.h"
9 
10 namespace v8 {
11 namespace internal {
12 
13 
14 template <typename Derived>
AddSlot(FeedbackVectorSlotKind kind)15 FeedbackVectorSlot FeedbackVectorSpecBase<Derived>::AddSlot(
16     FeedbackVectorSlotKind kind) {
17   int slot = This()->slots();
18   int entries_per_slot = TypeFeedbackMetadata::GetSlotSize(kind);
19   This()->append(kind);
20   for (int i = 1; i < entries_per_slot; i++) {
21     This()->append(FeedbackVectorSlotKind::INVALID);
22   }
23   return FeedbackVectorSlot(slot);
24 }
25 
26 
27 // static
cast(Object * obj)28 TypeFeedbackMetadata* TypeFeedbackMetadata::cast(Object* obj) {
29   DCHECK(obj->IsTypeFeedbackVector());
30   return reinterpret_cast<TypeFeedbackMetadata*>(obj);
31 }
32 
is_empty()33 bool TypeFeedbackMetadata::is_empty() const {
34   if (length() == 0) return true;
35   return false;
36 }
37 
slot_count()38 int TypeFeedbackMetadata::slot_count() const {
39   if (length() == 0) return 0;
40   DCHECK(length() > kReservedIndexCount);
41   return Smi::cast(get(kSlotsCountIndex))->value();
42 }
43 
44 
45 // static
cast(Object * obj)46 TypeFeedbackVector* TypeFeedbackVector::cast(Object* obj) {
47   DCHECK(obj->IsTypeFeedbackVector());
48   return reinterpret_cast<TypeFeedbackVector*>(obj);
49 }
50 
51 
GetSlotSize(FeedbackVectorSlotKind kind)52 int TypeFeedbackMetadata::GetSlotSize(FeedbackVectorSlotKind kind) {
53   DCHECK_NE(FeedbackVectorSlotKind::INVALID, kind);
54   DCHECK_NE(FeedbackVectorSlotKind::KINDS_NUMBER, kind);
55   return kind == FeedbackVectorSlotKind::GENERAL ? 1 : 2;
56 }
57 
SlotRequiresName(FeedbackVectorSlotKind kind)58 bool TypeFeedbackMetadata::SlotRequiresName(FeedbackVectorSlotKind kind) {
59   switch (kind) {
60     case FeedbackVectorSlotKind::LOAD_GLOBAL_IC:
61       return true;
62 
63     case FeedbackVectorSlotKind::CALL_IC:
64     case FeedbackVectorSlotKind::LOAD_IC:
65     case FeedbackVectorSlotKind::KEYED_LOAD_IC:
66     case FeedbackVectorSlotKind::STORE_IC:
67     case FeedbackVectorSlotKind::KEYED_STORE_IC:
68     case FeedbackVectorSlotKind::GENERAL:
69     case FeedbackVectorSlotKind::INVALID:
70       return false;
71 
72     case FeedbackVectorSlotKind::KINDS_NUMBER:
73       break;
74   }
75   UNREACHABLE();
76   return false;
77 }
78 
is_empty()79 bool TypeFeedbackVector::is_empty() const {
80   if (length() == 0) return true;
81   DCHECK(length() > kReservedIndexCount);
82   return false;
83 }
84 
85 
slot_count()86 int TypeFeedbackVector::slot_count() const {
87   if (length() == 0) return 0;
88   DCHECK(length() > kReservedIndexCount);
89   return length() - kReservedIndexCount;
90 }
91 
92 
metadata()93 TypeFeedbackMetadata* TypeFeedbackVector::metadata() const {
94   return is_empty() ? TypeFeedbackMetadata::cast(GetHeap()->empty_fixed_array())
95                     : TypeFeedbackMetadata::cast(get(kMetadataIndex));
96 }
97 
98 // Conversion from an integer index to either a slot or an ic slot.
99 // static
ToSlot(int index)100 FeedbackVectorSlot TypeFeedbackVector::ToSlot(int index) {
101   DCHECK(index >= kReservedIndexCount);
102   return FeedbackVectorSlot(index - kReservedIndexCount);
103 }
104 
105 
Get(FeedbackVectorSlot slot)106 Object* TypeFeedbackVector::Get(FeedbackVectorSlot slot) const {
107   return get(GetIndex(slot));
108 }
109 
110 
Set(FeedbackVectorSlot slot,Object * value,WriteBarrierMode mode)111 void TypeFeedbackVector::Set(FeedbackVectorSlot slot, Object* value,
112                              WriteBarrierMode mode) {
113   set(GetIndex(slot), value, mode);
114 }
115 
116 
ComputeCounts(int * with_type_info,int * generic)117 void TypeFeedbackVector::ComputeCounts(int* with_type_info, int* generic) {
118   Object* uninitialized_sentinel =
119       TypeFeedbackVector::RawUninitializedSentinel(GetIsolate());
120   Object* megamorphic_sentinel =
121       *TypeFeedbackVector::MegamorphicSentinel(GetIsolate());
122   int with = 0;
123   int gen = 0;
124   TypeFeedbackMetadataIterator iter(metadata());
125   while (iter.HasNext()) {
126     FeedbackVectorSlot slot = iter.Next();
127     FeedbackVectorSlotKind kind = iter.kind();
128 
129     Object* obj = Get(slot);
130     if (obj != uninitialized_sentinel &&
131         kind != FeedbackVectorSlotKind::GENERAL) {
132       if (obj->IsWeakCell() || obj->IsFixedArray() || obj->IsString()) {
133         with++;
134       } else if (obj == megamorphic_sentinel) {
135         gen++;
136       }
137     }
138   }
139 
140   *with_type_info = with;
141   *generic = gen;
142 }
143 
UninitializedSentinel(Isolate * isolate)144 Handle<Symbol> TypeFeedbackVector::UninitializedSentinel(Isolate* isolate) {
145   return isolate->factory()->uninitialized_symbol();
146 }
147 
MegamorphicSentinel(Isolate * isolate)148 Handle<Symbol> TypeFeedbackVector::MegamorphicSentinel(Isolate* isolate) {
149   return isolate->factory()->megamorphic_symbol();
150 }
151 
PremonomorphicSentinel(Isolate * isolate)152 Handle<Symbol> TypeFeedbackVector::PremonomorphicSentinel(Isolate* isolate) {
153   return isolate->factory()->premonomorphic_symbol();
154 }
155 
RawUninitializedSentinel(Isolate * isolate)156 Symbol* TypeFeedbackVector::RawUninitializedSentinel(Isolate* isolate) {
157   return isolate->heap()->uninitialized_symbol();
158 }
159 
HasNext()160 bool TypeFeedbackMetadataIterator::HasNext() const {
161   return next_slot_.ToInt() < metadata()->slot_count();
162 }
163 
Next()164 FeedbackVectorSlot TypeFeedbackMetadataIterator::Next() {
165   DCHECK(HasNext());
166   cur_slot_ = next_slot_;
167   slot_kind_ = metadata()->GetKind(cur_slot_);
168   next_slot_ = FeedbackVectorSlot(next_slot_.ToInt() + entry_size());
169   return cur_slot_;
170 }
171 
entry_size()172 int TypeFeedbackMetadataIterator::entry_size() const {
173   return TypeFeedbackMetadata::GetSlotSize(kind());
174 }
175 
GetFeedback()176 Object* FeedbackNexus::GetFeedback() const { return vector()->Get(slot()); }
177 
178 
GetFeedbackExtra()179 Object* FeedbackNexus::GetFeedbackExtra() const {
180 #ifdef DEBUG
181   FeedbackVectorSlotKind kind = vector()->GetKind(slot());
182   DCHECK_LT(1, TypeFeedbackMetadata::GetSlotSize(kind));
183 #endif
184   int extra_index = vector()->GetIndex(slot()) + 1;
185   return vector()->get(extra_index);
186 }
187 
188 
SetFeedback(Object * feedback,WriteBarrierMode mode)189 void FeedbackNexus::SetFeedback(Object* feedback, WriteBarrierMode mode) {
190   vector()->Set(slot(), feedback, mode);
191 }
192 
193 
SetFeedbackExtra(Object * feedback_extra,WriteBarrierMode mode)194 void FeedbackNexus::SetFeedbackExtra(Object* feedback_extra,
195                                      WriteBarrierMode mode) {
196 #ifdef DEBUG
197   FeedbackVectorSlotKind kind = vector()->GetKind(slot());
198   DCHECK_LT(1, TypeFeedbackMetadata::GetSlotSize(kind));
199 #endif
200   int index = vector()->GetIndex(slot()) + 1;
201   vector()->set(index, feedback_extra, mode);
202 }
203 
204 
GetIsolate()205 Isolate* FeedbackNexus::GetIsolate() const { return vector()->GetIsolate(); }
206 }  // namespace internal
207 }  // namespace v8
208 
209 #endif  // V8_TYPE_FEEDBACK_VECTOR_INL_H_
210