src/java.base/share/classes/sun/misc/Unsafe.java
Print this page
@@ -1141,6 +1141,319 @@
*/
private static void throwIllegalAccessError() {
throw new IllegalAccessError();
}
+ public final static boolean LITTLE_ENDIAN = false;
+ public final static boolean BIG_ENDIAN = true;
+
+ public native boolean getByteOrder();
+
+ public native boolean unalignedAccess();
+
+ public long getLongUnaligned(Object o, long offset) {
+ if ((offset & 7) == 0) {
+ return getLong(o, offset);
+ } else if ((offset & 3) == 0) {
+ return mem.makeLong(getInt(o, offset),
+ getInt(o, offset + 4));
+ } else if ((offset & 1) == 0) {
+ return mem.makeLong(getShort(o, offset),
+ getShort(o, offset + 2),
+ getShort(o, offset + 4),
+ getShort(o, offset + 6));
+ } else {
+ return mem.makeLong(getByte(o, offset),
+ getByte(o, offset + 1),
+ getByte(o, offset + 2),
+ getByte(o, offset + 3),
+ getByte(o, offset + 4),
+ getByte(o, offset + 5),
+ getByte(o, offset + 6),
+ getByte(o, offset + 7));
+}
+ }
+ public long getLongUnaligned(Object o, long offset, boolean bigEndian) {
+ return mem.fromEndian(bigEndian, getLongUnaligned(o, offset));
+ }
+
+ public int getIntUnaligned(Object o, long offset) {
+ if ((offset & 3) == 0) {
+ return getInt(o, offset);
+ } else if ((offset & 1) == 0) {
+ return mem.makeInt(getShort(o, offset),
+ getShort(o, offset + 2));
+ } else {
+ return mem.makeInt(getByte(o, offset),
+ getByte(o, offset + 1),
+ getByte(o, offset + 2),
+ getByte(o, offset + 3));
+ }
+ }
+ public int getIntUnaligned(Object o, long offset, boolean bigEndian) {
+ return mem.fromEndian(bigEndian, getIntUnaligned(o, offset));
+ }
+
+ public short getShortUnaligned(Object o, long offset) {
+ if ((offset & 1) == 0) {
+ return getShort(o, offset);
+ } else {
+ return mem.makeShort(getByte(o, offset),
+ getByte(o, offset + 1));
+ }
+ }
+ public short getShortUnaligned(Object o, long offset, boolean bigEndian) {
+ return mem.fromEndian(bigEndian, getShortUnaligned(o, offset));
+ }
+
+ public char getCharUnaligned(Object o, long offset) {
+ return (char)getShortUnaligned(o, offset);
+ }
+ public char getCharUnaligned(Object o, long offset, boolean bigEndian) {
+ return mem.fromEndian(bigEndian, getCharUnaligned(o, offset));
+ }
+
+ public void putLongUnaligned(Object o, long offset, long x) {
+ if ((offset & 7) == 0) {
+ putLong(o, offset, x);
+ } else if ((offset & 3) == 0) {
+ mem.putLongParts(this, o, offset,
+ (int)(x >> 0),
+ (int)(x >>> 32));
+ } else if ((offset & 1) == 0) {
+ mem.putLongParts(this, o, offset,
+ (short)(x >>> 0),
+ (short)(x >>> 16),
+ (short)(x >>> 32),
+ (short)(x >>> 48));
+ } else {
+ mem.putLongParts(this, o, offset,
+ (byte)(x >>> 0),
+ (byte)(x >>> 8),
+ (byte)(x >>> 16),
+ (byte)(x >>> 24),
+ (byte)(x >>> 32),
+ (byte)(x >>> 40),
+ (byte)(x >>> 48),
+ (byte)(x >>> 56));
+ }
+ }
+
+ public void putIntUnaligned(Object o, long offset, int x) {
+ if ((offset & 3) == 0) {
+ putInt(o, offset, x);
+ } else if ((offset & 1) == 0) {
+ mem.putIntParts(this, o, offset,
+ (short)(x >> 0),
+ (short)(x >>> 16));
+ } else {
+ mem.putIntParts(this, o, offset,
+ (byte)(x >>> 0),
+ (byte)(x >>> 8),
+ (byte)(x >>> 16),
+ (byte)(x >>> 24));
+ }
+ }
+
+ public void putShortUnaligned(Object o, long offset, short x) {
+ if ((offset & 1) == 0) {
+ putShort(o, offset, x);
+ } else {
+ mem.putShortParts(this, o, offset,
+ (byte)(x >>> 0),
+ (byte)(x >>> 8));
+ }
+ }
+
+ public void putCharUnaligned(Object o, long offset, char x) {
+ putShortUnaligned(o, offset, (short)x);
+ }
+
+ private static final boolean byteOrder = theUnsafe.getByteOrder();
+
+ private static final NativeAccess mem
+ = (byteOrder == LITTLE_ENDIAN) ? new NativeLittleEndian() : new NativeBigEndian();
+
+ private abstract static class NativeAccess {
+ // Native-enianness-dependent scatter/gather methods for integer types
+ abstract long makeLong(int i0, int i1);
+ abstract long makeLong(short i0, short i1, short i2, short i3);
+ abstract long makeLong(byte i0, byte i1, byte i2, byte i3, byte i4, byte i5, byte i6, byte i7);
+ abstract int makeInt(short i0, short i1);
+ abstract int makeInt(byte i0, byte i1, byte i2, byte i3);
+ abstract short makeShort(byte i0, byte i1);
+
+ abstract void putLongParts(Unsafe theUnsafe, Object o, long offset, int i0, int i1);
+ abstract void putLongParts(Unsafe theUnsafe, Object o, long offset,
+ short i0, short i1, short i2, short i3);
+ abstract void putLongParts(Unsafe theUnsafe, Object o, long offset,
+ byte i0, byte i1, byte i2, byte i3, byte i4,
+ byte i5, byte i6, byte i7);
+ abstract void putIntParts(Unsafe theUnsafe, Object o, long offset, short i0, short i1);
+ abstract void putIntParts(Unsafe theUnsafe, Object o, long offset,
+ byte i0, byte i1, byte i2, byte i3);
+ abstract void putShortParts(Unsafe theUnsafe, Object o, long offset, byte i0, byte i1);
+
+ // Byte-reverse an integer if necessary
+ abstract char fromEndian(boolean big, char n);
+ abstract short fromEndian(boolean big, short n);
+ abstract int fromEndian(boolean big, int n);
+ abstract long fromEndian(boolean big, long n);
+
+ // Zero-extend an integer type
+ final int toUnsignedInt(byte n) { return n & 0xff; }
+ final int toUnsignedInt(short n) { return n & 0xffff; }
+ final long toUnsignedLong(byte n) { return n & 0xffl; }
+ final long toUnsignedLong(short n) { return n & 0xffffl; }
+ final long toUnsignedLong(int n) { return n & 0xffffffffl; }
+ }
+
+ private static class NativeLittleEndian extends NativeAccess {
+ long makeLong(byte i0, byte i1, byte i2, byte i3, byte i4, byte i5, byte i6, byte i7) {
+ return ((toUnsignedLong(i0) << 0)
+ | (toUnsignedLong(i1) << 8)
+ | (toUnsignedLong(i2) << 16)
+ | (toUnsignedLong(i3) << 24)
+ | (toUnsignedLong(i4) << 32)
+ | (toUnsignedLong(i5) << 40)
+ | (toUnsignedLong(i6) << 48)
+ | (toUnsignedLong(i7) << 56));
+ }
+ long makeLong(short i0, short i1, short i2, short i3) {
+ return ((toUnsignedLong(i0) << 0)
+ | (toUnsignedLong(i1) << 16)
+ | (toUnsignedLong(i2) << 32)
+ | (toUnsignedLong(i3) << 48));
+ }
+ long makeLong(int i0, int i1) {
+ return (toUnsignedLong(i0) << 0)
+ | (toUnsignedLong(i1) << 32);
+ }
+ int makeInt(short i0, short i1) {
+ return (toUnsignedInt(i0) << 0)
+ | (toUnsignedInt(i1) << 16);
+ }
+ int makeInt(byte i0, byte i1, byte i2, byte i3) {
+ return ((toUnsignedInt(i0) << 0)
+ | (toUnsignedInt(i1) << 8)
+ | (toUnsignedInt(i2) << 16)
+ | (toUnsignedInt(i3) << 24));
+ }
+ short makeShort(byte i0, byte i1) {
+ return (short)((toUnsignedInt(i0) << 0)
+ | (toUnsignedInt(i1) << 8));
+ }
+ void putLongParts(Unsafe theUnsafe, Object o, long offset, byte i0, byte i1, byte i2, byte i3, byte i4, byte i5, byte i6, byte i7) {
+ theUnsafe.putByte(o, offset + 0, i0);
+ theUnsafe.putByte(o, offset + 1, i1);
+ theUnsafe.putByte(o, offset + 2, i2);
+ theUnsafe.putByte(o, offset + 3, i3);
+ theUnsafe.putByte(o, offset + 4, i4);
+ theUnsafe.putByte(o, offset + 5, i5);
+ theUnsafe.putByte(o, offset + 6, i6);
+ theUnsafe.putByte(o, offset + 7, i7);
+ }
+ void putLongParts(Unsafe theUnsafe, Object o, long offset, short i0, short i1, short i2, short i3) {
+ theUnsafe.putShort(o, offset + 0, i0);
+ theUnsafe.putShort(o, offset + 2, i1);
+ theUnsafe.putShort(o, offset + 4, i2);
+ theUnsafe.putShort(o, offset + 6, i3);
+ }
+ void putLongParts(Unsafe theUnsafe, Object o, long offset, int i0, int i1) {
+ theUnsafe.putInt(o, offset + 0, i0);
+ theUnsafe.putInt(o, offset + 4, i1);
+ }
+ void putIntParts(Unsafe theUnsafe, Object o, long offset, short i0, short i1) {
+ theUnsafe.putShort(o, offset + 0, i0);
+ theUnsafe.putShort(o, offset + 2, i1);
+ }
+ void putIntParts(Unsafe theUnsafe, Object o, long offset, byte i0, byte i1, byte i2, byte i3) {
+ theUnsafe.putByte(o, offset + 0, i0);
+ theUnsafe.putByte(o, offset + 1, i1);
+ theUnsafe.putByte(o, offset + 2, i2);
+ theUnsafe.putByte(o, offset + 3, i3);
+ }
+ void putShortParts(Unsafe theUnsafe, Object o, long offset, byte i0, byte i1) {
+ theUnsafe.putByte(o, offset + 0, i0);
+ theUnsafe.putByte(o, offset + 1, i1);
+ }
+ char fromEndian(boolean big, char n) { return big ? Character.reverseBytes(n) : n; }
+ short fromEndian(boolean big, short n) { return big ? Short.reverseBytes(n) : n; }
+ int fromEndian(boolean big, int n) { return big ? Integer.reverseBytes(n) : n; }
+ long fromEndian(boolean big, long n) { return big ? Long.reverseBytes(n) : n; }
+ }
+
+ private static class NativeBigEndian extends NativeAccess {
+ long makeLong(byte i0, byte i1, byte i2, byte i3, byte i4, byte i5, byte i6, byte i7) {
+ return ((toUnsignedLong(i0) << 56)
+ | (toUnsignedLong(i1) << 48)
+ | (toUnsignedLong(i2) << 40)
+ | (toUnsignedLong(i3) << 32)
+ | (toUnsignedLong(i4) << 24)
+ | (toUnsignedLong(i5) << 16)
+ | (toUnsignedLong(i6) << 8)
+ | (toUnsignedLong(i7) << 0));
+ }
+ long makeLong(short i0, short i1, short i2, short i3) {
+ return ((toUnsignedLong(i0) << 48)
+ | (toUnsignedLong(i1) << 32)
+ | (toUnsignedLong(i2) << 16)
+ | (toUnsignedLong(i3) << 0));
+ }
+ long makeLong(int i0, int i1) {
+ return (toUnsignedLong(i0) << 32)
+ | (toUnsignedLong(i1) << 0);
+ }
+ int makeInt(byte i0, byte i1, byte i2, byte i3) {
+ return ((toUnsignedInt(i0) << 24)
+ | (toUnsignedInt(i1) << 16)
+ | (toUnsignedInt(i2) << 8)
+ | (toUnsignedInt(i3) << 0));
+ }
+ int makeInt(short i0, short i1) {
+ return ((toUnsignedInt(i0) << 16)
+ | (toUnsignedInt(i1) << 0));
+ }
+ short makeShort(byte i0, byte i1) {
+ return (short)((toUnsignedInt(i0) << 8)
+ | (toUnsignedInt(i1) << 0));
+ }
+ void putLongParts(Unsafe theUnsafe, Object o, long offset, byte i0, byte i1, byte i2, byte i3, byte i4, byte i5, byte i6, byte i7) {
+ theUnsafe.putByte(o, offset + 0, i7);
+ theUnsafe.putByte(o, offset + 1, i6);
+ theUnsafe.putByte(o, offset + 2, i5);
+ theUnsafe.putByte(o, offset + 3, i4);
+ theUnsafe.putByte(o, offset + 4, i3);
+ theUnsafe.putByte(o, offset + 5, i2);
+ theUnsafe.putByte(o, offset + 6, i1);
+ theUnsafe.putByte(o, offset + 7, i0);
+ }
+ void putLongParts(Unsafe theUnsafe, Object o, long offset, short i0, short i1, short i2, short i3) {
+ theUnsafe.putShort(o, offset + 0, i3);
+ theUnsafe.putShort(o, offset + 2, i2);
+ theUnsafe.putShort(o, offset + 4, i1);
+ theUnsafe.putShort(o, offset + 6, i0);
+ }
+ void putLongParts(Unsafe theUnsafe, Object o, long offset, int i0, int i1) {
+ theUnsafe.putInt(o, offset + 0, i1);
+ theUnsafe.putInt(o, offset + 4, i0);
+ }
+ void putIntParts(Unsafe theUnsafe, Object o, long offset, byte i0, byte i1, byte i2, byte i3) {
+ theUnsafe.putByte(o, offset + 0, i3);
+ theUnsafe.putByte(o, offset + 1, i2);
+ theUnsafe.putByte(o, offset + 2, i1);
+ theUnsafe.putByte(o, offset + 3, i0);
+ }
+ void putIntParts(Unsafe theUnsafe, Object o, long offset, short i0, short i1) {
+ theUnsafe.putShort(o, offset + 0, i1);
+ theUnsafe.putShort(o, offset + 2, i0);
+ }
+ void putShortParts(Unsafe theUnsafe, Object o, long offset, byte i0, byte i1) {
+ theUnsafe.putByte(o, offset + 0, i1);
+ theUnsafe.putByte(o, offset + 1, i0);
+ }
+ char fromEndian(boolean big, char n) { return big ? n : Character.reverseBytes(n); }
+ short fromEndian(boolean big, short n) { return big ? n : Short.reverseBytes(n); }
+ int fromEndian(boolean big, int n) { return big ? n : Integer.reverseBytes(n); }
+ long fromEndian(boolean big, long n) { return big ? n : Long.reverseBytes(n); }
+ }
}