Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(186)

Unified Diff: src/heap/mark-compact.cc

Issue 1413763011: [heap] Fix rescanning live objects when aborting compaction. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Addressed comments Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/heap/mark-compact.h ('k') | src/heap/spaces.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/heap/mark-compact.cc
diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc
index e77e90e166bfaeb6e8347dd56698e94ec7ec8906..5ed7b4a1bf9e0f69117d336c42e9837a2357c9a1 100644
--- a/src/heap/mark-compact.cc
+++ b/src/heap/mark-compact.cc
@@ -2935,7 +2935,9 @@ class PointersUpdatingVisitor : public ObjectVisitor {
MapWord map_word = heap_obj->map_word();
if (map_word.IsForwardingAddress()) {
DCHECK(heap->InFromSpace(heap_obj) ||
- MarkCompactCollector::IsOnEvacuationCandidate(heap_obj));
+ MarkCompactCollector::IsOnEvacuationCandidate(heap_obj) ||
+ Page::FromAddress(heap_obj->address())
+ ->IsFlagSet(Page::COMPACTION_WAS_ABORTED));
HeapObject* target = map_word.ToForwardingAddress();
base::NoBarrier_CompareAndSwap(
reinterpret_cast<base::AtomicWord*>(slot),
@@ -3463,7 +3465,7 @@ void MarkCompactCollector::EvacuatePagesInParallel() {
// - Leave the page in the list of pages of a space since we could not
// fully evacuate it.
DCHECK(p->IsEvacuationCandidate());
- p->SetFlag(Page::RESCAN_ON_EVACUATION);
+ p->SetFlag(Page::COMPACTION_WAS_ABORTED);
abandoned_pages++;
break;
case MemoryChunk::kCompactingFinalize:
@@ -3701,6 +3703,57 @@ void MarkCompactCollector::RemoveObjectSlots(Address start_slot,
}
+void MarkCompactCollector::VisitLiveObjects(Page* page,
+ ObjectVisitor* visitor) {
+ // First pass on aborted pages.
+ int offsets[16];
+ for (MarkBitCellIterator it(page); !it.Done(); it.Advance()) {
+ Address cell_base = it.CurrentCellBase();
+ MarkBit::CellType* cell = it.CurrentCell();
+ if (*cell == 0) continue;
+ int live_objects = MarkWordToObjectStarts(*cell, offsets);
+ for (int i = 0; i < live_objects; i++) {
+ Address object_addr = cell_base + offsets[i] * kPointerSize;
+ HeapObject* live_object = HeapObject::FromAddress(object_addr);
+ DCHECK(Marking::IsBlack(Marking::MarkBitFrom(live_object)));
+ Map* map = live_object->synchronized_map();
+ int size = live_object->SizeFromMap(map);
+ live_object->IterateBody(map->instance_type(), size, visitor);
+ }
+ }
+}
+
+
+void MarkCompactCollector::SweepAbortedPages() {
+ // Second pass on aborted pages.
+ for (int i = 0; i < evacuation_candidates_.length(); i++) {
+ Page* p = evacuation_candidates_[i];
+ if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) {
+ p->ClearFlag(MemoryChunk::COMPACTION_WAS_ABORTED);
+ PagedSpace* space = static_cast<PagedSpace*>(p->owner());
+ switch (space->identity()) {
+ case OLD_SPACE:
+ Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST,
+ IGNORE_FREE_SPACE>(space, nullptr, p, nullptr);
+ break;
+ case CODE_SPACE:
+ if (FLAG_zap_code_space) {
+ Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST,
+ ZAP_FREE_SPACE>(space, NULL, p, nullptr);
+ } else {
+ Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST,
+ IGNORE_FREE_SPACE>(space, NULL, p, nullptr);
+ }
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+ }
+}
+
+
void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
Heap::RelocationLock relocation_lock(heap());
@@ -3794,13 +3847,15 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
// code objects from non-updated pc pointing into evacuation candidate.
SkipList* list = p->skip_list();
if (list != NULL) list->Clear();
- }
- if (p->IsEvacuationCandidate() &&
- p->IsFlagSet(Page::RESCAN_ON_EVACUATION)) {
- // Case where we've aborted compacting a page. Clear the flag here to
- // avoid release the page later on.
- p->ClearEvacuationCandidate();
+ // First pass on aborted pages, fixing up all live objects.
+ if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) {
+ // Clearing the evacuation candidate flag here has the effect of
+ // stopping recording of slots for it in the following pointer
+ // update phases.
+ p->ClearEvacuationCandidate();
+ VisitLiveObjects(p, &updating_visitor);
+ }
}
if (p->IsFlagSet(Page::RESCAN_ON_EVACUATION)) {
@@ -3836,17 +3891,26 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
}
}
- GCTracer::Scope gc_scope(heap()->tracer(),
- GCTracer::Scope::MC_UPDATE_MISC_POINTERS);
+ {
+ GCTracer::Scope gc_scope(heap()->tracer(),
+ GCTracer::Scope::MC_UPDATE_MISC_POINTERS);
+ heap_->string_table()->Iterate(&updating_visitor);
- heap_->string_table()->Iterate(&updating_visitor);
+ // Update pointers from external string table.
+ heap_->UpdateReferencesInExternalStringTable(
+ &UpdateReferenceInExternalStringTableEntry);
- // Update pointers from external string table.
- heap_->UpdateReferencesInExternalStringTable(
- &UpdateReferenceInExternalStringTableEntry);
+ EvacuationWeakObjectRetainer evacuation_object_retainer;
+ heap()->ProcessAllWeakReferences(&evacuation_object_retainer);
+ }
- EvacuationWeakObjectRetainer evacuation_object_retainer;
- heap()->ProcessAllWeakReferences(&evacuation_object_retainer);
+ {
+ GCTracer::Scope gc_scope(heap()->tracer(),
+ GCTracer::Scope::MC_SWEEP_ABORTED);
+ // After updating all pointers, we can finally sweep the aborted pages,
+ // effectively overriding any forward pointers.
+ SweepAbortedPages();
+ }
heap_->isolate()->inner_pointer_to_code_cache()->Flush();
« no previous file with comments | « src/heap/mark-compact.h ('k') | src/heap/spaces.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698