Commit 8f6135f1 authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

[heap] Refactor marking verification

Use MarkingState to abstract over the different sets of markbits.

BUG=chromium:651354

Change-Id: I1635eb0d441be2aeed19f0ed91999f0f0f1bbffc
Reviewed-on: https://chromium-review.googlesource.com/458398Reviewed-by: 's avatarHannes Payer <hpayer@chromium.org>
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44024}
parent 2c84924f
...@@ -65,58 +65,51 @@ MarkCompactCollector::MarkCompactCollector(Heap* heap) ...@@ -65,58 +65,51 @@ MarkCompactCollector::MarkCompactCollector(Heap* heap)
} }
#ifdef VERIFY_HEAP #ifdef VERIFY_HEAP
class VerifyMarkingVisitor : public ObjectVisitor { class MarkingVerifier : public ObjectVisitor {
public: public:
void VisitPointers(Object** start, Object** end) override { virtual void Run() = 0;
for (Object** current = start; current < end; current++) {
if ((*current)->IsHeapObject()) {
HeapObject* object = HeapObject::cast(*current);
CHECK(ObjectMarking::IsBlackOrGrey(object));
}
}
}
void VisitEmbeddedPointer(RelocInfo* rinfo) override { protected:
DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); explicit MarkingVerifier(Heap* heap) : heap_(heap) {}
if (!rinfo->host()->IsWeakObject(rinfo->target_object())) {
Object* p = rinfo->target_object();
VisitPointer(&p);
}
}
void VisitCell(RelocInfo* rinfo) override { virtual MarkingState marking_state(MemoryChunk* chunk) = 0;
Code* code = rinfo->host();
DCHECK(rinfo->rmode() == RelocInfo::CELL); void VerifyRoots(VisitMode mode);
if (!code->IsWeakObject(rinfo->target_cell())) { void VerifyMarkingOnPage(const Page& page, const MarkingState& state,
ObjectVisitor::VisitCell(rinfo); Address start, Address end);
} void VerifyMarking(NewSpace* new_space);
} void VerifyMarking(PagedSpace* paged_space);
Heap* heap_;
}; };
void MarkingVerifier::VerifyRoots(VisitMode mode) {
heap_->IterateStrongRoots(this, mode);
}
static void VerifyMarking(Heap* heap, Address bottom, Address top) { void MarkingVerifier::VerifyMarkingOnPage(const Page& page,
VerifyMarkingVisitor visitor; const MarkingState& state,
Address start, Address end) {
HeapObject* object; HeapObject* object;
Address next_object_must_be_here_or_later = bottom; Address next_object_must_be_here_or_later = start;
for (Address current = bottom; current < top;) { for (Address current = start; current < end;) {
object = HeapObject::FromAddress(current); object = HeapObject::FromAddress(current);
// One word fillers at the end of a black area can be grey. // One word fillers at the end of a black area can be grey.
if (ObjectMarking::IsBlackOrGrey(object) && if (ObjectMarking::IsBlackOrGrey(object, state) &&
object->map() != heap->one_pointer_filler_map()) { object->map() != heap_->one_pointer_filler_map()) {
CHECK(ObjectMarking::IsBlack(object)); CHECK(ObjectMarking::IsBlack(object, state));
CHECK(current >= next_object_must_be_here_or_later); CHECK(current >= next_object_must_be_here_or_later);
object->Iterate(&visitor); object->Iterate(this);
next_object_must_be_here_or_later = current + object->Size(); next_object_must_be_here_or_later = current + object->Size();
// The object is either part of a black area of black allocation or a // The object is either part of a black area of black allocation or a
// regular black object // regular black object
Page* page = Page::FromAddress(current);
CHECK( CHECK(
page->markbits()->AllBitsSetInRange( state.bitmap->AllBitsSetInRange(
page->AddressToMarkbitIndex(current), page.AddressToMarkbitIndex(current),
page->AddressToMarkbitIndex(next_object_must_be_here_or_later)) || page.AddressToMarkbitIndex(next_object_must_be_here_or_later)) ||
page->markbits()->AllBitsClearInRange( state.bitmap->AllBitsClearInRange(
page->AddressToMarkbitIndex(current + kPointerSize * 2), page.AddressToMarkbitIndex(current + kPointerSize * 2),
page->AddressToMarkbitIndex(next_object_must_be_here_or_later))); page.AddressToMarkbitIndex(next_object_must_be_here_or_later)));
current = next_object_must_be_here_or_later; current = next_object_must_be_here_or_later;
} else { } else {
current += kPointerSize; current += kPointerSize;
...@@ -124,7 +117,7 @@ static void VerifyMarking(Heap* heap, Address bottom, Address top) { ...@@ -124,7 +117,7 @@ static void VerifyMarking(Heap* heap, Address bottom, Address top) {
} }
} }
static void VerifyMarking(NewSpace* space) { void MarkingVerifier::VerifyMarking(NewSpace* space) {
Address end = space->top(); Address end = space->top();
// The bottom position is at the start of its page. Allows us to use // The bottom position is at the start of its page. Allows us to use
// page->area_start() as start of range on all pages. // page->area_start() as start of range on all pages.
...@@ -135,36 +128,97 @@ static void VerifyMarking(NewSpace* space) { ...@@ -135,36 +128,97 @@ static void VerifyMarking(NewSpace* space) {
Page* page = *(it++); Page* page = *(it++);
Address limit = it != range.end() ? page->area_end() : end; Address limit = it != range.end() ? page->area_end() : end;
CHECK(limit == end || !page->Contains(end)); CHECK(limit == end || !page->Contains(end));
VerifyMarking(space->heap(), page->area_start(), limit); VerifyMarkingOnPage(*page, marking_state(page), page->area_start(), limit);
} }
} }
void MarkingVerifier::VerifyMarking(PagedSpace* space) {
static void VerifyMarking(PagedSpace* space) {
for (Page* p : *space) { for (Page* p : *space) {
VerifyMarking(space->heap(), p->area_start(), p->area_end()); VerifyMarkingOnPage(*p, marking_state(p), p->area_start(), p->area_end());
} }
} }
class FullMarkingVerifier : public MarkingVerifier {
public:
explicit FullMarkingVerifier(Heap* heap) : MarkingVerifier(heap) {}
static void VerifyMarking(Heap* heap) { void Run() override {
VerifyMarking(heap->old_space()); VerifyRoots(VISIT_ONLY_STRONG);
VerifyMarking(heap->code_space()); VerifyMarking(heap_->new_space());
VerifyMarking(heap->map_space()); VerifyMarking(heap_->old_space());
VerifyMarking(heap->new_space()); VerifyMarking(heap_->code_space());
VerifyMarking(heap_->map_space());
VerifyMarkingVisitor visitor;
LargeObjectIterator it(heap->lo_space()); LargeObjectIterator it(heap_->lo_space());
for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) {
if (ObjectMarking::IsBlackOrGrey(obj)) { if (ObjectMarking::IsBlackOrGrey(obj, marking_state(obj))) {
obj->Iterate(&visitor); obj->Iterate(this);
}
} }
} }
heap->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); protected:
} MarkingState marking_state(MemoryChunk* chunk) override {
return MarkingState::FromPageInternal(chunk);
}
MarkingState marking_state(HeapObject* object) {
return marking_state(Page::FromAddress(object->address()));
}
void VisitPointers(Object** start, Object** end) override {
for (Object** current = start; current < end; current++) {
if ((*current)->IsHeapObject()) {
HeapObject* object = HeapObject::cast(*current);
CHECK(ObjectMarking::IsBlackOrGrey(object, marking_state(object)));
}
}
}
void VisitEmbeddedPointer(RelocInfo* rinfo) override {
DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
if (!rinfo->host()->IsWeakObject(rinfo->target_object())) {
Object* p = rinfo->target_object();
VisitPointer(&p);
}
}
void VisitCell(RelocInfo* rinfo) override {
Code* code = rinfo->host();
DCHECK(rinfo->rmode() == RelocInfo::CELL);
if (!code->IsWeakObject(rinfo->target_cell())) {
ObjectVisitor::VisitCell(rinfo);
}
}
};
class YoungGenerationMarkingVerifier : public MarkingVerifier {
public:
explicit YoungGenerationMarkingVerifier(Heap* heap) : MarkingVerifier(heap) {}
MarkingState marking_state(MemoryChunk* chunk) override {
return MarkingState::FromPageExternal(chunk);
}
MarkingState marking_state(HeapObject* object) {
return marking_state(Page::FromAddress(object->address()));
}
void Run() override {
VerifyRoots(VISIT_ALL_IN_SCAVENGE);
VerifyMarking(heap_->new_space());
}
void VisitPointers(Object** start, Object** end) override {
for (Object** current = start; current < end; current++) {
if ((*current)->IsHeapObject()) {
HeapObject* object = HeapObject::cast(*current);
if (!heap_->InNewSpace(object)) return;
CHECK(ObjectMarking::IsBlackOrGrey(object, marking_state(object)));
}
}
}
};
class VerifyEvacuationVisitor : public ObjectVisitor { class VerifyEvacuationVisitor : public ObjectVisitor {
public: public:
...@@ -310,7 +364,8 @@ void MarkCompactCollector::CollectGarbage() { ...@@ -310,7 +364,8 @@ void MarkCompactCollector::CollectGarbage() {
#ifdef VERIFY_HEAP #ifdef VERIFY_HEAP
if (FLAG_verify_heap) { if (FLAG_verify_heap) {
VerifyMarking(heap_); FullMarkingVerifier verifier(heap());
verifier.Run();
} }
#endif #endif
...@@ -2354,7 +2409,16 @@ void MinorMarkCompactCollector::EmptyMarkingDeque() { ...@@ -2354,7 +2409,16 @@ void MinorMarkCompactCollector::EmptyMarkingDeque() {
} }
} }
void MinorMarkCompactCollector::CollectGarbage() { MarkLiveObjects(); } void MinorMarkCompactCollector::CollectGarbage() {
MarkLiveObjects();
#ifdef VERIFY_HEAP
if (FLAG_verify_heap) {
YoungGenerationMarkingVerifier verifier(heap());
verifier.Run();
}
#endif // VERIFY_HEAP
}
void MarkCompactCollector::MarkLiveObjects() { void MarkCompactCollector::MarkLiveObjects() {
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK); TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment