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