Chromium Code Reviews| Index: src/heap/mark-compact.cc |
| diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc |
| index fe886ac8136ebe99d1924a9b9250aa357038eadf..2111339ad5aeb5ff9528045b5edd2329b67a49e4 100644 |
| --- a/src/heap/mark-compact.cc |
| +++ b/src/heap/mark-compact.cc |
| @@ -3140,7 +3140,7 @@ class Evacuator : public Malloced { |
| virtual ~Evacuator() {} |
| - virtual bool EvacuatePage(Page* page, const MarkingState& state) = 0; |
| + bool EvacuatePage(Page* page, const MarkingState& state); |
| // Merge back locally cached info sequentially. Note that this method needs |
| // to be called from the main thread. |
| @@ -3152,6 +3152,8 @@ class Evacuator : public Malloced { |
| protected: |
| static const int kInitialLocalPretenuringFeedbackCapacity = 256; |
| + virtual bool EvacuatePageImpl(Page* page, const MarkingState& state) = 0; |
| + |
| inline Heap* heap() { return heap_; } |
| void ReportCompactionProgress(double duration, intptr_t bytes_compacted) { |
| @@ -3178,6 +3180,34 @@ class Evacuator : public Malloced { |
| intptr_t bytes_compacted_; |
| }; |
| +bool Evacuator::EvacuatePage(Page* page, const MarkingState& state) { |
| + bool success = false; |
| + DCHECK(page->SweepingDone()); |
| + intptr_t saved_live_bytes = state.live_bytes(); |
| + double evacuation_time = 0.0; |
| + { |
| + AlwaysAllocateScope always_allocate(heap()->isolate()); |
| + TimedScope timed_scope(&evacuation_time); |
| + success = EvacuatePageImpl(page, state); |
| + } |
| + ReportCompactionProgress(evacuation_time, saved_live_bytes); |
| + if (FLAG_trace_evacuation) { |
| + PrintIsolate( |
| + heap()->isolate(), |
| + "evacuation[%p]: page=%p new_space=%d " |
| + "page_evacuation=%d executable=%d contains_age_mark=%d " |
| + "live_bytes=%" V8PRIdPTR " time=%f page_promotion_qualifies=%d\n", |
| + static_cast<void*>(this), static_cast<void*>(page), page->InNewSpace(), |
| + page->IsFlagSet(Page::PAGE_NEW_OLD_PROMOTION) || |
| + page->IsFlagSet(Page::PAGE_NEW_NEW_PROMOTION), |
| + page->IsFlagSet(MemoryChunk::IS_EXECUTABLE), |
| + page->Contains(heap()->new_space()->age_mark()), saved_live_bytes, |
| + evacuation_time, |
| + saved_live_bytes > Evacuator::PageEvacuationThreshold()); |
| + } |
| + return success; |
| +} |
| + |
| void Evacuator::Finalize() { |
| heap()->old_space()->MergeCompactionSpace(compaction_spaces_.Get(OLD_SPACE)); |
| heap()->code_space()->MergeCompactionSpace( |
| @@ -3201,116 +3231,66 @@ class FullEvacuator : public Evacuator { |
| FullEvacuator(Heap* heap, RecordMigratedSlotVisitor* record_visitor) |
| : Evacuator(heap, record_visitor) {} |
| - bool EvacuatePage(Page* page, const MarkingState& state) override; |
| + protected: |
| + bool EvacuatePageImpl(Page* page, const MarkingState& state) override; |
|
Hannes Payer (out of office)
2017/04/21 13:09:15
I do not like the name. I do not think this is how
Michael Lippautz
2017/04/21 15:02:25
In other parts of V8 we use *Impl suffixes. Change
|
| }; |
| -bool FullEvacuator::EvacuatePage(Page* page, const MarkingState& state) { |
| +bool FullEvacuator::EvacuatePageImpl(Page* page, const MarkingState& state) { |
| bool success = false; |
| - DCHECK(page->SweepingDone()); |
| - intptr_t saved_live_bytes = state.live_bytes(); |
| - double evacuation_time = 0.0; |
| - { |
| - AlwaysAllocateScope always_allocate(heap()->isolate()); |
| - TimedScope timed_scope(&evacuation_time); |
| - LiveObjectVisitor object_visitor; |
| - switch (ComputeEvacuationMode(page)) { |
| - case kObjectsNewToOld: |
| - success = |
| - object_visitor.VisitBlackObjects(page, state, &new_space_visitor_, |
| - LiveObjectVisitor::kClearMarkbits); |
| + LiveObjectVisitor object_visitor; |
| + switch (ComputeEvacuationMode(page)) { |
| + case kObjectsNewToOld: |
| + success = object_visitor.VisitBlackObjects( |
| + page, state, &new_space_visitor_, LiveObjectVisitor::kClearMarkbits); |
| + DCHECK(success); |
| + ArrayBufferTracker::ProcessBuffers( |
| + page, ArrayBufferTracker::kUpdateForwardedRemoveOthers); |
| + break; |
| + case kPageNewToOld: |
| + success = object_visitor.VisitBlackObjects( |
| + page, state, &new_to_old_page_visitor_, |
| + LiveObjectVisitor::kKeepMarking); |
| + DCHECK(success); |
| + new_to_old_page_visitor_.account_moved_bytes( |
| + MarkingState::Internal(page).live_bytes()); |
| + // ArrayBufferTracker will be updated during sweeping. |
| + break; |
| + case kPageNewToNew: |
| + success = object_visitor.VisitBlackObjects( |
| + page, state, &new_to_new_page_visitor_, |
| + LiveObjectVisitor::kKeepMarking); |
| + DCHECK(success); |
| + new_to_new_page_visitor_.account_moved_bytes( |
| + MarkingState::Internal(page).live_bytes()); |
| + // ArrayBufferTracker will be updated during sweeping. |
| + break; |
| + case kObjectsOldToOld: |
| + success = object_visitor.VisitBlackObjects( |
| + page, state, &old_space_visitor_, LiveObjectVisitor::kClearMarkbits); |
| + if (!success) { |
| + // Aborted compaction page. We have to record slots here, since we |
| + // might not have recorded them in first place. |
| + // Note: We mark the page as aborted here to be able to record slots |
| + // for code objects in |RecordMigratedSlotVisitor|. |
| + page->SetFlag(Page::COMPACTION_WAS_ABORTED); |
| + EvacuateRecordOnlyVisitor record_visitor(heap()); |
| + success = object_visitor.VisitBlackObjects( |
| + page, state, &record_visitor, LiveObjectVisitor::kKeepMarking); |
| + ArrayBufferTracker::ProcessBuffers( |
| + page, ArrayBufferTracker::kUpdateForwardedKeepOthers); |
| DCHECK(success); |
| + // We need to return failure here to indicate that we want this page |
| + // added to the sweeper. |
| + success = false; |
| + } else { |
| ArrayBufferTracker::ProcessBuffers( |
| page, ArrayBufferTracker::kUpdateForwardedRemoveOthers); |
| - break; |
| - case kPageNewToOld: |
| - success = object_visitor.VisitBlackObjects( |
| - page, state, &new_to_old_page_visitor_, |
| - LiveObjectVisitor::kKeepMarking); |
| - DCHECK(success); |
| - new_to_old_page_visitor_.account_moved_bytes( |
| - MarkingState::Internal(page).live_bytes()); |
| - // ArrayBufferTracker will be updated during sweeping. |
| - break; |
| - case kPageNewToNew: |
| - success = object_visitor.VisitBlackObjects( |
| - page, state, &new_to_new_page_visitor_, |
| - LiveObjectVisitor::kKeepMarking); |
| - DCHECK(success); |
| - new_to_new_page_visitor_.account_moved_bytes( |
| - MarkingState::Internal(page).live_bytes()); |
| - // ArrayBufferTracker will be updated during sweeping. |
| - break; |
| - case kObjectsOldToOld: |
| - success = |
| - object_visitor.VisitBlackObjects(page, state, &old_space_visitor_, |
| - LiveObjectVisitor::kClearMarkbits); |
| - if (!success) { |
| - // Aborted compaction page. We have to record slots here, since we |
| - // might not have recorded them in first place. |
| - // Note: We mark the page as aborted here to be able to record slots |
| - // for code objects in |RecordMigratedSlotVisitor|. |
| - page->SetFlag(Page::COMPACTION_WAS_ABORTED); |
| - EvacuateRecordOnlyVisitor record_visitor(heap()); |
| - success = object_visitor.VisitBlackObjects( |
| - page, state, &record_visitor, LiveObjectVisitor::kKeepMarking); |
| - ArrayBufferTracker::ProcessBuffers( |
| - page, ArrayBufferTracker::kUpdateForwardedKeepOthers); |
| - DCHECK(success); |
| - // We need to return failure here to indicate that we want this page |
| - // added to the sweeper. |
| - success = false; |
| - } else { |
| - ArrayBufferTracker::ProcessBuffers( |
| - page, ArrayBufferTracker::kUpdateForwardedRemoveOthers); |
| - } |
| - break; |
| - } |
| - } |
| - ReportCompactionProgress(evacuation_time, saved_live_bytes); |
| - if (FLAG_trace_evacuation) { |
| - PrintIsolate(heap()->isolate(), |
| - "evacuation[%p]: page=%p new_space=%d " |
| - "page_evacuation=%d executable=%d contains_age_mark=%d " |
| - "live_bytes=%" V8PRIdPTR " time=%f\n", |
| - static_cast<void*>(this), static_cast<void*>(page), |
| - page->InNewSpace(), |
| - page->IsFlagSet(Page::PAGE_NEW_OLD_PROMOTION) || |
| - page->IsFlagSet(Page::PAGE_NEW_NEW_PROMOTION), |
| - page->IsFlagSet(MemoryChunk::IS_EXECUTABLE), |
| - page->Contains(heap()->new_space()->age_mark()), |
| - saved_live_bytes, evacuation_time); |
| + } |
| + break; |
| } |
| return success; |
| } |
| -int MarkCompactCollector::NumberOfParallelCompactionTasks(int pages, |
| - intptr_t live_bytes) { |
| - if (!FLAG_parallel_compaction) return 1; |
| - // Compute the number of needed tasks based on a target compaction time, the |
| - // profiled compaction speed and marked live memory. |
| - // |
| - // The number of parallel compaction tasks is limited by: |
| - // - #evacuation pages |
| - // - #cores |
| - const double kTargetCompactionTimeInMs = .5; |
| - |
| - double compaction_speed = |
| - heap()->tracer()->CompactionSpeedInBytesPerMillisecond(); |
| - |
| - const int available_cores = Max( |
| - 1, static_cast<int>( |
| - V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads())); |
| - int tasks; |
| - if (compaction_speed > 0) { |
| - tasks = 1 + static_cast<int>(live_bytes / compaction_speed / |
| - kTargetCompactionTimeInMs); |
| - } else { |
| - tasks = pages; |
| - } |
| - const int tasks_capped_pages = Min(pages, tasks); |
| - return Min(available_cores, tasks_capped_pages); |
| -} |
| - |
| class EvacuationJobTraits { |
| public: |
| typedef int* PerPageData; // Pointer to number of aborted pages. |
| @@ -3356,6 +3336,39 @@ class EvacuationJobTraits { |
| } |
| }; |
| +namespace { |
|
Hannes Payer (out of office)
2017/04/21 13:09:15
Why are you moving this into a separate namespace?
Michael Lippautz
2017/04/21 15:02:25
Will be used by the minor MC. Let's see if we add
|
| + |
| +// The number of parallel compaction tasks, including the main thread. |
| +int NumberOfParallelCompactionTasks(Heap* heap, int pages, |
| + intptr_t live_bytes) { |
| + if (!FLAG_parallel_compaction) return 1; |
| + // Compute the number of needed tasks based on a target compaction time, the |
| + // profiled compaction speed and marked live memory. |
| + // |
| + // The number of parallel compaction tasks is limited by: |
| + // - #evacuation pages |
| + // - #cores |
| + const double kTargetCompactionTimeInMs = .5; |
| + |
| + double compaction_speed = |
| + heap->tracer()->CompactionSpeedInBytesPerMillisecond(); |
| + |
| + const int available_cores = Max( |
| + 1, static_cast<int>( |
| + V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads())); |
| + int tasks; |
| + if (compaction_speed > 0) { |
| + tasks = 1 + static_cast<int>(live_bytes / compaction_speed / |
| + kTargetCompactionTimeInMs); |
| + } else { |
| + tasks = pages; |
| + } |
| + const int tasks_capped_pages = Min(pages, tasks); |
| + return Min(available_cores, tasks_capped_pages); |
| +} |
| + |
| +} // namespace |
| + |
| void MarkCompactCollector::EvacuatePagesInParallel() { |
| PageParallelJob<EvacuationJobTraits> job( |
| heap_, heap_->isolate()->cancelable_task_manager(), |
| @@ -3395,7 +3408,7 @@ void MarkCompactCollector::EvacuatePagesInParallel() { |
| } |
| const int wanted_num_tasks = |
| - NumberOfParallelCompactionTasks(job.NumberOfPages(), live_bytes); |
| + NumberOfParallelCompactionTasks(heap(), job.NumberOfPages(), live_bytes); |
| FullEvacuator** evacuators = new FullEvacuator*[wanted_num_tasks]; |
| RecordMigratedSlotVisitor record_visitor(this); |
| for (int i = 0; i < wanted_num_tasks; i++) { |