| 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 24 matching lines...) Expand all Loading... |
| 35 bytes_rescanned_(0), | 35 bytes_rescanned_(0), |
| 36 should_hurry_(false), | 36 should_hurry_(false), |
| 37 marking_speed_(0), | 37 marking_speed_(0), |
| 38 bytes_scanned_(0), | 38 bytes_scanned_(0), |
| 39 allocated_(0), | 39 allocated_(0), |
| 40 write_barriers_invoked_since_last_step_(0), | 40 write_barriers_invoked_since_last_step_(0), |
| 41 idle_marking_delay_counter_(0), | 41 idle_marking_delay_counter_(0), |
| 42 no_marking_scope_depth_(0), | 42 no_marking_scope_depth_(0), |
| 43 unscanned_bytes_of_large_object_(0), | 43 unscanned_bytes_of_large_object_(0), |
| 44 was_activated_(false), | 44 was_activated_(false), |
| 45 black_allocation_(false), |
| 45 finalize_marking_completed_(false), | 46 finalize_marking_completed_(false), |
| 46 incremental_marking_finalization_rounds_(0), | 47 incremental_marking_finalization_rounds_(0), |
| 47 request_type_(COMPLETE_MARKING) {} | 48 request_type_(COMPLETE_MARKING) {} |
| 48 | 49 |
| 49 bool IncrementalMarking::BaseRecordWrite(HeapObject* obj, Object* value) { | 50 bool IncrementalMarking::BaseRecordWrite(HeapObject* obj, Object* value) { |
| 50 HeapObject* value_heap_obj = HeapObject::cast(value); | 51 HeapObject* value_heap_obj = HeapObject::cast(value); |
| 51 MarkBit value_bit = Marking::MarkBitFrom(value_heap_obj); | 52 MarkBit value_bit = Marking::MarkBitFrom(value_heap_obj); |
| 52 DCHECK(!Marking::IsImpossible(value_bit)); | 53 DCHECK(!Marking::IsImpossible(value_bit)); |
| 53 | 54 |
| 54 MarkBit obj_bit = Marking::MarkBitFrom(obj); | 55 MarkBit obj_bit = Marking::MarkBitFrom(obj); |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 MarkBit mark_bit = Marking::MarkBitFrom(heap_object); | 315 MarkBit mark_bit = Marking::MarkBitFrom(heap_object); |
| 315 if (Marking::IsWhite(mark_bit)) { | 316 if (Marking::IsWhite(mark_bit)) { |
| 316 Marking::MarkBlack(mark_bit); | 317 Marking::MarkBlack(mark_bit); |
| 317 MemoryChunk::IncrementLiveBytesFromGC(heap_object, heap_object->Size()); | 318 MemoryChunk::IncrementLiveBytesFromGC(heap_object, heap_object->Size()); |
| 318 return true; | 319 return true; |
| 319 } | 320 } |
| 320 return false; | 321 return false; |
| 321 } | 322 } |
| 322 }; | 323 }; |
| 323 | 324 |
| 325 void IncrementalMarking::IterateBlackObject(HeapObject* object) { |
| 326 if (black_allocation() && |
| 327 Page::FromAddress(object->address())->IsFlagSet(Page::BLACK_PAGE)) { |
| 328 IncrementalMarkingMarkingVisitor::IterateBody(object->map(), object); |
| 329 } |
| 330 } |
| 324 | 331 |
| 325 class IncrementalMarkingRootMarkingVisitor : public ObjectVisitor { | 332 class IncrementalMarkingRootMarkingVisitor : public ObjectVisitor { |
| 326 public: | 333 public: |
| 327 explicit IncrementalMarkingRootMarkingVisitor( | 334 explicit IncrementalMarkingRootMarkingVisitor( |
| 328 IncrementalMarking* incremental_marking) | 335 IncrementalMarking* incremental_marking) |
| 329 : heap_(incremental_marking->heap()) {} | 336 : heap_(incremental_marking->heap()) {} |
| 330 | 337 |
| 331 void VisitPointer(Object** p) override { MarkObjectByPointer(p); } | 338 void VisitPointer(Object** p) override { MarkObjectByPointer(p); } |
| 332 | 339 |
| 333 void VisitPointers(Object** start, Object** end) override { | 340 void VisitPointers(Object** start, Object** end) override { |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 588 if (FLAG_cleanup_code_caches_at_gc) { | 595 if (FLAG_cleanup_code_caches_at_gc) { |
| 589 // We will mark cache black with a separate pass | 596 // We will mark cache black with a separate pass |
| 590 // when we finish marking. | 597 // when we finish marking. |
| 591 MarkObjectGreyDoNotEnqueue(heap_->polymorphic_code_cache()); | 598 MarkObjectGreyDoNotEnqueue(heap_->polymorphic_code_cache()); |
| 592 } | 599 } |
| 593 | 600 |
| 594 // Mark strong roots grey. | 601 // Mark strong roots grey. |
| 595 IncrementalMarkingRootMarkingVisitor visitor(this); | 602 IncrementalMarkingRootMarkingVisitor visitor(this); |
| 596 heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); | 603 heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); |
| 597 | 604 |
| 605 if (FLAG_black_allocation) { |
| 606 StartBlackAllocation(); |
| 607 } |
| 608 |
| 598 // Ready to start incremental marking. | 609 // Ready to start incremental marking. |
| 599 if (FLAG_trace_incremental_marking) { | 610 if (FLAG_trace_incremental_marking) { |
| 600 PrintF("[IncrementalMarking] Running\n"); | 611 PrintF("[IncrementalMarking] Running\n"); |
| 601 } | 612 } |
| 602 } | 613 } |
| 603 | 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 } |
| 604 | 642 |
| 605 void IncrementalMarking::MarkRoots() { | 643 void IncrementalMarking::MarkRoots() { |
| 606 DCHECK(!finalize_marking_completed_); | 644 DCHECK(!finalize_marking_completed_); |
| 607 DCHECK(IsMarking()); | 645 DCHECK(IsMarking()); |
| 608 | 646 |
| 609 IncrementalMarkingRootMarkingVisitor visitor(this); | 647 IncrementalMarkingRootMarkingVisitor visitor(this); |
| 610 heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); | 648 heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); |
| 611 } | 649 } |
| 612 | 650 |
| 613 | 651 |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 796 // Only pointers to from space have to be updated. | 834 // Only pointers to from space have to be updated. |
| 797 if (heap_->InFromSpace(obj)) { | 835 if (heap_->InFromSpace(obj)) { |
| 798 MapWord map_word = obj->map_word(); | 836 MapWord map_word = obj->map_word(); |
| 799 // 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, |
| 800 // 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). |
| 801 // If these object are dead at scavenging time, their marking deque | 839 // If these object are dead at scavenging time, their marking deque |
| 802 // entries will not point to forwarding addresses. Hence, we can discard | 840 // entries will not point to forwarding addresses. Hence, we can discard |
| 803 // them. | 841 // them. |
| 804 if (map_word.IsForwardingAddress()) { | 842 if (map_word.IsForwardingAddress()) { |
| 805 HeapObject* dest = map_word.ToForwardingAddress(); | 843 HeapObject* dest = map_word.ToForwardingAddress(); |
| 844 if (Page::FromAddress(dest->address())->IsFlagSet(Page::BLACK_PAGE)) |
| 845 continue; |
| 806 array[new_top] = dest; | 846 array[new_top] = dest; |
| 807 new_top = ((new_top + 1) & mask); | 847 new_top = ((new_top + 1) & mask); |
| 808 DCHECK(new_top != marking_deque->bottom()); | 848 DCHECK(new_top != marking_deque->bottom()); |
| 809 #ifdef DEBUG | 849 #ifdef DEBUG |
| 810 MarkBit mark_bit = Marking::MarkBitFrom(obj); | 850 MarkBit mark_bit = Marking::MarkBitFrom(obj); |
| 811 DCHECK(Marking::IsGrey(mark_bit) || | 851 DCHECK(Marking::IsGrey(mark_bit) || |
| 812 (obj->IsFiller() && Marking::IsWhite(mark_bit))); | 852 (obj->IsFiller() && Marking::IsWhite(mark_bit))); |
| 813 #endif | 853 #endif |
| 814 } | 854 } |
| 815 } else if (obj->map() != filler_map) { | 855 } else if (obj->map() != filler_map) { |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 895 // correct only for objects that occupy at least two words. | 935 // correct only for objects that occupy at least two words. |
| 896 Map* map = obj->map(); | 936 Map* map = obj->map(); |
| 897 if (map == filler_map) continue; | 937 if (map == filler_map) continue; |
| 898 | 938 |
| 899 VisitObject(map, obj, obj->SizeFromMap(map)); | 939 VisitObject(map, obj, obj->SizeFromMap(map)); |
| 900 } | 940 } |
| 901 } | 941 } |
| 902 | 942 |
| 903 | 943 |
| 904 void IncrementalMarking::Hurry() { | 944 void IncrementalMarking::Hurry() { |
| 905 if (state() == MARKING) { | 945 // A scavenge may have pushed new objects on the marking deque (due to black |
| 946 // allocation) even in COMPLETE state. This may happen if scavenges are |
| 947 // forced e.g. in tests. It should not happen when COMPLETE was set when |
| 948 // incremental marking finished and a regular GC was triggered after that |
| 949 // because should_hurry_ will force a full GC. |
| 950 if (!heap_->mark_compact_collector()->marking_deque()->IsEmpty()) { |
| 906 double start = 0.0; | 951 double start = 0.0; |
| 907 if (FLAG_trace_incremental_marking || FLAG_print_cumulative_gc_stat) { | 952 if (FLAG_trace_incremental_marking || FLAG_print_cumulative_gc_stat) { |
| 908 start = heap_->MonotonicallyIncreasingTimeInMs(); | 953 start = heap_->MonotonicallyIncreasingTimeInMs(); |
| 909 if (FLAG_trace_incremental_marking) { | 954 if (FLAG_trace_incremental_marking) { |
| 910 PrintF("[IncrementalMarking] Hurry\n"); | 955 PrintF("[IncrementalMarking] Hurry\n"); |
| 911 } | 956 } |
| 912 } | 957 } |
| 913 // TODO(gc) hurry can mark objects it encounters black as mutator | 958 // TODO(gc) hurry can mark objects it encounters black as mutator |
| 914 // was stopped. | 959 // was stopped. |
| 915 ProcessMarkingDeque(); | 960 ProcessMarkingDeque(); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 960 IncrementalMarking::set_should_hurry(false); | 1005 IncrementalMarking::set_should_hurry(false); |
| 961 ResetStepCounters(); | 1006 ResetStepCounters(); |
| 962 if (IsMarking()) { | 1007 if (IsMarking()) { |
| 963 PatchIncrementalMarkingRecordWriteStubs(heap_, | 1008 PatchIncrementalMarkingRecordWriteStubs(heap_, |
| 964 RecordWriteStub::STORE_BUFFER_ONLY); | 1009 RecordWriteStub::STORE_BUFFER_ONLY); |
| 965 DeactivateIncrementalWriteBarrier(); | 1010 DeactivateIncrementalWriteBarrier(); |
| 966 } | 1011 } |
| 967 heap_->isolate()->stack_guard()->ClearGC(); | 1012 heap_->isolate()->stack_guard()->ClearGC(); |
| 968 state_ = STOPPED; | 1013 state_ = STOPPED; |
| 969 is_compacting_ = false; | 1014 is_compacting_ = false; |
| 1015 FinishBlackAllocation(); |
| 970 } | 1016 } |
| 971 | 1017 |
| 972 | 1018 |
| 973 void IncrementalMarking::Finalize() { | 1019 void IncrementalMarking::Finalize() { |
| 974 Hurry(); | 1020 Hurry(); |
| 975 Stop(); | 1021 Stop(); |
| 976 } | 1022 } |
| 977 | 1023 |
| 978 | 1024 |
| 979 void IncrementalMarking::FinalizeMarking(CompletionAction action) { | 1025 void IncrementalMarking::FinalizeMarking(CompletionAction action) { |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1179 if (heap_->mark_compact_collector()->sweeping_in_progress() && | 1225 if (heap_->mark_compact_collector()->sweeping_in_progress() && |
| 1180 (heap_->mark_compact_collector()->IsSweepingCompleted() || | 1226 (heap_->mark_compact_collector()->IsSweepingCompleted() || |
| 1181 !FLAG_concurrent_sweeping)) { | 1227 !FLAG_concurrent_sweeping)) { |
| 1182 heap_->mark_compact_collector()->EnsureSweepingCompleted(); | 1228 heap_->mark_compact_collector()->EnsureSweepingCompleted(); |
| 1183 } | 1229 } |
| 1184 if (!heap_->mark_compact_collector()->sweeping_in_progress()) { | 1230 if (!heap_->mark_compact_collector()->sweeping_in_progress()) { |
| 1185 bytes_scanned_ = 0; | 1231 bytes_scanned_ = 0; |
| 1186 StartMarking(); | 1232 StartMarking(); |
| 1187 } | 1233 } |
| 1188 } else if (state_ == MARKING) { | 1234 } else if (state_ == MARKING) { |
| 1235 if (FLAG_black_allocation && !black_allocation()) { |
| 1236 // If black allocation was not started when incremental marking started |
| 1237 // start it now. |
| 1238 StartBlackAllocation(); |
| 1239 } |
| 1189 bytes_processed = ProcessMarkingDeque(bytes_to_process); | 1240 bytes_processed = ProcessMarkingDeque(bytes_to_process); |
| 1190 if (heap_->mark_compact_collector()->marking_deque()->IsEmpty()) { | 1241 if (heap_->mark_compact_collector()->marking_deque()->IsEmpty()) { |
| 1191 if (completion == FORCE_COMPLETION || | 1242 if (completion == FORCE_COMPLETION || |
| 1192 IsIdleMarkingDelayCounterLimitReached()) { | 1243 IsIdleMarkingDelayCounterLimitReached()) { |
| 1193 if (!finalize_marking_completed_) { | 1244 if (!finalize_marking_completed_) { |
| 1194 FinalizeMarking(action); | 1245 FinalizeMarking(action); |
| 1195 } else { | 1246 } else { |
| 1196 MarkingComplete(action); | 1247 MarkingComplete(action); |
| 1197 } | 1248 } |
| 1198 } else { | 1249 } else { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1244 void IncrementalMarking::IncrementIdleMarkingDelayCounter() { | 1295 void IncrementalMarking::IncrementIdleMarkingDelayCounter() { |
| 1245 idle_marking_delay_counter_++; | 1296 idle_marking_delay_counter_++; |
| 1246 } | 1297 } |
| 1247 | 1298 |
| 1248 | 1299 |
| 1249 void IncrementalMarking::ClearIdleMarkingDelayCounter() { | 1300 void IncrementalMarking::ClearIdleMarkingDelayCounter() { |
| 1250 idle_marking_delay_counter_ = 0; | 1301 idle_marking_delay_counter_ = 0; |
| 1251 } | 1302 } |
| 1252 } // namespace internal | 1303 } // namespace internal |
| 1253 } // namespace v8 | 1304 } // namespace v8 |
| OLD | NEW |