| 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 |