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-inl.h" | 8 #include "src/ic/ic-inl.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" |
(...skipping 19 matching lines...) Expand all Loading... |
30 } | 30 } |
31 | 31 |
32 | 32 |
33 FeedbackVectorSlotKind TypeFeedbackMetadata::GetKind( | 33 FeedbackVectorSlotKind TypeFeedbackMetadata::GetKind( |
34 FeedbackVectorSlot slot) const { | 34 FeedbackVectorSlot slot) const { |
35 int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt()); | 35 int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt()); |
36 int data = Smi::cast(get(index))->value(); | 36 int data = Smi::cast(get(index))->value(); |
37 return VectorICComputer::decode(data, slot.ToInt()); | 37 return VectorICComputer::decode(data, slot.ToInt()); |
38 } | 38 } |
39 | 39 |
40 int TypeFeedbackMetadata::GetParameter(int parameter_index) const { | |
41 FixedArray* parameters = FixedArray::cast(get(kParametersTableIndex)); | |
42 return Smi::cast(parameters->get(parameter_index))->value(); | |
43 } | |
44 | |
45 void TypeFeedbackMetadata::SetKind(FeedbackVectorSlot slot, | 40 void TypeFeedbackMetadata::SetKind(FeedbackVectorSlot slot, |
46 FeedbackVectorSlotKind kind) { | 41 FeedbackVectorSlotKind kind) { |
47 int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt()); | 42 int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt()); |
48 int data = Smi::cast(get(index))->value(); | 43 int data = Smi::cast(get(index))->value(); |
49 int new_data = VectorICComputer::encode(data, slot.ToInt(), kind); | 44 int new_data = VectorICComputer::encode(data, slot.ToInt(), kind); |
50 set(index, Smi::FromInt(new_data)); | 45 set(index, Smi::FromInt(new_data)); |
51 } | 46 } |
52 | 47 |
53 | 48 |
54 template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New( | 49 template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New( |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 } | 84 } |
90 | 85 |
91 Handle<TypeFeedbackMetadata> metadata = | 86 Handle<TypeFeedbackMetadata> metadata = |
92 Handle<TypeFeedbackMetadata>::cast(array); | 87 Handle<TypeFeedbackMetadata>::cast(array); |
93 | 88 |
94 for (int i = 0; i < slot_count; i++) { | 89 for (int i = 0; i < slot_count; i++) { |
95 FeedbackVectorSlotKind kind = spec->GetKind(i); | 90 FeedbackVectorSlotKind kind = spec->GetKind(i); |
96 metadata->SetKind(FeedbackVectorSlot(i), kind); | 91 metadata->SetKind(FeedbackVectorSlot(i), kind); |
97 } | 92 } |
98 | 93 |
99 if (spec->parameters_count() > 0) { | |
100 const int parameters_count = spec->parameters_count(); | |
101 Handle<FixedArray> params_array = | |
102 factory->NewFixedArray(parameters_count, TENURED); | |
103 for (int i = 0; i < parameters_count; i++) { | |
104 params_array->set(i, Smi::FromInt(spec->GetParameter(i))); | |
105 } | |
106 metadata->set(kParametersTableIndex, *params_array); | |
107 } else { | |
108 metadata->set(kParametersTableIndex, *factory->empty_fixed_array()); | |
109 } | |
110 | |
111 // It's important that the TypeFeedbackMetadata have a COW map, since it's | 94 // It's important that the TypeFeedbackMetadata have a COW map, since it's |
112 // pointed to by both a SharedFunctionInfo and indirectly by closures through | 95 // pointed to by both a SharedFunctionInfo and indirectly by closures through |
113 // the TypeFeedbackVector. The serializer uses the COW map type to decide | 96 // the TypeFeedbackVector. The serializer uses the COW map type to decide |
114 // this object belongs in the startup snapshot and not the partial | 97 // this object belongs in the startup snapshot and not the partial |
115 // snapshot(s). | 98 // snapshot(s). |
116 metadata->set_map(isolate->heap()->fixed_cow_array_map()); | 99 metadata->set_map(isolate->heap()->fixed_cow_array_map()); |
117 | 100 |
118 return metadata; | 101 return metadata; |
119 } | 102 } |
120 | 103 |
121 | 104 |
122 bool TypeFeedbackMetadata::SpecDiffersFrom( | 105 bool TypeFeedbackMetadata::SpecDiffersFrom( |
123 const FeedbackVectorSpec* other_spec) const { | 106 const FeedbackVectorSpec* other_spec) const { |
124 if (other_spec->slots() != slot_count()) { | 107 if (other_spec->slots() != slot_count()) { |
125 return true; | 108 return true; |
126 } | 109 } |
127 | 110 |
128 int slots = slot_count(); | 111 int slots = slot_count(); |
129 int parameter_index = 0; | |
130 for (int i = 0; i < slots;) { | 112 for (int i = 0; i < slots;) { |
131 FeedbackVectorSlot slot(i); | 113 FeedbackVectorSlot slot(i); |
132 FeedbackVectorSlotKind kind = GetKind(slot); | 114 FeedbackVectorSlotKind kind = GetKind(slot); |
133 int entry_size = TypeFeedbackMetadata::GetSlotSize(kind); | 115 int entry_size = TypeFeedbackMetadata::GetSlotSize(kind); |
134 | 116 |
135 if (kind != other_spec->GetKind(i)) { | 117 if (kind != other_spec->GetKind(i)) { |
136 return true; | 118 return true; |
137 } | 119 } |
138 if (SlotRequiresParameter(kind)) { | |
139 int parameter = GetParameter(parameter_index); | |
140 int other_parameter = other_spec->GetParameter(parameter_index); | |
141 if (parameter != other_parameter) { | |
142 return true; | |
143 } | |
144 parameter_index++; | |
145 } | |
146 i += entry_size; | 120 i += entry_size; |
147 } | 121 } |
148 return false; | 122 return false; |
149 } | 123 } |
150 | 124 |
151 bool TypeFeedbackMetadata::DiffersFrom( | 125 bool TypeFeedbackMetadata::DiffersFrom( |
152 const TypeFeedbackMetadata* other_metadata) const { | 126 const TypeFeedbackMetadata* other_metadata) const { |
153 if (other_metadata->slot_count() != slot_count()) { | 127 if (other_metadata->slot_count() != slot_count()) { |
154 return true; | 128 return true; |
155 } | 129 } |
156 | 130 |
157 int slots = slot_count(); | 131 int slots = slot_count(); |
158 int parameter_index = 0; | |
159 for (int i = 0; i < slots;) { | 132 for (int i = 0; i < slots;) { |
160 FeedbackVectorSlot slot(i); | 133 FeedbackVectorSlot slot(i); |
161 FeedbackVectorSlotKind kind = GetKind(slot); | 134 FeedbackVectorSlotKind kind = GetKind(slot); |
162 int entry_size = TypeFeedbackMetadata::GetSlotSize(kind); | 135 int entry_size = TypeFeedbackMetadata::GetSlotSize(kind); |
163 if (GetKind(slot) != other_metadata->GetKind(slot)) { | 136 if (GetKind(slot) != other_metadata->GetKind(slot)) { |
164 return true; | 137 return true; |
165 } | 138 } |
166 if (SlotRequiresParameter(kind)) { | |
167 if (GetParameter(parameter_index) != | |
168 other_metadata->GetParameter(parameter_index)) { | |
169 return true; | |
170 } | |
171 parameter_index++; | |
172 } | |
173 i += entry_size; | 139 i += entry_size; |
174 } | 140 } |
175 return false; | 141 return false; |
176 } | 142 } |
177 | 143 |
178 const char* TypeFeedbackMetadata::Kind2String(FeedbackVectorSlotKind kind) { | 144 const char* TypeFeedbackMetadata::Kind2String(FeedbackVectorSlotKind kind) { |
179 switch (kind) { | 145 switch (kind) { |
180 case FeedbackVectorSlotKind::INVALID: | 146 case FeedbackVectorSlotKind::INVALID: |
181 return "INVALID"; | 147 return "INVALID"; |
182 case FeedbackVectorSlotKind::CALL_IC: | 148 case FeedbackVectorSlotKind::CALL_IC: |
183 return "CALL_IC"; | 149 return "CALL_IC"; |
184 case FeedbackVectorSlotKind::LOAD_IC: | 150 case FeedbackVectorSlotKind::LOAD_IC: |
185 return "LOAD_IC"; | 151 return "LOAD_IC"; |
186 case FeedbackVectorSlotKind::LOAD_GLOBAL_IC: | 152 case FeedbackVectorSlotKind::LOAD_GLOBAL_IC: |
187 return "LOAD_GLOBAL_IC"; | 153 return "LOAD_GLOBAL_IC"; |
188 case FeedbackVectorSlotKind::KEYED_LOAD_IC: | 154 case FeedbackVectorSlotKind::KEYED_LOAD_IC: |
189 return "KEYED_LOAD_IC"; | 155 return "KEYED_LOAD_IC"; |
190 case FeedbackVectorSlotKind::STORE_IC: | 156 case FeedbackVectorSlotKind::STORE_IC: |
191 return "STORE_IC"; | 157 return "STORE_IC"; |
192 case FeedbackVectorSlotKind::KEYED_STORE_IC: | 158 case FeedbackVectorSlotKind::KEYED_STORE_IC: |
193 return "KEYED_STORE_IC"; | 159 return "KEYED_STORE_IC"; |
194 case FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC: | 160 case FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC: |
195 return "INTERPRETER_BINARYOP_IC"; | 161 return "INTERPRETER_BINARYOP_IC"; |
196 case FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC: | 162 case FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC: |
197 return "INTERPRETER_COMPARE_IC"; | 163 return "INTERPRETER_COMPARE_IC"; |
198 case FeedbackVectorSlotKind::CREATE_CLOSURE: | |
199 return "CREATE_CLOSURE"; | |
200 case FeedbackVectorSlotKind::GENERAL: | 164 case FeedbackVectorSlotKind::GENERAL: |
201 return "STUB"; | 165 return "STUB"; |
202 case FeedbackVectorSlotKind::KINDS_NUMBER: | 166 case FeedbackVectorSlotKind::KINDS_NUMBER: |
203 break; | 167 break; |
204 } | 168 } |
205 UNREACHABLE(); | 169 UNREACHABLE(); |
206 return "?"; | 170 return "?"; |
207 } | 171 } |
208 | 172 |
209 FeedbackVectorSlotKind TypeFeedbackVector::GetKind( | 173 FeedbackVectorSlotKind TypeFeedbackVector::GetKind( |
210 FeedbackVectorSlot slot) const { | 174 FeedbackVectorSlot slot) const { |
211 DCHECK(!is_empty()); | 175 DCHECK(!is_empty()); |
212 return metadata()->GetKind(slot); | 176 return metadata()->GetKind(slot); |
213 } | 177 } |
214 | 178 |
215 int TypeFeedbackVector::GetParameter(FeedbackVectorSlot slot) const { | |
216 DCHECK(!is_empty()); | |
217 DCHECK( | |
218 TypeFeedbackMetadata::SlotRequiresParameter(metadata()->GetKind(slot))); | |
219 return FixedArray::cast(Get(slot))->length(); | |
220 } | |
221 | |
222 // static | 179 // static |
223 Handle<TypeFeedbackVector> TypeFeedbackVector::New( | 180 Handle<TypeFeedbackVector> TypeFeedbackVector::New( |
224 Isolate* isolate, Handle<TypeFeedbackMetadata> metadata) { | 181 Isolate* isolate, Handle<TypeFeedbackMetadata> metadata) { |
225 Factory* factory = isolate->factory(); | 182 Factory* factory = isolate->factory(); |
226 | 183 |
227 const int slot_count = metadata->slot_count(); | 184 const int slot_count = metadata->slot_count(); |
228 const int length = slot_count + kReservedIndexCount; | 185 const int length = slot_count + kReservedIndexCount; |
229 if (length == kReservedIndexCount) { | 186 if (length == kReservedIndexCount) { |
230 return Handle<TypeFeedbackVector>::cast( | 187 return Handle<TypeFeedbackVector>::cast( |
231 factory->empty_type_feedback_vector()); | 188 factory->empty_type_feedback_vector()); |
232 } | 189 } |
233 | 190 |
234 Handle<FixedArray> array = factory->NewFixedArray(length, TENURED); | 191 Handle<FixedArray> array = factory->NewFixedArray(length, TENURED); |
235 array->set(kMetadataIndex, *metadata); | 192 array->set(kMetadataIndex, *metadata); |
236 array->set(kInvocationCountIndex, Smi::kZero); | 193 array->set(kInvocationCountIndex, Smi::kZero); |
237 int parameter_index = 0; | |
238 for (int i = 0; i < slot_count;) { | |
239 FeedbackVectorSlot slot(i); | |
240 FeedbackVectorSlotKind kind = metadata->GetKind(slot); | |
241 int index = TypeFeedbackVector::GetIndex(slot); | |
242 int entry_size = TypeFeedbackMetadata::GetSlotSize(kind); | |
243 | |
244 if (kind == FeedbackVectorSlotKind::CREATE_CLOSURE) { | |
245 // This fixed array is filled with undefined. | |
246 int length = metadata->GetParameter(parameter_index++); | |
247 if (length == 0) { | |
248 // This is a native function literal. We can always point to | |
249 // the empty literals array here. | |
250 array->set(index, *factory->empty_literals_array(), SKIP_WRITE_BARRIER); | |
251 } else { | |
252 Handle<FixedArray> value = factory->NewFixedArray(length); | |
253 array->set(index, *value); | |
254 } | |
255 } | |
256 i += entry_size; | |
257 } | |
258 | 194 |
259 DisallowHeapAllocation no_gc; | 195 DisallowHeapAllocation no_gc; |
260 | 196 |
261 // Ensure we can skip the write barrier | 197 // Ensure we can skip the write barrier |
262 Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate); | 198 Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate); |
263 DCHECK_EQ(isolate->heap()->uninitialized_symbol(), *uninitialized_sentinel); | 199 DCHECK_EQ(isolate->heap()->uninitialized_symbol(), *uninitialized_sentinel); |
264 for (int i = 0; i < slot_count;) { | 200 for (int i = 0; i < slot_count;) { |
265 FeedbackVectorSlot slot(i); | 201 FeedbackVectorSlot slot(i); |
266 FeedbackVectorSlotKind kind = metadata->GetKind(slot); | 202 FeedbackVectorSlotKind kind = metadata->GetKind(slot); |
267 int index = TypeFeedbackVector::GetIndex(slot); | 203 int index = TypeFeedbackVector::GetIndex(slot); |
268 int entry_size = TypeFeedbackMetadata::GetSlotSize(kind); | 204 int entry_size = TypeFeedbackMetadata::GetSlotSize(kind); |
269 | 205 |
270 Object* value; | 206 Object* value; |
271 if (kind == FeedbackVectorSlotKind::LOAD_GLOBAL_IC) { | 207 if (kind == FeedbackVectorSlotKind::LOAD_GLOBAL_IC) { |
272 value = isolate->heap()->empty_weak_cell(); | 208 value = isolate->heap()->empty_weak_cell(); |
273 } else if (kind == FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC || | 209 } else if (kind == FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC || |
274 kind == FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC) { | 210 kind == FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC) { |
275 value = Smi::kZero; | 211 value = Smi::kZero; |
276 } else { | 212 } else { |
277 value = *uninitialized_sentinel; | 213 value = *uninitialized_sentinel; |
278 } | 214 } |
| 215 array->set(index, value, SKIP_WRITE_BARRIER); |
279 | 216 |
280 if (kind != FeedbackVectorSlotKind::CREATE_CLOSURE) { | 217 value = kind == FeedbackVectorSlotKind::CALL_IC ? Smi::kZero |
281 array->set(index, value, SKIP_WRITE_BARRIER); | 218 : *uninitialized_sentinel; |
282 value = kind == FeedbackVectorSlotKind::CALL_IC ? Smi::kZero | 219 for (int j = 1; j < entry_size; j++) { |
283 : *uninitialized_sentinel; | 220 array->set(index + j, value, SKIP_WRITE_BARRIER); |
284 for (int j = 1; j < entry_size; j++) { | |
285 array->set(index + j, value, SKIP_WRITE_BARRIER); | |
286 } | |
287 } | 221 } |
288 i += entry_size; | 222 i += entry_size; |
289 } | 223 } |
290 return Handle<TypeFeedbackVector>::cast(array); | 224 return Handle<TypeFeedbackVector>::cast(array); |
291 } | 225 } |
292 | 226 |
293 | 227 |
294 // static | 228 // static |
295 int TypeFeedbackVector::GetIndexFromSpec(const FeedbackVectorSpec* spec, | 229 int TypeFeedbackVector::GetIndexFromSpec(const FeedbackVectorSpec* spec, |
296 FeedbackVectorSlot slot) { | 230 FeedbackVectorSlot slot) { |
(...skipping 14 matching lines...) Expand all Loading... |
311 // This logic is copied from | 245 // This logic is copied from |
312 // StaticMarkingVisitor<StaticVisitor>::VisitCodeTarget. | 246 // StaticMarkingVisitor<StaticVisitor>::VisitCodeTarget. |
313 static bool ClearLogic(Isolate* isolate) { | 247 static bool ClearLogic(Isolate* isolate) { |
314 return FLAG_cleanup_code_caches_at_gc && isolate->serializer_enabled(); | 248 return FLAG_cleanup_code_caches_at_gc && isolate->serializer_enabled(); |
315 } | 249 } |
316 | 250 |
317 | 251 |
318 void TypeFeedbackVector::ClearSlotsImpl(SharedFunctionInfo* shared, | 252 void TypeFeedbackVector::ClearSlotsImpl(SharedFunctionInfo* shared, |
319 bool force_clear) { | 253 bool force_clear) { |
320 Isolate* isolate = GetIsolate(); | 254 Isolate* isolate = GetIsolate(); |
| 255 |
321 if (!force_clear && !ClearLogic(isolate)) return; | 256 if (!force_clear && !ClearLogic(isolate)) return; |
322 | 257 |
323 if (this == isolate->heap()->empty_type_feedback_vector()) return; | |
324 | |
325 Object* uninitialized_sentinel = | 258 Object* uninitialized_sentinel = |
326 TypeFeedbackVector::RawUninitializedSentinel(isolate); | 259 TypeFeedbackVector::RawUninitializedSentinel(isolate); |
327 | 260 |
328 TypeFeedbackMetadataIterator iter(metadata()); | 261 TypeFeedbackMetadataIterator iter(metadata()); |
329 while (iter.HasNext()) { | 262 while (iter.HasNext()) { |
330 FeedbackVectorSlot slot = iter.Next(); | 263 FeedbackVectorSlot slot = iter.Next(); |
331 FeedbackVectorSlotKind kind = iter.kind(); | 264 FeedbackVectorSlotKind kind = iter.kind(); |
332 | 265 |
333 Object* obj = Get(slot); | 266 Object* obj = Get(slot); |
334 if (obj != uninitialized_sentinel) { | 267 if (obj != uninitialized_sentinel) { |
(...skipping 28 matching lines...) Expand all Loading... |
363 nexus.Clear(shared->code()); | 296 nexus.Clear(shared->code()); |
364 break; | 297 break; |
365 } | 298 } |
366 case FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC: | 299 case FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC: |
367 case FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC: { | 300 case FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC: { |
368 DCHECK(Get(slot)->IsSmi()); | 301 DCHECK(Get(slot)->IsSmi()); |
369 // don't clear these smi slots. | 302 // don't clear these smi slots. |
370 // Set(slot, Smi::kZero); | 303 // Set(slot, Smi::kZero); |
371 break; | 304 break; |
372 } | 305 } |
373 case FeedbackVectorSlotKind::CREATE_CLOSURE: { | |
374 // Fill the array with undefined. | |
375 FixedArray* array = FixedArray::cast(Get(slot)); | |
376 for (int i = 0; i < array->length(); i++) { | |
377 array->set_undefined(i); | |
378 } | |
379 break; | |
380 } | |
381 case FeedbackVectorSlotKind::GENERAL: { | 306 case FeedbackVectorSlotKind::GENERAL: { |
382 if (obj->IsHeapObject()) { | 307 if (obj->IsHeapObject()) { |
383 InstanceType instance_type = | 308 InstanceType instance_type = |
384 HeapObject::cast(obj)->map()->instance_type(); | 309 HeapObject::cast(obj)->map()->instance_type(); |
385 // AllocationSites are exempt from clearing. They don't store Maps | 310 // AllocationSites are exempt from clearing. They don't store Maps |
386 // or Code pointers which can cause memory leaks if not cleared | 311 // or Code pointers which can cause memory leaks if not cleared |
387 // regularly. | 312 // regularly. |
388 if (instance_type != ALLOCATION_SITE_TYPE) { | 313 if (instance_type != ALLOCATION_SITE_TYPE) { |
389 Set(slot, uninitialized_sentinel, SKIP_WRITE_BARRIER); | 314 Set(slot, uninitialized_sentinel, SKIP_WRITE_BARRIER); |
390 } | 315 } |
(...skipping 666 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1057 return BinaryOperationHintFromFeedback(feedback); | 982 return BinaryOperationHintFromFeedback(feedback); |
1058 } | 983 } |
1059 | 984 |
1060 CompareOperationHint CompareICNexus::GetCompareOperationFeedback() const { | 985 CompareOperationHint CompareICNexus::GetCompareOperationFeedback() const { |
1061 int feedback = Smi::cast(GetFeedback())->value(); | 986 int feedback = Smi::cast(GetFeedback())->value(); |
1062 return CompareOperationHintFromFeedback(feedback); | 987 return CompareOperationHintFromFeedback(feedback); |
1063 } | 988 } |
1064 | 989 |
1065 } // namespace internal | 990 } // namespace internal |
1066 } // namespace v8 | 991 } // namespace v8 |
OLD | NEW |