package com.oracle.svm.core.heap;
import org.graalvm.word.Pointer;
import org.graalvm.word.UnsignedWord;
import org.graalvm.word.WordFactory;
import com.oracle.svm.core.annotate.AlwaysInline;
import com.oracle.svm.core.annotate.DuplicatedInNativeCode;
import com.oracle.svm.core.c.NonmovableArray;
import com.oracle.svm.core.code.CodeInfoQueryResult;
import com.oracle.svm.core.config.ConfigurationValues;
import com.oracle.svm.core.util.NonmovableByteArrayReader;
import com.oracle.svm.core.util.TypedMemoryReader;
@DuplicatedInNativeCode
public class InstanceReferenceMapDecoder {
@AlwaysInline("de-virtualize calls to ObjectReferenceVisitor")
public static boolean walkOffsetsFromPointer(Pointer baseAddress, NonmovableArray<Byte> referenceMapEncoding, long referenceMapIndex, ObjectReferenceVisitor visitor, Object holderObject) {
assert referenceMapIndex >= CodeInfoQueryResult.EMPTY_REFERENCE_MAP;
assert referenceMapEncoding.isNonNull();
Pointer position = NonmovableByteArrayReader.pointerTo(referenceMapEncoding, referenceMapIndex);
int entryCount = TypedMemoryReader.getS4(position);
position = position.add(4);
int referenceSize = ConfigurationValues.getObjectLayout().getReferenceSize();
boolean compressed = ReferenceAccess.singleton().haveCompressedReferences();
assert entryCount >= 0;
UnsignedWord sizeOfEntries = WordFactory.unsigned(InstanceReferenceMapEncoder.MAP_ENTRY_SIZE).multiply(entryCount);
Pointer end = position.add(sizeOfEntries);
while (position.belowThan(end)) {
int offset = TypedMemoryReader.getS4(position);
position = position.add(4);
long count = TypedMemoryReader.getU4(position);
position = position.add(4);
Pointer objRef = baseAddress.add(offset);
for (int c = 0; c < count; c++) {
final boolean visitResult = visitor.visitObjectReferenceInline(objRef, 0, compressed, holderObject);
if (!visitResult) {
return false;
}
objRef = objRef.add(referenceSize);
}
}
return true;
}
}