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::IterateBlackCode(Code* code) { |
| 327 Code::BodyDescriptor::IterateBody<IncrementalMarkingMarkingVisitor>(code); |
| 328 } |
327 | 329 |
328 class IncrementalMarkingRootMarkingVisitor : public ObjectVisitor { | 330 class IncrementalMarkingRootMarkingVisitor : public ObjectVisitor { |
329 public: | 331 public: |
330 explicit IncrementalMarkingRootMarkingVisitor( | 332 explicit IncrementalMarkingRootMarkingVisitor( |
331 IncrementalMarking* incremental_marking) | 333 IncrementalMarking* incremental_marking) |
332 : heap_(incremental_marking->heap()) {} | 334 : heap_(incremental_marking->heap()) {} |
333 | 335 |
334 void VisitPointer(Object** p) override { MarkObjectByPointer(p); } | 336 void VisitPointer(Object** p) override { MarkObjectByPointer(p); } |
335 | 337 |
336 void VisitPointers(Object** start, Object** end) override { | 338 void VisitPointers(Object** start, Object** end) override { |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
591 if (FLAG_cleanup_code_caches_at_gc) { | 593 if (FLAG_cleanup_code_caches_at_gc) { |
592 // We will mark cache black with a separate pass | 594 // We will mark cache black with a separate pass |
593 // when we finish marking. | 595 // when we finish marking. |
594 MarkObjectGreyDoNotEnqueue(heap_->polymorphic_code_cache()); | 596 MarkObjectGreyDoNotEnqueue(heap_->polymorphic_code_cache()); |
595 } | 597 } |
596 | 598 |
597 // Mark strong roots grey. | 599 // Mark strong roots grey. |
598 IncrementalMarkingRootMarkingVisitor visitor(this); | 600 IncrementalMarkingRootMarkingVisitor visitor(this); |
599 heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); | 601 heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); |
600 | 602 |
| 603 if (FLAG_black_allocation) { |
| 604 StartBlackAllocation(); |
| 605 } |
| 606 |
601 // Ready to start incremental marking. | 607 // Ready to start incremental marking. |
602 if (FLAG_trace_incremental_marking) { | 608 if (FLAG_trace_incremental_marking) { |
603 PrintF("[IncrementalMarking] Running\n"); | 609 PrintF("[IncrementalMarking] Running\n"); |
604 } | 610 } |
605 } | 611 } |
606 | 612 |
| 613 void IncrementalMarking::StartBlackAllocation() { |
| 614 DCHECK(FLAG_black_allocation); |
| 615 DCHECK(IsMarking()); |
| 616 black_allocation_ = true; |
| 617 PagedSpaces spaces(heap()); |
| 618 for (PagedSpace* space = spaces.next(); space != NULL; |
| 619 space = spaces.next()) { |
| 620 space->EmptyAllocationInfo(); |
| 621 space->free_list()->Reset(); |
| 622 } |
| 623 } |
| 624 |
| 625 void IncrementalMarking::FinishBlackAllocation() { black_allocation_ = false; } |
607 | 626 |
608 void IncrementalMarking::MarkRoots() { | 627 void IncrementalMarking::MarkRoots() { |
609 DCHECK(!finalize_marking_completed_); | 628 DCHECK(!finalize_marking_completed_); |
610 DCHECK(IsMarking()); | 629 DCHECK(IsMarking()); |
611 | 630 |
612 IncrementalMarkingRootMarkingVisitor visitor(this); | 631 IncrementalMarkingRootMarkingVisitor visitor(this); |
613 heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); | 632 heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); |
614 } | 633 } |
615 | 634 |
616 | 635 |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
793 Map* filler_map = heap_->one_pointer_filler_map(); | 812 Map* filler_map = heap_->one_pointer_filler_map(); |
794 | 813 |
795 while (current != limit) { | 814 while (current != limit) { |
796 HeapObject* obj = array[current]; | 815 HeapObject* obj = array[current]; |
797 DCHECK(obj->IsHeapObject()); | 816 DCHECK(obj->IsHeapObject()); |
798 current = ((current + 1) & mask); | 817 current = ((current + 1) & mask); |
799 if (heap_->InNewSpace(obj)) { | 818 if (heap_->InNewSpace(obj)) { |
800 MapWord map_word = obj->map_word(); | 819 MapWord map_word = obj->map_word(); |
801 if (map_word.IsForwardingAddress()) { | 820 if (map_word.IsForwardingAddress()) { |
802 HeapObject* dest = map_word.ToForwardingAddress(); | 821 HeapObject* dest = map_word.ToForwardingAddress(); |
| 822 if (Page::FromAddress(dest->address())->IsFlagSet(Page::BLACK_PAGE)) |
| 823 continue; |
| 824 // If the color of the source object was not transitioned, fix that |
| 825 // now. |
| 826 MarkBit mark_bit_dest = Marking::MarkBitFrom(dest); |
| 827 if (Marking::IsWhite(mark_bit_dest)) { |
| 828 Marking::WhiteToGrey(mark_bit_dest); |
| 829 } |
803 array[new_top] = dest; | 830 array[new_top] = dest; |
804 new_top = ((new_top + 1) & mask); | 831 new_top = ((new_top + 1) & mask); |
805 DCHECK(new_top != marking_deque->bottom()); | 832 DCHECK(new_top != marking_deque->bottom()); |
806 #ifdef DEBUG | 833 #ifdef DEBUG |
807 MarkBit mark_bit = Marking::MarkBitFrom(obj); | 834 MarkBit mark_bit = Marking::MarkBitFrom(obj); |
808 DCHECK(Marking::IsGrey(mark_bit) || | 835 DCHECK(Marking::IsGrey(mark_bit) || |
809 (obj->IsFiller() && Marking::IsWhite(mark_bit))); | 836 (obj->IsFiller() && Marking::IsWhite(mark_bit))); |
810 #endif | 837 #endif |
811 } | 838 } |
812 } else if (obj->map() != filler_map) { | 839 } else if (obj->map() != filler_map) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
887 // correct only for objects that occupy at least two words. | 914 // correct only for objects that occupy at least two words. |
888 Map* map = obj->map(); | 915 Map* map = obj->map(); |
889 if (map == filler_map) continue; | 916 if (map == filler_map) continue; |
890 | 917 |
891 VisitObject(map, obj, obj->SizeFromMap(map)); | 918 VisitObject(map, obj, obj->SizeFromMap(map)); |
892 } | 919 } |
893 } | 920 } |
894 | 921 |
895 | 922 |
896 void IncrementalMarking::Hurry() { | 923 void IncrementalMarking::Hurry() { |
897 if (state() == MARKING) { | 924 // A scavenge may have pushed new objects on the marking deque (due to black |
| 925 // allocation) even in COMPLETE state. This may happen if scavenges are |
| 926 // forced e.g. in tests. It should not happen when COMPLETE was set when |
| 927 // incremental marking finished and a regular GC was triggered after that |
| 928 // because should_hurry_ will force a full GC. |
| 929 if (!heap_->mark_compact_collector()->marking_deque()->IsEmpty()) { |
898 double start = 0.0; | 930 double start = 0.0; |
899 if (FLAG_trace_incremental_marking || FLAG_print_cumulative_gc_stat) { | 931 if (FLAG_trace_incremental_marking || FLAG_print_cumulative_gc_stat) { |
900 start = heap_->MonotonicallyIncreasingTimeInMs(); | 932 start = heap_->MonotonicallyIncreasingTimeInMs(); |
901 if (FLAG_trace_incremental_marking) { | 933 if (FLAG_trace_incremental_marking) { |
902 PrintF("[IncrementalMarking] Hurry\n"); | 934 PrintF("[IncrementalMarking] Hurry\n"); |
903 } | 935 } |
904 } | 936 } |
905 // TODO(gc) hurry can mark objects it encounters black as mutator | 937 // TODO(gc) hurry can mark objects it encounters black as mutator |
906 // was stopped. | 938 // was stopped. |
907 ProcessMarkingDeque(); | 939 ProcessMarkingDeque(); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
952 IncrementalMarking::set_should_hurry(false); | 984 IncrementalMarking::set_should_hurry(false); |
953 ResetStepCounters(); | 985 ResetStepCounters(); |
954 if (IsMarking()) { | 986 if (IsMarking()) { |
955 PatchIncrementalMarkingRecordWriteStubs(heap_, | 987 PatchIncrementalMarkingRecordWriteStubs(heap_, |
956 RecordWriteStub::STORE_BUFFER_ONLY); | 988 RecordWriteStub::STORE_BUFFER_ONLY); |
957 DeactivateIncrementalWriteBarrier(); | 989 DeactivateIncrementalWriteBarrier(); |
958 } | 990 } |
959 heap_->isolate()->stack_guard()->ClearGC(); | 991 heap_->isolate()->stack_guard()->ClearGC(); |
960 state_ = STOPPED; | 992 state_ = STOPPED; |
961 is_compacting_ = false; | 993 is_compacting_ = false; |
| 994 black_allocation_ = false; |
962 } | 995 } |
963 | 996 |
964 | 997 |
965 void IncrementalMarking::Finalize() { | 998 void IncrementalMarking::Finalize() { |
966 Hurry(); | 999 Hurry(); |
967 Stop(); | 1000 Stop(); |
968 } | 1001 } |
969 | 1002 |
970 | 1003 |
971 void IncrementalMarking::FinalizeMarking(CompletionAction action) { | 1004 void IncrementalMarking::FinalizeMarking(CompletionAction action) { |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1235 void IncrementalMarking::IncrementIdleMarkingDelayCounter() { | 1268 void IncrementalMarking::IncrementIdleMarkingDelayCounter() { |
1236 idle_marking_delay_counter_++; | 1269 idle_marking_delay_counter_++; |
1237 } | 1270 } |
1238 | 1271 |
1239 | 1272 |
1240 void IncrementalMarking::ClearIdleMarkingDelayCounter() { | 1273 void IncrementalMarking::ClearIdleMarkingDelayCounter() { |
1241 idle_marking_delay_counter_ = 0; | 1274 idle_marking_delay_counter_ = 0; |
1242 } | 1275 } |
1243 } // namespace internal | 1276 } // namespace internal |
1244 } // namespace v8 | 1277 } // namespace v8 |
OLD | NEW |