[heap] Refactor evacuation routine

Have clear prologue and epilogue steps. For a minor MC we can then
templatize the prologue without changing the actual evacuation routine.

BUG=chromium:651354

Change-Id: Ia238748e90bc6b616cd813d31198de182fe11498
Reviewed-on: https://chromium-review.googlesource.com/445898
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Reviewed-by: Hannes Payer <hpayer@chromium.org>
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#43378}
This commit is contained in:
Michael Lippautz 2017-02-22 14:52:53 +01:00 committed by Commit Bot
parent b008f27f02
commit e800933eee
4 changed files with 42 additions and 17 deletions

View File

@ -550,6 +550,8 @@ void GCTracer::PrintNVP() const {
"evacuate.candidates=%.1f "
"evacuate.clean_up=%.1f "
"evacuate.copy=%.1f "
"evacuate.prologue=%.1f "
"evacuate.epilogue=%.1f "
"evacuate.rebalance=%.1f "
"evacuate.update_pointers=%.1f "
"evacuate.update_pointers.to_evacuated=%.1f "
@ -634,6 +636,8 @@ void GCTracer::PrintNVP() const {
current_.scopes[Scope::MC_EVACUATE_CANDIDATES],
current_.scopes[Scope::MC_EVACUATE_CLEAN_UP],
current_.scopes[Scope::MC_EVACUATE_COPY],
current_.scopes[Scope::MC_EVACUATE_PROLOGUE],
current_.scopes[Scope::MC_EVACUATE_EPILOGUE],
current_.scopes[Scope::MC_EVACUATE_REBALANCE],
current_.scopes[Scope::MC_EVACUATE_UPDATE_POINTERS],
current_.scopes[Scope::MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED],

View File

@ -56,6 +56,8 @@ enum ScavengeSpeedMode { kForAllObjects, kForSurvivedObjects };
F(MC_EVACUATE_CANDIDATES) \
F(MC_EVACUATE_CLEAN_UP) \
F(MC_EVACUATE_COPY) \
F(MC_EVACUATE_EPILOGUE) \
F(MC_EVACUATE_PROLOGUE) \
F(MC_EVACUATE_REBALANCE) \
F(MC_EVACUATE_UPDATE_POINTERS) \
F(MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED) \

View File

@ -2994,14 +2994,26 @@ static String* UpdateReferenceInExternalStringTableEntry(Heap* heap,
return String::cast(*p);
}
void MarkCompactCollector::EvacuateNewSpacePrologue() {
void MarkCompactCollector::EvacuatePrologue() {
// New space.
NewSpace* new_space = heap()->new_space();
// Append the list of new space pages to be processed.
for (Page* p : PageRange(new_space->bottom(), new_space->top())) {
newspace_evacuation_candidates_.Add(p);
new_space_evacuation_pages_.Add(p);
}
new_space->Flip();
new_space->ResetAllocationInfo();
// Old space.
CHECK(old_space_evacuation_pages_.is_empty());
old_space_evacuation_pages_.Swap(&evacuation_candidates_);
}
void MarkCompactCollector::EvacuateEpilogue() {
// New space.
heap()->new_space()->set_age_mark(heap()->new_space()->top());
// Old space. Deallocate evacuated candidate pages.
ReleaseEvacuationCandidates();
}
class MarkCompactCollector::Evacuator : public Malloced {
@ -3255,14 +3267,14 @@ void MarkCompactCollector::EvacuatePagesInParallel() {
int abandoned_pages = 0;
intptr_t live_bytes = 0;
for (Page* page : evacuation_candidates_) {
for (Page* page : old_space_evacuation_pages_) {
live_bytes += page->LiveBytes();
job.AddPage(page, &abandoned_pages);
}
const bool reduce_memory = heap()->ShouldReduceMemory();
const Address age_mark = heap()->new_space()->age_mark();
for (Page* page : newspace_evacuation_candidates_) {
for (Page* page : new_space_evacuation_pages_) {
live_bytes += page->LiveBytes();
if (!reduce_memory && !page->NeverEvacuate() &&
(page->LiveBytes() > Evacuator::PageEvacuationThreshold()) &&
@ -3556,13 +3568,15 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE);
Heap::RelocationLock relocation_lock(heap());
{
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_PROLOGUE);
EvacuatePrologue();
}
{
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_COPY);
EvacuationScope evacuation_scope(this);
EvacuateNewSpacePrologue();
EvacuatePagesInParallel();
heap()->new_space()->set_age_mark(heap()->new_space()->top());
}
UpdatePointersAfterEvacuation();
@ -3583,7 +3597,7 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
{
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_CLEAN_UP);
for (Page* p : newspace_evacuation_candidates_) {
for (Page* p : new_space_evacuation_pages_) {
if (p->IsFlagSet(Page::PAGE_NEW_NEW_PROMOTION)) {
p->ClearFlag(Page::PAGE_NEW_NEW_PROMOTION);
sweeper().AddPage(p->owner()->identity(), p);
@ -3594,9 +3608,9 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
sweeper().AddPage(p->owner()->identity(), p);
}
}
newspace_evacuation_candidates_.Rewind(0);
new_space_evacuation_pages_.Rewind(0);
for (Page* p : evacuation_candidates_) {
for (Page* p : old_space_evacuation_pages_) {
// Important: skip list should be cleared only after roots were updated
// because root iteration traverses the stack and might have to find
// code objects from non-updated pc pointing into evacuation candidate.
@ -3607,9 +3621,11 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
p->ClearFlag(Page::COMPACTION_WAS_ABORTED);
}
}
}
// Deallocate evacuated candidate pages.
ReleaseEvacuationCandidates();
{
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_EPILOGUE);
EvacuateEpilogue();
}
#ifdef VERIFY_HEAP
@ -3836,14 +3852,14 @@ void MarkCompactCollector::UpdatePointersAfterEvacuation() {
void MarkCompactCollector::ReleaseEvacuationCandidates() {
for (Page* p : evacuation_candidates_) {
for (Page* p : old_space_evacuation_pages_) {
if (!p->IsEvacuationCandidate()) continue;
PagedSpace* space = static_cast<PagedSpace*>(p->owner());
p->ResetLiveBytes();
CHECK(p->SweepingDone());
space->ReleasePage(p);
}
evacuation_candidates_.Rewind(0);
old_space_evacuation_pages_.Rewind(0);
compacting_ = false;
heap()->memory_allocator()->unmapper()->FreeQueuedChunks();
}

View File

@ -754,8 +754,8 @@ class MarkCompactCollector {
void StartSweepSpaces();
void StartSweepSpace(PagedSpace* space);
void EvacuateNewSpacePrologue();
void EvacuatePrologue();
void EvacuateEpilogue();
void EvacuatePagesInParallel();
// The number of parallel compaction tasks, including the main thread.
@ -819,8 +819,11 @@ class MarkCompactCollector {
CodeFlusher* code_flusher_;
// Candidates for pages that should be evacuated.
List<Page*> evacuation_candidates_;
List<Page*> newspace_evacuation_candidates_;
// Pages that are actually processed during evacuation.
List<Page*> old_space_evacuation_pages_;
List<Page*> new_space_evacuation_pages_;
Sweeper sweeper_;