package com.oracle.svm.core.genscavenge;
import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FREQUENT_PROBABILITY;
import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LUDICROUSLY_SLOW_PATH_PROBABILITY;
import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
import org.graalvm.compiler.word.Word;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.word.Pointer;
import org.graalvm.word.UnsignedWord;
import org.graalvm.word.WordFactory;
import com.oracle.svm.core.MemoryWalker;
import com.oracle.svm.core.SubstrateOptions;
import com.oracle.svm.core.annotate.Uninterruptible;
import com.oracle.svm.core.config.ConfigurationValues;
import com.oracle.svm.core.genscavenge.GCImpl.ChunkReleaser;
import com.oracle.svm.core.heap.ObjectVisitor;
import com.oracle.svm.core.hub.LayoutEncoding;
import com.oracle.svm.core.log.Log;
import com.oracle.svm.core.thread.VMOperation;
import com.oracle.svm.core.thread.VMThreads;
import com.oracle.svm.core.util.VMError;
final class Space {
private final String name;
private final boolean isFromSpace;
private final int age;
private final SpaceAccounting accounting;
private AlignedHeapChunk.AlignedHeader firstAlignedHeapChunk;
private AlignedHeapChunk.AlignedHeader lastAlignedHeapChunk;
private UnalignedHeapChunk.UnalignedHeader firstUnalignedHeapChunk;
private UnalignedHeapChunk.UnalignedHeader lastUnalignedHeapChunk;
@Platforms(Platform.HOSTED_ONLY.class)
Space(String name, boolean isFromSpace, int age) {
this.name = name;
assert name != null : "Space name should not be null.";
this.isFromSpace = isFromSpace;
this.age = age;
this.accounting = new SpaceAccounting();
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public String getName() {
return name;
}
public boolean isEmpty() {
return (getFirstAlignedHeapChunk().isNull() && getFirstUnalignedHeapChunk().isNull());
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
void tearDown() {
HeapChunkProvider.freeAlignedChunkList(getFirstAlignedHeapChunk());
HeapChunkProvider.freeUnalignedChunkList(getFirstUnalignedHeapChunk());
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
boolean isEdenSpace() {
return age == 0;
}
boolean isYoungSpace() {
return age <= HeapPolicy.getMaxSurvivorSpaces();
}
boolean isSurvivorSpace() {
return age > 0 && age <= HeapPolicy.getMaxSurvivorSpaces();
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
boolean isOldSpace() {
return age == (HeapPolicy.getMaxSurvivorSpaces() + 1);
}
int getAge() {
return age;
}
int getNextAgeForPromotion() {
return age + 1;
}
boolean isFromSpace() {
return isFromSpace;
}
public boolean walkObjects(ObjectVisitor visitor) {
AlignedHeapChunk.AlignedHeader aChunk = getFirstAlignedHeapChunk();
while (aChunk.isNonNull()) {
if (!AlignedHeapChunk.walkObjects(aChunk, visitor)) {
return false;
}
aChunk = HeapChunk.getNext(aChunk);
}
UnalignedHeapChunk.UnalignedHeader uChunk = getFirstUnalignedHeapChunk();
while (uChunk.isNonNull()) {
if (!UnalignedHeapChunk.walkObjects(uChunk, visitor)) {
return false;
}
uChunk = HeapChunk.getNext(uChunk);
}
return true;
}
public boolean walkDirtyObjects(ObjectVisitor visitor, boolean clean) {
Log trace = Log.noopLog().string("[Space.walkDirtyObjects:");
trace.string(" space: ").string(getName()).string(" clean: ").bool(clean);
AlignedHeapChunk.AlignedHeader aChunk = getFirstAlignedHeapChunk();
while (aChunk.isNonNull()) {
trace.newline().string(" aChunk: ").hex(aChunk);
if (!AlignedHeapChunk.walkDirtyObjects(aChunk, visitor, clean)) {
Log failureLog = Log.log().string("[Space.walkDirtyObjects:");
failureLog.string(" aChunk.walkDirtyObjects fails").string("]").newline();
return false;
}
aChunk = HeapChunk.getNext(aChunk);
}
UnalignedHeapChunk.UnalignedHeader uChunk = getFirstUnalignedHeapChunk();
while (uChunk.isNonNull()) {
trace.newline().string(" uChunk: ").hex(uChunk);
if (!UnalignedHeapChunk.walkDirtyObjects(uChunk, visitor, clean)) {
Log failureLog = Log.log().string("[Space.walkDirtyObjects:");
failureLog.string(" uChunk.walkDirtyObjects fails").string("]").newline();
return false;
}
uChunk = HeapChunk.getNext(uChunk);
}
trace.string("]").newline();
return true;
}
public Log report(Log log, boolean traceHeapChunks) {
log.string("[").string(getName()).string(":").indent(true);
accounting.report(log);
if (traceHeapChunks) {
if (getFirstAlignedHeapChunk().isNonNull()) {
log.newline().string("aligned chunks:").redent(true);
for (AlignedHeapChunk.AlignedHeader aChunk = getFirstAlignedHeapChunk(); aChunk.isNonNull(); aChunk = HeapChunk.getNext(aChunk)) {
log.newline().hex(aChunk).string(" (").hex(AlignedHeapChunk.getObjectsStart(aChunk)).string("-").hex(HeapChunk.getTopPointer(aChunk)).string(")");
}
log.redent(false);
}
if (getFirstUnalignedHeapChunk().isNonNull()) {
log.newline().string("unaligned chunks:").redent(true);
for (UnalignedHeapChunk.UnalignedHeader uChunk = getFirstUnalignedHeapChunk(); uChunk.isNonNull(); uChunk = HeapChunk.getNext(uChunk)) {
log.newline().hex(uChunk).string(" (").hex(UnalignedHeapChunk.getObjectStart(uChunk)).string("-").hex(HeapChunk.getTopPointer(uChunk)).string(")");
}
log.redent(false);
}
}
log.redent(false).string("]");
return log;
}
private Pointer allocateMemory(UnsignedWord objectSize) {
Log trace = Log.noopLog().string("[Space.allocateMemory:").string(" space: ").string(getName()).string(" size: ").unsigned(objectSize).newline();
Pointer result = WordFactory.nullPointer();
AlignedHeapChunk.AlignedHeader oldChunk = getLastAlignedHeapChunk();
trace.string(" oldChunk: ").hex(oldChunk);
if (oldChunk.isNonNull()) {
result = AlignedHeapChunk.allocateMemory(oldChunk, objectSize);
trace.string(" oldChunk provides: ").hex(result);
}
if (result.isNull()) {
AlignedHeapChunk.AlignedHeader newChunk = requestAlignedHeapChunk();
trace.string(" newChunk: ").hex(newChunk);
if (newChunk.isNonNull()) {
result = AlignedHeapChunk.allocateMemory(newChunk, objectSize);
if (isSurvivorSpace()) {
trace.string(" newSurvivorChunk provides: ").hex(result);
} else {
trace.string(" newChunk provides: ").hex(result);
}
}
}
trace.string(" returns: ").hex(result).string("]").newline();
return result;
}
void promoteObjectChunk(Object original) {
if (ObjectHeaderImpl.isAlignedObject(original)) {
AlignedHeapChunk.AlignedHeader aChunk = AlignedHeapChunk.getEnclosingChunk(original);
Space originalSpace = HeapChunk.getSpace(aChunk);
if (originalSpace.isFromSpace()) {
promoteAlignedHeapChunk(aChunk, originalSpace);
}
} else {
assert ObjectHeaderImpl.isUnalignedObject(original);
UnalignedHeapChunk.UnalignedHeader uChunk = UnalignedHeapChunk.getEnclosingChunk(original);
Space originalSpace = HeapChunk.getSpace(uChunk);
if (originalSpace.isFromSpace()) {
promoteUnalignedHeapChunk(uChunk, originalSpace);
}
}
}
public void releaseChunks(ChunkReleaser chunkReleaser) {
chunkReleaser.add(firstAlignedHeapChunk);
chunkReleaser.add(firstUnalignedHeapChunk);
firstAlignedHeapChunk = WordFactory.nullPointer();
lastAlignedHeapChunk = WordFactory.nullPointer();
firstUnalignedHeapChunk = WordFactory.nullPointer();
lastUnalignedHeapChunk = WordFactory.nullPointer();
accounting.reset();
}
void cleanRememberedSet() {
cleanRememberedSetAlignedHeapChunks();
cleanRememberedSetUnalignedHeapChunks();
}
private void cleanRememberedSetAlignedHeapChunks() {
Log trace = Log.noopLog().string("[Space.cleanRememberedSetAlignedHeapChunks:").string(" space: ").string(getName());
AlignedHeapChunk.AlignedHeader aChunk = getFirstAlignedHeapChunk();
while (aChunk.isNonNull()) {
trace.newline().string(" aChunk: ").hex(aChunk);
AlignedHeapChunk.cleanRememberedSet(aChunk);
aChunk = HeapChunk.getNext(aChunk);
}
trace.string("]").newline();
}
private void cleanRememberedSetUnalignedHeapChunks() {
Log trace = Log.noopLog().string("[Space.cleanRememberedSetUnalignedHeapChunks:").string(" space: ").string(getName());
UnalignedHeapChunk.UnalignedHeader uChunk = getFirstUnalignedHeapChunk();
while (uChunk.isNonNull()) {
trace.newline().string(" uChunk: ").hex(uChunk);
UnalignedHeapChunk.cleanRememberedSet(uChunk);
uChunk = HeapChunk.getNext(uChunk);
}
trace.string("]").newline();
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
void (AlignedHeapChunk.AlignedHeader aChunk) {
if (SubstrateOptions.MultiThreaded.getValue()) {
VMThreads.guaranteeOwnsThreadMutex("Trying to append an aligned heap chunk but no mutual exclusion.");
}
appendAlignedHeapChunkUninterruptibly(aChunk);
accounting.noteAlignedHeapChunk(aChunk);
}
@Uninterruptible(reason = "Must not interact with garbage collections.")
private void (AlignedHeapChunk.AlignedHeader aChunk) {
AlignedHeapChunk.AlignedHeader oldLast = getLastAlignedHeapChunk();
HeapChunk.setSpace(aChunk, this);
HeapChunk.setPrevious(aChunk, oldLast);
HeapChunk.setNext(aChunk, WordFactory.nullPointer());
if (oldLast.isNonNull()) {
HeapChunk.setNext(oldLast, aChunk);
}
setLastAlignedHeapChunk(aChunk);
if (getFirstAlignedHeapChunk().isNull()) {
setFirstAlignedHeapChunk(aChunk);
}
}
void (AlignedHeapChunk.AlignedHeader aChunk) {
assert VMOperation.isGCInProgress() : "Should only be called by the collector.";
extractAlignedHeapChunkUninterruptibly(aChunk);
accounting.unnoteAlignedHeapChunk(aChunk);
}
@Uninterruptible(reason = "Must not interact with garbage collections.")
private void (AlignedHeapChunk.AlignedHeader aChunk) {
AlignedHeapChunk.AlignedHeader chunkNext = HeapChunk.getNext(aChunk);
AlignedHeapChunk.AlignedHeader chunkPrev = HeapChunk.getPrevious(aChunk);
if (chunkPrev.isNonNull()) {
HeapChunk.setNext(chunkPrev, chunkNext);
} else {
setFirstAlignedHeapChunk(chunkNext);
}
if (chunkNext.isNonNull()) {
HeapChunk.setPrevious(chunkNext, chunkPrev);
} else {
setLastAlignedHeapChunk(chunkPrev);
}
HeapChunk.setNext(aChunk, WordFactory.nullPointer());
HeapChunk.setPrevious(aChunk, WordFactory.nullPointer());
HeapChunk.setSpace(aChunk, null);
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
void (UnalignedHeapChunk.UnalignedHeader uChunk) {
if (SubstrateOptions.MultiThreaded.getValue()) {
VMThreads.guaranteeOwnsThreadMutex("Trying to append an unaligned chunk but no mutual exclusion.");
}
appendUnalignedHeapChunkUninterruptibly(uChunk);
accounting.noteUnalignedHeapChunk(uChunk);
}
@Uninterruptible(reason = "Must not interact with garbage collections.")
private void (UnalignedHeapChunk.UnalignedHeader uChunk) {
UnalignedHeapChunk.UnalignedHeader oldLast = getLastUnalignedHeapChunk();
HeapChunk.setSpace(uChunk, this);
HeapChunk.setPrevious(uChunk, oldLast);
HeapChunk.setNext(uChunk, WordFactory.nullPointer());
if (oldLast.isNonNull()) {
HeapChunk.setNext(oldLast, uChunk);
}
setLastUnalignedHeapChunk(uChunk);
if (getFirstUnalignedHeapChunk().isNull()) {
setFirstUnalignedHeapChunk(uChunk);
}
}
void (UnalignedHeapChunk.UnalignedHeader uChunk) {
assert VMOperation.isGCInProgress() : "Trying to extract an unaligned chunk but not in a VMOperation.";
extractUnalignedHeapChunkUninterruptibly(uChunk);
accounting.unnoteUnalignedHeapChunk(uChunk);
}
@Uninterruptible(reason = "Must not interact with garbage collections.")
private void (UnalignedHeapChunk.UnalignedHeader uChunk) {
UnalignedHeapChunk.UnalignedHeader chunkNext = HeapChunk.getNext(uChunk);
UnalignedHeapChunk.UnalignedHeader chunkPrev = HeapChunk.getPrevious(uChunk);
if (chunkPrev.isNonNull()) {
HeapChunk.setNext(chunkPrev, chunkNext);
} else {
setFirstUnalignedHeapChunk(chunkNext);
}
if (chunkNext.isNonNull()) {
HeapChunk.setPrevious(chunkNext, chunkPrev);
} else {
setLastUnalignedHeapChunk(chunkPrev);
}
HeapChunk.setNext(uChunk, WordFactory.nullPointer());
HeapChunk.setPrevious(uChunk, WordFactory.nullPointer());
HeapChunk.setSpace(uChunk, null);
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
AlignedHeapChunk.AlignedHeader getFirstAlignedHeapChunk() {
return firstAlignedHeapChunk;
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
private void (AlignedHeapChunk.AlignedHeader chunk) {
firstAlignedHeapChunk = chunk;
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
AlignedHeapChunk.AlignedHeader getLastAlignedHeapChunk() {
return lastAlignedHeapChunk;
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
private void (AlignedHeapChunk.AlignedHeader chunk) {
lastAlignedHeapChunk = chunk;
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
UnalignedHeapChunk.UnalignedHeader getFirstUnalignedHeapChunk() {
return firstUnalignedHeapChunk;
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
private void (UnalignedHeapChunk.UnalignedHeader chunk) {
this.firstUnalignedHeapChunk = chunk;
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
UnalignedHeapChunk.UnalignedHeader getLastUnalignedHeapChunk() {
return lastUnalignedHeapChunk;
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
private void (UnalignedHeapChunk.UnalignedHeader chunk) {
lastUnalignedHeapChunk = chunk;
}
Object promoteAlignedObject(Object original, Space originalSpace) {
assert ObjectHeaderImpl.isAlignedObject(original);
assert this != originalSpace && originalSpace.isFromSpace();
if (HeapOptions.TraceObjectPromotion.getValue()) {
Log.log().string("[promoteAlignedObject:").string(" obj: ").object(original).string(" fromSpace: ").string(originalSpace.getName()).string(" toSpace: ").string(this.getName())
.string(" size: ").unsigned(LayoutEncoding.getSizeFromObject(original)).string("]").newline();
}
Object copy = copyAlignedObject(original);
ObjectHeaderImpl.installForwardingPointer(original, copy);
return copy;
}
private Object copyAlignedObject(Object originalObj) {
assert VMOperation.isGCInProgress();
assert ObjectHeaderImpl.isAlignedObject(originalObj);
UnsignedWord size = LayoutEncoding.getSizeFromObject(originalObj);
Pointer copyMemory = allocateMemory(size);
if (probability(LUDICROUSLY_SLOW_PATH_PROBABILITY, copyMemory.isNull())) {
Log failureLog = Log.log().string("[! Space.copyAlignedObject:").indent(true);
failureLog.string(" failure to allocate ").unsigned(size).string(" bytes").newline();
failureLog.string(" object to be promoted: ").object(originalObj).string(" header ").hex(ObjectHeaderImpl.readHeaderFromObject(originalObj)).newline();
failureLog.string(" !]").indent(false);
throw VMError.shouldNotReachHere("Promotion failure");
}
Pointer originalMemory = Word.objectToUntrackedPointer(originalObj);
UnsignedWord offset = WordFactory.zero();
while (probability(FREQUENT_PROBABILITY, offset.belowThan(size))) {
copyMemory.writeWord(offset, originalMemory.readWord(offset));
offset = offset.add(ConfigurationValues.getTarget().wordSize);
}
Object copy = copyMemory.toObject();
AlignedHeapChunk.AlignedHeader copyChunk = AlignedHeapChunk.getEnclosingChunk(copy);
if (HeapChunk.getSpace(copyChunk).isOldSpace()) {
AlignedHeapChunk.setUpRememberedSetForObject(copyChunk, copy);
}
return copy;
}
private void (AlignedHeapChunk.AlignedHeader chunk, Space originalSpace) {
assert this != originalSpace && originalSpace.isFromSpace();
if (HeapOptions.TraceObjectPromotion.getValue()) {
Log.log().string("[promoteAlignedHeapChunk:").string(" chunk: ").hex(chunk).string(" fromSpace: ").string(originalSpace.getName()).string(" toSpace: ").string(this.getName())
.string("]").newline();
}
originalSpace.extractAlignedHeapChunk(chunk);
appendAlignedHeapChunk(chunk);
if (isOldSpace() && originalSpace.isYoungSpace()) {
AlignedHeapChunk.constructRememberedSet(chunk);
}
}
void (UnalignedHeapChunk.UnalignedHeader chunk, Space originalSpace) {
assert this != originalSpace && originalSpace.isFromSpace();
if (HeapOptions.TraceObjectPromotion.getValue()) {
Log.log().string("[promoteUnalignedHeapChunk:").string(" chunk: ").hex(chunk).string(" fromSpace: ").string(originalSpace.getName()).string(" toSpace: ").string(this.getName())
.string("]").newline();
}
originalSpace.extractUnalignedHeapChunk(chunk);
appendUnalignedHeapChunk(chunk);
if (this.isOldSpace()) {
UnalignedHeapChunk.setUpRememberedSet(chunk);
}
}
private AlignedHeapChunk.AlignedHeader requestAlignedHeapChunk() {
assert VMOperation.isGCInProgress() : "Should only be called from the collector.";
Log trace = Log.noopLog().string("[Space.requestAlignedHeapChunk:").string(" space: ").string(getName()).newline();
AlignedHeapChunk.AlignedHeader aChunk = HeapImpl.getChunkProvider().produceAlignedChunk();
trace.string(" aChunk: ").hex(aChunk);
if (aChunk.isNonNull()) {
appendAlignedHeapChunk(aChunk);
}
trace.string(" Space.requestAlignedHeapChunk returns: ").hex(aChunk).string("]").newline();
return aChunk;
}
void absorb(Space src) {
AlignedHeapChunk.AlignedHeader aChunk = src.getFirstAlignedHeapChunk();
while (aChunk.isNonNull()) {
AlignedHeapChunk.AlignedHeader next = HeapChunk.getNext(aChunk);
src.extractAlignedHeapChunk(aChunk);
appendAlignedHeapChunk(aChunk);
aChunk = next;
}
UnalignedHeapChunk.UnalignedHeader uChunk = src.getFirstUnalignedHeapChunk();
while (uChunk.isNonNull()) {
UnalignedHeapChunk.UnalignedHeader next = HeapChunk.getNext(uChunk);
src.extractUnalignedHeapChunk(uChunk);
appendUnalignedHeapChunk(uChunk);
uChunk = next;
}
}
boolean walkHeapChunks(MemoryWalker.Visitor visitor) {
boolean continueVisiting = true;
AlignedHeapChunk.AlignedHeader aChunk = getFirstAlignedHeapChunk();
while (continueVisiting && aChunk.isNonNull()) {
continueVisiting = visitor.visitHeapChunk(aChunk, AlignedHeapChunk.getMemoryWalkerAccess());
aChunk = HeapChunk.getNext(aChunk);
}
UnalignedHeapChunk.UnalignedHeader uChunk = getFirstUnalignedHeapChunk();
while (continueVisiting && uChunk.isNonNull()) {
continueVisiting = visitor.visitHeapChunk(uChunk, UnalignedHeapChunk.getMemoryWalkerAccess());
uChunk = HeapChunk.getNext(uChunk);
}
return continueVisiting;
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
UnsignedWord getChunkBytes() {
assert !isEdenSpace() || VMOperation.isGCInProgress() : "eden data is only accurate during a GC";
return accounting.getAlignedChunkBytes().add(accounting.getUnalignedChunkBytes());
}
UnsignedWord computeObjectBytes() {
assert !isEdenSpace() || VMOperation.isGCInProgress() : "eden data is only accurate during a GC";
return computeAlignedObjectBytes().add(computeUnalignedObjectBytes());
}
private UnsignedWord computeAlignedObjectBytes() {
UnsignedWord result = WordFactory.zero();
AlignedHeapChunk.AlignedHeader aChunk = getFirstAlignedHeapChunk();
while (aChunk.isNonNull()) {
UnsignedWord allocatedBytes = HeapChunk.getTopOffset(aChunk).subtract(AlignedHeapChunk.getObjectsStartOffset());
result = result.add(allocatedBytes);
aChunk = HeapChunk.getNext(aChunk);
}
return result;
}
private UnsignedWord computeUnalignedObjectBytes() {
UnsignedWord result = WordFactory.zero();
UnalignedHeapChunk.UnalignedHeader uChunk = getFirstUnalignedHeapChunk();
while (uChunk.isNonNull()) {
UnsignedWord allocatedBytes = HeapChunk.getTopOffset(uChunk).subtract(UnalignedHeapChunk.getObjectStartOffset());
result = result.add(allocatedBytes);
uChunk = HeapChunk.getNext(uChunk);
}
return result;
}
public void verifyDirtyCards() {
AlignedHeapChunk.AlignedHeader aChunk = getFirstAlignedHeapChunk();
while (aChunk.isNonNull()) {
if (!CardTable.verify(AlignedHeapChunk.getCardTableStart(aChunk),
AlignedHeapChunk.getFirstObjectTableStart(aChunk),
AlignedHeapChunk.getObjectsStart(aChunk),
HeapChunk.getTopPointer(aChunk))) {
Log.log().string("AlignedChunk card verification failed!").newline();
Log.log().flush();
}
aChunk = HeapChunk.getNext(aChunk);
}
}
}
final class SpaceAccounting {
private long alignedCount;
private UnsignedWord alignedChunkBytes;
private long unalignedCount;
private UnsignedWord unalignedChunkBytes;
@Platforms(Platform.HOSTED_ONLY.class)
SpaceAccounting() {
reset();
}
public void reset() {
alignedCount = 0L;
alignedChunkBytes = WordFactory.zero();
unalignedCount = 0L;
unalignedChunkBytes = WordFactory.zero();
}
public UnsignedWord getChunkBytes() {
return getAlignedChunkBytes().add(getUnalignedChunkBytes());
}
public long getAlignedChunkCount() {
return alignedCount;
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public UnsignedWord getAlignedChunkBytes() {
return alignedChunkBytes;
}
public long getUnalignedChunkCount() {
return unalignedCount;
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public UnsignedWord getUnalignedChunkBytes() {
return unalignedChunkBytes;
}
void report(Log reportLog) {
reportLog.string("aligned: ").unsigned(alignedChunkBytes).string("/").unsigned(alignedCount);
reportLog.string(" ");
reportLog.string("unaligned: ").unsigned(unalignedChunkBytes).string("/").unsigned(unalignedCount);
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
void (AlignedHeapChunk.AlignedHeader chunk) {
UnsignedWord size = AlignedHeapChunk.getCommittedObjectMemory(chunk);
alignedCount += 1;
alignedChunkBytes = alignedChunkBytes.add(size);
}
void (AlignedHeapChunk.AlignedHeader chunk) {
UnsignedWord size = AlignedHeapChunk.getCommittedObjectMemory(chunk);
alignedCount -= 1;
alignedChunkBytes = alignedChunkBytes.subtract(size);
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
void (UnalignedHeapChunk.UnalignedHeader chunk) {
UnsignedWord size = UnalignedHeapChunk.getCommittedObjectMemory(chunk);
unalignedCount += 1;
unalignedChunkBytes = unalignedChunkBytes.add(size);
}
void (UnalignedHeapChunk.UnalignedHeader chunk) {
UnsignedWord size = UnalignedHeapChunk.getCommittedObjectMemory(chunk);
unalignedCount -= 1;
unalignedChunkBytes = unalignedChunkBytes.subtract(size);
}
}