[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:
parent
b008f27f02
commit
e800933eee
@ -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],
|
||||
|
@ -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) \
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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_;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user