# HG changeset patch # User Stefan Anzinger # Date 1428586529 -7200 # Node ID 43b3db5e8a9e093b00e11f12fd72724c025cce6c # Parent 4dbbc4b3bb4da00f9c8480de63a3ac804b816b80 UnsafeArrayType(Writer|Reader): Use naturally aligned Unsafe access (Important for SPARC) diff -r 4dbbc4b3bb4d -r 43b3db5e8a9e graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/UnsafeArrayTypeReader.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/UnsafeArrayTypeReader.java Thu Apr 09 13:27:37 2015 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/UnsafeArrayTypeReader.java Thu Apr 09 15:35:29 2015 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.compiler.common.util; +import java.nio.*; + import sun.misc.*; import com.oracle.graal.compiler.common.*; @@ -41,23 +43,44 @@ } public static int getS2(byte[] data, long byteIndex) { - return UnsafeAccess.unsafe.getShort(data, readOffset(data, byteIndex, Short.BYTES)); + if (byteIndex % Short.BYTES == 0) { + return UnsafeAccess.unsafe.getShort(data, readOffset(data, byteIndex, Short.BYTES)); + } else { + ByteBuffer buf = ByteBuffer.wrap(new byte[Short.BYTES]); + buf.put((byte) getU1(data, byteIndex)); + buf.put((byte) getU1(data, byteIndex + Byte.BYTES)); + return buf.getShort(0); + } } public static int getU2(byte[] data, long byteIndex) { - return UnsafeAccess.unsafe.getShort(data, readOffset(data, byteIndex, Short.BYTES)) & 0xFFFF; + return getS2(data, byteIndex) & 0xFFFF; } public static int getS4(byte[] data, long byteIndex) { - return UnsafeAccess.unsafe.getInt(data, readOffset(data, byteIndex, Integer.BYTES)); + if (byteIndex % Integer.BYTES == 0) { + return UnsafeAccess.unsafe.getInt(data, readOffset(data, byteIndex, Integer.BYTES)); + } else { + ByteBuffer buf = ByteBuffer.wrap(new byte[Integer.BYTES]); + buf.putShort((short) getS2(data, byteIndex)); + buf.putShort((short) getS2(data, byteIndex + Short.BYTES)); + return buf.getInt(0); + } } public static long getU4(byte[] data, long byteIndex) { - return UnsafeAccess.unsafe.getInt(data, readOffset(data, byteIndex, Integer.BYTES)) & 0xFFFFFFFFL; + return getS4(data, byteIndex) & 0xFFFFFFFFL; } public static long getLong(byte[] data, long byteIndex) { - return UnsafeAccess.unsafe.getLong(data, readOffset(data, byteIndex, Long.BYTES)); + if (byteIndex % Long.BYTES == 0) { + return UnsafeAccess.unsafe.getLong(data, readOffset(data, byteIndex, Long.BYTES)); + } else { + ByteBuffer buf = ByteBuffer.wrap(new byte[Long.BYTES]); + buf.putInt(getS4(data, byteIndex)); + buf.putInt(getS4(data, byteIndex + Integer.BYTES)); + return buf.getLong(0); + } } private static long readOffset(byte[] data, long byteIndex, int numBytes) { diff -r 4dbbc4b3bb4d -r 43b3db5e8a9e graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/UnsafeArrayTypeWriter.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/UnsafeArrayTypeWriter.java Thu Apr 09 13:27:37 2015 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/UnsafeArrayTypeWriter.java Thu Apr 09 15:35:29 2015 +0200 @@ -22,6 +22,10 @@ */ package com.oracle.graal.compiler.common.util; +import static com.oracle.graal.compiler.common.util.TypeConversion.*; + +import java.nio.*; + import sun.misc.*; import com.oracle.graal.compiler.common.*; @@ -72,43 +76,79 @@ @Override public void putS1(long value) { long offset = writeOffset(Byte.BYTES); - UnsafeAccess.unsafe.putByte(writeChunk.data, offset, TypeConversion.asS1(value)); + UnsafeAccess.unsafe.putByte(writeChunk.data, offset, asS1(value)); + commitWrite(Byte.BYTES); } @Override public void putU1(long value) { long offset = writeOffset(Byte.BYTES); - UnsafeAccess.unsafe.putByte(writeChunk.data, offset, TypeConversion.asU1(value)); + UnsafeAccess.unsafe.putByte(writeChunk.data, offset, asU1(value)); + commitWrite(Byte.BYTES); } @Override public void putS2(long value) { long offset = writeOffset(Short.BYTES); - UnsafeAccess.unsafe.putShort(writeChunk.data, offset, TypeConversion.asS2(value)); + if (offset % Short.BYTES == 0) { + UnsafeAccess.unsafe.putShort(writeChunk.data, offset, asS2(value)); + commitWrite(Short.BYTES); + } else { + ByteBuffer buf = ByteBuffer.wrap(new byte[Short.BYTES]); + buf.putShort(asS2(value)); + putS1(buf.get(0)); + putS1(buf.get(Byte.BYTES)); + } } @Override public void putU2(long value) { - long offset = writeOffset(Short.BYTES); - UnsafeAccess.unsafe.putShort(writeChunk.data, offset, TypeConversion.asU2(value)); + putS2(asU2(value)); } @Override public void putS4(long value) { long offset = writeOffset(Integer.BYTES); - UnsafeAccess.unsafe.putInt(writeChunk.data, offset, TypeConversion.asS4(value)); + if (offset % Integer.BYTES == 0) { + UnsafeAccess.unsafe.putInt(writeChunk.data, offset, asS4(value)); + commitWrite(Integer.BYTES); + } else { + ByteBuffer buf = ByteBuffer.wrap(new byte[Integer.BYTES]); + buf.putInt(asS4(value)); + if (offset % Short.BYTES == 0) { + putS2(buf.getShort(0)); + putS2(buf.getShort(2)); + } else { + putS1(buf.get(0)); + putS2(buf.getShort(1)); + putS1(buf.get(3)); + } + } } @Override public void putU4(long value) { - long offset = writeOffset(Integer.BYTES); - UnsafeAccess.unsafe.putInt(writeChunk.data, offset, TypeConversion.asU4(value)); + putS4(asU4(value)); } @Override public void putS8(long value) { long offset = writeOffset(Long.BYTES); - UnsafeAccess.unsafe.putLong(writeChunk.data, offset, value); + if (offset % Long.BYTES == 0) { + UnsafeAccess.unsafe.putLong(writeChunk.data, offset, value); + commitWrite(Long.BYTES); + } else { + ByteBuffer buf = ByteBuffer.wrap(new byte[Long.BYTES]); + buf.putLong(value); + if (offset % Integer.BYTES == 0) { + putS4(buf.getInt(0)); + putS4(buf.getInt(4)); + } else { + putS2(buf.getShort(0)); + putS4(buf.getInt(2)); + putS2(buf.getShort(6)); + } + } } private long writeOffset(int writeBytes) { @@ -121,10 +161,12 @@ assert Unsafe.ARRAY_BYTE_INDEX_SCALE == 1; long result = writeChunk.size + Unsafe.ARRAY_BYTE_BASE_OFFSET; + return result; + } + + private void commitWrite(int writeBytes) { totalSize += writeBytes; writeChunk.size += writeBytes; assert writeChunk.size <= writeChunk.data.length; - - return result; } }