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/mark-compact.h" | 5 #include "src/heap/mark-compact.h" |
6 | 6 |
7 #include "src/base/atomicops.h" | 7 #include "src/base/atomicops.h" |
8 #include "src/base/bits.h" | 8 #include "src/base/bits.h" |
9 #include "src/base/sys-info.h" | 9 #include "src/base/sys-info.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 25 matching lines...) Expand all Loading... | |
36 | 36 |
37 const char* Marking::kWhiteBitPattern = "00"; | 37 const char* Marking::kWhiteBitPattern = "00"; |
38 const char* Marking::kBlackBitPattern = "11"; | 38 const char* Marking::kBlackBitPattern = "11"; |
39 const char* Marking::kGreyBitPattern = "10"; | 39 const char* Marking::kGreyBitPattern = "10"; |
40 const char* Marking::kImpossibleBitPattern = "01"; | 40 const char* Marking::kImpossibleBitPattern = "01"; |
41 | 41 |
42 // The following has to hold in order for {ObjectMarking::MarkBitFrom} to not | 42 // The following has to hold in order for {ObjectMarking::MarkBitFrom} to not |
43 // produce invalid {kImpossibleBitPattern} in the marking bitmap by overlapping. | 43 // produce invalid {kImpossibleBitPattern} in the marking bitmap by overlapping. |
44 STATIC_ASSERT(Heap::kMinObjectSizeInWords >= 2); | 44 STATIC_ASSERT(Heap::kMinObjectSizeInWords >= 2); |
45 | 45 |
46 | 46 // ============================================================================= |
47 // ------------------------------------------------------------------------- | 47 // Verifiers |
48 // MarkCompactCollector | 48 // ============================================================================= |
49 | |
50 MarkCompactCollector::MarkCompactCollector(Heap* heap) | |
51 : // NOLINT | |
52 heap_(heap), | |
53 page_parallel_job_semaphore_(0), | |
54 #ifdef DEBUG | |
55 state_(IDLE), | |
56 #endif | |
57 was_marked_incrementally_(false), | |
58 evacuation_(false), | |
59 compacting_(false), | |
60 black_allocation_(false), | |
61 have_code_to_deoptimize_(false), | |
62 marking_deque_(heap), | |
63 code_flusher_(nullptr), | |
64 sweeper_(heap) { | |
65 } | |
66 | 49 |
67 #ifdef VERIFY_HEAP | 50 #ifdef VERIFY_HEAP |
51 namespace { | |
52 | |
68 class MarkingVerifier : public ObjectVisitor { | 53 class MarkingVerifier : public ObjectVisitor { |
69 public: | 54 public: |
70 virtual void Run() = 0; | 55 virtual void Run() = 0; |
71 | 56 |
72 protected: | 57 protected: |
73 explicit MarkingVerifier(Heap* heap) : heap_(heap) {} | 58 explicit MarkingVerifier(Heap* heap) : heap_(heap) {} |
74 | 59 |
75 virtual MarkingState marking_state(MemoryChunk* chunk) = 0; | 60 virtual MarkingState marking_state(MemoryChunk* chunk) = 0; |
76 | 61 |
77 void VerifyRoots(VisitMode mode); | 62 void VerifyRoots(VisitMode mode); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
213 for (Object** current = start; current < end; current++) { | 198 for (Object** current = start; current < end; current++) { |
214 if ((*current)->IsHeapObject()) { | 199 if ((*current)->IsHeapObject()) { |
215 HeapObject* object = HeapObject::cast(*current); | 200 HeapObject* object = HeapObject::cast(*current); |
216 if (!heap_->InNewSpace(object)) return; | 201 if (!heap_->InNewSpace(object)) return; |
217 CHECK(ObjectMarking::IsBlackOrGrey(object, marking_state(object))); | 202 CHECK(ObjectMarking::IsBlackOrGrey(object, marking_state(object))); |
218 } | 203 } |
219 } | 204 } |
220 } | 205 } |
221 }; | 206 }; |
222 | 207 |
223 class VerifyEvacuationVisitor : public ObjectVisitor { | 208 class EvacuationVerifier : public ObjectVisitor { |
224 public: | 209 public: |
210 virtual void Run() = 0; | |
211 | |
225 void VisitPointers(Object** start, Object** end) override { | 212 void VisitPointers(Object** start, Object** end) override { |
226 for (Object** current = start; current < end; current++) { | 213 for (Object** current = start; current < end; current++) { |
227 if ((*current)->IsHeapObject()) { | 214 if ((*current)->IsHeapObject()) { |
228 HeapObject* object = HeapObject::cast(*current); | 215 HeapObject* object = HeapObject::cast(*current); |
229 CHECK(!MarkCompactCollector::IsOnEvacuationCandidate(object)); | 216 CHECK(!MarkCompactCollector::IsOnEvacuationCandidate(object)); |
230 } | 217 } |
231 } | 218 } |
232 } | 219 } |
220 | |
221 protected: | |
222 explicit EvacuationVerifier(Heap* heap) : heap_(heap) {} | |
223 | |
224 void VerifyRoots(VisitMode mode); | |
225 void VerifyEvacuationOnPage(Address start, Address end); | |
226 void VerifyEvacuation(NewSpace* new_space); | |
227 void VerifyEvacuation(PagedSpace* paged_space); | |
228 | |
229 Heap* heap_; | |
233 }; | 230 }; |
234 | 231 |
232 void EvacuationVerifier::VerifyRoots(VisitMode mode) { | |
233 heap_->IterateStrongRoots(this, mode); | |
234 } | |
235 | 235 |
236 static void VerifyEvacuation(Page* page) { | 236 void EvacuationVerifier::VerifyEvacuationOnPage(Address start, Address end) { |
237 VerifyEvacuationVisitor visitor; | 237 Address current = start; |
238 HeapObjectIterator iterator(page); | 238 while (current < end) { |
239 for (HeapObject* heap_object = iterator.Next(); heap_object != NULL; | 239 HeapObject* object = HeapObject::FromAddress(current); |
240 heap_object = iterator.Next()) { | 240 if (!object->IsFiller()) object->Iterate(this); |
241 // We skip free space objects. | 241 current += object->Size(); |
242 if (!heap_object->IsFiller()) { | |
243 heap_object->Iterate(&visitor); | |
244 } | |
245 } | 242 } |
246 } | 243 } |
247 | 244 |
248 | 245 void EvacuationVerifier::VerifyEvacuation(NewSpace* space) { |
249 static void VerifyEvacuation(NewSpace* space) { | |
250 VerifyEvacuationVisitor visitor; | |
251 PageRange range(space->bottom(), space->top()); | 246 PageRange range(space->bottom(), space->top()); |
252 for (auto it = range.begin(); it != range.end();) { | 247 for (auto it = range.begin(); it != range.end();) { |
253 Page* page = *(it++); | 248 Page* page = *(it++); |
254 Address current = page->area_start(); | 249 Address current = page->area_start(); |
255 Address limit = it != range.end() ? page->area_end() : space->top(); | 250 Address limit = it != range.end() ? page->area_end() : space->top(); |
256 CHECK(limit == space->top() || !page->Contains(space->top())); | 251 CHECK(limit == space->top() || !page->Contains(space->top())); |
257 while (current < limit) { | 252 VerifyEvacuationOnPage(current, limit); |
258 HeapObject* object = HeapObject::FromAddress(current); | |
259 object->Iterate(&visitor); | |
260 current += object->Size(); | |
261 } | |
262 } | 253 } |
263 } | 254 } |
264 | 255 |
265 | 256 void EvacuationVerifier::VerifyEvacuation(PagedSpace* space) { |
266 static void VerifyEvacuation(Heap* heap, PagedSpace* space) { | 257 if (FLAG_use_allocation_folding && (space == heap_->old_space())) { |
267 if (FLAG_use_allocation_folding && (space == heap->old_space())) { | |
268 return; | 258 return; |
269 } | 259 } |
270 for (Page* p : *space) { | 260 for (Page* p : *space) { |
271 if (p->IsEvacuationCandidate()) continue; | 261 if (p->IsEvacuationCandidate()) continue; |
272 VerifyEvacuation(p); | 262 if (p->Contains(space->top())) |
Michael Lippautz
2017/04/04 14:50:27
Previously we used the HeapObjectIterator for this
| |
263 heap_->CreateFillerObjectAt(space->top(), space->limit() - space->top(), | |
264 ClearRecordedSlots::kNo); | |
265 | |
266 VerifyEvacuationOnPage(p->area_start(), p->area_end()); | |
273 } | 267 } |
274 } | 268 } |
275 | 269 |
270 class FullEvacuationVerifier : public EvacuationVerifier { | |
271 public: | |
272 explicit FullEvacuationVerifier(Heap* heap) : EvacuationVerifier(heap) {} | |
276 | 273 |
277 static void VerifyEvacuation(Heap* heap) { | 274 void Run() override { |
278 VerifyEvacuation(heap, heap->old_space()); | 275 VerifyRoots(VISIT_ALL); |
279 VerifyEvacuation(heap, heap->code_space()); | 276 VerifyEvacuation(heap_->new_space()); |
280 VerifyEvacuation(heap, heap->map_space()); | 277 VerifyEvacuation(heap_->old_space()); |
281 VerifyEvacuation(heap->new_space()); | 278 VerifyEvacuation(heap_->code_space()); |
279 VerifyEvacuation(heap_->map_space()); | |
280 } | |
281 }; | |
282 | 282 |
283 VerifyEvacuationVisitor visitor; | 283 } // namespace |
284 heap->IterateStrongRoots(&visitor, VISIT_ALL); | |
285 } | |
286 #endif // VERIFY_HEAP | 284 #endif // VERIFY_HEAP |
287 | 285 |
286 // ============================================================================= | |
287 // MarkCompactCollector | |
288 // ============================================================================= | |
289 | |
290 MarkCompactCollector::MarkCompactCollector(Heap* heap) | |
291 : // NOLINT | |
292 heap_(heap), | |
293 page_parallel_job_semaphore_(0), | |
294 #ifdef DEBUG | |
295 state_(IDLE), | |
296 #endif | |
297 was_marked_incrementally_(false), | |
298 evacuation_(false), | |
299 compacting_(false), | |
300 black_allocation_(false), | |
301 have_code_to_deoptimize_(false), | |
302 marking_deque_(heap), | |
303 code_flusher_(nullptr), | |
304 sweeper_(heap) { | |
305 } | |
288 | 306 |
289 void MarkCompactCollector::SetUp() { | 307 void MarkCompactCollector::SetUp() { |
290 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); | 308 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); |
291 DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0); | 309 DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0); |
292 DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0); | 310 DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0); |
293 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); | 311 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); |
294 marking_deque()->SetUp(); | 312 marking_deque()->SetUp(); |
295 | 313 |
296 if (FLAG_flush_code) { | 314 if (FLAG_flush_code) { |
297 code_flusher_ = new CodeFlusher(isolate()); | 315 code_flusher_ = new CodeFlusher(isolate()); |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
579 void MarkCompactCollector::EnsureSweepingCompleted() { | 597 void MarkCompactCollector::EnsureSweepingCompleted() { |
580 if (!sweeper().sweeping_in_progress()) return; | 598 if (!sweeper().sweeping_in_progress()) return; |
581 | 599 |
582 sweeper().EnsureCompleted(); | 600 sweeper().EnsureCompleted(); |
583 heap()->old_space()->RefillFreeList(); | 601 heap()->old_space()->RefillFreeList(); |
584 heap()->code_space()->RefillFreeList(); | 602 heap()->code_space()->RefillFreeList(); |
585 heap()->map_space()->RefillFreeList(); | 603 heap()->map_space()->RefillFreeList(); |
586 | 604 |
587 #ifdef VERIFY_HEAP | 605 #ifdef VERIFY_HEAP |
588 if (FLAG_verify_heap && !evacuation()) { | 606 if (FLAG_verify_heap && !evacuation()) { |
589 VerifyEvacuation(heap_); | 607 FullEvacuationVerifier verifier(heap_); |
608 verifier.Run(); | |
590 } | 609 } |
591 #endif | 610 #endif |
592 | 611 |
593 if (heap()->memory_allocator()->unmapper()->has_delayed_chunks()) | 612 if (heap()->memory_allocator()->unmapper()->has_delayed_chunks()) |
594 heap()->memory_allocator()->unmapper()->FreeQueuedChunks(); | 613 heap()->memory_allocator()->unmapper()->FreeQueuedChunks(); |
595 } | 614 } |
596 | 615 |
597 bool MarkCompactCollector::Sweeper::AreSweeperTasksRunning() { | 616 bool MarkCompactCollector::Sweeper::AreSweeperTasksRunning() { |
598 return num_sweeping_tasks_.Value() != 0; | 617 return num_sweeping_tasks_.Value() != 0; |
599 } | 618 } |
(...skipping 3104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3704 } | 3723 } |
3705 } | 3724 } |
3706 | 3725 |
3707 { | 3726 { |
3708 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_EPILOGUE); | 3727 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_EPILOGUE); |
3709 EvacuateEpilogue(); | 3728 EvacuateEpilogue(); |
3710 } | 3729 } |
3711 | 3730 |
3712 #ifdef VERIFY_HEAP | 3731 #ifdef VERIFY_HEAP |
3713 if (FLAG_verify_heap && !sweeper().sweeping_in_progress()) { | 3732 if (FLAG_verify_heap && !sweeper().sweeping_in_progress()) { |
3714 VerifyEvacuation(heap()); | 3733 FullEvacuationVerifier verifier(heap()); |
3734 verifier.Run(); | |
3715 } | 3735 } |
3716 #endif | 3736 #endif |
3717 } | 3737 } |
3718 | 3738 |
3719 template <RememberedSetType type> | 3739 template <RememberedSetType type> |
3720 class PointerUpdateJobTraits { | 3740 class PointerUpdateJobTraits { |
3721 public: | 3741 public: |
3722 typedef int PerPageData; // Per page data is not used in this job. | 3742 typedef int PerPageData; // Per page data is not used in this job. |
3723 typedef int PerTaskData; // Per task data is not used in this job. | 3743 typedef int PerTaskData; // Per task data is not used in this job. |
3724 | 3744 |
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4152 // The target is always in old space, we don't have to record the slot in | 4172 // The target is always in old space, we don't have to record the slot in |
4153 // the old-to-new remembered set. | 4173 // the old-to-new remembered set. |
4154 DCHECK(!heap()->InNewSpace(target)); | 4174 DCHECK(!heap()->InNewSpace(target)); |
4155 RecordRelocSlot(host, &rinfo, target); | 4175 RecordRelocSlot(host, &rinfo, target); |
4156 } | 4176 } |
4157 } | 4177 } |
4158 } | 4178 } |
4159 | 4179 |
4160 } // namespace internal | 4180 } // namespace internal |
4161 } // namespace v8 | 4181 } // namespace v8 |
OLD | NEW |