OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 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 | 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/heap/incremental-marking.h" | 5 #include "src/heap/incremental-marking.h" |
6 | 6 |
7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
8 #include "src/compilation-cache.h" | 8 #include "src/compilation-cache.h" |
9 #include "src/conversions.h" | 9 #include "src/conversions.h" |
10 #include "src/heap/gc-idle-time-handler.h" | 10 #include "src/heap/gc-idle-time-handler.h" |
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
678 } | 678 } |
679 prev_weak_cell_obj = weak_cell; | 679 prev_weak_cell_obj = weak_cell; |
680 weak_cell_obj = weak_cell->next(); | 680 weak_cell_obj = weak_cell->next(); |
681 } | 681 } |
682 } | 682 } |
683 // Top may have changed. | 683 // Top may have changed. |
684 heap()->set_encountered_weak_cells(weak_cell_head); | 684 heap()->set_encountered_weak_cells(weak_cell_head); |
685 } | 685 } |
686 | 686 |
687 | 687 |
| 688 bool ShouldRetainMap(Map* map, int age) { |
| 689 if (age == 0) { |
| 690 // The map has aged. Do not retain this map. |
| 691 return false; |
| 692 } |
| 693 Object* constructor = map->GetConstructor(); |
| 694 if (!constructor->IsHeapObject() || |
| 695 Marking::IsWhite(Marking::MarkBitFrom(HeapObject::cast(constructor)))) { |
| 696 // The constructor is dead, no new objects with this map can |
| 697 // be created. Do not retain this map. |
| 698 return false; |
| 699 } |
| 700 return true; |
| 701 } |
| 702 |
| 703 |
| 704 void IncrementalMarking::RetainMaps() { |
| 705 // Do not retain dead maps if flag disables it or there is |
| 706 // - memory pressure (reduce_memory_footprint_), |
| 707 // - GC is requested by tests or dev-tools (abort_incremental_marking_). |
| 708 bool map_retaining_is_disabled = heap()->ShouldReduceMemory() || |
| 709 heap()->ShouldAbortIncrementalMarking() || |
| 710 FLAG_retain_maps_for_n_gc == 0; |
| 711 ArrayList* retained_maps = heap()->retained_maps(); |
| 712 int length = retained_maps->Length(); |
| 713 // The number_of_disposed_maps separates maps in the retained_maps |
| 714 // array that were created before and after context disposal. |
| 715 // We do not age and retain disposed maps to avoid memory leaks. |
| 716 int number_of_disposed_maps = heap()->number_of_disposed_maps_; |
| 717 for (int i = 0; i < length; i += 2) { |
| 718 DCHECK(retained_maps->Get(i)->IsWeakCell()); |
| 719 WeakCell* cell = WeakCell::cast(retained_maps->Get(i)); |
| 720 if (cell->cleared()) continue; |
| 721 int age = Smi::cast(retained_maps->Get(i + 1))->value(); |
| 722 int new_age; |
| 723 Map* map = Map::cast(cell->value()); |
| 724 MarkBit map_mark = Marking::MarkBitFrom(map); |
| 725 if (i >= number_of_disposed_maps && !map_retaining_is_disabled && |
| 726 Marking::IsWhite(map_mark)) { |
| 727 if (ShouldRetainMap(map, age)) { |
| 728 MarkObject(heap(), map); |
| 729 } |
| 730 Object* prototype = map->prototype(); |
| 731 if (age > 0 && prototype->IsHeapObject() && |
| 732 Marking::IsWhite(Marking::MarkBitFrom(HeapObject::cast(prototype)))) { |
| 733 // The prototype is not marked, age the map. |
| 734 new_age = age - 1; |
| 735 } else { |
| 736 // The prototype and the constructor are marked, this map keeps only |
| 737 // transition tree alive, not JSObjects. Do not age the map. |
| 738 new_age = age; |
| 739 } |
| 740 } else { |
| 741 new_age = FLAG_retain_maps_for_n_gc; |
| 742 } |
| 743 // Compact the array and update the age. |
| 744 if (new_age != age) { |
| 745 retained_maps->Set(i + 1, Smi::FromInt(new_age)); |
| 746 } |
| 747 } |
| 748 } |
| 749 |
| 750 |
688 void IncrementalMarking::FinalizeIncrementally() { | 751 void IncrementalMarking::FinalizeIncrementally() { |
689 DCHECK(FLAG_finalize_marking_incrementally); | 752 DCHECK(FLAG_finalize_marking_incrementally); |
690 DCHECK(!finalize_marking_completed_); | 753 DCHECK(!finalize_marking_completed_); |
691 DCHECK(IsMarking()); | 754 DCHECK(IsMarking()); |
692 | 755 |
693 int old_marking_deque_top = | 756 int old_marking_deque_top = |
694 heap_->mark_compact_collector()->marking_deque()->top(); | 757 heap_->mark_compact_collector()->marking_deque()->top(); |
695 | 758 |
696 // After finishing incremental marking, we try to discover all unmarked | 759 // After finishing incremental marking, we try to discover all unmarked |
697 // objects to reduce the marking load in the final pause. | 760 // objects to reduce the marking load in the final pause. |
698 // 1) We scan and mark the roots again to find all changes to the root set. | 761 // 1) We scan and mark the roots again to find all changes to the root set. |
699 // 2) We mark the object groups. | 762 // 2) We mark the object groups. |
700 // 3) Remove weak cell with live values from the list of weak cells, they | 763 // 3) Age and retain maps embedded in optimized code. |
| 764 // 4) Remove weak cell with live values from the list of weak cells, they |
701 // do not need processing during GC. | 765 // do not need processing during GC. |
702 MarkRoots(); | 766 MarkRoots(); |
703 MarkObjectGroups(); | 767 MarkObjectGroups(); |
| 768 if (incremental_marking_finalization_rounds_ == 0) { |
| 769 // Map retaining is needed for perfromance, not correctness, |
| 770 // so we can do it only once at the beginning of the finalization. |
| 771 RetainMaps(); |
| 772 } |
704 ProcessWeakCells(); | 773 ProcessWeakCells(); |
705 | 774 |
706 int marking_progress = | 775 int marking_progress = |
707 abs(old_marking_deque_top - | 776 abs(old_marking_deque_top - |
708 heap_->mark_compact_collector()->marking_deque()->top()); | 777 heap_->mark_compact_collector()->marking_deque()->top()); |
709 | 778 |
710 ++incremental_marking_finalization_rounds_; | 779 ++incremental_marking_finalization_rounds_; |
711 if ((incremental_marking_finalization_rounds_ >= | 780 if ((incremental_marking_finalization_rounds_ >= |
712 FLAG_max_incremental_marking_finalization_rounds) || | 781 FLAG_max_incremental_marking_finalization_rounds) || |
713 (marking_progress < | 782 (marking_progress < |
(...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1195 void IncrementalMarking::IncrementIdleMarkingDelayCounter() { | 1264 void IncrementalMarking::IncrementIdleMarkingDelayCounter() { |
1196 idle_marking_delay_counter_++; | 1265 idle_marking_delay_counter_++; |
1197 } | 1266 } |
1198 | 1267 |
1199 | 1268 |
1200 void IncrementalMarking::ClearIdleMarkingDelayCounter() { | 1269 void IncrementalMarking::ClearIdleMarkingDelayCounter() { |
1201 idle_marking_delay_counter_ = 0; | 1270 idle_marking_delay_counter_ = 0; |
1202 } | 1271 } |
1203 } // namespace internal | 1272 } // namespace internal |
1204 } // namespace v8 | 1273 } // namespace v8 |
OLD | NEW |