OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/type-feedback-vector.h" | 5 #include "src/type-feedback-vector.h" |
6 | 6 |
7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
8 #include "src/ic/ic.h" | 8 #include "src/ic/ic.h" |
9 #include "src/ic/ic-state.h" | 9 #include "src/ic/ic-state.h" |
10 #include "src/objects.h" | 10 #include "src/objects.h" |
11 #include "src/type-feedback-vector-inl.h" | 11 #include "src/type-feedback-vector-inl.h" |
12 | 12 |
13 namespace v8 { | 13 namespace v8 { |
14 namespace internal { | 14 namespace internal { |
15 | 15 |
16 std::ostream& operator<<(std::ostream& os, FeedbackVectorSlotKind kind) { | 16 std::ostream& operator<<(std::ostream& os, FeedbackVectorSlotKind kind) { |
17 return os << TypeFeedbackVector::Kind2String(kind); | 17 return os << TypeFeedbackMetadata::Kind2String(kind); |
18 } | 18 } |
19 | 19 |
20 | 20 |
21 FeedbackVectorSlotKind TypeFeedbackVector::GetKind( | 21 FeedbackVectorSlotKind TypeFeedbackMetadata::GetKind( |
22 FeedbackVectorSlot slot) const { | 22 FeedbackVectorSlot slot) const { |
23 int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt()); | 23 int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt()); |
24 int data = Smi::cast(get(index))->value(); | 24 int data = Smi::cast(get(index))->value(); |
25 return VectorICComputer::decode(data, slot.ToInt()); | 25 return VectorICComputer::decode(data, slot.ToInt()); |
26 } | 26 } |
27 | 27 |
28 | 28 |
29 void TypeFeedbackVector::SetKind(FeedbackVectorSlot slot, | 29 void TypeFeedbackMetadata::SetKind(FeedbackVectorSlot slot, |
30 FeedbackVectorSlotKind kind) { | 30 FeedbackVectorSlotKind kind) { |
31 int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt()); | 31 int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt()); |
32 int data = Smi::cast(get(index))->value(); | 32 int data = Smi::cast(get(index))->value(); |
33 int new_data = VectorICComputer::encode(data, slot.ToInt(), kind); | 33 int new_data = VectorICComputer::encode(data, slot.ToInt(), kind); |
34 set(index, Smi::FromInt(new_data)); | 34 set(index, Smi::FromInt(new_data)); |
35 } | 35 } |
36 | 36 |
37 | 37 |
38 template Handle<TypeFeedbackVector> TypeFeedbackVector::New( | 38 template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New( |
39 Isolate* isolate, const StaticFeedbackVectorSpec* spec); | 39 Isolate* isolate, const StaticFeedbackVectorSpec* spec); |
40 template Handle<TypeFeedbackVector> TypeFeedbackVector::New( | 40 template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New( |
41 Isolate* isolate, const FeedbackVectorSpec* spec); | 41 Isolate* isolate, const FeedbackVectorSpec* spec); |
42 | 42 |
43 | 43 |
44 // static | 44 // static |
45 template <typename Spec> | 45 template <typename Spec> |
46 Handle<TypeFeedbackVector> TypeFeedbackVector::New(Isolate* isolate, | 46 Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(Isolate* isolate, |
47 const Spec* spec) { | 47 const Spec* spec) { |
48 const int slot_count = spec->slots(); | 48 const int slot_count = spec->slots(); |
49 const int index_count = VectorICComputer::word_count(slot_count); | 49 const int slot_kinds_length = VectorICComputer::word_count(slot_count); |
50 const int length = slot_count + index_count + kReservedIndexCount; | 50 const int length = slot_kinds_length + kReservedIndexCount; |
51 if (length == kReservedIndexCount) { | 51 if (length == kReservedIndexCount) { |
52 return Handle<TypeFeedbackVector>::cast( | 52 return Handle<TypeFeedbackMetadata>::cast( |
53 isolate->factory()->empty_fixed_array()); | 53 isolate->factory()->empty_fixed_array()); |
54 } | 54 } |
55 #ifdef DEBUG | 55 #ifdef DEBUG |
56 for (int i = 0; i < slot_count;) { | 56 for (int i = 0; i < slot_count;) { |
57 FeedbackVectorSlotKind kind = spec->GetKind(i); | 57 FeedbackVectorSlotKind kind = spec->GetKind(i); |
58 int entry_size = TypeFeedbackVector::GetSlotSize(kind); | 58 int entry_size = TypeFeedbackMetadata::GetSlotSize(kind); |
59 for (int j = 1; j < entry_size; j++) { | 59 for (int j = 1; j < entry_size; j++) { |
60 FeedbackVectorSlotKind kind = spec->GetKind(i + j); | 60 FeedbackVectorSlotKind kind = spec->GetKind(i + j); |
61 DCHECK_EQ(FeedbackVectorSlotKind::INVALID, kind); | 61 DCHECK_EQ(FeedbackVectorSlotKind::INVALID, kind); |
62 } | 62 } |
63 i += entry_size; | 63 i += entry_size; |
64 } | 64 } |
65 #endif | 65 #endif |
66 | 66 |
67 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length, TENURED); | 67 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length, TENURED); |
68 array->set(kSlotsCountIndex, Smi::FromInt(slot_count)); | 68 array->set(kSlotsCountIndex, Smi::FromInt(slot_count)); |
69 array->set(kWithTypesIndex, Smi::FromInt(0)); | 69 // Fill the bit-vector part with zeros. |
70 array->set(kGenericCountIndex, Smi::FromInt(0)); | 70 for (int i = 0; i < slot_kinds_length; i++) { |
71 // Fill the indexes with zeros. | |
72 for (int i = 0; i < index_count; i++) { | |
73 array->set(kReservedIndexCount + i, Smi::FromInt(0)); | 71 array->set(kReservedIndexCount + i, Smi::FromInt(0)); |
74 } | 72 } |
75 | 73 |
| 74 Handle<TypeFeedbackMetadata> metadata = |
| 75 Handle<TypeFeedbackMetadata>::cast(array); |
| 76 for (int i = 0; i < slot_count; i++) { |
| 77 metadata->SetKind(FeedbackVectorSlot(i), spec->GetKind(i)); |
| 78 } |
| 79 return metadata; |
| 80 } |
| 81 |
| 82 |
| 83 bool TypeFeedbackMetadata::SpecDiffersFrom( |
| 84 const FeedbackVectorSpec* other_spec) const { |
| 85 if (other_spec->slots() != slot_count()) { |
| 86 return true; |
| 87 } |
| 88 |
| 89 int slots = slot_count(); |
| 90 for (int i = 0; i < slots; i++) { |
| 91 if (GetKind(FeedbackVectorSlot(i)) != other_spec->GetKind(i)) { |
| 92 return true; |
| 93 } |
| 94 } |
| 95 return false; |
| 96 } |
| 97 |
| 98 |
| 99 const char* TypeFeedbackMetadata::Kind2String(FeedbackVectorSlotKind kind) { |
| 100 switch (kind) { |
| 101 case FeedbackVectorSlotKind::INVALID: |
| 102 return "INVALID"; |
| 103 case FeedbackVectorSlotKind::CALL_IC: |
| 104 return "CALL_IC"; |
| 105 case FeedbackVectorSlotKind::LOAD_IC: |
| 106 return "LOAD_IC"; |
| 107 case FeedbackVectorSlotKind::KEYED_LOAD_IC: |
| 108 return "KEYED_LOAD_IC"; |
| 109 case FeedbackVectorSlotKind::STORE_IC: |
| 110 return "STORE_IC"; |
| 111 case FeedbackVectorSlotKind::KEYED_STORE_IC: |
| 112 return "KEYED_STORE_IC"; |
| 113 case FeedbackVectorSlotKind::GENERAL: |
| 114 return "STUB"; |
| 115 case FeedbackVectorSlotKind::KINDS_NUMBER: |
| 116 break; |
| 117 } |
| 118 UNREACHABLE(); |
| 119 return "?"; |
| 120 } |
| 121 |
| 122 |
| 123 // static |
| 124 Handle<TypeFeedbackVector> TypeFeedbackVector::New( |
| 125 Isolate* isolate, Handle<TypeFeedbackMetadata> metadata) { |
| 126 Factory* factory = isolate->factory(); |
| 127 |
| 128 const int slot_count = metadata->slot_count(); |
| 129 const int length = slot_count + kReservedIndexCount; |
| 130 if (length == kReservedIndexCount) { |
| 131 return Handle<TypeFeedbackVector>::cast(factory->empty_fixed_array()); |
| 132 } |
| 133 |
| 134 Handle<FixedArray> array = factory->NewFixedArray(length, TENURED); |
| 135 array->set(kMetadataIndex, *metadata); |
| 136 array->set(kWithTypesIndex, Smi::FromInt(0)); |
| 137 array->set(kGenericCountIndex, Smi::FromInt(0)); |
| 138 |
76 // Ensure we can skip the write barrier | 139 // Ensure we can skip the write barrier |
77 Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate); | 140 Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate); |
78 DCHECK_EQ(isolate->heap()->uninitialized_symbol(), *uninitialized_sentinel); | 141 DCHECK_EQ(*factory->uninitialized_symbol(), *uninitialized_sentinel); |
79 for (int i = kReservedIndexCount + index_count; i < length; i++) { | 142 for (int i = kReservedIndexCount; i < length; i++) { |
80 array->set(i, *uninitialized_sentinel, SKIP_WRITE_BARRIER); | 143 array->set(i, *uninitialized_sentinel, SKIP_WRITE_BARRIER); |
81 } | 144 } |
82 | 145 |
83 Handle<TypeFeedbackVector> vector = Handle<TypeFeedbackVector>::cast(array); | 146 return Handle<TypeFeedbackVector>::cast(array); |
84 for (int i = 0; i < slot_count; i++) { | |
85 vector->SetKind(FeedbackVectorSlot(i), spec->GetKind(i)); | |
86 } | |
87 return vector; | |
88 } | 147 } |
89 | 148 |
90 | 149 |
91 // static | 150 // static |
92 int TypeFeedbackVector::GetIndexFromSpec(const FeedbackVectorSpec* spec, | 151 int TypeFeedbackVector::GetIndexFromSpec(const FeedbackVectorSpec* spec, |
93 FeedbackVectorSlot slot) { | 152 FeedbackVectorSlot slot) { |
94 const int slot_count = spec->slots(); | 153 return kReservedIndexCount + slot.ToInt(); |
95 const int index_count = VectorICComputer::word_count(slot_count); | |
96 return kReservedIndexCount + index_count + slot.ToInt(); | |
97 } | 154 } |
98 | 155 |
99 | 156 |
100 // static | 157 // static |
101 int TypeFeedbackVector::PushAppliedArgumentsIndex() { | 158 int TypeFeedbackVector::PushAppliedArgumentsIndex() { |
102 const int index_count = VectorICComputer::word_count(1); | 159 return kReservedIndexCount; |
103 return kReservedIndexCount + index_count; | |
104 } | 160 } |
105 | 161 |
106 | 162 |
107 // static | 163 // static |
108 Handle<TypeFeedbackVector> TypeFeedbackVector::CreatePushAppliedArgumentsVector( | 164 Handle<TypeFeedbackVector> TypeFeedbackVector::CreatePushAppliedArgumentsVector( |
109 Isolate* isolate) { | 165 Isolate* isolate) { |
110 StaticFeedbackVectorSpec spec; | 166 StaticFeedbackVectorSpec spec; |
111 FeedbackVectorSlot slot = spec.AddKeyedLoadICSlot(); | 167 FeedbackVectorSlot slot = spec.AddKeyedLoadICSlot(); |
| 168 // TODO(ishell): allocate this metadata only once. |
| 169 Handle<TypeFeedbackMetadata> feedback_metadata = |
| 170 TypeFeedbackMetadata::New(isolate, &spec); |
112 Handle<TypeFeedbackVector> feedback_vector = | 171 Handle<TypeFeedbackVector> feedback_vector = |
113 TypeFeedbackVector::New(isolate, &spec); | 172 TypeFeedbackVector::New(isolate, feedback_metadata); |
114 DCHECK_EQ(PushAppliedArgumentsIndex(), feedback_vector->GetIndex(slot)); | 173 DCHECK_EQ(PushAppliedArgumentsIndex(), feedback_vector->GetIndex(slot)); |
115 USE(slot); | 174 USE(slot); |
116 return feedback_vector; | 175 return feedback_vector; |
117 } | 176 } |
118 | 177 |
119 | 178 |
120 // static | 179 // static |
121 Handle<TypeFeedbackVector> TypeFeedbackVector::Copy( | 180 Handle<TypeFeedbackVector> TypeFeedbackVector::Copy( |
122 Isolate* isolate, Handle<TypeFeedbackVector> vector) { | 181 Isolate* isolate, Handle<TypeFeedbackVector> vector) { |
123 Handle<TypeFeedbackVector> result; | 182 Handle<TypeFeedbackVector> result; |
124 result = Handle<TypeFeedbackVector>::cast( | 183 result = Handle<TypeFeedbackVector>::cast( |
125 isolate->factory()->CopyFixedArray(Handle<FixedArray>::cast(vector))); | 184 isolate->factory()->CopyFixedArray(Handle<FixedArray>::cast(vector))); |
126 return result; | 185 return result; |
127 } | 186 } |
128 | 187 |
129 | 188 |
130 bool TypeFeedbackVector::SpecDiffersFrom( | |
131 const FeedbackVectorSpec* other_spec) const { | |
132 if (other_spec->slots() != Slots()) { | |
133 return true; | |
134 } | |
135 | |
136 int slots = Slots(); | |
137 for (int i = 0; i < slots; i++) { | |
138 if (GetKind(FeedbackVectorSlot(i)) != other_spec->GetKind(i)) { | |
139 return true; | |
140 } | |
141 } | |
142 return false; | |
143 } | |
144 | |
145 | |
146 // This logic is copied from | 189 // This logic is copied from |
147 // StaticMarkingVisitor<StaticVisitor>::VisitCodeTarget. | 190 // StaticMarkingVisitor<StaticVisitor>::VisitCodeTarget. |
148 static bool ClearLogic(Isolate* isolate) { | 191 static bool ClearLogic(Isolate* isolate) { |
149 return FLAG_cleanup_code_caches_at_gc && isolate->serializer_enabled(); | 192 return FLAG_cleanup_code_caches_at_gc && isolate->serializer_enabled(); |
150 } | 193 } |
151 | 194 |
152 | 195 |
153 void TypeFeedbackVector::ClearSlotsImpl(SharedFunctionInfo* shared, | 196 void TypeFeedbackVector::ClearSlotsImpl(SharedFunctionInfo* shared, |
154 bool force_clear) { | 197 bool force_clear) { |
155 Isolate* isolate = GetIsolate(); | 198 Isolate* isolate = GetIsolate(); |
156 | 199 |
157 if (!force_clear && !ClearLogic(isolate)) return; | 200 if (!force_clear && !ClearLogic(isolate)) return; |
158 | 201 |
159 Object* uninitialized_sentinel = | 202 Object* uninitialized_sentinel = |
160 TypeFeedbackVector::RawUninitializedSentinel(isolate); | 203 TypeFeedbackVector::RawUninitializedSentinel(isolate); |
161 | 204 |
162 TypeFeedbackMetadataIterator iter(this); | 205 TypeFeedbackMetadataIterator iter(metadata()); |
163 while (iter.HasNext()) { | 206 while (iter.HasNext()) { |
164 FeedbackVectorSlot slot = iter.Next(); | 207 FeedbackVectorSlot slot = iter.Next(); |
165 FeedbackVectorSlotKind kind = iter.kind(); | 208 FeedbackVectorSlotKind kind = iter.kind(); |
166 | 209 |
167 Object* obj = Get(slot); | 210 Object* obj = Get(slot); |
168 if (obj != uninitialized_sentinel) { | 211 if (obj != uninitialized_sentinel) { |
169 switch (kind) { | 212 switch (kind) { |
170 case FeedbackVectorSlotKind::CALL_IC: { | 213 case FeedbackVectorSlotKind::CALL_IC: { |
171 CallICNexus nexus(this, slot); | 214 CallICNexus nexus(this, slot); |
172 nexus.Clear(shared->code()); | 215 nexus.Clear(shared->code()); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 } | 272 } |
230 | 273 |
231 | 274 |
232 void TypeFeedbackVector::ClearKeyedStoreICs(SharedFunctionInfo* shared) { | 275 void TypeFeedbackVector::ClearKeyedStoreICs(SharedFunctionInfo* shared) { |
233 Isolate* isolate = GetIsolate(); | 276 Isolate* isolate = GetIsolate(); |
234 | 277 |
235 Code* host = shared->code(); | 278 Code* host = shared->code(); |
236 Object* uninitialized_sentinel = | 279 Object* uninitialized_sentinel = |
237 TypeFeedbackVector::RawUninitializedSentinel(isolate); | 280 TypeFeedbackVector::RawUninitializedSentinel(isolate); |
238 | 281 |
239 TypeFeedbackMetadataIterator iter(this); | 282 TypeFeedbackMetadataIterator iter(metadata()); |
240 while (iter.HasNext()) { | 283 while (iter.HasNext()) { |
241 FeedbackVectorSlot slot = iter.Next(); | 284 FeedbackVectorSlot slot = iter.Next(); |
242 FeedbackVectorSlotKind kind = iter.kind(); | 285 FeedbackVectorSlotKind kind = iter.kind(); |
243 if (kind != FeedbackVectorSlotKind::KEYED_STORE_IC) continue; | 286 if (kind != FeedbackVectorSlotKind::KEYED_STORE_IC) continue; |
244 Object* obj = Get(slot); | 287 Object* obj = Get(slot); |
245 if (obj != uninitialized_sentinel) { | 288 if (obj != uninitialized_sentinel) { |
246 DCHECK(FLAG_vector_stores); | 289 DCHECK(FLAG_vector_stores); |
247 KeyedStoreICNexus nexus(this, slot); | 290 KeyedStoreICNexus nexus(this, slot); |
248 nexus.Clear(host); | 291 nexus.Clear(host); |
249 } | 292 } |
250 } | 293 } |
251 } | 294 } |
252 | 295 |
253 | 296 |
254 // static | 297 // static |
255 Handle<TypeFeedbackVector> TypeFeedbackVector::DummyVector(Isolate* isolate) { | 298 Handle<TypeFeedbackVector> TypeFeedbackVector::DummyVector(Isolate* isolate) { |
256 return isolate->factory()->dummy_vector(); | 299 return isolate->factory()->dummy_vector(); |
257 } | 300 } |
258 | 301 |
259 | 302 |
260 const char* TypeFeedbackVector::Kind2String(FeedbackVectorSlotKind kind) { | |
261 switch (kind) { | |
262 case FeedbackVectorSlotKind::INVALID: | |
263 return "INVALID"; | |
264 case FeedbackVectorSlotKind::CALL_IC: | |
265 return "CALL_IC"; | |
266 case FeedbackVectorSlotKind::LOAD_IC: | |
267 return "LOAD_IC"; | |
268 case FeedbackVectorSlotKind::KEYED_LOAD_IC: | |
269 return "KEYED_LOAD_IC"; | |
270 case FeedbackVectorSlotKind::STORE_IC: | |
271 return "STORE_IC"; | |
272 case FeedbackVectorSlotKind::KEYED_STORE_IC: | |
273 return "KEYED_STORE_IC"; | |
274 case FeedbackVectorSlotKind::GENERAL: | |
275 return "STUB"; | |
276 case FeedbackVectorSlotKind::KINDS_NUMBER: | |
277 break; | |
278 } | |
279 UNREACHABLE(); | |
280 return "?"; | |
281 } | |
282 | |
283 | |
284 Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) { | 303 Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) { |
285 Isolate* isolate = GetIsolate(); | 304 Isolate* isolate = GetIsolate(); |
286 Handle<Object> feedback = handle(GetFeedback(), isolate); | 305 Handle<Object> feedback = handle(GetFeedback(), isolate); |
287 if (!feedback->IsFixedArray() || | 306 if (!feedback->IsFixedArray() || |
288 FixedArray::cast(*feedback)->length() != length) { | 307 FixedArray::cast(*feedback)->length() != length) { |
289 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length); | 308 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length); |
290 SetFeedback(*array); | 309 SetFeedback(*array); |
291 return array; | 310 return array; |
292 } | 311 } |
293 return Handle<FixedArray>::cast(feedback); | 312 return Handle<FixedArray>::cast(feedback); |
(...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
805 return mode; | 824 return mode; |
806 } | 825 } |
807 | 826 |
808 | 827 |
809 IcCheckType KeyedStoreICNexus::GetKeyType() const { | 828 IcCheckType KeyedStoreICNexus::GetKeyType() const { |
810 // The structure of the vector slots tells us the type. | 829 // The structure of the vector slots tells us the type. |
811 return GetFeedback()->IsName() ? PROPERTY : ELEMENT; | 830 return GetFeedback()->IsName() ? PROPERTY : ELEMENT; |
812 } | 831 } |
813 } // namespace internal | 832 } // namespace internal |
814 } // namespace v8 | 833 } // namespace v8 |
OLD | NEW |