Index: src/heap/mark-compact.cc |
diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc |
index ea0b75daa1a430bb055adcb4272a644fad31e96d..2c998c8817a090478f0e209881aaad04efde6e61 100644 |
--- a/src/heap/mark-compact.cc |
+++ b/src/heap/mark-compact.cc |
@@ -119,6 +119,15 @@ static void VerifyMarking(Heap* heap, Address bottom, Address top) { |
} |
} |
+static void VerifyMarkingBlackPage(Heap* heap, Page* page) { |
+ CHECK(page->IsFlagSet(Page::BLACK_PAGE)); |
+ VerifyMarkingVisitor visitor(heap); |
+ HeapObjectIterator it(page); |
+ for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) { |
+ CHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); |
+ object->Iterate(&visitor); |
+ } |
+} |
static void VerifyMarking(NewSpace* space) { |
Address end = space->top(); |
@@ -141,7 +150,11 @@ static void VerifyMarking(PagedSpace* space) { |
while (it.has_next()) { |
Page* p = it.next(); |
- VerifyMarking(space->heap(), p->area_start(), p->area_end()); |
+ if (p->IsFlagSet(Page::BLACK_PAGE)) { |
+ VerifyMarkingBlackPage(space->heap(), p); |
+ } else { |
+ VerifyMarking(space->heap(), p->area_start(), p->area_end()); |
+ } |
} |
} |
@@ -414,7 +427,11 @@ static void ClearMarkbitsInPagedSpace(PagedSpace* space) { |
PageIterator it(space); |
while (it.has_next()) { |
- Bitmap::Clear(it.next()); |
+ Page* p = it.next(); |
+ Bitmap::Clear(p); |
+ if (p->IsFlagSet(Page::BLACK_PAGE)) { |
+ p->ClearFlag(Page::BLACK_PAGE); |
+ } |
} |
} |
@@ -437,8 +454,12 @@ void MarkCompactCollector::ClearMarkbits() { |
LargeObjectIterator it(heap_->lo_space()); |
for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { |
Marking::MarkWhite(Marking::MarkBitFrom(obj)); |
- Page::FromAddress(obj->address())->ResetProgressBar(); |
- Page::FromAddress(obj->address())->ResetLiveBytes(); |
+ MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); |
+ chunk->ResetProgressBar(); |
+ chunk->ResetLiveBytes(); |
+ if (chunk->IsFlagSet(Page::BLACK_PAGE)) { |
+ chunk->ClearFlag(Page::BLACK_PAGE); |
+ } |
} |
} |
@@ -555,7 +576,9 @@ void Marking::TransferMark(Heap* heap, Address old_start, Address new_start) { |
DCHECK(MemoryChunk::FromAddress(old_start) == |
MemoryChunk::FromAddress(new_start)); |
- if (!heap->incremental_marking()->IsMarking()) return; |
+ if (!heap->incremental_marking()->IsMarking() || |
+ Page::FromAddress(old_start)->IsFlagSet(Page::BLACK_PAGE)) |
+ return; |
// If the mark doesn't move, we don't check the color of the object. |
// It doesn't matter whether the object is black, since it hasn't changed |
@@ -664,6 +687,7 @@ void MarkCompactCollector::CollectEvacuationCandidates(PagedSpace* space) { |
while (it.has_next()) { |
Page* p = it.next(); |
if (p->NeverEvacuate()) continue; |
+ if (p->IsFlagSet(Page::BLACK_PAGE)) continue; |
// Invariant: Evacuation candidates are just created when marking is |
// started. This means that sweeping has finished. Furthermore, at the end |
// of a GC all evacuation candidates are cleared and their slot buffers are |
@@ -1467,10 +1491,11 @@ void MarkCompactCollector::DiscoverGreyObjectsWithIterator(T* it) { |
} |
} |
- |
+template <LiveObjectIterationMode T> |
void MarkCompactCollector::DiscoverGreyObjectsOnPage(MemoryChunk* p) { |
DCHECK(!marking_deque()->IsFull()); |
- LiveObjectIterator<kGreyObjects> it(p); |
+ DCHECK(T == kGreyObjects || T == kGreyObjectsOnBlackPage); |
+ LiveObjectIterator<T> it(p); |
HeapObject* object = NULL; |
while ((object = it.Next()) != NULL) { |
MarkBit markbit = Marking::MarkBitFrom(object); |
@@ -1704,7 +1729,11 @@ void MarkCompactCollector::DiscoverGreyObjectsInSpace(PagedSpace* space) { |
PageIterator it(space); |
while (it.has_next()) { |
Page* p = it.next(); |
- DiscoverGreyObjectsOnPage(p); |
+ if (p->IsFlagSet(Page::BLACK_PAGE)) { |
+ DiscoverGreyObjectsOnPage<kGreyObjectsOnBlackPage>(p); |
+ } else { |
+ DiscoverGreyObjectsOnPage<kGreyObjects>(p); |
+ } |
if (marking_deque()->IsFull()) return; |
} |
} |
@@ -1715,7 +1744,7 @@ void MarkCompactCollector::DiscoverGreyObjectsInNewSpace() { |
NewSpacePageIterator it(space->bottom(), space->top()); |
while (it.has_next()) { |
NewSpacePage* page = it.next(); |
- DiscoverGreyObjectsOnPage(page); |
+ DiscoverGreyObjectsOnPage<kGreyObjects>(page); |
if (marking_deque()->IsFull()) return; |
} |
} |
@@ -2805,6 +2834,12 @@ bool MarkCompactCollector::IsSlotInBlackObject(Page* p, Address slot, |
return false; |
} |
+ // If we are on a black page, we cannot find the actual object start |
+ // easiliy. We just return true but do not set the out_object. |
+ if (p->IsFlagSet(Page::BLACK_PAGE)) { |
+ return true; |
+ } |
+ |
uint32_t mark_bit_index = p->AddressToMarkbitIndex(slot); |
unsigned int cell_index = mark_bit_index >> Bitmap::kBitsPerCellLog2; |
MarkBit::CellType index_mask = 1u << Bitmap::IndexInCell(mark_bit_index); |
@@ -2885,7 +2920,6 @@ bool MarkCompactCollector::IsSlotInBlackObject(Page* p, Address slot, |
HeapObject* MarkCompactCollector::FindBlackObjectBySlotSlow(Address slot) { |
Page* p = Page::FromAddress(slot); |
- // This function does not support large objects right now. |
Space* owner = p->owner(); |
if (owner == heap_->lo_space() || owner == nullptr) { |
Object* large_object = heap_->lo_space()->FindObject(slot); |
@@ -2900,13 +2934,25 @@ HeapObject* MarkCompactCollector::FindBlackObjectBySlotSlow(Address slot) { |
return nullptr; |
} |
- LiveObjectIterator<kBlackObjects> it(p); |
- HeapObject* object = nullptr; |
- while ((object = it.Next()) != nullptr) { |
- int size = object->Size(); |
- if (object->address() > slot) return nullptr; |
- if (object->address() <= slot && slot < (object->address() + size)) { |
- return object; |
+ if (p->IsFlagSet(Page::BLACK_PAGE)) { |
+ HeapObjectIterator it(p); |
+ HeapObject* object = nullptr; |
+ while ((object = it.Next()) != nullptr) { |
+ int size = object->Size(); |
+ if (object->address() > slot) return nullptr; |
+ if (object->address() <= slot && slot < (object->address() + size)) { |
+ return object; |
+ } |
+ } |
+ } else { |
+ LiveObjectIterator<kBlackObjects> it(p); |
+ HeapObject* object = nullptr; |
+ while ((object = it.Next()) != nullptr) { |
+ int size = object->Size(); |
+ if (object->address() > slot) return nullptr; |
+ if (object->address() <= slot && slot < (object->address() + size)) { |
+ return object; |
+ } |
} |
} |
return nullptr; |
@@ -2914,15 +2960,21 @@ HeapObject* MarkCompactCollector::FindBlackObjectBySlotSlow(Address slot) { |
bool MarkCompactCollector::IsSlotInLiveObject(Address slot) { |
- HeapObject* object = NULL; |
// The target object is black but we don't know if the source slot is black. |
// The source object could have died and the slot could be part of a free |
// space. Find out based on mark bits if the slot is part of a live object. |
- if (!IsSlotInBlackObject(Page::FromAddress(slot), slot, &object)) { |
+ Page* page = Page::FromAddress(slot); |
+ HeapObject* object = NULL; |
+ if (!IsSlotInBlackObject(page, slot, &object)) { |
return false; |
} |
- DCHECK(object != NULL); |
+ // If the slot is on a black page, the object will be live. |
+ DCHECK(object != NULL || page->IsFlagSet(Page::BLACK_PAGE)); |
+ if (page->IsFlagSet(Page::BLACK_PAGE)) { |
+ return true; |
+ } |
+ |
int offset = static_cast<int>(slot - object->address()); |
return object->IsValidSlot(offset); |
} |
@@ -3226,6 +3278,7 @@ template <SweepingMode sweeping_mode, |
static int Sweep(PagedSpace* space, FreeList* free_list, Page* p, |
ObjectVisitor* v) { |
DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone()); |
+ DCHECK(!p->IsFlagSet(Page::BLACK_PAGE)); |
DCHECK_EQ(skip_list_mode == REBUILD_SKIP_LIST, |
space->identity() == CODE_SPACE); |
DCHECK((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST)); |
@@ -3698,6 +3751,16 @@ void MarkCompactCollector::StartSweepSpace(PagedSpace* space) { |
continue; |
} |
+ // We can not sweep black pages, since all mark bits are set for these |
+ // pages. |
+ if (p->IsFlagSet(Page::BLACK_PAGE)) { |
+ Bitmap::Clear(p); |
+ p->concurrent_sweeping_state().SetValue(Page::kSweepingDone); |
+ p->ClearFlag(Page::BLACK_PAGE); |
+ // TODO(hpayer): Free unused memory of last black page. |
+ continue; |
+ } |
+ |
if (p->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) { |
// We need to sweep the page to get it into an iterable state again. Note |
// that this adds unusable memory into the free list that is later on |