package com.oracle.svm.core.genscavenge;
import org.graalvm.word.WordFactory;
import com.oracle.svm.core.log.Log;
final class SpaceVerifier {
private Space space;
SpaceVerifier() {
}
public void initialize(Space s) {
this.space = s;
}
public boolean verify() {
Log trace = HeapVerifier.getTraceLog();
trace.string("[SpaceVerifier.verify:").string(" ").string(space.getName()).newline();
boolean isTLASpace = ThreadLocalAllocation.isThreadLocalAllocationSpace(space);
if (isTLASpace) {
ThreadLocalAllocation.disableAndFlushForAllThreads();
}
boolean result = true;
if (!verifyChunkLists()) {
HeapImpl.getHeapImpl().getHeapVerifier().getWitnessLog().string("verifyChunkLists() returns false").string("]").newline();
result = false;
}
if (result && !verifyChunks()) {
HeapImpl.getHeapImpl().getHeapVerifier().getWitnessLog().string("[SpaceVerifier.verify:").string(" verifyChunks fails").string("]").newline();
result = false;
}
trace.string(" returns: ").bool(result).string("]").newline();
return result;
}
boolean containsChunks() {
AlignedHeapChunk.AlignedHeader aChunk = space.getFirstAlignedHeapChunk();
UnalignedHeapChunk.UnalignedHeader uChunk = space.getFirstUnalignedHeapChunk();
return (aChunk.isNonNull() || uChunk.isNonNull());
}
private boolean verifyChunkLists() {
Log trace = HeapVerifier.getTraceLog();
trace.string("[SpaceVerifier.verifyChunkLists:");
boolean result = verifyAlignedChunkList() && verifyUnalignedChunkList();
trace.string(" returns: ").bool(result);
trace.string("]").newline();
return result;
}
private boolean verifyAlignedChunkList() {
Log trace = HeapVerifier.getTraceLog().string("[SpaceVerifier.verifyAlignedChunkList:");
trace.string(" Space: ").string(space.getName()).newline();
boolean result = true;
AlignedHeapChunk.AlignedHeader current = space.getFirstAlignedHeapChunk();
AlignedHeapChunk.AlignedHeader previous = WordFactory.nullPointer();
while (current.isNonNull()) {
AlignedHeapChunk.AlignedHeader previousOfCurrent = HeapChunk.getPrevious(current);
result &= previousOfCurrent.equal(previous);
if (!result) {
Log failure = HeapImpl.getHeapImpl().getHeapVerifier().getWitnessLog().string("[SpaceVerifier.verifyAlignedChunkList:");
failure.string(" space: ").string(space.getName()).string(" doubly-linked list failure").newline();
failure.string(" current: ").hex(current);
failure.string(" current.previous: ").hex(previousOfCurrent);
failure.string(" previous: ").hex(previous);
failure.string("]").newline();
break;
}
previous = current;
current = HeapChunk.getNext(current);
}
result &= previous.equal(space.getLastAlignedHeapChunk());
if (!result) {
Log failure = HeapImpl.getHeapImpl().getHeapVerifier().getWitnessLog().string("[SpaceVerifier.verifyAlignedChunkList:");
failure.string(" space: ").string(space.getName()).string(" lastAlignedHeapChunk failure").string("]").newline();
failure.string(" previous: ").hex(previous);
failure.string(" lastAlignedHeapChunk: ").hex(space.getLastAlignedHeapChunk());
failure.string("]").newline();
result = false;
}
trace.string(" returns: ").bool(result).string("]").newline();
return result;
}
private boolean verifyUnalignedChunkList() {
Log trace = HeapVerifier.getTraceLog().string("[SpaceVerifier.verifyUnalignedChunkList:");
boolean result = true;
UnalignedHeapChunk.UnalignedHeader current = space.getFirstUnalignedHeapChunk();
UnalignedHeapChunk.UnalignedHeader previous = WordFactory.nullPointer();
while (current.isNonNull()) {
result &= HeapChunk.getPrevious(current).equal(previous);
if (!result) {
Log failure = HeapImpl.getHeapImpl().getHeapVerifier().getWitnessLog().string("[SpaceVerifier.verifyUnalignedChunkList:");
failure.string(" space: ").string(space.getName()).string(" doubly-linked list failure").string("]").newline();
break;
}
previous = current;
current = HeapChunk.getNext(current);
}
result &= previous.equal(space.getLastUnalignedHeapChunk());
if (!result) {
Log failure = HeapImpl.getHeapImpl().getHeapVerifier().getWitnessLog().string("[SpaceVerifier.verifyUnalignedChunkList:");
failure.string(" space: ").string(space.getName()).string(" lastUnalignedHeapChunk failure").string("]").newline();
result = false;
}
trace.string(" returns: ").bool(result).string("]").newline();
return result;
}
private boolean verifyChunks() {
Log trace = HeapVerifier.getTraceLog().string("[SpaceVerifier.verifyChunks:");
boolean result = verifyAlignedChunks() && verifyUnalignedChunks();
trace.string(" returns: ").bool(result).string("]").newline();
return result;
}
private boolean verifyAlignedChunks() {
Log trace = HeapVerifier.getTraceLog().string("[SpaceVerifier.verifyAlignedChunks:");
boolean result = true;
AlignedHeapChunk.AlignedHeader chunk = space.getFirstAlignedHeapChunk();
while (chunk.isNonNull()) {
result &= AlignedHeapChunk.verify(chunk);
chunk = HeapChunk.getNext(chunk);
}
trace.string(" returns: ").bool(result).string("]").newline();
return result;
}
private boolean verifyUnalignedChunks() {
Log trace = HeapVerifier.getTraceLog().string("[SpaceVerifier.verifyUnalignedChunks:");
boolean result = true;
UnalignedHeapChunk.UnalignedHeader chunk = space.getFirstUnalignedHeapChunk();
while (chunk.isNonNull()) {
result &= UnalignedHeapChunk.verify(chunk);
chunk = HeapChunk.getNext(chunk);
}
trace.string(" returns: ").bool(result).string("]").newline();
return result;
}
boolean verifyOnlyCleanCards() {
Log trace = HeapVerifier.getTraceLog().string("[SpaceVerifier.verifyOnlyCleanCards:");
trace.string(" space: ").string(space.getName()).newline();
boolean result = verifyOnlyCleanAlignedChunks() && verifyOnlyCleanUnalignedChunks();
trace.string(" returns: ").bool(result).string("]").newline();
return result;
}
private boolean verifyOnlyCleanAlignedChunks() {
Log trace = HeapVerifier.getTraceLog().string("[SpaceVerifier.verifyOnlyCleanAlignedChunks:").newline();
boolean result = true;
AlignedHeapChunk.AlignedHeader chunk = space.getFirstAlignedHeapChunk();
while (chunk.isNonNull()) {
result &= AlignedHeapChunk.verifyOnlyCleanCards(chunk);
chunk = HeapChunk.getNext(chunk);
}
trace.string(" returns: ").bool(result).string("]").newline();
return result;
}
private boolean verifyOnlyCleanUnalignedChunks() {
Log trace = HeapVerifier.getTraceLog().string("[SpaceVerifier.verifyOnlyCleanUnalignedChunks:").newline();
boolean result = true;
UnalignedHeapChunk.UnalignedHeader chunk = space.getFirstUnalignedHeapChunk();
while (chunk.isNonNull()) {
result &= UnalignedHeapChunk.verifyOnlyCleanCards(chunk);
chunk = HeapChunk.getNext(chunk);
}
trace.string(" returns: ").bool(result).string("]").newline();
return result;
}
}