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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 was_marked_incrementally_(false), | 56 was_marked_incrementally_(false), |
57 evacuation_(false), | 57 evacuation_(false), |
58 heap_(heap), | 58 heap_(heap), |
59 marking_deque_memory_(NULL), | 59 marking_deque_memory_(NULL), |
60 marking_deque_memory_committed_(0), | 60 marking_deque_memory_committed_(0), |
61 code_flusher_(nullptr), | 61 code_flusher_(nullptr), |
62 have_code_to_deoptimize_(false), | 62 have_code_to_deoptimize_(false), |
63 compacting_(false), | 63 compacting_(false), |
64 sweeping_in_progress_(false), | 64 sweeping_in_progress_(false), |
65 pending_sweeper_tasks_semaphore_(0), | 65 pending_sweeper_tasks_semaphore_(0), |
66 pending_compaction_tasks_semaphore_(0) { | 66 pending_compaction_tasks_semaphore_(0), |
| 67 page_parallel_job_semaphore_(0) { |
67 } | 68 } |
68 | 69 |
69 #ifdef VERIFY_HEAP | 70 #ifdef VERIFY_HEAP |
70 class VerifyMarkingVisitor : public ObjectVisitor { | 71 class VerifyMarkingVisitor : public ObjectVisitor { |
71 public: | 72 public: |
72 explicit VerifyMarkingVisitor(Heap* heap) : heap_(heap) {} | 73 explicit VerifyMarkingVisitor(Heap* heap) : heap_(heap) {} |
73 | 74 |
74 void VisitPointers(Object** start, Object** end) override { | 75 void VisitPointers(Object** start, Object** end) override { |
75 for (Object** current = start; current < end; current++) { | 76 for (Object** current = start; current < end; current++) { |
76 if ((*current)->IsHeapObject()) { | 77 if ((*current)->IsHeapObject()) { |
(...skipping 3024 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3101 DCHECK(p->IsEvacuationCandidate()); | 3102 DCHECK(p->IsEvacuationCandidate()); |
3102 p->SetFlag(Page::COMPACTION_WAS_ABORTED); | 3103 p->SetFlag(Page::COMPACTION_WAS_ABORTED); |
3103 *data += 1; | 3104 *data += 1; |
3104 } | 3105 } |
3105 } | 3106 } |
3106 } | 3107 } |
3107 }; | 3108 }; |
3108 | 3109 |
3109 void MarkCompactCollector::EvacuatePagesInParallel() { | 3110 void MarkCompactCollector::EvacuatePagesInParallel() { |
3110 PageParallelJob<EvacuationJobTraits> job( | 3111 PageParallelJob<EvacuationJobTraits> job( |
3111 heap_, heap_->isolate()->cancelable_task_manager()); | 3112 heap_, heap_->isolate()->cancelable_task_manager(), |
| 3113 &page_parallel_job_semaphore_); |
3112 | 3114 |
3113 int abandoned_pages = 0; | 3115 int abandoned_pages = 0; |
3114 intptr_t live_bytes = 0; | 3116 intptr_t live_bytes = 0; |
3115 for (Page* page : evacuation_candidates_) { | 3117 for (Page* page : evacuation_candidates_) { |
3116 live_bytes += page->LiveBytes(); | 3118 live_bytes += page->LiveBytes(); |
3117 job.AddPage(page, &abandoned_pages); | 3119 job.AddPage(page, &abandoned_pages); |
3118 } | 3120 } |
3119 for (NewSpacePage* page : newspace_evacuation_candidates_) { | 3121 for (NewSpacePage* page : newspace_evacuation_candidates_) { |
3120 live_bytes += page->LiveBytes(); | 3122 live_bytes += page->LiveBytes(); |
3121 job.AddPage(page, &abandoned_pages); | 3123 job.AddPage(page, &abandoned_pages); |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3486 }; | 3488 }; |
3487 | 3489 |
3488 int NumberOfPointerUpdateTasks(int pages) { | 3490 int NumberOfPointerUpdateTasks(int pages) { |
3489 if (!FLAG_parallel_pointer_update) return 1; | 3491 if (!FLAG_parallel_pointer_update) return 1; |
3490 const int kMaxTasks = 4; | 3492 const int kMaxTasks = 4; |
3491 const int kPagesPerTask = 4; | 3493 const int kPagesPerTask = 4; |
3492 return Min(kMaxTasks, (pages + kPagesPerTask - 1) / kPagesPerTask); | 3494 return Min(kMaxTasks, (pages + kPagesPerTask - 1) / kPagesPerTask); |
3493 } | 3495 } |
3494 | 3496 |
3495 template <PointerDirection direction> | 3497 template <PointerDirection direction> |
3496 void UpdatePointersInParallel(Heap* heap) { | 3498 void UpdatePointersInParallel(Heap* heap, base::Semaphore* semaphore) { |
3497 PageParallelJob<PointerUpdateJobTraits<direction> > job( | 3499 PageParallelJob<PointerUpdateJobTraits<direction> > job( |
3498 heap, heap->isolate()->cancelable_task_manager()); | 3500 heap, heap->isolate()->cancelable_task_manager(), semaphore); |
3499 RememberedSet<direction>::IterateMemoryChunks( | 3501 RememberedSet<direction>::IterateMemoryChunks( |
3500 heap, [&job](MemoryChunk* chunk) { job.AddPage(chunk, 0); }); | 3502 heap, [&job](MemoryChunk* chunk) { job.AddPage(chunk, 0); }); |
3501 PointersUpdatingVisitor visitor(heap); | 3503 PointersUpdatingVisitor visitor(heap); |
3502 int num_pages = job.NumberOfPages(); | 3504 int num_pages = job.NumberOfPages(); |
3503 int num_tasks = NumberOfPointerUpdateTasks(num_pages); | 3505 int num_tasks = NumberOfPointerUpdateTasks(num_pages); |
3504 job.Run(num_tasks, [&visitor](int i) { return &visitor; }); | 3506 job.Run(num_tasks, [&visitor](int i) { return &visitor; }); |
3505 } | 3507 } |
3506 | 3508 |
3507 class ToSpacePointerUpdateJobTraits { | 3509 class ToSpacePointerUpdateJobTraits { |
3508 public: | 3510 public: |
3509 typedef std::pair<Address, Address> PerPageData; | 3511 typedef std::pair<Address, Address> PerPageData; |
3510 typedef PointersUpdatingVisitor* PerTaskData; | 3512 typedef PointersUpdatingVisitor* PerTaskData; |
3511 | 3513 |
3512 static bool ProcessPageInParallel(Heap* heap, PerTaskData visitor, | 3514 static bool ProcessPageInParallel(Heap* heap, PerTaskData visitor, |
3513 MemoryChunk* chunk, PerPageData limits) { | 3515 MemoryChunk* chunk, PerPageData limits) { |
3514 for (Address cur = limits.first; cur < limits.second;) { | 3516 for (Address cur = limits.first; cur < limits.second;) { |
3515 HeapObject* object = HeapObject::FromAddress(cur); | 3517 HeapObject* object = HeapObject::FromAddress(cur); |
3516 Map* map = object->map(); | 3518 Map* map = object->map(); |
3517 int size = object->SizeFromMap(map); | 3519 int size = object->SizeFromMap(map); |
3518 object->IterateBody(map->instance_type(), size, visitor); | 3520 object->IterateBody(map->instance_type(), size, visitor); |
3519 cur += size; | 3521 cur += size; |
3520 } | 3522 } |
3521 return true; | 3523 return true; |
3522 } | 3524 } |
3523 static const bool NeedSequentialFinalization = false; | 3525 static const bool NeedSequentialFinalization = false; |
3524 static void FinalizePageSequentially(Heap*, MemoryChunk*, bool, PerPageData) { | 3526 static void FinalizePageSequentially(Heap*, MemoryChunk*, bool, PerPageData) { |
3525 } | 3527 } |
3526 }; | 3528 }; |
3527 | 3529 |
3528 void UpdateToSpacePointersInParallel(Heap* heap) { | 3530 void UpdateToSpacePointersInParallel(Heap* heap, base::Semaphore* semaphore) { |
3529 PageParallelJob<ToSpacePointerUpdateJobTraits> job( | 3531 PageParallelJob<ToSpacePointerUpdateJobTraits> job( |
3530 heap, heap->isolate()->cancelable_task_manager()); | 3532 heap, heap->isolate()->cancelable_task_manager(), semaphore); |
3531 Address space_start = heap->new_space()->bottom(); | 3533 Address space_start = heap->new_space()->bottom(); |
3532 Address space_end = heap->new_space()->top(); | 3534 Address space_end = heap->new_space()->top(); |
3533 NewSpacePageIterator it(space_start, space_end); | 3535 NewSpacePageIterator it(space_start, space_end); |
3534 while (it.has_next()) { | 3536 while (it.has_next()) { |
3535 NewSpacePage* page = it.next(); | 3537 NewSpacePage* page = it.next(); |
3536 Address start = | 3538 Address start = |
3537 page->Contains(space_start) ? space_start : page->area_start(); | 3539 page->Contains(space_start) ? space_start : page->area_start(); |
3538 Address end = page->Contains(space_end) ? space_end : page->area_end(); | 3540 Address end = page->Contains(space_end) ? space_end : page->area_end(); |
3539 job.AddPage(page, std::make_pair(start, end)); | 3541 job.AddPage(page, std::make_pair(start, end)); |
3540 } | 3542 } |
3541 PointersUpdatingVisitor visitor(heap); | 3543 PointersUpdatingVisitor visitor(heap); |
3542 int num_tasks = FLAG_parallel_pointer_update ? job.NumberOfPages() : 1; | 3544 int num_tasks = FLAG_parallel_pointer_update ? job.NumberOfPages() : 1; |
3543 job.Run(num_tasks, [&visitor](int i) { return &visitor; }); | 3545 job.Run(num_tasks, [&visitor](int i) { return &visitor; }); |
3544 } | 3546 } |
3545 | 3547 |
3546 void MarkCompactCollector::UpdatePointersAfterEvacuation() { | 3548 void MarkCompactCollector::UpdatePointersAfterEvacuation() { |
3547 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS); | 3549 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS); |
3548 | 3550 |
3549 PointersUpdatingVisitor updating_visitor(heap()); | 3551 PointersUpdatingVisitor updating_visitor(heap()); |
3550 | 3552 |
3551 { | 3553 { |
3552 TRACE_GC(heap()->tracer(), | 3554 TRACE_GC(heap()->tracer(), |
3553 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_NEW); | 3555 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_NEW); |
3554 UpdateToSpacePointersInParallel(heap_); | 3556 UpdateToSpacePointersInParallel(heap_, &page_parallel_job_semaphore_); |
3555 // Update roots. | 3557 // Update roots. |
3556 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); | 3558 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); |
3557 UpdatePointersInParallel<OLD_TO_NEW>(heap_); | 3559 UpdatePointersInParallel<OLD_TO_NEW>(heap_, &page_parallel_job_semaphore_); |
3558 } | 3560 } |
3559 | 3561 |
3560 { | 3562 { |
3561 Heap* heap = this->heap(); | 3563 Heap* heap = this->heap(); |
3562 TRACE_GC(heap->tracer(), | 3564 TRACE_GC(heap->tracer(), |
3563 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED); | 3565 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED); |
3564 UpdatePointersInParallel<OLD_TO_OLD>(heap_); | 3566 UpdatePointersInParallel<OLD_TO_OLD>(heap_, &page_parallel_job_semaphore_); |
3565 } | 3567 } |
3566 | 3568 |
3567 { | 3569 { |
3568 TRACE_GC(heap()->tracer(), | 3570 TRACE_GC(heap()->tracer(), |
3569 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_BETWEEN_EVACUATED); | 3571 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_BETWEEN_EVACUATED); |
3570 for (Page* p : evacuation_candidates_) { | 3572 for (Page* p : evacuation_candidates_) { |
3571 DCHECK(p->IsEvacuationCandidate()); | 3573 DCHECK(p->IsEvacuationCandidate()); |
3572 // Important: skip list should be cleared only after roots were updated | 3574 // Important: skip list should be cleared only after roots were updated |
3573 // because root iteration traverses the stack and might have to find | 3575 // because root iteration traverses the stack and might have to find |
3574 // code objects from non-updated pc pointing into evacuation candidate. | 3576 // code objects from non-updated pc pointing into evacuation candidate. |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3806 MarkBit mark_bit = Marking::MarkBitFrom(host); | 3808 MarkBit mark_bit = Marking::MarkBitFrom(host); |
3807 if (Marking::IsBlack(mark_bit)) { | 3809 if (Marking::IsBlack(mark_bit)) { |
3808 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); | 3810 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); |
3809 RecordRelocSlot(host, &rinfo, target); | 3811 RecordRelocSlot(host, &rinfo, target); |
3810 } | 3812 } |
3811 } | 3813 } |
3812 } | 3814 } |
3813 | 3815 |
3814 } // namespace internal | 3816 } // namespace internal |
3815 } // namespace v8 | 3817 } // namespace v8 |
OLD | NEW |