OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 void StaticMarkingVisitor<StaticVisitor>::VisitMap( | 255 void StaticMarkingVisitor<StaticVisitor>::VisitMap( |
256 Map* map, HeapObject* object) { | 256 Map* map, HeapObject* object) { |
257 Heap* heap = map->GetHeap(); | 257 Heap* heap = map->GetHeap(); |
258 Map* map_object = Map::cast(object); | 258 Map* map_object = Map::cast(object); |
259 | 259 |
260 // Clears the cache of ICs related to this map. | 260 // Clears the cache of ICs related to this map. |
261 if (FLAG_cleanup_code_caches_at_gc) { | 261 if (FLAG_cleanup_code_caches_at_gc) { |
262 map_object->ClearCodeCache(heap); | 262 map_object->ClearCodeCache(heap); |
263 } | 263 } |
264 | 264 |
265 // When map collection is enabled we have to mark through map's | 265 // When map collection is enabled we have to mark through map's transitions |
266 // transitions and back pointers in a special way to make these links | 266 // and back pointers in a special way to make these links weak. |
267 // weak. Only maps for subclasses of JSReceiver can have transitions. | 267 if (FLAG_collect_maps && map_object->CanTransition()) { |
268 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); | |
269 if (FLAG_collect_maps && | |
270 map_object->instance_type() >= FIRST_JS_RECEIVER_TYPE) { | |
271 MarkMapContents(heap, map_object); | 268 MarkMapContents(heap, map_object); |
272 } else { | 269 } else { |
273 StaticVisitor::VisitPointers(heap, | 270 StaticVisitor::VisitPointers(heap, |
274 HeapObject::RawField(object, Map::kPointerFieldsBeginOffset), | 271 HeapObject::RawField(object, Map::kPointerFieldsBeginOffset), |
275 HeapObject::RawField(object, Map::kPointerFieldsEndOffset)); | 272 HeapObject::RawField(object, Map::kPointerFieldsEndOffset)); |
276 } | 273 } |
277 } | 274 } |
278 | 275 |
279 | 276 |
280 template<typename StaticVisitor> | 277 template<typename StaticVisitor> |
281 void StaticMarkingVisitor<StaticVisitor>::VisitCode( | 278 void StaticMarkingVisitor<StaticVisitor>::VisitCode( |
282 Map* map, HeapObject* object) { | 279 Map* map, HeapObject* object) { |
283 Heap* heap = map->GetHeap(); | 280 Heap* heap = map->GetHeap(); |
284 Code* code = Code::cast(object); | 281 Code* code = Code::cast(object); |
285 if (FLAG_cleanup_code_caches_at_gc) { | 282 if (FLAG_cleanup_code_caches_at_gc) { |
286 code->ClearTypeFeedbackCells(heap); | 283 code->ClearTypeFeedbackCells(heap); |
287 } | 284 } |
288 if (FLAG_age_code && !Serializer::enabled()) { | 285 if (FLAG_age_code && !Serializer::enabled()) { |
289 code->MakeOlder(heap->mark_compact_collector()->marking_parity()); | 286 code->MakeOlder(heap->mark_compact_collector()->marking_parity()); |
290 } | 287 } |
291 code->CodeIterateBody<StaticVisitor>(heap); | 288 code->CodeIterateBody<StaticVisitor, Code::SKIP_EMBEDDED_MAPS>(heap); |
292 } | 289 } |
293 | 290 |
294 | 291 |
295 template<typename StaticVisitor> | 292 template<typename StaticVisitor> |
296 void StaticMarkingVisitor<StaticVisitor>::VisitSharedFunctionInfo( | 293 void StaticMarkingVisitor<StaticVisitor>::VisitSharedFunctionInfo( |
297 Map* map, HeapObject* object) { | 294 Map* map, HeapObject* object) { |
298 Heap* heap = map->GetHeap(); | 295 Heap* heap = map->GetHeap(); |
299 SharedFunctionInfo* shared = SharedFunctionInfo::cast(object); | 296 SharedFunctionInfo* shared = SharedFunctionInfo::cast(object); |
300 if (shared->ic_age() != heap->global_ic_age()) { | 297 if (shared->ic_age() != heap->global_ic_age()) { |
301 shared->ResetForNewContext(heap->global_ic_age()); | 298 shared->ResetForNewContext(heap->global_ic_age()); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
388 // array slot, since it will be implicitly recorded when the pointer | 385 // array slot, since it will be implicitly recorded when the pointer |
389 // fields of this map are visited. | 386 // fields of this map are visited. |
390 TransitionArray* transitions = map->unchecked_transition_array(); | 387 TransitionArray* transitions = map->unchecked_transition_array(); |
391 if (transitions->IsTransitionArray()) { | 388 if (transitions->IsTransitionArray()) { |
392 MarkTransitionArray(heap, transitions); | 389 MarkTransitionArray(heap, transitions); |
393 } else { | 390 } else { |
394 // Already marked by marking map->GetBackPointer() above. | 391 // Already marked by marking map->GetBackPointer() above. |
395 ASSERT(transitions->IsMap() || transitions->IsUndefined()); | 392 ASSERT(transitions->IsMap() || transitions->IsUndefined()); |
396 } | 393 } |
397 | 394 |
| 395 // Mark prototype dependent codes array but do not push it onto marking |
| 396 // stack, this will make references from it weak. We will clean dead |
| 397 // dead codes when we iterate over maps in ClearNonLiveTransitions. |
| 398 Object** slot = HeapObject::RawField(reinterpret_cast<HeapObject*>(map), |
| 399 Map::kDependentCodesOffset); |
| 400 HeapObject* obj = HeapObject::cast(*slot); |
| 401 heap->mark_compact_collector()->RecordSlot(slot, slot, obj); |
| 402 StaticVisitor::MarkObjectWithoutPush(heap, obj); |
| 403 |
398 // Mark the pointer fields of the Map. Since the transitions array has | 404 // Mark the pointer fields of the Map. Since the transitions array has |
399 // been marked already, it is fine that one of these fields contains a | 405 // been marked already, it is fine that one of these fields contains a |
400 // pointer to it. | 406 // pointer to it. |
401 StaticVisitor::VisitPointers(heap, | 407 StaticVisitor::VisitPointers(heap, |
402 HeapObject::RawField(map, Map::kPointerFieldsBeginOffset), | 408 HeapObject::RawField(map, Map::kPointerFieldsBeginOffset), |
403 HeapObject::RawField(map, Map::kPointerFieldsEndOffset)); | 409 HeapObject::RawField(map, Map::kPointerFieldsEndOffset)); |
404 } | 410 } |
405 | 411 |
406 | 412 |
407 template<typename StaticVisitor> | 413 template<typename StaticVisitor> |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
631 | 637 |
632 void Code::CodeIterateBody(ObjectVisitor* v) { | 638 void Code::CodeIterateBody(ObjectVisitor* v) { |
633 int mode_mask = RelocInfo::kCodeTargetMask | | 639 int mode_mask = RelocInfo::kCodeTargetMask | |
634 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | | 640 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | |
635 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) | | 641 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) | |
636 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | | 642 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | |
637 RelocInfo::ModeMask(RelocInfo::JS_RETURN) | | 643 RelocInfo::ModeMask(RelocInfo::JS_RETURN) | |
638 RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) | | 644 RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) | |
639 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); | 645 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); |
640 | 646 |
641 // There are two places where we iterate code bodies: here and the | 647 // There are two places where we iterate code bodies: here and the non- |
642 // templated CodeIterateBody (below). They should be kept in sync. | 648 // templated CodeIterateBody (above). They should be kept in sync. The only |
| 649 // difference between the two versions is in handling of embedded maps. |
| 650 // Static marking visitors do not visit embedded maps, but most of the non- |
| 651 // static visitors need to visit embedded maps. Non-static visitor can skip |
| 652 // embedded maps by overriding VisitEmbeddedPointer, like |
| 653 // VerifyMarkingVisitor does. |
643 IteratePointer(v, kRelocationInfoOffset); | 654 IteratePointer(v, kRelocationInfoOffset); |
644 IteratePointer(v, kHandlerTableOffset); | 655 IteratePointer(v, kHandlerTableOffset); |
645 IteratePointer(v, kDeoptimizationDataOffset); | 656 IteratePointer(v, kDeoptimizationDataOffset); |
646 IteratePointer(v, kTypeFeedbackInfoOffset); | 657 IteratePointer(v, kTypeFeedbackInfoOffset); |
647 | 658 |
648 RelocIterator it(this, mode_mask); | 659 RelocIterator it(this, mode_mask); |
649 for (; !it.done(); it.next()) { | 660 for (; !it.done(); it.next()) { |
650 it.rinfo()->Visit(v); | 661 it.rinfo()->Visit(v); |
651 } | 662 } |
652 } | 663 } |
653 | 664 |
654 | 665 |
655 template<typename StaticVisitor> | 666 template<typename StaticVisitor, Code::EmbeddedMapVisitMode map_visit_mode> |
656 void Code::CodeIterateBody(Heap* heap) { | 667 void Code::CodeIterateBody(Heap* heap) { |
657 int mode_mask = RelocInfo::kCodeTargetMask | | 668 int mode_mask = RelocInfo::kCodeTargetMask | |
658 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | | 669 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | |
659 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) | | 670 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) | |
660 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | | 671 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | |
661 RelocInfo::ModeMask(RelocInfo::JS_RETURN) | | 672 RelocInfo::ModeMask(RelocInfo::JS_RETURN) | |
662 RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) | | 673 RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) | |
663 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); | 674 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); |
664 | 675 |
665 // There are two places where we iterate code bodies: here and the | 676 // There are two places where we iterate code bodies: here and the non- |
666 // non-templated CodeIterateBody (above). They should be kept in sync. | 677 // templated CodeIterateBody (above). They should be kept in sync. The only |
| 678 // difference between the two versions is in handling of embedded maps. |
| 679 // Static marking visitors do not visit embedded maps, but most of the non- |
| 680 // static visitors need to visit embedded maps. Non-static visitor can skip |
| 681 // embedded maps by overriding VisitEmbeddedPointer, like |
| 682 // VerifyMarkingVisitor does. |
667 StaticVisitor::VisitPointer( | 683 StaticVisitor::VisitPointer( |
668 heap, | 684 heap, |
669 reinterpret_cast<Object**>(this->address() + kRelocationInfoOffset)); | 685 reinterpret_cast<Object**>(this->address() + kRelocationInfoOffset)); |
670 StaticVisitor::VisitPointer( | 686 StaticVisitor::VisitPointer( |
671 heap, | 687 heap, |
672 reinterpret_cast<Object**>(this->address() + kHandlerTableOffset)); | 688 reinterpret_cast<Object**>(this->address() + kHandlerTableOffset)); |
673 StaticVisitor::VisitPointer( | 689 StaticVisitor::VisitPointer( |
674 heap, | 690 heap, |
675 reinterpret_cast<Object**>(this->address() + kDeoptimizationDataOffset)); | 691 reinterpret_cast<Object**>(this->address() + kDeoptimizationDataOffset)); |
676 StaticVisitor::VisitPointer( | 692 StaticVisitor::VisitPointer( |
677 heap, | 693 heap, |
678 reinterpret_cast<Object**>(this->address() + kTypeFeedbackInfoOffset)); | 694 reinterpret_cast<Object**>(this->address() + kTypeFeedbackInfoOffset)); |
679 | 695 |
680 RelocIterator it(this, mode_mask); | 696 RelocIterator it(this, mode_mask); |
681 for (; !it.done(); it.next()) { | 697 if (map_visit_mode == SKIP_EMBEDDED_MAPS && kind() == OPTIMIZED_FUNCTION) { |
682 it.rinfo()->template Visit<StaticVisitor>(heap); | 698 // Treat embedded maps in optimized code as weak. |
| 699 for (; !it.done(); it.next()) { |
| 700 RelocInfo* info = it.rinfo(); |
| 701 if (!RelocInfo::IsEmbeddedObject(info->rmode()) || |
| 702 !info->target_object()->IsMap() || |
| 703 !Map::cast(info->target_object())->CanTransition()) { |
| 704 it.rinfo()->template Visit<StaticVisitor>(heap); |
| 705 } |
| 706 } |
| 707 } else { |
| 708 for (; !it.done(); it.next()) { |
| 709 it.rinfo()->template Visit<StaticVisitor>(heap); |
| 710 } |
683 } | 711 } |
684 } | 712 } |
685 | 713 |
686 | 714 |
687 } } // namespace v8::internal | 715 } } // namespace v8::internal |
688 | 716 |
689 #endif // V8_OBJECTS_VISITING_INL_H_ | 717 #endif // V8_OBJECTS_VISITING_INL_H_ |
OLD | NEW |