| 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 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 state_ = SWEEPING; | 554 state_ = SWEEPING; |
| 548 } | 555 } |
| 549 | 556 |
| 550 heap_->new_space()->AddAllocationObserver(&observer_); | 557 heap_->new_space()->AddAllocationObserver(&observer_); |
| 551 | 558 |
| 552 incremental_marking_job()->Start(heap_); | 559 incremental_marking_job()->Start(heap_); |
| 553 } | 560 } |
| 554 | 561 |
| 555 | 562 |
| 556 void IncrementalMarking::StartMarking() { | 563 void IncrementalMarking::StartMarking() { |
| 564 if (heap_->isolate()->serializer_enabled()) { |
| 565 // Black allocation currently starts when we start incremental marking, |
| 566 // but we cannot enable black allocation while deserializing. Hence, we |
| 567 // have to delay the start of incremental marking in that case. |
| 568 if (FLAG_trace_incremental_marking) { |
| 569 PrintF("[IncrementalMarking] Start delayed - serializer\n"); |
| 570 } |
| 571 return; |
| 572 } |
| 557 if (FLAG_trace_incremental_marking) { | 573 if (FLAG_trace_incremental_marking) { |
| 558 PrintF("[IncrementalMarking] Start marking\n"); | 574 PrintF("[IncrementalMarking] Start marking\n"); |
| 559 } | 575 } |
| 560 | 576 |
| 561 is_compacting_ = !FLAG_never_compact && | 577 is_compacting_ = !FLAG_never_compact && |
| 562 heap_->mark_compact_collector()->StartCompaction( | 578 heap_->mark_compact_collector()->StartCompaction( |
| 563 MarkCompactCollector::INCREMENTAL_COMPACTION); | 579 MarkCompactCollector::INCREMENTAL_COMPACTION); |
| 564 | 580 |
| 565 state_ = MARKING; | 581 state_ = MARKING; |
| 566 | 582 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 588 if (FLAG_cleanup_code_caches_at_gc) { | 604 if (FLAG_cleanup_code_caches_at_gc) { |
| 589 // We will mark cache black with a separate pass | 605 // We will mark cache black with a separate pass |
| 590 // when we finish marking. | 606 // when we finish marking. |
| 591 MarkObjectGreyDoNotEnqueue(heap_->polymorphic_code_cache()); | 607 MarkObjectGreyDoNotEnqueue(heap_->polymorphic_code_cache()); |
| 592 } | 608 } |
| 593 | 609 |
| 594 // Mark strong roots grey. | 610 // Mark strong roots grey. |
| 595 IncrementalMarkingRootMarkingVisitor visitor(this); | 611 IncrementalMarkingRootMarkingVisitor visitor(this); |
| 596 heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); | 612 heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); |
| 597 | 613 |
| 614 if (FLAG_black_allocation) { |
| 615 StartBlackAllocation(); |
| 616 } |
| 617 |
| 598 // Ready to start incremental marking. | 618 // Ready to start incremental marking. |
| 599 if (FLAG_trace_incremental_marking) { | 619 if (FLAG_trace_incremental_marking) { |
| 600 PrintF("[IncrementalMarking] Running\n"); | 620 PrintF("[IncrementalMarking] Running\n"); |
| 601 } | 621 } |
| 602 } | 622 } |
| 603 | 623 |
| 624 void IncrementalMarking::StartBlackAllocation() { |
| 625 DCHECK(FLAG_black_allocation); |
| 626 DCHECK(IsMarking()); |
| 627 black_allocation_ = true; |
| 628 PagedSpaces spaces(heap()); |
| 629 for (PagedSpace* space = spaces.next(); space != NULL; |
| 630 space = spaces.next()) { |
| 631 space->EmptyAllocationInfo(); |
| 632 space->free_list()->Reset(); |
| 633 } |
| 634 if (FLAG_trace_incremental_marking) { |
| 635 PrintF("[IncrementalMarking] Black allocation started\n"); |
| 636 } |
| 637 } |
| 638 |
| 639 void IncrementalMarking::FinishBlackAllocation() { |
| 640 black_allocation_ = false; |
| 641 if (FLAG_trace_incremental_marking) { |
| 642 PrintF("[IncrementalMarking] Black allocation finished\n"); |
| 643 } |
| 644 } |
| 604 | 645 |
| 605 void IncrementalMarking::MarkRoots() { | 646 void IncrementalMarking::MarkRoots() { |
| 606 DCHECK(!finalize_marking_completed_); | 647 DCHECK(!finalize_marking_completed_); |
| 607 DCHECK(IsMarking()); | 648 DCHECK(IsMarking()); |
| 608 | 649 |
| 609 IncrementalMarkingRootMarkingVisitor visitor(this); | 650 IncrementalMarkingRootMarkingVisitor visitor(this); |
| 610 heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); | 651 heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); |
| 611 } | 652 } |
| 612 | 653 |
| 613 | 654 |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 796 // Only pointers to from space have to be updated. | 837 // Only pointers to from space have to be updated. |
| 797 if (heap_->InFromSpace(obj)) { | 838 if (heap_->InFromSpace(obj)) { |
| 798 MapWord map_word = obj->map_word(); | 839 MapWord map_word = obj->map_word(); |
| 799 // There may be objects on the marking deque that do not exist anymore, | 840 // 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). | 841 // e.g. left trimmed objects or objects from the root set (frames). |
| 801 // If these object are dead at scavenging time, their marking deque | 842 // If these object are dead at scavenging time, their marking deque |
| 802 // entries will not point to forwarding addresses. Hence, we can discard | 843 // entries will not point to forwarding addresses. Hence, we can discard |
| 803 // them. | 844 // them. |
| 804 if (map_word.IsForwardingAddress()) { | 845 if (map_word.IsForwardingAddress()) { |
| 805 HeapObject* dest = map_word.ToForwardingAddress(); | 846 HeapObject* dest = map_word.ToForwardingAddress(); |
| 847 if (Page::FromAddress(dest->address())->IsFlagSet(Page::BLACK_PAGE)) |
| 848 continue; |
| 806 array[new_top] = dest; | 849 array[new_top] = dest; |
| 807 new_top = ((new_top + 1) & mask); | 850 new_top = ((new_top + 1) & mask); |
| 808 DCHECK(new_top != marking_deque->bottom()); | 851 DCHECK(new_top != marking_deque->bottom()); |
| 809 #ifdef DEBUG | 852 #ifdef DEBUG |
| 810 MarkBit mark_bit = Marking::MarkBitFrom(obj); | 853 MarkBit mark_bit = Marking::MarkBitFrom(obj); |
| 811 DCHECK(Marking::IsGrey(mark_bit) || | 854 DCHECK(Marking::IsGrey(mark_bit) || |
| 812 (obj->IsFiller() && Marking::IsWhite(mark_bit))); | 855 (obj->IsFiller() && Marking::IsWhite(mark_bit))); |
| 813 #endif | 856 #endif |
| 814 } | 857 } |
| 815 } else if (obj->map() != filler_map) { | 858 } 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. | 938 // correct only for objects that occupy at least two words. |
| 896 Map* map = obj->map(); | 939 Map* map = obj->map(); |
| 897 if (map == filler_map) continue; | 940 if (map == filler_map) continue; |
| 898 | 941 |
| 899 VisitObject(map, obj, obj->SizeFromMap(map)); | 942 VisitObject(map, obj, obj->SizeFromMap(map)); |
| 900 } | 943 } |
| 901 } | 944 } |
| 902 | 945 |
| 903 | 946 |
| 904 void IncrementalMarking::Hurry() { | 947 void IncrementalMarking::Hurry() { |
| 905 if (state() == MARKING) { | 948 // A scavenge may have pushed new objects on the marking deque (due to black |
| 949 // allocation) even in COMPLETE state. This may happen if scavenges are |
| 950 // forced e.g. in tests. It should not happen when COMPLETE was set when |
| 951 // incremental marking finished and a regular GC was triggered after that |
| 952 // because should_hurry_ will force a full GC. |
| 953 if (!heap_->mark_compact_collector()->marking_deque()->IsEmpty()) { |
| 906 double start = 0.0; | 954 double start = 0.0; |
| 907 if (FLAG_trace_incremental_marking || FLAG_print_cumulative_gc_stat) { | 955 if (FLAG_trace_incremental_marking || FLAG_print_cumulative_gc_stat) { |
| 908 start = heap_->MonotonicallyIncreasingTimeInMs(); | 956 start = heap_->MonotonicallyIncreasingTimeInMs(); |
| 909 if (FLAG_trace_incremental_marking) { | 957 if (FLAG_trace_incremental_marking) { |
| 910 PrintF("[IncrementalMarking] Hurry\n"); | 958 PrintF("[IncrementalMarking] Hurry\n"); |
| 911 } | 959 } |
| 912 } | 960 } |
| 913 // TODO(gc) hurry can mark objects it encounters black as mutator | 961 // TODO(gc) hurry can mark objects it encounters black as mutator |
| 914 // was stopped. | 962 // was stopped. |
| 915 ProcessMarkingDeque(); | 963 ProcessMarkingDeque(); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 960 IncrementalMarking::set_should_hurry(false); | 1008 IncrementalMarking::set_should_hurry(false); |
| 961 ResetStepCounters(); | 1009 ResetStepCounters(); |
| 962 if (IsMarking()) { | 1010 if (IsMarking()) { |
| 963 PatchIncrementalMarkingRecordWriteStubs(heap_, | 1011 PatchIncrementalMarkingRecordWriteStubs(heap_, |
| 964 RecordWriteStub::STORE_BUFFER_ONLY); | 1012 RecordWriteStub::STORE_BUFFER_ONLY); |
| 965 DeactivateIncrementalWriteBarrier(); | 1013 DeactivateIncrementalWriteBarrier(); |
| 966 } | 1014 } |
| 967 heap_->isolate()->stack_guard()->ClearGC(); | 1015 heap_->isolate()->stack_guard()->ClearGC(); |
| 968 state_ = STOPPED; | 1016 state_ = STOPPED; |
| 969 is_compacting_ = false; | 1017 is_compacting_ = false; |
| 1018 FinishBlackAllocation(); |
| 970 } | 1019 } |
| 971 | 1020 |
| 972 | 1021 |
| 973 void IncrementalMarking::Finalize() { | 1022 void IncrementalMarking::Finalize() { |
| 974 Hurry(); | 1023 Hurry(); |
| 975 Stop(); | 1024 Stop(); |
| 976 } | 1025 } |
| 977 | 1026 |
| 978 | 1027 |
| 979 void IncrementalMarking::FinalizeMarking(CompletionAction action) { | 1028 void IncrementalMarking::FinalizeMarking(CompletionAction action) { |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1244 void IncrementalMarking::IncrementIdleMarkingDelayCounter() { | 1293 void IncrementalMarking::IncrementIdleMarkingDelayCounter() { |
| 1245 idle_marking_delay_counter_++; | 1294 idle_marking_delay_counter_++; |
| 1246 } | 1295 } |
| 1247 | 1296 |
| 1248 | 1297 |
| 1249 void IncrementalMarking::ClearIdleMarkingDelayCounter() { | 1298 void IncrementalMarking::ClearIdleMarkingDelayCounter() { |
| 1250 idle_marking_delay_counter_ = 0; | 1299 idle_marking_delay_counter_ = 0; |
| 1251 } | 1300 } |
| 1252 } // namespace internal | 1301 } // namespace internal |
| 1253 } // namespace v8 | 1302 } // namespace v8 |
| OLD | NEW |