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++) { |