--- old/src/java.base/share/classes/java/nio/Bits.java 2015-03-02 18:37:40.934869925 +0000 +++ new/src/java.base/share/classes/java/nio/Bits.java 2015-03-02 18:37:40.758875363 +0000 @@ -567,7 +567,8 @@ // -- Processor and memory-system properties -- - private static final ByteOrder byteOrder; + private static final ByteOrder byteOrder + = unsafe.getByteOrder() == Unsafe.LITTLE_ENDIAN ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN; static ByteOrder byteOrder() { if (byteOrder == null) @@ -575,24 +576,6 @@ return byteOrder; } - static { - long a = unsafe.allocateMemory(8); - try { - unsafe.putLong(a, 0x0102030405060708L); - byte b = unsafe.getByte(a); - switch (b) { - case 0x01: byteOrder = ByteOrder.BIG_ENDIAN; break; - case 0x08: byteOrder = ByteOrder.LITTLE_ENDIAN; break; - default: - assert false; - byteOrder = null; - } - } finally { - unsafe.freeMemory(a); - } - } - - private static int pageSize = -1; static int pageSize() { @@ -613,8 +596,7 @@ return unaligned; String arch = AccessController.doPrivileged( new sun.security.action.GetPropertyAction("os.arch")); - unaligned = arch.equals("i386") || arch.equals("x86") - || arch.equals("amd64") || arch.equals("x86_64"); + unaligned = unsafe.unalignedAccess(); unalignedKnown = true; return unaligned; } --- old/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template 2015-03-02 18:37:41.303858525 +0000 +++ new/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template 2015-03-02 18:37:41.177862418 +0000 @@ -27,6 +27,7 @@ package java.nio; +import sun.misc.Unsafe; /** #if[rw] @@ -52,6 +53,19 @@ #end[rw] */ +#if[byte] + + // Cached unsafe-access object + protected static final Unsafe unsafe = Bits.unsafe(); + + // Cached array base offset + private static final long arrayBaseOffset = unsafe.arrayBaseOffset($type$[].class); + + // Cached unaligned-access capability + protected static final boolean unaligned = Bits.unaligned(); + +#end[byte] + Heap$Type$Buffer$RW$(int cap, int lim) { // package-private #if[rw] super(-1, 0, lim, cap, new $type$[cap], 0); @@ -131,6 +145,12 @@ return i + offset; } +#if[byte] + protected long byteOffset(long i) { + return arrayBaseOffset + i + offset; + } +#end[byte] + public $type$ get() { return hb[ix(nextGetIndex())]; } @@ -235,8 +255,6 @@ #end[rw] } - - #if[byte] byte _get(int i) { // package-private @@ -256,18 +274,18 @@ #if[rw] public char getChar() { - return Bits.getChar(this, ix(nextGetIndex(2)), bigEndian); + return getChar(nextGetIndex(2)); } public char getChar(int i) { - return Bits.getChar(this, ix(checkIndex(i, 2)), bigEndian); + return unsafe.getCharUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian); } #end[rw] public $Type$Buffer putChar(char x) { #if[rw] - Bits.putChar(this, ix(nextPutIndex(2)), x, bigEndian); + putChar(nextPutIndex(2), x); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -276,7 +294,9 @@ public $Type$Buffer putChar(int i, char x) { #if[rw] - Bits.putChar(this, ix(checkIndex(i, 2)), x, bigEndian); + char y = (x); + unsafe.putCharUnaligned(hb, byteOffset(checkIndex(i, 2)), + nativeByteOrder ? y : Bits.swap(y)); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -307,18 +327,18 @@ #if[rw] public short getShort() { - return Bits.getShort(this, ix(nextGetIndex(2)), bigEndian); + return getShort(nextGetIndex(2)); } public short getShort(int i) { - return Bits.getShort(this, ix(checkIndex(i, 2)), bigEndian); + return unsafe.getShortUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian); } #end[rw] public $Type$Buffer putShort(short x) { #if[rw] - Bits.putShort(this, ix(nextPutIndex(2)), x, bigEndian); + putShort(nextPutIndex(2), x); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -327,7 +347,9 @@ public $Type$Buffer putShort(int i, short x) { #if[rw] - Bits.putShort(this, ix(checkIndex(i, 2)), x, bigEndian); + short y = (x); + unsafe.putShortUnaligned(hb, byteOffset(checkIndex(i, 2)), + nativeByteOrder ? y : Bits.swap(y)); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -358,18 +380,18 @@ #if[rw] public int getInt() { - return Bits.getInt(this, ix(nextGetIndex(4)), bigEndian); + return getInt(nextGetIndex(4)); } public int getInt(int i) { - return Bits.getInt(this, ix(checkIndex(i, 4)), bigEndian); + return unsafe.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian); } #end[rw] public $Type$Buffer putInt(int x) { #if[rw] - Bits.putInt(this, ix(nextPutIndex(4)), x, bigEndian); + putInt(nextPutIndex(4), x); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -378,7 +400,9 @@ public $Type$Buffer putInt(int i, int x) { #if[rw] - Bits.putInt(this, ix(checkIndex(i, 4)), x, bigEndian); + int y = (x); + unsafe.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), + nativeByteOrder ? y : Bits.swap(y)); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -409,18 +433,18 @@ #if[rw] public long getLong() { - return Bits.getLong(this, ix(nextGetIndex(8)), bigEndian); + return getLong(nextGetIndex(8)); } public long getLong(int i) { - return Bits.getLong(this, ix(checkIndex(i, 8)), bigEndian); + return unsafe.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian); } #end[rw] public $Type$Buffer putLong(long x) { #if[rw] - Bits.putLong(this, ix(nextPutIndex(8)), x, bigEndian); + putLong(nextPutIndex(8), x); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -429,7 +453,9 @@ public $Type$Buffer putLong(int i, long x) { #if[rw] - Bits.putLong(this, ix(checkIndex(i, 8)), x, bigEndian); + long y = (x); + unsafe.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), + nativeByteOrder ? y : Bits.swap(y)); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -460,18 +486,19 @@ #if[rw] public float getFloat() { - return Bits.getFloat(this, ix(nextGetIndex(4)), bigEndian); + return getFloat(nextGetIndex(4)); } public float getFloat(int i) { - return Bits.getFloat(this, ix(checkIndex(i, 4)), bigEndian); + int x = unsafe.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian); + return Float.intBitsToFloat(x); } #end[rw] public $Type$Buffer putFloat(float x) { #if[rw] - Bits.putFloat(this, ix(nextPutIndex(4)), x, bigEndian); + putFloat(nextPutIndex(4), x); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -480,7 +507,9 @@ public $Type$Buffer putFloat(int i, float x) { #if[rw] - Bits.putFloat(this, ix(checkIndex(i, 4)), x, bigEndian); + int y = Float.floatToRawIntBits(x); + unsafe.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), + nativeByteOrder ? y : Bits.swap(y)); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -511,18 +540,19 @@ #if[rw] public double getDouble() { - return Bits.getDouble(this, ix(nextGetIndex(8)), bigEndian); + return getDouble(nextGetIndex(8)); } public double getDouble(int i) { - return Bits.getDouble(this, ix(checkIndex(i, 8)), bigEndian); + long x = unsafe.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian); + return Double.longBitsToDouble(x); } #end[rw] public $Type$Buffer putDouble(double x) { #if[rw] - Bits.putDouble(this, ix(nextPutIndex(8)), x, bigEndian); + putDouble(nextPutIndex(8), x); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -531,7 +561,9 @@ public $Type$Buffer putDouble(int i, double x) { #if[rw] - Bits.putDouble(this, ix(checkIndex(i, 8)), x, bigEndian); + long y = Double.doubleToRawLongBits(x); + unsafe.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), + nativeByteOrder ? y : Bits.swap(y)); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -560,6 +592,7 @@ #end[byte] + #if[char] String toString(int start, int end) { // package-private --- old/src/java.base/share/classes/sun/misc/Unsafe.java 2015-03-02 18:37:41.619848763 +0000 +++ new/src/java.base/share/classes/sun/misc/Unsafe.java 2015-03-02 18:37:41.513852038 +0000 @@ -1143,4 +1143,317 @@ 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); } + } } --- old/src/java.base/share/classes/sun/security/provider/ByteArrayAccess.java 2015-03-02 18:37:41.904839958 +0000 +++ new/src/java.base/share/classes/sun/security/provider/ByteArrayAccess.java 2015-03-02 18:37:41.800843171 +0000 @@ -88,13 +88,8 @@ // Return whether this platform supports full speed int/long memory access // at unaligned addresses. - // This code was copied from java.nio.Bits because there is no equivalent - // public API. private static boolean unaligned() { - String arch = java.security.AccessController.doPrivileged - (new sun.security.action.GetPropertyAction("os.arch", "")); - return arch.equals("i386") || arch.equals("x86") || arch.equals("amd64") - || arch.equals("x86_64"); + return unsafe.unalignedAccess(); } /**