package org.graalvm.compiler.core.common.util;
import static org.graalvm.compiler.core.common.util.UnsafeAccess.UNSAFE;
import sun.misc.Unsafe;
public abstract class UnsafeArrayTypeReader implements TypeReader {
public static int getS1(byte[] data, long byteIndex) {
return UNSAFE.getByte(data, readOffset(data, byteIndex, Byte.BYTES));
}
public static int getU1(byte[] data, long byteIndex) {
return UNSAFE.getByte(data, readOffset(data, byteIndex, Byte.BYTES)) & 0xFF;
}
public static int getS2(byte[] data, long byteIndex, boolean supportsUnalignedMemoryAccess) {
if (supportsUnalignedMemoryAccess) {
return UnalignedUnsafeArrayTypeReader.getS2(data, byteIndex);
} else {
return AlignedUnsafeArrayTypeReader.getS2(data, byteIndex);
}
}
public static int getU2(byte[] data, long byteIndex, boolean supportsUnalignedMemoryAccess) {
return getS2(data, byteIndex, supportsUnalignedMemoryAccess) & 0xFFFF;
}
public static int getS4(byte[] data, long byteIndex, boolean supportsUnalignedMemoryAccess) {
if (supportsUnalignedMemoryAccess) {
return UnalignedUnsafeArrayTypeReader.getS4(data, byteIndex);
} else {
return AlignedUnsafeArrayTypeReader.getS4(data, byteIndex);
}
}
public static long getU4(byte[] data, long byteIndex, boolean supportsUnalignedMemoryAccess) {
return getS4(data, byteIndex, supportsUnalignedMemoryAccess) & 0xFFFFFFFFL;
}
public static long getS8(byte[] data, long byteIndex, boolean supportsUnalignedMemoryAccess) {
if (supportsUnalignedMemoryAccess) {
return UnalignedUnsafeArrayTypeReader.getS8(data, byteIndex);
} else {
return AlignedUnsafeArrayTypeReader.getS8(data, byteIndex);
}
}
protected static long readOffset(byte[] data, long byteIndex, int numBytes) {
assert byteIndex >= 0;
assert numBytes > 0;
assert byteIndex + numBytes <= data.length;
assert Unsafe.ARRAY_BYTE_INDEX_SCALE == 1;
return byteIndex + Unsafe.ARRAY_BYTE_BASE_OFFSET;
}
public static UnsafeArrayTypeReader create(byte[] data, long byteIndex, boolean supportsUnalignedMemoryAccess) {
if (supportsUnalignedMemoryAccess) {
return new UnalignedUnsafeArrayTypeReader(data, byteIndex);
} else {
return new AlignedUnsafeArrayTypeReader(data, byteIndex);
}
}
protected final byte[] data;
protected long byteIndex;
protected UnsafeArrayTypeReader(byte[] data, long byteIndex) {
this.data = data;
this.byteIndex = byteIndex;
}
@Override
public long getByteIndex() {
return byteIndex;
}
@Override
public void setByteIndex(long byteIndex) {
this.byteIndex = byteIndex;
}
@Override
public final int getS1() {
int result = getS1(data, byteIndex);
byteIndex += Byte.BYTES;
return result;
}
@Override
public final int getU1() {
int result = getU1(data, byteIndex);
byteIndex += Byte.BYTES;
return result;
}
@Override
public final int getU2() {
return getS2() & 0xFFFF;
}
@Override
public final long getU4() {
return getS4() & 0xFFFFFFFFL;
}
}
final class UnalignedUnsafeArrayTypeReader extends UnsafeArrayTypeReader {
protected static int getS2(byte[] data, long byteIndex) {
return UNSAFE.getShort(data, readOffset(data, byteIndex, Short.BYTES));
}
protected static int getS4(byte[] data, long byteIndex) {
return UNSAFE.getInt(data, readOffset(data, byteIndex, Integer.BYTES));
}
protected static long getS8(byte[] data, long byteIndex) {
return UNSAFE.getLong(data, readOffset(data, byteIndex, Long.BYTES));
}
protected UnalignedUnsafeArrayTypeReader(byte[] data, long byteIndex) {
super(data, byteIndex);
}
@Override
public int getS2() {
int result = getS2(data, byteIndex);
byteIndex += Short.BYTES;
return result;
}
@Override
public int getS4() {
int result = getS4(data, byteIndex);
byteIndex += Integer.BYTES;
return result;
}
@Override
public long getS8() {
long result = getS8(data, byteIndex);
byteIndex += Long.BYTES;
return result;
}
}
class AlignedUnsafeArrayTypeReader extends UnsafeArrayTypeReader {
protected static int getS2(byte[] data, long byteIndex) {
long offset = readOffset(data, byteIndex, Short.BYTES);
return ((UNSAFE.getByte(data, offset + 0) & 0xFF) << 0) |
(UNSAFE.getByte(data, offset + 1) << 8);
}
protected static int getS4(byte[] data, long byteIndex) {
long offset = readOffset(data, byteIndex, Integer.BYTES);
return ((UNSAFE.getByte(data, offset + 0) & 0xFF) << 0) |
((UNSAFE.getByte(data, offset + 1) & 0xFF) << 8) |
((UNSAFE.getByte(data, offset + 2) & 0xFF) << 16) |
(UNSAFE.getByte(data, offset + 3) << 24);
}
protected static long getS8(byte[] data, long byteIndex) {
long offset = readOffset(data, byteIndex, Long.BYTES);
return ((long) ((UNSAFE.getByte(data, offset + 0) & 0xFF)) << 0) |
((long) ((UNSAFE.getByte(data, offset + 1) & 0xFF)) << 8) |
((long) ((UNSAFE.getByte(data, offset + 2) & 0xFF)) << 16) |
((long) ((UNSAFE.getByte(data, offset + 3) & 0xFF)) << 24) |
((long) ((UNSAFE.getByte(data, offset + 4) & 0xFF)) << 32) |
((long) ((UNSAFE.getByte(data, offset + 5) & 0xFF)) << 40) |
((long) ((UNSAFE.getByte(data, offset + 6) & 0xFF)) << 48) |
((long) (UNSAFE.getByte(data, offset + 7)) << 56);
}
protected AlignedUnsafeArrayTypeReader(byte[] data, long byteIndex) {
super(data, byteIndex);
}
@Override
public int getS2() {
int result = getS2(data, byteIndex);
byteIndex += Short.BYTES;
return result;
}
@Override
public int getS4() {
int result = getS4(data, byteIndex);
byteIndex += Integer.BYTES;
return result;
}
@Override
public long getS8() {
long result = getS8(data, byteIndex);
byteIndex += Long.BYTES;
return result;
}
}