| 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
|
|
|