package com.oracle.svm.core.config;
import org.graalvm.compiler.api.replacements.Fold;
import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.nativeimage.c.constant.CEnum;
import org.graalvm.util.GuardedAnnotationAccess;
import org.graalvm.word.WordBase;
import com.oracle.svm.core.SubstrateTargetDescription;
import com.oracle.svm.core.annotate.Uninterruptible;
import com.oracle.svm.core.deopt.DeoptimizedFrame;
import jdk.vm.ci.code.CodeUtil;
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaType;
public final class ObjectLayout {
private final SubstrateTargetDescription target;
private final int referenceSize;
private final int objectAlignment;
private final int alignmentMask;
private final int hubOffset;
private final int firstFieldOffset;
private final int arrayLengthOffset;
private final int arrayBaseOffset;
private final int identityHashCodeOffset;
public ObjectLayout(SubstrateTargetDescription target, int referenceSize, int objectAlignment, int hubOffset, int firstFieldOffset, int arrayLengthOffset, int arrayBaseOffset,
int identityHashCodeOffset) {
assert CodeUtil.isPowerOf2(referenceSize);
assert CodeUtil.isPowerOf2(objectAlignment);
assert hubOffset < firstFieldOffset && hubOffset < arrayLengthOffset;
assert identityHashCodeOffset > 0 && identityHashCodeOffset < arrayLengthOffset;
this.target = target;
this.referenceSize = referenceSize;
this.objectAlignment = objectAlignment;
this.alignmentMask = objectAlignment - 1;
this.hubOffset = hubOffset;
this.firstFieldOffset = firstFieldOffset;
this.arrayLengthOffset = arrayLengthOffset;
this.arrayBaseOffset = arrayBaseOffset;
this.identityHashCodeOffset = identityHashCodeOffset;
}
public int getAlignment() {
return objectAlignment;
}
public boolean isAligned(final long value) {
return (value % getAlignment() == 0L);
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public int getReferenceSize() {
return referenceSize;
}
public int getDeoptScratchSpace() {
return target.getDeoptScratchSpace();
}
public int sizeInBytes(JavaKind kind) {
return (kind == JavaKind.Object) ? referenceSize : target.arch.getPlatformKind(kind).getSizeInBytes();
}
public int getArrayIndexShift(JavaKind kind) {
return CodeUtil.log2(getArrayIndexScale(kind));
}
public int getArrayIndexScale(JavaKind kind) {
return sizeInBytes(kind);
}
public int alignUp(int obj) {
return (obj + alignmentMask) & ~alignmentMask;
}
public long alignUp(long obj) {
return (obj + alignmentMask) & ~alignmentMask;
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public int getHubOffset() {
return hubOffset;
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public int getFirstFieldOffset() {
return firstFieldOffset;
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public int getArrayLengthOffset() {
return arrayLengthOffset;
}
@Fold
public int getIdentityHashCodeOffset() {
return identityHashCodeOffset;
}
public int getArrayBaseOffset(JavaKind kind) {
return NumUtil.roundUp(arrayBaseOffset, sizeInBytes(kind));
}
public long getArrayElementOffset(JavaKind kind, int index) {
return getArrayBaseOffset(kind) + index * sizeInBytes(kind);
}
public long getArraySize(JavaKind kind, int length) {
assert length >= 0;
return alignUp(getArrayBaseOffset(kind) + ((long) length << getArrayIndexShift(kind)));
}
public int getMinimumInstanceObjectSize() {
return alignUp(firstFieldOffset);
}
public int getMinimumArraySize() {
return NumUtil.safeToInt(getArraySize(JavaKind.Byte, 0));
}
public int getMinimumObjectSize() {
return Math.min(getMinimumArraySize(), getMinimumInstanceObjectSize());
}
public static JavaKind getCallSignatureKind(boolean isEntryPoint, ResolvedJavaType type, MetaAccessProvider metaAccess, TargetDescription target) {
if (metaAccess.lookupJavaType(WordBase.class).isAssignableFrom(type)) {
return target.wordJavaKind;
}
if (isEntryPoint && GuardedAnnotationAccess.isAnnotationPresent(type, CEnum.class)) {
return JavaKind.Int;
}
return type.getJavaKind();
}
}