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" |
11 #include "src/heap/gc-tracer.h" | 11 #include "src/heap/gc-tracer.h" |
12 #include "src/heap/mark-compact-inl.h" | 12 #include "src/heap/mark-compact-inl.h" |
13 #include "src/heap/objects-visiting.h" | 13 #include "src/heap/objects-visiting.h" |
14 #include "src/heap/objects-visiting-inl.h" | 14 #include "src/heap/objects-visiting-inl.h" |
15 #include "src/v8.h" | 15 #include "src/v8.h" |
16 | 16 |
17 namespace v8 { | 17 namespace v8 { |
18 namespace internal { | 18 namespace internal { |
19 | 19 |
20 IncrementalMarking::StepActions IncrementalMarking::IdleStepActions() { | 20 IncrementalMarking::StepActions IncrementalMarking::IdleStepActions() { |
21 return StepActions(IncrementalMarking::NO_GC_VIA_STACK_GUARD, | 21 return StepActions(IncrementalMarking::NO_GC_VIA_STACK_GUARD, |
22 IncrementalMarking::FORCE_MARKING, | 22 IncrementalMarking::FORCE_MARKING, |
23 IncrementalMarking::DO_NOT_FORCE_COMPLETION); | 23 IncrementalMarking::DO_NOT_FORCE_COMPLETION); |
24 } | 24 } |
25 | 25 |
26 | |
27 IncrementalMarking::IncrementalMarking(Heap* heap) | 26 IncrementalMarking::IncrementalMarking(Heap* heap) |
28 : heap_(heap), | 27 : heap_(heap), |
29 observer_(*this, kAllocatedThreshold), | 28 observer_(*this, kAllocatedThreshold), |
30 state_(STOPPED), | 29 state_(STOPPED), |
31 is_compacting_(false), | 30 is_compacting_(false), |
32 steps_count_(0), | 31 steps_count_(0), |
33 old_generation_space_available_at_start_of_incremental_(0), | 32 old_generation_space_available_at_start_of_incremental_(0), |
34 old_generation_space_used_at_start_of_incremental_(0), | 33 old_generation_space_used_at_start_of_incremental_(0), |
35 bytes_rescanned_(0), | 34 bytes_rescanned_(0), |
36 should_hurry_(false), | 35 should_hurry_(false), |
37 marking_speed_(0), | 36 marking_speed_(0), |
38 bytes_scanned_(0), | 37 bytes_scanned_(0), |
39 allocated_(0), | 38 allocated_(0), |
40 write_barriers_invoked_since_last_step_(0), | 39 write_barriers_invoked_since_last_step_(0), |
41 idle_marking_delay_counter_(0), | 40 idle_marking_delay_counter_(0), |
42 no_marking_scope_depth_(0), | 41 no_marking_scope_depth_(0), |
43 unscanned_bytes_of_large_object_(0), | 42 unscanned_bytes_of_large_object_(0), |
44 was_activated_(false), | 43 was_activated_(false), |
| 44 black_allocation_(false), |
45 finalize_marking_completed_(false), | 45 finalize_marking_completed_(false), |
46 incremental_marking_finalization_rounds_(0), | 46 incremental_marking_finalization_rounds_(0), |
47 request_type_(COMPLETE_MARKING) {} | 47 request_type_(COMPLETE_MARKING) {} |
48 | 48 |
49 | |
50 bool IncrementalMarking::BaseRecordWrite(HeapObject* obj, Object* value) { | 49 bool IncrementalMarking::BaseRecordWrite(HeapObject* obj, Object* value) { |
51 HeapObject* value_heap_obj = HeapObject::cast(value); | 50 HeapObject* value_heap_obj = HeapObject::cast(value); |
52 MarkBit value_bit = Marking::MarkBitFrom(value_heap_obj); | 51 MarkBit value_bit = Marking::MarkBitFrom(value_heap_obj); |
53 DCHECK(!Marking::IsImpossible(value_bit)); | 52 DCHECK(!Marking::IsImpossible(value_bit)); |
54 | 53 |
55 MarkBit obj_bit = Marking::MarkBitFrom(obj); | 54 MarkBit obj_bit = Marking::MarkBitFrom(obj); |
56 DCHECK(!Marking::IsImpossible(obj_bit)); | 55 DCHECK(!Marking::IsImpossible(obj_bit)); |
57 bool is_black = Marking::IsBlack(obj_bit); | 56 bool is_black = Marking::IsBlack(obj_bit); |
58 | 57 |
59 if (is_black && Marking::IsWhite(value_bit)) { | 58 if (is_black && Marking::IsWhite(value_bit)) { |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 MarkBit mark_bit = Marking::MarkBitFrom(heap_object); | 316 MarkBit mark_bit = Marking::MarkBitFrom(heap_object); |
318 if (Marking::IsWhite(mark_bit)) { | 317 if (Marking::IsWhite(mark_bit)) { |
319 Marking::MarkBlack(mark_bit); | 318 Marking::MarkBlack(mark_bit); |
320 MemoryChunk::IncrementLiveBytesFromGC(heap_object, heap_object->Size()); | 319 MemoryChunk::IncrementLiveBytesFromGC(heap_object, heap_object->Size()); |
321 return true; | 320 return true; |
322 } | 321 } |
323 return false; | 322 return false; |
324 } | 323 } |
325 }; | 324 }; |
326 | 325 |
| 326 void IncrementalMarking::IterateBlackObject(HeapObject* object) { |
| 327 if (black_allocation() && |
| 328 Page::FromAddress(object->address())->IsFlagSet(Page::BLACK_PAGE)) { |
| 329 IncrementalMarkingMarkingVisitor::IterateBody(object->map(), object); |
| 330 } |
| 331 } |
327 | 332 |
328 class IncrementalMarkingRootMarkingVisitor : public ObjectVisitor { | 333 class IncrementalMarkingRootMarkingVisitor : public ObjectVisitor { |
329 public: | 334 public: |
330 explicit IncrementalMarkingRootMarkingVisitor( | 335 explicit IncrementalMarkingRootMarkingVisitor( |
331 IncrementalMarking* incremental_marking) | 336 IncrementalMarking* incremental_marking) |
332 : heap_(incremental_marking->heap()) {} | 337 : heap_(incremental_marking->heap()) {} |
333 | 338 |
334 void VisitPointer(Object** p) override { MarkObjectByPointer(p); } | 339 void VisitPointer(Object** p) override { MarkObjectByPointer(p); } |
335 | 340 |
336 void VisitPointers(Object** start, Object** end) override { | 341 void VisitPointers(Object** start, Object** end) override { |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
590 if (FLAG_cleanup_code_caches_at_gc) { | 595 if (FLAG_cleanup_code_caches_at_gc) { |
591 // We will mark cache black with a separate pass | 596 // We will mark cache black with a separate pass |
592 // when we finish marking. | 597 // when we finish marking. |
593 MarkObjectGreyDoNotEnqueue(heap_->polymorphic_code_cache()); | 598 MarkObjectGreyDoNotEnqueue(heap_->polymorphic_code_cache()); |
594 } | 599 } |
595 | 600 |
596 // Mark strong roots grey. | 601 // Mark strong roots grey. |
597 IncrementalMarkingRootMarkingVisitor visitor(this); | 602 IncrementalMarkingRootMarkingVisitor visitor(this); |
598 heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); | 603 heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); |
599 | 604 |
| 605 if (FLAG_black_allocation) { |
| 606 StartBlackAllocation(); |
| 607 } |
| 608 |
600 // Ready to start incremental marking. | 609 // Ready to start incremental marking. |
601 if (FLAG_trace_incremental_marking) { | 610 if (FLAG_trace_incremental_marking) { |
602 PrintF("[IncrementalMarking] Running\n"); | 611 PrintF("[IncrementalMarking] Running\n"); |
603 } | 612 } |
604 } | 613 } |
605 | 614 |
| 615 void IncrementalMarking::StartBlackAllocation() { |
| 616 if (heap_->isolate()->serializer_enabled()) { |
| 617 if (FLAG_trace_incremental_marking) { |
| 618 PrintF("[IncrementalMarking] Black allocation delayed - serializer\n"); |
| 619 } |
| 620 return; |
| 621 } |
| 622 DCHECK(FLAG_black_allocation); |
| 623 DCHECK(IsMarking()); |
| 624 black_allocation_ = true; |
| 625 PagedSpaces spaces(heap()); |
| 626 for (PagedSpace* space = spaces.next(); space != NULL; |
| 627 space = spaces.next()) { |
| 628 space->EmptyAllocationInfo(); |
| 629 space->free_list()->Reset(); |
| 630 } |
| 631 if (FLAG_trace_incremental_marking) { |
| 632 PrintF("[IncrementalMarking] Black allocation started\n"); |
| 633 } |
| 634 } |
| 635 |
| 636 void IncrementalMarking::FinishBlackAllocation() { |
| 637 black_allocation_ = false; |
| 638 if (FLAG_trace_incremental_marking) { |
| 639 PrintF("[IncrementalMarking] Black allocation finished\n"); |
| 640 } |
| 641 } |
606 | 642 |
607 void IncrementalMarking::MarkRoots() { | 643 void IncrementalMarking::MarkRoots() { |
608 DCHECK(!finalize_marking_completed_); | 644 DCHECK(!finalize_marking_completed_); |
609 DCHECK(IsMarking()); | 645 DCHECK(IsMarking()); |
610 | 646 |
611 IncrementalMarkingRootMarkingVisitor visitor(this); | 647 IncrementalMarkingRootMarkingVisitor visitor(this); |
612 heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); | 648 heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); |
613 } | 649 } |
614 | 650 |
615 | 651 |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
798 // Only pointers to from space have to be updated. | 834 // Only pointers to from space have to be updated. |
799 if (heap_->InFromSpace(obj)) { | 835 if (heap_->InFromSpace(obj)) { |
800 MapWord map_word = obj->map_word(); | 836 MapWord map_word = obj->map_word(); |
801 // There may be objects on the marking deque that do not exist anymore, | 837 // There may be objects on the marking deque that do not exist anymore, |
802 // e.g. left trimmed objects or objects from the root set (frames). | 838 // e.g. left trimmed objects or objects from the root set (frames). |
803 // If these object are dead at scavenging time, their marking deque | 839 // If these object are dead at scavenging time, their marking deque |
804 // entries will not point to forwarding addresses. Hence, we can discard | 840 // entries will not point to forwarding addresses. Hence, we can discard |
805 // them. | 841 // them. |
806 if (map_word.IsForwardingAddress()) { | 842 if (map_word.IsForwardingAddress()) { |
807 HeapObject* dest = map_word.ToForwardingAddress(); | 843 HeapObject* dest = map_word.ToForwardingAddress(); |
| 844 if (Page::FromAddress(dest->address())->IsFlagSet(Page::BLACK_PAGE)) |
| 845 continue; |
808 array[new_top] = dest; | 846 array[new_top] = dest; |
809 new_top = ((new_top + 1) & mask); | 847 new_top = ((new_top + 1) & mask); |
810 DCHECK(new_top != marking_deque->bottom()); | 848 DCHECK(new_top != marking_deque->bottom()); |
811 #ifdef DEBUG | 849 #ifdef DEBUG |
812 MarkBit mark_bit = Marking::MarkBitFrom(obj); | 850 MarkBit mark_bit = Marking::MarkBitFrom(obj); |
813 DCHECK(Marking::IsGrey(mark_bit) || | 851 DCHECK(Marking::IsGrey(mark_bit) || |
814 (obj->IsFiller() && Marking::IsWhite(mark_bit))); | 852 (obj->IsFiller() && Marking::IsWhite(mark_bit))); |
815 #endif | 853 #endif |
816 } | 854 } |
817 } else if (obj->map() != filler_map) { | 855 } else if (obj->map() != filler_map) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
892 // correct only for objects that occupy at least two words. | 930 // correct only for objects that occupy at least two words. |
893 Map* map = obj->map(); | 931 Map* map = obj->map(); |
894 if (map == filler_map) continue; | 932 if (map == filler_map) continue; |
895 | 933 |
896 VisitObject(map, obj, obj->SizeFromMap(map)); | 934 VisitObject(map, obj, obj->SizeFromMap(map)); |
897 } | 935 } |
898 } | 936 } |
899 | 937 |
900 | 938 |
901 void IncrementalMarking::Hurry() { | 939 void IncrementalMarking::Hurry() { |
902 if (state() == MARKING) { | 940 // A scavenge may have pushed new objects on the marking deque (due to black |
| 941 // allocation) even in COMPLETE state. This may happen if scavenges are |
| 942 // forced e.g. in tests. It should not happen when COMPLETE was set when |
| 943 // incremental marking finished and a regular GC was triggered after that |
| 944 // because should_hurry_ will force a full GC. |
| 945 if (!heap_->mark_compact_collector()->marking_deque()->IsEmpty()) { |
903 double start = 0.0; | 946 double start = 0.0; |
904 if (FLAG_trace_incremental_marking || FLAG_print_cumulative_gc_stat) { | 947 if (FLAG_trace_incremental_marking || FLAG_print_cumulative_gc_stat) { |
905 start = heap_->MonotonicallyIncreasingTimeInMs(); | 948 start = heap_->MonotonicallyIncreasingTimeInMs(); |
906 if (FLAG_trace_incremental_marking) { | 949 if (FLAG_trace_incremental_marking) { |
907 PrintF("[IncrementalMarking] Hurry\n"); | 950 PrintF("[IncrementalMarking] Hurry\n"); |
908 } | 951 } |
909 } | 952 } |
910 // TODO(gc) hurry can mark objects it encounters black as mutator | 953 // TODO(gc) hurry can mark objects it encounters black as mutator |
911 // was stopped. | 954 // was stopped. |
912 ProcessMarkingDeque(); | 955 ProcessMarkingDeque(); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
957 IncrementalMarking::set_should_hurry(false); | 1000 IncrementalMarking::set_should_hurry(false); |
958 ResetStepCounters(); | 1001 ResetStepCounters(); |
959 if (IsMarking()) { | 1002 if (IsMarking()) { |
960 PatchIncrementalMarkingRecordWriteStubs(heap_, | 1003 PatchIncrementalMarkingRecordWriteStubs(heap_, |
961 RecordWriteStub::STORE_BUFFER_ONLY); | 1004 RecordWriteStub::STORE_BUFFER_ONLY); |
962 DeactivateIncrementalWriteBarrier(); | 1005 DeactivateIncrementalWriteBarrier(); |
963 } | 1006 } |
964 heap_->isolate()->stack_guard()->ClearGC(); | 1007 heap_->isolate()->stack_guard()->ClearGC(); |
965 state_ = STOPPED; | 1008 state_ = STOPPED; |
966 is_compacting_ = false; | 1009 is_compacting_ = false; |
| 1010 FinishBlackAllocation(); |
967 } | 1011 } |
968 | 1012 |
969 | 1013 |
970 void IncrementalMarking::Finalize() { | 1014 void IncrementalMarking::Finalize() { |
971 Hurry(); | 1015 Hurry(); |
972 Stop(); | 1016 Stop(); |
973 } | 1017 } |
974 | 1018 |
975 | 1019 |
976 void IncrementalMarking::FinalizeMarking(CompletionAction action) { | 1020 void IncrementalMarking::FinalizeMarking(CompletionAction action) { |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1175 if (heap_->mark_compact_collector()->sweeping_in_progress() && | 1219 if (heap_->mark_compact_collector()->sweeping_in_progress() && |
1176 (heap_->mark_compact_collector()->IsSweepingCompleted() || | 1220 (heap_->mark_compact_collector()->IsSweepingCompleted() || |
1177 !FLAG_concurrent_sweeping)) { | 1221 !FLAG_concurrent_sweeping)) { |
1178 heap_->mark_compact_collector()->EnsureSweepingCompleted(); | 1222 heap_->mark_compact_collector()->EnsureSweepingCompleted(); |
1179 } | 1223 } |
1180 if (!heap_->mark_compact_collector()->sweeping_in_progress()) { | 1224 if (!heap_->mark_compact_collector()->sweeping_in_progress()) { |
1181 bytes_scanned_ = 0; | 1225 bytes_scanned_ = 0; |
1182 StartMarking(); | 1226 StartMarking(); |
1183 } | 1227 } |
1184 } else if (state_ == MARKING) { | 1228 } else if (state_ == MARKING) { |
| 1229 if (FLAG_black_allocation && !black_allocation()) { |
| 1230 // If black allocation was not started when incremental marking started |
| 1231 // start it now. |
| 1232 StartBlackAllocation(); |
| 1233 } |
1185 bytes_processed = ProcessMarkingDeque(bytes_to_process); | 1234 bytes_processed = ProcessMarkingDeque(bytes_to_process); |
1186 if (heap_->mark_compact_collector()->marking_deque()->IsEmpty()) { | 1235 if (heap_->mark_compact_collector()->marking_deque()->IsEmpty()) { |
1187 if (completion == FORCE_COMPLETION || | 1236 if (completion == FORCE_COMPLETION || |
1188 IsIdleMarkingDelayCounterLimitReached()) { | 1237 IsIdleMarkingDelayCounterLimitReached()) { |
1189 if (!finalize_marking_completed_) { | 1238 if (!finalize_marking_completed_) { |
1190 FinalizeMarking(action); | 1239 FinalizeMarking(action); |
1191 } else { | 1240 } else { |
1192 MarkingComplete(action); | 1241 MarkingComplete(action); |
1193 } | 1242 } |
1194 } else { | 1243 } else { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1240 void IncrementalMarking::IncrementIdleMarkingDelayCounter() { | 1289 void IncrementalMarking::IncrementIdleMarkingDelayCounter() { |
1241 idle_marking_delay_counter_++; | 1290 idle_marking_delay_counter_++; |
1242 } | 1291 } |
1243 | 1292 |
1244 | 1293 |
1245 void IncrementalMarking::ClearIdleMarkingDelayCounter() { | 1294 void IncrementalMarking::ClearIdleMarkingDelayCounter() { |
1246 idle_marking_delay_counter_ = 0; | 1295 idle_marking_delay_counter_ = 0; |
1247 } | 1296 } |
1248 } // namespace internal | 1297 } // namespace internal |
1249 } // namespace v8 | 1298 } // namespace v8 |
OLD | NEW |