changeset 20832:43b3db5e8a9e

UnsafeArrayType(Writer|Reader): Use naturally aligned Unsafe access (Important for SPARC)
author Stefan Anzinger <stefan.anzinger@oracle.com>
date Thu, 09 Apr 2015 15:35:29 +0200
parents 4dbbc4b3bb4d
children 98af261f22f0
files graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/UnsafeArrayTypeReader.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/UnsafeArrayTypeWriter.java
diffstat 2 files changed, 81 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- 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) {
--- 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;
     }
 }