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)
}
#ifdef VERIFY_HEAP
class VerifyMarkingVisitor : public ObjectVisitor {
class MarkingVerifier : public ObjectVisitor {
public:
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));
}
}
}
virtual void Run() = 0;
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);
}
}
protected:
explicit MarkingVerifier(Heap* heap) : heap_(heap) {}
void VisitCell(RelocInfo* rinfo) override {
Code* code = rinfo->host();
DCHECK(rinfo->rmode() == RelocInfo::CELL);
if (!code->IsWeakObject(rinfo->target_cell())) {
ObjectVisitor::VisitCell(rinfo);
}
}
virtual MarkingState marking_state(MemoryChunk* chunk) = 0;
void VerifyRoots(VisitMode mode);
void VerifyMarkingOnPage(const Page& page, const MarkingState& state,
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) {
VerifyMarkingVisitor visitor;
void MarkingVerifier::VerifyMarkingOnPage(const Page& page,
const MarkingState& state,
Address start, Address end) {
HeapObject* object;
Address next_object_must_be_here_or_later = bottom;
for (Address current = bottom; current < top;) {
Address next_object_must_be_here_or_later = start;
for (Address current = start; current < end;) {
object = HeapObject::FromAddress(current);
// One word fillers at the end of a black area can be grey.
if (ObjectMarking::IsBlackOrGrey(object) &&
object->map() != heap->one_pointer_filler_map()) {
CHECK(ObjectMarking::IsBlack(object));
if (ObjectMarking::IsBlackOrGrey(object, state) &&
object->map() != heap_->one_pointer_filler_map()) {
CHECK(ObjectMarking::IsBlack(object, state));
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();
// The object is either part of a black area of black allocation or a
// regular black object
Page* page = Page::FromAddress(current);
CHECK(
page->markbits()->AllBitsSetInRange(
page->AddressToMarkbitIndex(current),
page->AddressToMarkbitIndex(next_object_must_be_here_or_later)) ||
page->markbits()->AllBitsClearInRange(
page->AddressToMarkbitIndex(current + kPointerSize * 2),
page->AddressToMarkbitIndex(next_object_must_be_here_or_later)));
state.bitmap->AllBitsSetInRange(
page.AddressToMarkbitIndex(current),
page.AddressToMarkbitIndex(next_object_must_be_here_or_later)) ||
state.bitmap->AllBitsClearInRange(
page.AddressToMarkbitIndex(current + kPointerSize * 2),
page.AddressToMarkbitIndex(next_object_must_be_here_or_later)));
current = next_object_must_be_here_or_later;
} else {
current += kPointerSize;
......@@ -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();
// The bottom position is at the start of its page. Allows us to use
// page->area_start() as start of range on all pages.
......@@ -135,36 +128,97 @@ static void VerifyMarking(NewSpace* space) {
Page* page = *(it++);
Address limit = it != range.end() ? page->area_end() : end;
CHECK(limit == end || !page->Contains(end));
VerifyMarking(space->heap(), page->area_start(), limit);
VerifyMarkingOnPage(*page, marking_state(page), page->area_start(), limit);
}
}
static void VerifyMarking(PagedSpace* space) {
void MarkingVerifier::VerifyMarking(PagedSpace* 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) {
VerifyMarking(heap->old_space());
VerifyMarking(heap->code_space());
VerifyMarking(heap->map_space());
VerifyMarking(heap->new_space());
VerifyMarkingVisitor visitor;
void Run() override {
VerifyRoots(VISIT_ONLY_STRONG);
VerifyMarking(heap_->new_space());
VerifyMarking(heap_->old_space());
VerifyMarking(heap_->code_space());
VerifyMarking(heap_->map_space());
LargeObjectIterator it(heap->lo_space());
LargeObjectIterator it(heap_->lo_space());
for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) {
if (ObjectMarking::IsBlackOrGrey(obj)) {
obj->Iterate(&visitor);
if (ObjectMarking::IsBlackOrGrey(obj, marking_state(obj))) {
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 {
public:
......@@ -310,7 +364,8 @@ void MarkCompactCollector::CollectGarbage() {
#ifdef VERIFY_HEAP
if (FLAG_verify_heap) {
VerifyMarking(heap_);
FullMarkingVerifier verifier(heap());
verifier.Run();
}
#endif
......@@ -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() {
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