Index: src/heap/mark-compact.cc |
diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc |
index 9a565b972956d955c9c10a265915343e30b7daaf..31107f06fb902d646227f413a3e5ebc5226b48a2 100644 |
--- a/src/heap/mark-compact.cc |
+++ b/src/heap/mark-compact.cc |
@@ -317,7 +317,7 @@ void MarkCompactCollector::CollectGarbage() { |
} |
#endif |
- StartSweepSpaces(); |
+ SweepSpaces(); |
EvacuateNewSpaceAndCandidates(); |
@@ -447,20 +447,22 @@ void MarkCompactCollector::Sweeper::StartSweeping() { |
std::sort(sweeping_list_[space].begin(), sweeping_list_[space].end(), |
[](Page* a, Page* b) { return a->LiveBytes() < b->LiveBytes(); }); |
}); |
-} |
- |
-void MarkCompactCollector::Sweeper::StartSweeperTasks() { |
- if (FLAG_concurrent_sweeping && sweeping_in_progress_) { |
+ if (FLAG_concurrent_sweeping) { |
ForAllSweepingSpaces([this](AllocationSpace space) { |
if (space == NEW_SPACE) return; |
- num_sweeping_tasks_.Increment(1); |
- V8::GetCurrentPlatform()->CallOnBackgroundThread( |
- new SweeperTask(this, &pending_sweeper_tasks_semaphore_, space), |
- v8::Platform::kShortRunningTask); |
+ StartSweepingHelper(space); |
}); |
} |
} |
+void MarkCompactCollector::Sweeper::StartSweepingHelper( |
+ AllocationSpace space_to_start) { |
+ num_sweeping_tasks_.Increment(1); |
+ V8::GetCurrentPlatform()->CallOnBackgroundThread( |
+ new SweeperTask(this, &pending_sweeper_tasks_semaphore_, space_to_start), |
+ v8::Platform::kShortRunningTask); |
+} |
+ |
void MarkCompactCollector::Sweeper::SweepOrWaitUntilSweepingCompleted( |
Page* page) { |
if (!page->SweepingDone()) { |
@@ -475,8 +477,7 @@ void MarkCompactCollector::Sweeper::SweepOrWaitUntilSweepingCompleted( |
} |
void MarkCompactCollector::SweepAndRefill(CompactionSpace* space) { |
- if (FLAG_concurrent_sweeping && |
- !sweeper().IsSweepingCompleted(space->identity())) { |
+ if (FLAG_concurrent_sweeping && !sweeper().IsSweepingCompleted()) { |
sweeper().ParallelSweepSpace(space->identity(), 0); |
space->RefillFreeList(); |
} |
@@ -496,11 +497,10 @@ void MarkCompactCollector::Sweeper::EnsureCompleted() { |
// If sweeping is not completed or not running at all, we try to complete it |
// here. |
- ForAllSweepingSpaces([this](AllocationSpace space) { |
- if (!FLAG_concurrent_sweeping || !this->IsSweepingCompleted(space)) { |
- ParallelSweepSpace(space, 0); |
- } |
- }); |
+ if (!FLAG_concurrent_sweeping || !IsSweepingCompleted()) { |
+ ForAllSweepingSpaces( |
+ [this](AllocationSpace space) { ParallelSweepSpace(space, 0); }); |
+ } |
if (FLAG_concurrent_sweeping) { |
while (num_sweeping_tasks_.Value() > 0) { |
@@ -515,12 +515,13 @@ void MarkCompactCollector::Sweeper::EnsureCompleted() { |
} |
DCHECK(sweeping_list_[space].empty()); |
}); |
+ late_pages_ = false; |
sweeping_in_progress_ = false; |
} |
void MarkCompactCollector::Sweeper::EnsureNewSpaceCompleted() { |
if (!sweeping_in_progress_) return; |
- if (!FLAG_concurrent_sweeping || !IsSweepingCompleted(NEW_SPACE)) { |
+ if (!FLAG_concurrent_sweeping || !IsSweepingCompleted()) { |
for (Page* p : *heap_->new_space()) { |
SweepOrWaitUntilSweepingCompleted(p); |
} |
@@ -542,20 +543,13 @@ void MarkCompactCollector::EnsureSweepingCompleted() { |
#endif |
} |
-bool MarkCompactCollector::Sweeper::AreSweeperTasksRunning() { |
+bool MarkCompactCollector::Sweeper::IsSweepingCompleted() { |
DCHECK(FLAG_concurrent_sweeping); |
while (pending_sweeper_tasks_semaphore_.WaitFor( |
base::TimeDelta::FromSeconds(0))) { |
num_sweeping_tasks_.Increment(-1); |
} |
- return num_sweeping_tasks_.Value() != 0; |
-} |
- |
-bool MarkCompactCollector::Sweeper::IsSweepingCompleted(AllocationSpace space) { |
- DCHECK(FLAG_concurrent_sweeping); |
- if (AreSweeperTasksRunning()) return false; |
- base::LockGuard<base::Mutex> guard(&mutex_); |
- return sweeping_list_[space].empty(); |
+ return num_sweeping_tasks_.Value() == 0; |
} |
const char* AllocationSpaceName(AllocationSpace space) { |
@@ -839,7 +833,11 @@ void MarkCompactCollector::Prepare() { |
void MarkCompactCollector::Finish() { |
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_FINISH); |
- sweeper().StartSweeperTasks(); |
+ if (sweeper().contains_late_pages() && FLAG_concurrent_sweeping) { |
+ // If we added some more pages during MC, we need to start at least one |
+ // more task as all other tasks might already be finished. |
+ sweeper().StartSweepingHelper(OLD_SPACE); |
+ } |
// The hashing of weak_object_to_code_table is no longer valid. |
heap()->weak_object_to_code_table()->Rehash( |
@@ -3034,15 +3032,17 @@ int MarkCompactCollector::NumberOfParallelCompactionTasks(int pages, |
// |
// The number of parallel compaction tasks is limited by: |
// - #evacuation pages |
- // - #cores |
+ // - (#cores - 1) |
const double kTargetCompactionTimeInMs = .5; |
+ const int kNumSweepingTasks = 3; |
double compaction_speed = |
heap()->tracer()->CompactionSpeedInBytesPerMillisecond(); |
const int available_cores = Max( |
1, static_cast<int>( |
- V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads())); |
+ V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads()) - |
+ kNumSweepingTasks - 1); |
int tasks; |
if (compaction_speed > 0) { |
tasks = 1 + static_cast<int>(live_bytes / compaction_speed / |
@@ -3429,12 +3429,12 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { |
for (Page* p : newspace_evacuation_candidates_) { |
if (p->IsFlagSet(Page::PAGE_NEW_NEW_PROMOTION)) { |
p->ClearFlag(Page::PAGE_NEW_NEW_PROMOTION); |
- sweeper().AddPage(p->owner()->identity(), p); |
+ sweeper().AddLatePage(p->owner()->identity(), p); |
} else if (p->IsFlagSet(Page::PAGE_NEW_OLD_PROMOTION)) { |
p->ClearFlag(Page::PAGE_NEW_OLD_PROMOTION); |
p->ForAllFreeListCategories( |
[](FreeListCategory* category) { DCHECK(!category->is_linked()); }); |
- sweeper().AddPage(p->owner()->identity(), p); |
+ sweeper().AddLatePage(p->owner()->identity(), p); |
} |
} |
newspace_evacuation_candidates_.Rewind(0); |
@@ -3446,7 +3446,7 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { |
SkipList* list = p->skip_list(); |
if (list != NULL) list->Clear(); |
if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) { |
- sweeper().AddPage(p->owner()->identity(), p); |
+ sweeper().AddLatePage(p->owner()->identity(), p); |
p->ClearFlag(Page::COMPACTION_WAS_ABORTED); |
} |
} |
@@ -3745,11 +3745,19 @@ int MarkCompactCollector::Sweeper::ParallelSweepPage(Page* page, |
} |
void MarkCompactCollector::Sweeper::AddPage(AllocationSpace space, Page* page) { |
- DCHECK(!FLAG_concurrent_sweeping || !AreSweeperTasksRunning()); |
+ DCHECK(!sweeping_in_progress_); |
PrepareToBeSweptPage(space, page); |
sweeping_list_[space].push_back(page); |
} |
+void MarkCompactCollector::Sweeper::AddLatePage(AllocationSpace space, |
+ Page* page) { |
+ DCHECK(sweeping_in_progress_); |
+ PrepareToBeSweptPage(space, page); |
+ late_pages_ = true; |
+ AddSweepingPageSafe(space, page); |
+} |
+ |
void MarkCompactCollector::Sweeper::PrepareToBeSweptPage(AllocationSpace space, |
Page* page) { |
page->concurrent_sweeping_state().SetValue(Page::kSweepingPending); |
@@ -3829,7 +3837,7 @@ void MarkCompactCollector::StartSweepSpace(PagedSpace* space) { |
} |
} |
-void MarkCompactCollector::StartSweepSpaces() { |
+void MarkCompactCollector::SweepSpaces() { |
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_SWEEP); |
#ifdef DEBUG |
state_ = SWEEP_SPACES; |