Index: src/heap/mark-compact.cc |
diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc |
index 8b1c7085c0b2fdf8190b3193b69a6059bd54e223..bfc2952d1ea051ca3efa4671f4995400c35b3347 100644 |
--- a/src/heap/mark-compact.cc |
+++ b/src/heap/mark-compact.cc |
@@ -200,6 +200,7 @@ static void VerifyEvacuation(NewSpace* space) { |
NewSpacePageRange range(space->bottom(), space->top()); |
for (auto it = range.begin(); it != range.end();) { |
Page* page = *(it++); |
+ if (page->IsFlagSet(Page::CANNOT_BE_VERIFIED)) continue; |
Address current = page->area_start(); |
Address limit = it != range.end() ? page->area_end() : space->top(); |
CHECK(limit == space->top() || !page->Contains(space->top())); |
@@ -222,11 +223,13 @@ static void VerifyEvacuation(Heap* heap, PagedSpace* space) { |
} |
} |
- |
+template <MarkCompactMode mode> |
static void VerifyEvacuation(Heap* heap) { |
- VerifyEvacuation(heap, heap->old_space()); |
- VerifyEvacuation(heap, heap->code_space()); |
- VerifyEvacuation(heap, heap->map_space()); |
+ if (mode == MarkCompactMode::FULL) { |
+ VerifyEvacuation(heap, heap->old_space()); |
+ VerifyEvacuation(heap, heap->code_space()); |
+ VerifyEvacuation(heap, heap->map_space()); |
+ } |
VerifyEvacuation(heap->new_space()); |
VerifyEvacuationVisitor visitor; |
@@ -296,6 +299,18 @@ bool MarkCompactCollector::StartCompaction() { |
return compacting_; |
} |
+void MarkCompactCollector::CollectGarbageInYoungGeneration() { |
+ AlwaysAllocateScope scope(isolate()); |
+ sweeper().EnsureNewSpaceCompleted(); |
+ MarkLiveObjectsInYoungGeneration(); |
+ isolate() |
+ ->global_handles() |
+ ->IterateNewSpaceWeakUnmodifiedRoots<GlobalHandles::HANDLE_PHANTOM_NODES>( |
+ nullptr); |
+ ClearNonLiveReferencesInYoungGeneration(); |
+ EvacuateNewSpaceAndCandidates<MarkCompactMode::YOUNG_GENERATION>(); |
Hannes Payer (out of office)
2016/11/23 11:25:37
How about restructuring EvacuateNewSpaceAndCandida
|
+} |
+ |
void MarkCompactCollector::CollectGarbage() { |
// Make sure that Prepare() has been called. The individual steps below will |
// update the state as they proceed. |
@@ -317,7 +332,7 @@ void MarkCompactCollector::CollectGarbage() { |
StartSweepSpaces(); |
- EvacuateNewSpaceAndCandidates(); |
+ EvacuateNewSpaceAndCandidates<MarkCompactMode::FULL>(); |
Finish(); |
} |
@@ -533,7 +548,7 @@ void MarkCompactCollector::EnsureSweepingCompleted() { |
#ifdef VERIFY_HEAP |
if (FLAG_verify_heap && !evacuation()) { |
- VerifyEvacuation(heap_); |
+ VerifyEvacuation<MarkCompactMode::FULL>(heap_); |
} |
#endif |
} |
@@ -2498,6 +2513,17 @@ void MarkCompactCollector::MarkLiveObjects() { |
} |
} |
+void MarkCompactCollector::ClearNonLiveReferencesInYoungGeneration() { |
+ TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR); |
+ |
+ { |
+ TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_STRING_TABLE); |
+ |
+ ExternalStringTableCleaner external_visitor(heap(), nullptr); |
+ heap()->external_string_table_.IterateNewSpaceStrings(&external_visitor); |
+ heap()->external_string_table_.CleanupNewSpaceStrings(); |
+ } |
+} |
void MarkCompactCollector::ClearNonLiveReferences() { |
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR); |
@@ -3032,6 +3058,7 @@ void MarkCompactCollector::EvacuateNewSpacePrologue() { |
NewSpace* new_space = heap()->new_space(); |
// Append the list of new space pages to be processed. |
for (Page* p : NewSpacePageRange(new_space->bottom(), new_space->top())) { |
+ p->ClearFlag(Page::CANNOT_BE_VERIFIED); |
newspace_evacuation_candidates_.Add(p); |
} |
new_space->Flip(); |
@@ -3282,6 +3309,7 @@ class EvacuationJobTraits { |
} |
}; |
+template <MarkCompactMode mode> |
void MarkCompactCollector::EvacuatePagesInParallel() { |
PageParallelJob<EvacuationJobTraits> job( |
heap_, heap_->isolate()->cancelable_task_manager(), |
@@ -3289,9 +3317,11 @@ void MarkCompactCollector::EvacuatePagesInParallel() { |
int abandoned_pages = 0; |
intptr_t live_bytes = 0; |
- for (Page* page : evacuation_candidates_) { |
- live_bytes += page->LiveBytes(); |
- job.AddPage(page, &abandoned_pages); |
+ if (mode == MarkCompactMode::FULL) { |
+ for (Page* page : evacuation_candidates_) { |
+ live_bytes += page->LiveBytes(); |
+ job.AddPage(page, &abandoned_pages); |
+ } |
} |
const bool reduce_memory = heap()->ShouldReduceMemory(); |
@@ -3358,6 +3388,26 @@ class EvacuationWeakObjectRetainer : public WeakObjectRetainer { |
} |
}; |
+class MinorMCWeakObjectRetainer : public WeakObjectRetainer { |
+ public: |
+ explicit MinorMCWeakObjectRetainer(Heap* heap) : heap_(heap) {} |
+ |
+ virtual Object* RetainAs(Object* object) { |
+ if (!heap_->InFromSpace(object)) { |
+ return object; |
+ } |
+ |
+ MapWord map_word = HeapObject::cast(object)->map_word(); |
+ if (map_word.IsForwardingAddress()) { |
+ return map_word.ToForwardingAddress(); |
+ } |
+ return NULL; |
+ } |
+ |
+ private: |
+ Heap* heap_; |
+}; |
+ |
MarkCompactCollector::Sweeper::ClearOldToNewSlotsMode |
MarkCompactCollector::Sweeper::GetClearOldToNewSlotsMode(Page* p) { |
AllocationSpace identity = p->owner()->identity(); |
@@ -3581,6 +3631,7 @@ void MarkCompactCollector::Sweeper::AddSweptPageSafe(PagedSpace* space, |
swept_list_[space->identity()].Add(page); |
} |
+template <MarkCompactMode mode> |
void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { |
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE); |
Heap::RelocationLock relocation_lock(heap()); |
@@ -3590,14 +3641,17 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { |
EvacuationScope evacuation_scope(this); |
EvacuateNewSpacePrologue(); |
- EvacuatePagesInParallel(); |
+ EvacuatePagesInParallel<mode>(); |
heap()->new_space()->set_age_mark(heap()->new_space()->top()); |
} |
- UpdatePointersAfterEvacuation(); |
+ UpdatePointersAfterEvacuation<mode>(); |
- if (!heap()->new_space()->Rebalance()) { |
- FatalProcessOutOfMemory("NewSpace::Rebalance"); |
+ { |
+ TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_REBALANCE); |
+ if (!heap()->new_space()->Rebalance()) { |
+ FatalProcessOutOfMemory("NewSpace::Rebalance"); |
+ } |
} |
// Give pages that are queued to be freed back to the OS. Note that filtering |
@@ -3612,35 +3666,44 @@ 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); |
+ p->SetFlag(Page::CANNOT_BE_VERIFIED); |
+ if (mode == MarkCompactMode::FULL) |
+ sweeper().AddPage(p->owner()->identity(), p); |
} else if (p->IsFlagSet(Page::PAGE_NEW_OLD_PROMOTION)) { |
p->ClearFlag(Page::PAGE_NEW_OLD_PROMOTION); |
+ p->SetFlag(Page::CANNOT_BE_VERIFIED); |
p->ForAllFreeListCategories( |
[](FreeListCategory* category) { DCHECK(!category->is_linked()); }); |
- sweeper().AddPage(p->owner()->identity(), p); |
+ if (mode == MarkCompactMode::FULL) |
+ sweeper().AddPage(p->owner()->identity(), p); |
+ } |
+ if (mode == MarkCompactMode::YOUNG_GENERATION) { |
+ p->ClearLiveness(); |
} |
} |
newspace_evacuation_candidates_.Rewind(0); |
- for (Page* p : evacuation_candidates_) { |
- // 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. |
- SkipList* list = p->skip_list(); |
- if (list != NULL) list->Clear(); |
- if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) { |
- sweeper().AddPage(p->owner()->identity(), p); |
- p->ClearFlag(Page::COMPACTION_WAS_ABORTED); |
+ if (mode == MarkCompactMode::FULL) { |
+ for (Page* p : evacuation_candidates_) { |
+ // 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. |
+ SkipList* list = p->skip_list(); |
+ if (list != NULL) list->Clear(); |
+ if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) { |
+ sweeper().AddPage(p->owner()->identity(), p); |
+ p->ClearFlag(Page::COMPACTION_WAS_ABORTED); |
+ } |
} |
- } |
- // Deallocate evacuated candidate pages. |
- ReleaseEvacuationCandidates(); |
+ // Deallocate evacuated candidate pages. |
+ ReleaseEvacuationCandidates(); |
+ } |
} |
#ifdef VERIFY_HEAP |
if (FLAG_verify_heap && !sweeper().sweeping_in_progress()) { |
- VerifyEvacuation(heap()); |
+ VerifyEvacuation<mode>(heap()); |
} |
#endif |
} |
@@ -3828,6 +3891,7 @@ void UpdateToSpacePointersInParallel(Heap* heap, base::Semaphore* semaphore) { |
job.Run(num_tasks, [&visitor](int i) { return &visitor; }); |
} |
+template <MarkCompactMode mode> |
void MarkCompactCollector::UpdatePointersAfterEvacuation() { |
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS); |
@@ -3842,7 +3906,7 @@ void MarkCompactCollector::UpdatePointersAfterEvacuation() { |
UpdatePointersInParallel<OLD_TO_NEW>(heap_, &page_parallel_job_semaphore_); |
} |
- { |
+ if (mode == MarkCompactMode::FULL) { |
Heap* heap = this->heap(); |
TRACE_GC(heap->tracer(), |
GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED); |
@@ -3853,11 +3917,17 @@ void MarkCompactCollector::UpdatePointersAfterEvacuation() { |
TRACE_GC(heap()->tracer(), |
GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_WEAK); |
// Update pointers from external string table. |
- heap_->UpdateReferencesInExternalStringTable( |
- &UpdateReferenceInExternalStringTableEntry); |
- |
- EvacuationWeakObjectRetainer evacuation_object_retainer; |
- heap()->ProcessWeakListRoots(&evacuation_object_retainer); |
+ if (mode == MarkCompactMode::FULL) { |
+ heap_->UpdateReferencesInExternalStringTable( |
+ &UpdateReferenceInExternalStringTableEntry); |
+ EvacuationWeakObjectRetainer evacuation_object_retainer; |
+ heap()->ProcessWeakListRoots(&evacuation_object_retainer); |
+ } else { |
+ heap_->UpdateNewSpaceReferencesInExternalStringTable( |
+ &UpdateReferenceInExternalStringTableEntry); |
+ MinorMCWeakObjectRetainer weak_object_retainer(heap()); |
+ heap()->ProcessYoungWeakReferences(&weak_object_retainer); |
+ } |
} |
} |