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 |