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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/ic/ic.h" | 7 #include "src/ic/ic.h" |
8 #include "src/ic/ic-state.h" | 8 #include "src/ic/ic-state.h" |
9 #include "src/objects.h" | 9 #include "src/objects.h" |
10 #include "src/type-feedback-vector-inl.h" | 10 #include "src/type-feedback-vector-inl.h" |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
114 // static | 114 // static |
115 Handle<TypeFeedbackVector> TypeFeedbackVector::Copy( | 115 Handle<TypeFeedbackVector> TypeFeedbackVector::Copy( |
116 Isolate* isolate, Handle<TypeFeedbackVector> vector) { | 116 Isolate* isolate, Handle<TypeFeedbackVector> vector) { |
117 Handle<TypeFeedbackVector> result; | 117 Handle<TypeFeedbackVector> result; |
118 result = Handle<TypeFeedbackVector>::cast( | 118 result = Handle<TypeFeedbackVector>::cast( |
119 isolate->factory()->CopyFixedArray(Handle<FixedArray>::cast(vector))); | 119 isolate->factory()->CopyFixedArray(Handle<FixedArray>::cast(vector))); |
120 return result; | 120 return result; |
121 } | 121 } |
122 | 122 |
123 | 123 |
124 // This logic is copied from | |
125 // StaticMarkingVisitor<StaticVisitor>::VisitCodeTarget. | |
126 // TODO(mvstanton): with weak handling of all vector ics, this logic should | |
127 // actually be completely eliminated and we no longer need to clear the | |
128 // vector ICs. | |
129 static bool ClearLogic(Heap* heap, int ic_age, Code::Kind kind, | |
130 InlineCacheState state) { | |
131 if (FLAG_cleanup_code_caches_at_gc && | |
132 (kind == Code::CALL_IC || state == MEGAMORPHIC || state == GENERIC || | |
133 state == POLYMORPHIC || heap->flush_monomorphic_ics() || | |
134 // TODO(mvstanton): is this ic_age granular enough? it comes from | |
135 // the SharedFunctionInfo which may change on a different schedule | |
136 // than ic targets. | |
137 // ic_age != heap->global_ic_age() || | |
138 // is_invalidated_weak_stub || | |
139 heap->isolate()->serializer_enabled())) { | |
140 return true; | |
141 } | |
142 return false; | |
143 } | |
144 | |
145 | |
124 void TypeFeedbackVector::ClearSlots(SharedFunctionInfo* shared) { | 146 void TypeFeedbackVector::ClearSlots(SharedFunctionInfo* shared) { |
125 int slots = Slots(); | 147 int slots = Slots(); |
126 Isolate* isolate = GetIsolate(); | 148 Isolate* isolate = GetIsolate(); |
127 Object* uninitialized_sentinel = | 149 Object* uninitialized_sentinel = |
128 TypeFeedbackVector::RawUninitializedSentinel(isolate->heap()); | 150 TypeFeedbackVector::RawUninitializedSentinel(isolate->heap()); |
129 | 151 |
130 for (int i = 0; i < slots; i++) { | 152 for (int i = 0; i < slots; i++) { |
131 FeedbackVectorSlot slot(i); | 153 FeedbackVectorSlot slot(i); |
132 Object* obj = Get(slot); | 154 Object* obj = Get(slot); |
133 if (obj->IsHeapObject()) { | 155 if (obj->IsHeapObject()) { |
134 InstanceType instance_type = | 156 InstanceType instance_type = |
135 HeapObject::cast(obj)->map()->instance_type(); | 157 HeapObject::cast(obj)->map()->instance_type(); |
136 // AllocationSites are exempt from clearing. They don't store Maps | 158 // AllocationSites are exempt from clearing. They don't store Maps |
137 // or Code pointers which can cause memory leaks if not cleared | 159 // or Code pointers which can cause memory leaks if not cleared |
138 // regularly. | 160 // regularly. |
139 if (instance_type != ALLOCATION_SITE_TYPE) { | 161 if (instance_type != ALLOCATION_SITE_TYPE) { |
140 Set(slot, uninitialized_sentinel, SKIP_WRITE_BARRIER); | 162 Set(slot, uninitialized_sentinel, SKIP_WRITE_BARRIER); |
141 } | 163 } |
142 } | 164 } |
143 } | 165 } |
144 | 166 |
145 slots = ICSlots(); | 167 slots = ICSlots(); |
146 if (slots == 0) return; | 168 if (slots == 0) return; |
147 | 169 |
148 // Now clear vector-based ICs. They are all CallICs. | 170 // Now clear vector-based ICs. They are all CallICs. |
Jakob Kummerow
2014/11/26 15:14:15
nit: s/They are all CallICs.//
mvstanton
2014/11/27 13:09:26
Done.
| |
149 // Try and pass the containing code (the "host"). | 171 // Try and pass the containing code (the "host"). |
172 Heap* heap = isolate->heap(); | |
150 Code* host = shared->code(); | 173 Code* host = shared->code(); |
174 // I'm not sure yet if this ic age is the correct one. | |
175 int ic_age = shared->ic_age(); | |
151 for (int i = 0; i < slots; i++) { | 176 for (int i = 0; i < slots; i++) { |
152 FeedbackVectorICSlot slot(i); | 177 FeedbackVectorICSlot slot(i); |
153 Object* obj = Get(slot); | 178 Object* obj = Get(slot); |
154 if (obj != uninitialized_sentinel) { | 179 if (obj != uninitialized_sentinel) { |
155 // TODO(mvstanton): To make this code work with --vector-ics, | 180 // Discover the correct Code::Kind. |
Jakob Kummerow
2014/11/26 15:14:15
nit: this comment doesn't add value
mvstanton
2014/11/27 13:09:26
Done.
| |
156 // additional Nexus types must be created. | 181 Code::Kind kind = GetKind(slot); |
157 DCHECK(!FLAG_vector_ics); | 182 if (kind == Code::CALL_IC) { |
158 DCHECK(GetKind(slot) == Code::CALL_IC); | 183 CallICNexus nexus(this, slot); |
159 CallICNexus nexus(this, slot); | 184 // bool is_invalidated = nexus.IsInvalidatedWeakIC(); |
Jakob Kummerow
2014/11/26 15:14:15
leftover?
mvstanton
2014/11/27 13:09:26
Yes, I think so, removed.
| |
160 ICUtility::Clear(isolate, Code::CALL_IC, host, &nexus); | 185 if (ClearLogic(heap, ic_age, kind, nexus.StateFromFeedback())) { |
186 nexus.Clear(host); | |
187 } | |
188 } else if (kind == Code::LOAD_IC) { | |
189 LoadICNexus nexus(this, slot); | |
190 if (ClearLogic(heap, ic_age, kind, nexus.StateFromFeedback())) { | |
191 nexus.Clear(host); | |
192 } | |
193 } else if (kind == Code::KEYED_LOAD_IC) { | |
194 KeyedLoadICNexus nexus(this, slot); | |
195 if (ClearLogic(heap, ic_age, kind, nexus.StateFromFeedback())) { | |
196 nexus.Clear(host); | |
197 } | |
198 } | |
161 } | 199 } |
162 } | 200 } |
163 } | 201 } |
164 | 202 |
165 | 203 |
166 Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) { | 204 Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) { |
167 Isolate* isolate = GetIsolate(); | 205 Isolate* isolate = GetIsolate(); |
168 Handle<Object> feedback = handle(GetFeedback(), isolate); | 206 Handle<Object> feedback = handle(GetFeedback(), isolate); |
169 if (!feedback->IsFixedArray() || | 207 if (!feedback->IsFixedArray() || |
170 FixedArray::cast(*feedback)->length() != length) { | 208 FixedArray::cast(*feedback)->length() != length) { |
(...skipping 12 matching lines...) Expand all Loading... | |
183 int receiver_count = types->length(); | 221 int receiver_count = types->length(); |
184 for (int current = 0; current < receiver_count; ++current) { | 222 for (int current = 0; current < receiver_count; ++current) { |
185 Handle<HeapType> type = types->at(current); | 223 Handle<HeapType> type = types->at(current); |
186 Handle<Map> map = IC::TypeToMap(*type, isolate); | 224 Handle<Map> map = IC::TypeToMap(*type, isolate); |
187 array->set(start_index + (current * 2), *map); | 225 array->set(start_index + (current * 2), *map); |
188 array->set(start_index + (current * 2 + 1), *handlers->at(current)); | 226 array->set(start_index + (current * 2 + 1), *handlers->at(current)); |
189 } | 227 } |
190 } | 228 } |
191 | 229 |
192 | 230 |
231 InlineCacheState LoadICNexus::StateFromFeedback() const { | |
232 Isolate* isolate = GetIsolate(); | |
233 InlineCacheState state = UNINITIALIZED; | |
234 Object* feedback = GetFeedback(); | |
235 if (feedback == *vector()->UninitializedSentinel(isolate)) { | |
236 state = UNINITIALIZED; | |
Jakob Kummerow
2014/11/26 15:14:15
consider to directly "return UNINITIALIZED;" (and
mvstanton
2014/11/27 13:09:26
Done.
| |
237 } else if (feedback == *vector()->MegamorphicSentinel(isolate)) { | |
238 state = MEGAMORPHIC; | |
239 } else if (feedback == *vector()->PremonomorphicSentinel(isolate)) { | |
240 state = PREMONOMORPHIC; | |
241 } else if (feedback->IsFixedArray()) { | |
242 FixedArray* array = FixedArray::cast(feedback); | |
243 int length = array->length(); | |
244 DCHECK(length >= 2); | |
245 if (length == 2) { | |
246 state = MONOMORPHIC; | |
247 } else if (length > 2) { | |
Jakob Kummerow
2014/11/26 15:14:15
s/if (length > 2)//, it's guaranteed anyway.
mvstanton
2014/11/27 13:09:26
Done.
| |
248 state = POLYMORPHIC; | |
249 } | |
250 } | |
251 | |
252 return state; | |
253 } | |
254 | |
255 | |
256 InlineCacheState KeyedLoadICNexus::StateFromFeedback() const { | |
257 Isolate* isolate = GetIsolate(); | |
258 InlineCacheState state = UNINITIALIZED; | |
259 Object* feedback = GetFeedback(); | |
260 if (feedback == *vector()->UninitializedSentinel(isolate)) { | |
261 state = UNINITIALIZED; | |
262 } else if (feedback == *vector()->PremonomorphicSentinel(isolate)) { | |
263 state = PREMONOMORPHIC; | |
264 } else if (feedback == *vector()->MegamorphicSentinel(isolate)) { | |
265 state = MEGAMORPHIC; | |
266 } else if (feedback == *vector()->GenericSentinel(isolate)) { | |
267 state = GENERIC; | |
268 } else if (feedback->IsFixedArray()) { | |
269 FixedArray* array = FixedArray::cast(feedback); | |
270 int length = array->length(); | |
271 DCHECK(length >= 3); | |
272 | |
273 if (length == 3) { | |
274 state = MONOMORPHIC; | |
275 } else if (length > 3) { | |
Jakob Kummerow
2014/11/26 15:14:15
s/if (length > 3)//, it's guaranteed anyway.
mvstanton
2014/11/27 13:09:26
Done.
| |
276 state = POLYMORPHIC; | |
277 } | |
278 } | |
279 | |
280 return state; | |
281 } | |
282 | |
283 | |
193 InlineCacheState CallICNexus::StateFromFeedback() const { | 284 InlineCacheState CallICNexus::StateFromFeedback() const { |
194 Isolate* isolate = GetIsolate(); | 285 Isolate* isolate = GetIsolate(); |
195 InlineCacheState state = UNINITIALIZED; | 286 InlineCacheState state = UNINITIALIZED; |
196 Object* feedback = GetFeedback(); | 287 Object* feedback = GetFeedback(); |
197 | 288 |
198 if (feedback == *vector()->MegamorphicSentinel(isolate)) { | 289 if (feedback == *vector()->MegamorphicSentinel(isolate)) { |
199 state = GENERIC; | 290 state = GENERIC; |
200 } else if (feedback->IsAllocationSite() || feedback->IsJSFunction()) { | 291 } else if (feedback->IsAllocationSite() || feedback->IsJSFunction()) { |
201 state = MONOMORPHIC; | 292 state = MONOMORPHIC; |
202 } else { | 293 } else { |
203 CHECK(feedback == *vector()->UninitializedSentinel(isolate)); | 294 CHECK(feedback == *vector()->UninitializedSentinel(isolate)); |
204 } | 295 } |
205 | 296 |
206 return state; | 297 return state; |
207 } | 298 } |
208 | 299 |
209 | 300 |
301 void CallICNexus::Clear(Code* host) { CallIC::Clear(GetIsolate(), host, this); } | |
302 | |
303 | |
210 void CallICNexus::ConfigureGeneric() { | 304 void CallICNexus::ConfigureGeneric() { |
211 SetFeedback(*vector()->MegamorphicSentinel(GetIsolate()), SKIP_WRITE_BARRIER); | 305 SetFeedback(*vector()->MegamorphicSentinel(GetIsolate()), SKIP_WRITE_BARRIER); |
212 } | 306 } |
213 | 307 |
214 | 308 |
215 void CallICNexus::ConfigureMonomorphicArray() { | 309 void CallICNexus::ConfigureMonomorphicArray() { |
216 Object* feedback = GetFeedback(); | 310 Object* feedback = GetFeedback(); |
217 if (!feedback->IsAllocationSite()) { | 311 if (!feedback->IsAllocationSite()) { |
218 Handle<AllocationSite> new_site = | 312 Handle<AllocationSite> new_site = |
219 GetIsolate()->factory()->NewAllocationSite(); | 313 GetIsolate()->factory()->NewAllocationSite(); |
220 SetFeedback(*new_site); | 314 SetFeedback(*new_site); |
221 } | 315 } |
222 } | 316 } |
223 | 317 |
224 | 318 |
225 void CallICNexus::ConfigureUninitialized() { | 319 void CallICNexus::ConfigureUninitialized() { |
226 SetFeedback(*vector()->UninitializedSentinel(GetIsolate()), | 320 SetFeedback(*vector()->UninitializedSentinel(GetIsolate()), |
227 SKIP_WRITE_BARRIER); | 321 SKIP_WRITE_BARRIER); |
228 } | 322 } |
229 | 323 |
230 | 324 |
231 void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) { | 325 void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) { |
232 SetFeedback(*function); | 326 SetFeedback(*function); |
233 } | 327 } |
234 | 328 |
235 | 329 |
330 void KeyedLoadICNexus::ConfigureGeneric() { | |
331 SetFeedback(*vector()->GenericSentinel(GetIsolate()), SKIP_WRITE_BARRIER); | |
Jakob Kummerow
2014/11/26 15:14:15
Looks like return raw pointers in the various vect
mvstanton
2014/11/27 13:09:26
Yes, I'll come back for that later. I think I want
| |
332 } | |
333 | |
334 | |
335 void KeyedLoadICNexus::ConfigureMegamorphic() { | |
336 SetFeedback(*vector()->MegamorphicSentinel(GetIsolate()), SKIP_WRITE_BARRIER); | |
337 } | |
338 | |
339 | |
340 void LoadICNexus::ConfigureMegamorphic() { | |
341 SetFeedback(*vector()->MegamorphicSentinel(GetIsolate()), SKIP_WRITE_BARRIER); | |
342 } | |
343 | |
344 | |
345 void LoadICNexus::ConfigurePremonomorphic() { | |
346 SetFeedback(*vector()->PremonomorphicSentinel(GetIsolate()), | |
347 SKIP_WRITE_BARRIER); | |
348 } | |
349 | |
350 | |
351 void KeyedLoadICNexus::ConfigurePremonomorphic() { | |
352 SetFeedback(*vector()->PremonomorphicSentinel(GetIsolate()), | |
353 SKIP_WRITE_BARRIER); | |
354 } | |
355 | |
356 | |
357 void LoadICNexus::ConfigureMonomorphic(Handle<HeapType> type, | |
358 Handle<Code> handler) { | |
359 Handle<FixedArray> array = EnsureArrayOfSize(2); | |
360 Handle<Map> receiver_map = IC::TypeToMap(*type, GetIsolate()); | |
361 array->set(0, *receiver_map); | |
362 array->set(1, *handler); | |
363 } | |
364 | |
365 | |
366 void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name, | |
367 Handle<HeapType> type, | |
368 Handle<Code> handler) { | |
369 Handle<FixedArray> array = EnsureArrayOfSize(3); | |
370 Handle<Map> receiver_map = IC::TypeToMap(*type, GetIsolate()); | |
371 if (name.is_null()) { | |
372 array->set(0, Smi::FromInt(0)); | |
373 } else { | |
374 array->set(0, *name); | |
375 } | |
376 array->set(1, *receiver_map); | |
377 array->set(2, *handler); | |
378 } | |
379 | |
380 | |
381 void LoadICNexus::ConfigurePolymorphic(TypeHandleList* types, | |
382 CodeHandleList* handlers) { | |
383 int receiver_count = types->length(); | |
384 EnsureArrayOfSize(receiver_count * 2); | |
385 InstallHandlers(0, types, handlers); | |
386 } | |
387 | |
388 | |
389 void KeyedLoadICNexus::ConfigurePolymorphic(Handle<Name> name, | |
390 TypeHandleList* types, | |
391 CodeHandleList* handlers) { | |
392 int receiver_count = types->length(); | |
393 Handle<FixedArray> array = EnsureArrayOfSize(1 + receiver_count * 2); | |
394 if (name.is_null()) { | |
395 array->set(0, Smi::FromInt(0)); | |
396 } else { | |
397 array->set(0, *name); | |
398 } | |
399 InstallHandlers(1, types, handlers); | |
400 } | |
401 | |
402 | |
236 int FeedbackNexus::ExtractMaps(int start_index, MapHandleList* maps) const { | 403 int FeedbackNexus::ExtractMaps(int start_index, MapHandleList* maps) const { |
237 Isolate* isolate = GetIsolate(); | 404 Isolate* isolate = GetIsolate(); |
238 Object* feedback = GetFeedback(); | 405 Object* feedback = GetFeedback(); |
239 if (feedback->IsFixedArray()) { | 406 if (feedback->IsFixedArray()) { |
240 FixedArray* array = FixedArray::cast(feedback); | 407 FixedArray* array = FixedArray::cast(feedback); |
241 // The array should be of the form [<optional name>], then | 408 // The array should be of the form [<optional name>], then |
242 // [map, handler, map, handler, ... ] | 409 // [map, handler, map, handler, ... ] |
243 DCHECK(array->length() >= (2 + start_index)); | 410 DCHECK(array->length() >= (2 + start_index)); |
244 for (int i = start_index; i < array->length(); i += 2) { | 411 for (int i = start_index; i < array->length(); i += 2) { |
245 Map* map = Map::cast(array->get(i)); | 412 Map* map = Map::cast(array->get(i)); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
282 DCHECK(array->length() >= (2 + start_index)); | 449 DCHECK(array->length() >= (2 + start_index)); |
283 for (int i = start_index; i < array->length(); i += 2) { | 450 for (int i = start_index; i < array->length(); i += 2) { |
284 Code* code = Code::cast(array->get(i + 1)); | 451 Code* code = Code::cast(array->get(i + 1)); |
285 DCHECK(code->kind() == Code::HANDLER); | 452 DCHECK(code->kind() == Code::HANDLER); |
286 code_list->Add(handle(code)); | 453 code_list->Add(handle(code)); |
287 count++; | 454 count++; |
288 } | 455 } |
289 } | 456 } |
290 return count == length; | 457 return count == length; |
291 } | 458 } |
459 | |
460 | |
461 int LoadICNexus::ExtractMaps(MapHandleList* maps) const { | |
462 return FeedbackNexus::ExtractMaps(0, maps); | |
463 } | |
464 | |
465 | |
466 void LoadICNexus::Clear(Code* host) { LoadIC::Clear(GetIsolate(), host, this); } | |
467 | |
468 | |
469 void KeyedLoadICNexus::Clear(Code* host) { | |
470 KeyedLoadIC::Clear(GetIsolate(), host, this); | |
471 } | |
472 | |
473 | |
474 int KeyedLoadICNexus::ExtractMaps(MapHandleList* maps) const { | |
475 return FeedbackNexus::ExtractMaps(1, maps); | |
476 } | |
477 | |
478 | |
479 MaybeHandle<Code> LoadICNexus::FindHandlerForMap(Handle<Map> map) const { | |
480 return FeedbackNexus::FindHandlerForMap(0, map); | |
481 } | |
482 | |
483 | |
484 MaybeHandle<Code> KeyedLoadICNexus::FindHandlerForMap(Handle<Map> map) const { | |
485 return FeedbackNexus::FindHandlerForMap(1, map); | |
486 } | |
487 | |
488 | |
489 bool LoadICNexus::FindHandlers(CodeHandleList* code_list, int length) const { | |
490 return FeedbackNexus::FindHandlers(0, code_list, length); | |
491 } | |
492 | |
493 | |
494 bool KeyedLoadICNexus::FindHandlers(CodeHandleList* code_list, | |
495 int length) const { | |
496 return FeedbackNexus::FindHandlers(1, code_list, length); | |
497 } | |
498 | |
499 | |
500 Name* KeyedLoadICNexus::FindFirstName() const { | |
501 Object* feedback = GetFeedback(); | |
502 if (feedback->IsFixedArray()) { | |
503 FixedArray* array = FixedArray::cast(feedback); | |
504 DCHECK(array->length() >= 3); | |
505 Object* name = array->get(0); | |
506 if (name->IsName()) return Name::cast(name); | |
507 } | |
508 return NULL; | |
509 } | |
292 } | 510 } |
293 } // namespace v8::internal | 511 } // namespace v8::internal |
OLD | NEW |