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/concurrent-marking.h" | 10 #include "src/heap/concurrent-marking.h" |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
130 } | 130 } |
131 | 131 |
132 bool IncrementalMarking::WhiteToGreyAndPush(HeapObject* obj) { | 132 bool IncrementalMarking::WhiteToGreyAndPush(HeapObject* obj) { |
133 if (ObjectMarking::WhiteToGrey<kAtomicity>(obj, marking_state(obj))) { | 133 if (ObjectMarking::WhiteToGrey<kAtomicity>(obj, marking_state(obj))) { |
134 marking_deque()->Push(obj); | 134 marking_deque()->Push(obj); |
135 return true; | 135 return true; |
136 } | 136 } |
137 return false; | 137 return false; |
138 } | 138 } |
139 | 139 |
| 140 void IncrementalMarking::MarkBlackAndPush(HeapObject* obj) { |
| 141 // Color the object black and push it into the bailout deque. |
| 142 ObjectMarking::WhiteToGrey<kAtomicity>(obj, marking_state(obj)); |
| 143 if (ObjectMarking::GreyToBlack<kAtomicity>(obj, marking_state(obj))) { |
| 144 #if V8_CONCURRENT_MARKING |
| 145 marking_deque()->Push(obj, MarkingThread::kMain, TargetDeque::kBailout); |
| 146 #else |
| 147 if (!marking_deque()->Push(obj)) { |
| 148 ObjectMarking::BlackToGrey<kAtomicity>(obj, marking_state(obj)); |
| 149 } |
| 150 #endif |
| 151 } |
| 152 } |
| 153 |
140 void IncrementalMarking::TransferMark(Heap* heap, HeapObject* from, | 154 void IncrementalMarking::TransferMark(Heap* heap, HeapObject* from, |
141 HeapObject* to) { | 155 HeapObject* to) { |
142 DCHECK(MemoryChunk::FromAddress(from->address())->SweepingDone()); | 156 DCHECK(MemoryChunk::FromAddress(from->address())->SweepingDone()); |
143 // This is only used when resizing an object. | 157 // This is only used when resizing an object. |
144 DCHECK(MemoryChunk::FromAddress(from->address()) == | 158 DCHECK(MemoryChunk::FromAddress(from->address()) == |
145 MemoryChunk::FromAddress(to->address())); | 159 MemoryChunk::FromAddress(to->address())); |
146 | 160 |
147 if (!IsMarking()) return; | 161 if (!IsMarking()) return; |
148 | 162 |
149 // If the mark doesn't move, we don't check the color of the object. | 163 // If the mark doesn't move, we don't check the color of the object. |
(...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
806 MapWord map_word = obj->map_word(); | 820 MapWord map_word = obj->map_word(); |
807 if (!map_word.IsForwardingAddress()) { | 821 if (!map_word.IsForwardingAddress()) { |
808 // There may be objects on the marking deque that do not exist anymore, | 822 // There may be objects on the marking deque that do not exist anymore, |
809 // e.g. left trimmed objects or objects from the root set (frames). | 823 // e.g. left trimmed objects or objects from the root set (frames). |
810 // If these object are dead at scavenging time, their marking deque | 824 // If these object are dead at scavenging time, their marking deque |
811 // entries will not point to forwarding addresses. Hence, we can discard | 825 // entries will not point to forwarding addresses. Hence, we can discard |
812 // them. | 826 // them. |
813 return nullptr; | 827 return nullptr; |
814 } | 828 } |
815 HeapObject* dest = map_word.ToForwardingAddress(); | 829 HeapObject* dest = map_word.ToForwardingAddress(); |
816 if (ObjectMarking::IsBlack<kAtomicity>(dest, marking_state(dest))) { | 830 DCHECK_IMPLIES( |
817 // The object is already processed by the marker. | 831 ObjectMarking::IsWhite<kAtomicity>(obj, marking_state(obj)), |
818 return nullptr; | 832 obj->IsFiller()); |
819 } | |
820 DCHECK(ObjectMarking::IsGrey<kAtomicity>(obj, marking_state(obj)) || | |
821 (obj->IsFiller() && | |
822 ObjectMarking::IsWhite<kAtomicity>(obj, marking_state(obj)))); | |
823 return dest; | 833 return dest; |
824 } else if (heap_->InToSpace(obj)) { | 834 } else if (heap_->InToSpace(obj)) { |
825 // The object may be on a page that was moved in new space. | 835 // The object may be on a page that was moved in new space. |
826 DCHECK( | 836 DCHECK( |
827 Page::FromAddress(obj->address())->IsFlagSet(Page::SWEEP_TO_ITERATE)); | 837 Page::FromAddress(obj->address())->IsFlagSet(Page::SWEEP_TO_ITERATE)); |
828 return ObjectMarking::IsBlack<kAtomicity>(obj, | 838 return ObjectMarking::IsBlack<kAtomicity>(obj, |
829 MarkingState::External(obj)) | 839 MarkingState::External(obj)) |
830 ? obj | 840 ? obj |
831 : nullptr; | 841 : nullptr; |
832 } else { | 842 } else { |
833 // The object may be on a page that was moved from new to old space. | 843 // The object may be on a page that was moved from new to old space. |
834 if (Page::FromAddress(obj->address()) | 844 if (Page::FromAddress(obj->address()) |
835 ->IsFlagSet(Page::SWEEP_TO_ITERATE)) { | 845 ->IsFlagSet(Page::SWEEP_TO_ITERATE)) { |
836 return ObjectMarking::IsBlack<kAtomicity>(obj, | 846 return ObjectMarking::IsBlack<kAtomicity>(obj, |
837 MarkingState::External(obj)) | 847 MarkingState::External(obj)) |
838 ? obj | 848 ? obj |
839 : nullptr; | 849 : nullptr; |
840 } | 850 } |
841 DCHECK(ObjectMarking::IsGrey<kAtomicity>(obj, marking_state(obj)) || | 851 DCHECK_IMPLIES( |
842 (obj->IsFiller() && | 852 ObjectMarking::IsWhite<kAtomicity>(obj, marking_state(obj)), |
843 ObjectMarking::IsWhite<kAtomicity>(obj, marking_state(obj))) || | 853 obj->IsFiller()); |
844 (MemoryChunk::FromAddress(obj->address()) | |
845 ->IsFlagSet(MemoryChunk::HAS_PROGRESS_BAR) && | |
846 ObjectMarking::IsBlack<kAtomicity>(obj, marking_state(obj)))); | |
847 // Skip one word filler objects that appear on the | 854 // Skip one word filler objects that appear on the |
848 // stack when we perform in place array shift. | 855 // stack when we perform in place array shift. |
849 return (obj->map() == filler_map) ? nullptr : obj; | 856 return (obj->map() == filler_map) ? nullptr : obj; |
850 } | 857 } |
851 }); | 858 }); |
852 } | 859 } |
853 | 860 |
854 bool IncrementalMarking::IsFixedArrayWithProgressBar(HeapObject* obj) { | 861 bool IncrementalMarking::IsFixedArrayWithProgressBar(HeapObject* obj) { |
855 if (!obj->IsFixedArray()) return false; | 862 if (!obj->IsFixedArray()) return false; |
856 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); | 863 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); |
857 return chunk->IsFlagSet(MemoryChunk::HAS_PROGRESS_BAR); | 864 return chunk->IsFlagSet(MemoryChunk::HAS_PROGRESS_BAR); |
858 } | 865 } |
859 | 866 |
860 void IncrementalMarking::VisitObject(Map* map, HeapObject* obj, int size) { | 867 void IncrementalMarking::VisitObject(Map* map, HeapObject* obj, int size) { |
861 #if ENABLE_SLOW_DCHECKS | |
862 MarkBit mark_bit = ObjectMarking::MarkBitFrom(obj, marking_state(obj)); | 868 MarkBit mark_bit = ObjectMarking::MarkBitFrom(obj, marking_state(obj)); |
863 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); | 869 DCHECK(Marking::IsGrey<kAtomicity>(mark_bit) || |
864 SLOW_DCHECK(Marking::IsGrey<kAtomicity>(mark_bit) || | 870 Marking::IsBlack<kAtomicity>(mark_bit)); |
865 (chunk->IsFlagSet(MemoryChunk::HAS_PROGRESS_BAR) && | 871 USE(mark_bit); |
866 Marking::IsBlack<kAtomicity>(mark_bit))); | 872 // The object can already be black in two cases: |
867 #endif | 873 // 1. The object is a fixed array with the progress bar. |
868 if (ObjectMarking::GreyToBlack<kAtomicity>(obj, marking_state(obj))) { | 874 // 2. The object is a JSObject that was colored black before |
869 WhiteToGreyAndPush(map); | 875 // unsafe layout change. |
870 IncrementalMarkingMarkingVisitor::IterateBody(map, obj); | 876 if (!ObjectMarking::GreyToBlack<kAtomicity>(obj, marking_state(obj))) { |
871 } else if (IsFixedArrayWithProgressBar(obj)) { | 877 DCHECK(IsFixedArrayWithProgressBar(obj) || obj->IsJSObject()); |
872 DCHECK(ObjectMarking::IsBlack<kAtomicity>(obj, marking_state(obj))); | |
873 IncrementalMarkingMarkingVisitor::VisitFixedArrayIncremental(map, obj); | |
874 } | 878 } |
| 879 DCHECK(ObjectMarking::IsBlack<kAtomicity>(obj, marking_state(obj))); |
| 880 WhiteToGreyAndPush(map); |
| 881 IncrementalMarkingMarkingVisitor::IterateBody(map, obj); |
875 } | 882 } |
876 | 883 |
877 intptr_t IncrementalMarking::ProcessMarkingDeque( | 884 intptr_t IncrementalMarking::ProcessMarkingDeque( |
878 intptr_t bytes_to_process, ForceCompletionAction completion) { | 885 intptr_t bytes_to_process, ForceCompletionAction completion) { |
879 intptr_t bytes_processed = 0; | 886 intptr_t bytes_processed = 0; |
880 while (!marking_deque()->IsEmpty() && (bytes_processed < bytes_to_process || | 887 while (!marking_deque()->IsEmpty() && (bytes_processed < bytes_to_process || |
881 completion == FORCE_COMPLETION)) { | 888 completion == FORCE_COMPLETION)) { |
882 HeapObject* obj = marking_deque()->Pop(); | 889 HeapObject* obj = marking_deque()->Pop(); |
883 | 890 |
884 // Left trimming may result in white, grey, or black filler objects on the | 891 // Left trimming may result in white, grey, or black filler objects on the |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1217 idle_marking_delay_counter_++; | 1224 idle_marking_delay_counter_++; |
1218 } | 1225 } |
1219 | 1226 |
1220 | 1227 |
1221 void IncrementalMarking::ClearIdleMarkingDelayCounter() { | 1228 void IncrementalMarking::ClearIdleMarkingDelayCounter() { |
1222 idle_marking_delay_counter_ = 0; | 1229 idle_marking_delay_counter_ = 0; |
1223 } | 1230 } |
1224 | 1231 |
1225 } // namespace internal | 1232 } // namespace internal |
1226 } // namespace v8 | 1233 } // namespace v8 |
OLD | NEW |