changeset 21001:acc86d08e1cc

Support Sparc without the need of a temporary ByteBuffer for every memory access
author Christian Wimmer <christian.wimmer@oracle.com>
date Thu, 16 Apr 2015 16:07:34 -0700
parents fdf55f1ffc59
children 95931055060f
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 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraphEncoderTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeWriterTest.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphEncoder.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CachingPEGraphDecoder.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PEGraphDecoder.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java
diffstat 10 files changed, 250 insertions(+), 145 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/UnsafeArrayTypeReader.java	Thu Apr 16 22:38:52 2015 +0200
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/UnsafeArrayTypeReader.java	Thu Apr 16 16:07:34 2015 -0700
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.compiler.common.util;
 
-import java.nio.*;
-
 import sun.misc.*;
 
 import com.oracle.graal.compiler.common.*;
@@ -31,8 +29,16 @@
 /**
  * Provides low-level read access from a byte[] array for signed and unsigned values of size 1, 2,
  * 4, and 8 bytes.
+ *
+ * The class can either be instantiated for sequential access to the byte[] array; or static methods
+ * can be used to read values without the overhead of creating an instance.
+ *
+ * The flag {@code supportsUnalignedMemoryAccess} must be set according to the capabilities of the
+ * hardware architecture: the value {@code true} allows more efficient memory access on
+ * architectures that support unaligned memory accesses; the value {@code false} is the safe
+ * fallback that works on every hardware.
  */
-public class UnsafeArrayTypeReader implements TypeReader {
+public abstract class UnsafeArrayTypeReader implements TypeReader {
 
     public static int getS1(byte[] data, long byteIndex) {
         return UnsafeAccess.unsafe.getByte(data, readOffset(data, byteIndex, Byte.BYTES));
@@ -42,48 +48,39 @@
         return UnsafeAccess.unsafe.getByte(data, readOffset(data, byteIndex, Byte.BYTES)) & 0xFF;
     }
 
-    public static int getS2(byte[] data, long byteIndex) {
-        if (byteIndex % Short.BYTES == 0) {
-            return UnsafeAccess.unsafe.getShort(data, readOffset(data, byteIndex, Short.BYTES));
+    public static int getS2(byte[] data, long byteIndex, boolean supportsUnalignedMemoryAccess) {
+        if (supportsUnalignedMemoryAccess) {
+            return UnalignedUnsafeArrayTypeReader.getS2(data, byteIndex);
         } else {
-            ByteBuffer buf = ByteBuffer.wrap(new byte[Short.BYTES]).order(ByteOrder.nativeOrder());
-            buf.put((byte) getU1(data, byteIndex));
-            buf.put((byte) getU1(data, byteIndex + Byte.BYTES));
-            return buf.getShort(0);
+            return AlignedUnsafeArrayTypeReader.getS2(data, byteIndex);
         }
     }
 
-    public static int getU2(byte[] data, long byteIndex) {
-        return getS2(data, byteIndex) & 0xFFFF;
+    public static int getU2(byte[] data, long byteIndex, boolean supportsUnalignedMemoryAccess) {
+        return getS2(data, byteIndex, supportsUnalignedMemoryAccess) & 0xFFFF;
     }
 
-    public static int getS4(byte[] data, long byteIndex) {
-        if (byteIndex % Integer.BYTES == 0) {
-            return UnsafeAccess.unsafe.getInt(data, readOffset(data, byteIndex, Integer.BYTES));
+    public static int getS4(byte[] data, long byteIndex, boolean supportsUnalignedMemoryAccess) {
+        if (supportsUnalignedMemoryAccess) {
+            return UnalignedUnsafeArrayTypeReader.getS4(data, byteIndex);
         } else {
-            ByteBuffer buf = ByteBuffer.wrap(new byte[Integer.BYTES]).order(ByteOrder.nativeOrder());
-            buf.putShort((short) getS2(data, byteIndex));
-            buf.putShort((short) getS2(data, byteIndex + Short.BYTES));
-            return buf.getInt(0);
+            return AlignedUnsafeArrayTypeReader.getS4(data, byteIndex);
         }
     }
 
-    public static long getU4(byte[] data, long byteIndex) {
-        return getS4(data, byteIndex) & 0xFFFFFFFFL;
+    public static long getU4(byte[] data, long byteIndex, boolean supportsUnalignedMemoryAccess) {
+        return getS4(data, byteIndex, supportsUnalignedMemoryAccess) & 0xFFFFFFFFL;
     }
 
-    public static long getLong(byte[] data, long byteIndex) {
-        if (byteIndex % Long.BYTES == 0) {
-            return UnsafeAccess.unsafe.getLong(data, readOffset(data, byteIndex, Long.BYTES));
+    public static long getS8(byte[] data, long byteIndex, boolean supportsUnalignedMemoryAccess) {
+        if (supportsUnalignedMemoryAccess) {
+            return UnalignedUnsafeArrayTypeReader.getS8(data, byteIndex);
         } else {
-            ByteBuffer buf = ByteBuffer.wrap(new byte[Long.BYTES]).order(ByteOrder.nativeOrder());
-            buf.putInt(getS4(data, byteIndex));
-            buf.putInt(getS4(data, byteIndex + Integer.BYTES));
-            return buf.getLong(0);
+            return AlignedUnsafeArrayTypeReader.getS8(data, byteIndex);
         }
     }
 
-    private static long readOffset(byte[] data, long byteIndex, int numBytes) {
+    protected static long readOffset(byte[] data, long byteIndex, int numBytes) {
         assert byteIndex >= 0;
         assert numBytes > 0;
         assert byteIndex + numBytes <= data.length;
@@ -92,10 +89,18 @@
         return byteIndex + Unsafe.ARRAY_BYTE_BASE_OFFSET;
     }
 
-    private final byte[] data;
-    private long byteIndex;
+    public static UnsafeArrayTypeReader create(byte[] data, long byteIndex, boolean supportsUnalignedMemoryAccess) {
+        if (supportsUnalignedMemoryAccess) {
+            return new UnalignedUnsafeArrayTypeReader(data, byteIndex);
+        } else {
+            return new AlignedUnsafeArrayTypeReader(data, byteIndex);
+        }
+    }
 
-    public UnsafeArrayTypeReader(byte[] data, long byteIndex) {
+    protected final byte[] data;
+    protected long byteIndex;
+
+    protected UnsafeArrayTypeReader(byte[] data, long byteIndex) {
         this.data = data;
         this.byteIndex = byteIndex;
     }
@@ -111,29 +116,50 @@
     }
 
     @Override
-    public int getS1() {
+    public final int getS1() {
         int result = getS1(data, byteIndex);
         byteIndex += Byte.BYTES;
         return result;
     }
 
     @Override
-    public int getU1() {
+    public final int getU1() {
         int result = getU1(data, byteIndex);
         byteIndex += Byte.BYTES;
         return result;
     }
 
     @Override
-    public int getS2() {
-        int result = getS2(data, byteIndex);
-        byteIndex += Short.BYTES;
-        return result;
+    public final int getU2() {
+        return getS2() & 0xFFFF;
     }
 
     @Override
-    public int getU2() {
-        int result = getU2(data, byteIndex);
+    public final long getU4() {
+        return getS4() & 0xFFFFFFFFL;
+    }
+}
+
+final class UnalignedUnsafeArrayTypeReader extends UnsafeArrayTypeReader {
+    protected static int getS2(byte[] data, long byteIndex) {
+        return UnsafeAccess.unsafe.getShort(data, readOffset(data, byteIndex, Short.BYTES));
+    }
+
+    protected static int getS4(byte[] data, long byteIndex) {
+        return UnsafeAccess.unsafe.getInt(data, readOffset(data, byteIndex, Integer.BYTES));
+    }
+
+    protected static long getS8(byte[] data, long byteIndex) {
+        return UnsafeAccess.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;
     }
@@ -146,15 +172,61 @@
     }
 
     @Override
-    public long getU4() {
-        long result = getU4(data, byteIndex);
+    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 ((UnsafeAccess.unsafe.getByte(data, offset + 0) & 0xFF) << 0) | //
+                        (UnsafeAccess.unsafe.getByte(data, offset + 1) << 8);
+    }
+
+    protected static int getS4(byte[] data, long byteIndex) {
+        long offset = readOffset(data, byteIndex, Integer.BYTES);
+        return ((UnsafeAccess.unsafe.getByte(data, offset + 0) & 0xFF) << 0) | //
+                        ((UnsafeAccess.unsafe.getByte(data, offset + 1) & 0xFF) << 8) | //
+                        ((UnsafeAccess.unsafe.getByte(data, offset + 2) & 0xFF) << 16) | //
+                        (UnsafeAccess.unsafe.getByte(data, offset + 3) << 24);
+    }
+
+    protected static long getS8(byte[] data, long byteIndex) {
+        long offset = readOffset(data, byteIndex, Long.BYTES);
+        return ((long) ((UnsafeAccess.unsafe.getByte(data, offset + 0) & 0xFF)) << 0) | //
+                        ((long) ((UnsafeAccess.unsafe.getByte(data, offset + 1) & 0xFF)) << 8) | //
+                        ((long) ((UnsafeAccess.unsafe.getByte(data, offset + 2) & 0xFF)) << 16) | //
+                        ((long) ((UnsafeAccess.unsafe.getByte(data, offset + 3) & 0xFF)) << 24) | //
+                        ((long) ((UnsafeAccess.unsafe.getByte(data, offset + 4) & 0xFF)) << 32) | //
+                        ((long) ((UnsafeAccess.unsafe.getByte(data, offset + 5) & 0xFF)) << 40) | //
+                        ((long) ((UnsafeAccess.unsafe.getByte(data, offset + 6) & 0xFF)) << 48) | //
+                        ((long) (UnsafeAccess.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 = getLong(data, byteIndex);
+        long result = getS8(data, byteIndex);
         byteIndex += Long.BYTES;
         return result;
     }
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/UnsafeArrayTypeWriter.java	Thu Apr 16 22:38:52 2015 +0200
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/UnsafeArrayTypeWriter.java	Thu Apr 16 16:07:34 2015 -0700
@@ -23,9 +23,6 @@
 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.*;
@@ -34,8 +31,13 @@
  * Provides low-level sequential write access to a byte[] array for signed and unsigned values of
  * size 1, 2, 4, and 8 bytes. To avoid copying an array when the buffer size is no longer
  * sufficient, the buffer is split into chunks of a fixed size.
+ *
+ * The flag {@code supportsUnalignedMemoryAccess} must be set according to the capabilities of the
+ * hardware architecture: the value {@code true} allows more efficient memory access on
+ * architectures that support unaligned memory accesses; the value {@code false} is the safe
+ * fallback that works on every hardware.
  */
-public class UnsafeArrayTypeWriter implements TypeWriter {
+public abstract class UnsafeArrayTypeWriter implements TypeWriter {
 
     private static final int MIN_CHUNK_LENGTH = 200;
     private static final int MAX_CHUNK_LENGTH = 16000;
@@ -50,24 +52,32 @@
         }
     }
 
-    private Chunk firstChunk;
-    private Chunk writeChunk;
-    private int totalSize;
+    protected final Chunk firstChunk;
+    protected Chunk writeChunk;
+    protected int totalSize;
 
-    public UnsafeArrayTypeWriter() {
+    public static UnsafeArrayTypeWriter create(boolean supportsUnalignedMemoryAccess) {
+        if (supportsUnalignedMemoryAccess) {
+            return new UnalignedUnsafeArrayTypeWriter();
+        } else {
+            return new AlignedUnsafeArrayTypeWriter();
+        }
+    }
+
+    protected UnsafeArrayTypeWriter() {
         firstChunk = new Chunk(MIN_CHUNK_LENGTH);
         writeChunk = firstChunk;
     }
 
     @Override
-    public long getBytesWritten() {
+    public final long getBytesWritten() {
         return totalSize;
     }
 
     /**
      * Copies the buffer into the provided byte[] array of length {@link #getBytesWritten()}.
      */
-    public byte[] toArray(byte[] result) {
+    public final byte[] toArray(byte[] result) {
         assert result.length == totalSize;
         int resultIdx = 0;
         for (Chunk cur = firstChunk; cur != null; cur = cur.next) {
@@ -79,84 +89,28 @@
     }
 
     @Override
-    public void putS1(long value) {
+    public final void putS1(long value) {
         long offset = writeOffset(Byte.BYTES);
         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, asU1(value));
-        commitWrite(Byte.BYTES);
     }
 
     @Override
-    public void putS2(long value) {
-        long offset = writeOffset(Short.BYTES);
-        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]).order(ByteOrder.nativeOrder());
-            buf.putShort(asS2(value));
-            putS1(buf.get(0));
-            putS1(buf.get(Byte.BYTES));
-        }
+    public final void putU1(long value) {
+        long offset = writeOffset(Byte.BYTES);
+        UnsafeAccess.unsafe.putByte(writeChunk.data, offset, asU1(value));
     }
 
     @Override
-    public void putU2(long value) {
+    public final void putU2(long value) {
         putS2(asU2(value));
     }
 
     @Override
-    public void putS4(long value) {
-        long offset = writeOffset(Integer.BYTES);
-        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]).order(ByteOrder.nativeOrder());
-            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) {
+    public final void putU4(long value) {
         putS4(asU4(value));
     }
 
-    @Override
-    public void putS8(long value) {
-        long offset = writeOffset(Long.BYTES);
-        if (offset % Long.BYTES == 0) {
-            UnsafeAccess.unsafe.putLong(writeChunk.data, offset, value);
-            commitWrite(Long.BYTES);
-        } else {
-            ByteBuffer buf = ByteBuffer.wrap(new byte[Long.BYTES]).order(ByteOrder.nativeOrder());
-            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) {
+    protected long writeOffset(int writeBytes) {
         if (writeChunk.size + writeBytes >= writeChunk.data.length) {
             Chunk newChunk = new Chunk(Math.min(writeChunk.data.length * 2, MAX_CHUNK_LENGTH));
             writeChunk.next = newChunk;
@@ -166,12 +120,61 @@
         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;
+    }
+}
+
+final class UnalignedUnsafeArrayTypeWriter extends UnsafeArrayTypeWriter {
+    @Override
+    public void putS2(long value) {
+        long offset = writeOffset(Short.BYTES);
+        UnsafeAccess.unsafe.putShort(writeChunk.data, offset, asS2(value));
+    }
+
+    @Override
+    public void putS4(long value) {
+        long offset = writeOffset(Integer.BYTES);
+        UnsafeAccess.unsafe.putInt(writeChunk.data, offset, asS4(value));
+    }
+
+    @Override
+    public void putS8(long value) {
+        long offset = writeOffset(Long.BYTES);
+        UnsafeAccess.unsafe.putLong(writeChunk.data, offset, value);
     }
 }
+
+final class AlignedUnsafeArrayTypeWriter extends UnsafeArrayTypeWriter {
+    @Override
+    public void putS2(long value) {
+        long offset = writeOffset(Short.BYTES);
+        UnsafeAccess.unsafe.putByte(writeChunk.data, offset + 0, (byte) (value >> 0));
+        UnsafeAccess.unsafe.putByte(writeChunk.data, offset + 1, (byte) (value >> 8));
+    }
+
+    @Override
+    public void putS4(long value) {
+        long offset = writeOffset(Integer.BYTES);
+        UnsafeAccess.unsafe.putByte(writeChunk.data, offset + 0, (byte) (value >> 0));
+        UnsafeAccess.unsafe.putByte(writeChunk.data, offset + 1, (byte) (value >> 8));
+        UnsafeAccess.unsafe.putByte(writeChunk.data, offset + 2, (byte) (value >> 16));
+        UnsafeAccess.unsafe.putByte(writeChunk.data, offset + 3, (byte) (value >> 24));
+    }
+
+    @Override
+    public void putS8(long value) {
+        long offset = writeOffset(Long.BYTES);
+        UnsafeAccess.unsafe.putByte(writeChunk.data, offset + 0, (byte) (value >> 0));
+        UnsafeAccess.unsafe.putByte(writeChunk.data, offset + 1, (byte) (value >> 8));
+        UnsafeAccess.unsafe.putByte(writeChunk.data, offset + 2, (byte) (value >> 16));
+        UnsafeAccess.unsafe.putByte(writeChunk.data, offset + 3, (byte) (value >> 24));
+        UnsafeAccess.unsafe.putByte(writeChunk.data, offset + 4, (byte) (value >> 32));
+        UnsafeAccess.unsafe.putByte(writeChunk.data, offset + 5, (byte) (value >> 40));
+        UnsafeAccess.unsafe.putByte(writeChunk.data, offset + 6, (byte) (value >> 48));
+        UnsafeAccess.unsafe.putByte(writeChunk.data, offset + 7, (byte) (value >> 56));
+    }
+}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraphEncoderTest.java	Thu Apr 16 22:38:52 2015 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraphEncoderTest.java	Thu Apr 16 16:07:34 2015 -0700
@@ -60,7 +60,7 @@
             }
         }
 
-        GraphEncoder encoder = new GraphEncoder();
+        GraphEncoder encoder = new GraphEncoder(getTarget().arch);
         for (StructuredGraph originalGraph : originalGraphs) {
             encoder.prepare(originalGraph);
         }
@@ -73,7 +73,7 @@
         for (StructuredGraph originalGraph : originalGraphs) {
             EncodedGraph encodedGraph = new EncodedGraph(encoder.getEncoding(), startOffsets.get(originalGraph), encoder.getObjects(), encoder.getNodeClasses(), originalGraph.getAssumptions(),
                             originalGraph.getInlinedMethods());
-            GraphEncoder.verifyEncoding(originalGraph, encodedGraph);
+            GraphEncoder.verifyEncoding(originalGraph, encodedGraph, getTarget().arch);
         }
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeWriterTest.java	Thu Apr 16 22:38:52 2015 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeWriterTest.java	Thu Apr 16 16:07:34 2015 -0700
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.compiler.common.util.*;
 
-public class TypeWriterTest {
+public class TypeWriterTest extends GraalCompilerTest {
 
     private static void putValue(TypeWriter writer, long value) {
         if (TypeConversion.isS1(value)) {
@@ -114,17 +114,26 @@
         }
     }
 
-    @Test
-    public void test01() {
-        UnsafeArrayTypeWriter writer = new UnsafeArrayTypeWriter();
+    private static void test01(boolean supportsUnalignedMemoryAccess) {
+        UnsafeArrayTypeWriter writer = UnsafeArrayTypeWriter.create(supportsUnalignedMemoryAccess);
         putValues(writer);
 
         byte[] array = new byte[(int) writer.getBytesWritten()];
         writer.toArray(array);
-        UnsafeArrayTypeReader reader = new UnsafeArrayTypeReader(array, 0);
+        UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(array, 0, supportsUnalignedMemoryAccess);
         checkValues(reader);
     }
 
+    @Test
+    public void test01a() {
+        test01(getTarget().arch.supportsUnalignedMemoryAccess());
+    }
+
+    @Test
+    public void test01b() {
+        test01(false);
+    }
+
     private static void checkSignedSize(TypeWriter writer, long value, int expectedSize) {
         long sizeBefore = writer.getBytesWritten();
         writer.putSV(value);
@@ -159,7 +168,12 @@
     }
 
     @Test
-    public void test02() {
-        checkSizes(new UnsafeArrayTypeWriter());
+    public void test02a() {
+        checkSizes(UnsafeArrayTypeWriter.create(getTarget().arch.supportsUnalignedMemoryAccess()));
+    }
+
+    @Test
+    public void test02b() {
+        checkSizes(UnsafeArrayTypeWriter.create(false));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java	Thu Apr 16 22:38:52 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java	Thu Apr 16 16:07:34 2015 -0700
@@ -26,6 +26,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.util.*;
@@ -68,7 +69,7 @@
     }
 
     /** Decoding state maintained for each encoded graph. */
-    protected static class MethodScope {
+    protected class MethodScope {
         /** The target graph where decoded nodes are added to. */
         public final StructuredGraph graph;
         /** The encode graph that is decoded. */
@@ -90,7 +91,7 @@
             this.returnNodes = new ArrayList<>();
 
             if (encodedGraph != null) {
-                reader = new UnsafeArrayTypeReader(encodedGraph.getEncoding(), encodedGraph.getStartOffset());
+                reader = UnsafeArrayTypeReader.create(encodedGraph.getEncoding(), encodedGraph.getStartOffset(), architecture.supportsUnalignedMemoryAccess());
                 if (encodedGraph.nodeStartOffsets == null) {
                     int nodeCount = reader.getUVInt();
                     long[] nodeStartOffsets = new long[nodeCount];
@@ -249,6 +250,12 @@
         }
     }
 
+    protected final Architecture architecture;
+
+    public GraphDecoder(Architecture architecture) {
+        this.architecture = architecture;
+    }
+
     public final void decode(StructuredGraph graph, EncodedGraph encodedGraph) {
         MethodScope methodScope = new MethodScope(graph, encodedGraph, LoopExplosionKind.NONE);
         decode(methodScope, null);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphEncoder.java	Thu Apr 16 22:38:52 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphEncoder.java	Thu Apr 16 16:07:34 2015 -0700
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.util.*;
 import com.oracle.graal.graph.*;
@@ -106,6 +107,8 @@
      */
     protected static final int BEGIN_NEXT_ORDER_ID_OFFSET = 1;
 
+    protected final Architecture architecture;
+
     /**
      * Collects all non-primitive data referenced from nodes. The encoding uses an index into an
      * array for decoding. Because of the variable-length encoding, it is beneficial that frequently
@@ -128,18 +131,19 @@
     /**
      * Utility method that does everything necessary to encode a single graph.
      */
-    public static EncodedGraph encodeSingleGraph(StructuredGraph graph) {
-        GraphEncoder encoder = new GraphEncoder();
+    public static EncodedGraph encodeSingleGraph(StructuredGraph graph, Architecture architecture) {
+        GraphEncoder encoder = new GraphEncoder(architecture);
         encoder.prepare(graph);
         encoder.finishPrepare();
         long startOffset = encoder.encode(graph);
         return new EncodedGraph(encoder.getEncoding(), startOffset, encoder.getObjects(), encoder.getNodeClasses(), graph.getAssumptions(), graph.getInlinedMethods());
     }
 
-    public GraphEncoder() {
+    public GraphEncoder(Architecture architecture) {
+        this.architecture = architecture;
         objects = FrequencyEncoder.createEqualityEncoder();
         nodeClasses = FrequencyEncoder.createIdentityEncoder();
-        writer = new UnsafeArrayTypeWriter();
+        writer = UnsafeArrayTypeWriter.create(architecture.supportsUnalignedMemoryAccess());
     }
 
     /**
@@ -262,7 +266,7 @@
         }
 
         /* Check that the decoding of the encode graph is the same as the input. */
-        assert verifyEncoding(graph, new EncodedGraph(getEncoding(), nodeTableStart, getObjects(), getNodeClasses(), graph.getAssumptions(), graph.getInlinedMethods()));
+        assert verifyEncoding(graph, new EncodedGraph(getEncoding(), nodeTableStart, getObjects(), getNodeClasses(), graph.getAssumptions(), graph.getInlinedMethods()), architecture);
 
         return nodeTableStart;
     }
@@ -378,9 +382,9 @@
      * Verification code that checks that the decoding of an encode graph is the same as the
      * original graph.
      */
-    public static boolean verifyEncoding(StructuredGraph originalGraph, EncodedGraph encodedGraph) {
+    public static boolean verifyEncoding(StructuredGraph originalGraph, EncodedGraph encodedGraph, Architecture architecture) {
         StructuredGraph decodedGraph = new StructuredGraph(originalGraph.method(), AllowAssumptions.YES);
-        GraphDecoder decoder = new GraphDecoder();
+        GraphDecoder decoder = new GraphDecoder(architecture);
         decoder.decode(decodedGraph, encodedGraph);
 
         decodedGraph.verify();
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CachingPEGraphDecoder.java	Thu Apr 16 22:38:52 2015 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CachingPEGraphDecoder.java	Thu Apr 16 16:07:34 2015 -0700
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graphbuilderconf.*;
@@ -45,8 +46,8 @@
     private final AllowAssumptions allowAssumptions;
     private final Map<ResolvedJavaMethod, EncodedGraph> graphCache;
 
-    public CachingPEGraphDecoder(Providers providers, GraphBuilderConfiguration graphBuilderConfig, AllowAssumptions allowAssumptions) {
-        super(providers.getMetaAccess(), providers.getConstantReflection(), providers.getStampProvider());
+    public CachingPEGraphDecoder(Providers providers, GraphBuilderConfiguration graphBuilderConfig, AllowAssumptions allowAssumptions, Architecture architecture) {
+        super(providers.getMetaAccess(), providers.getConstantReflection(), providers.getStampProvider(), architecture);
 
         this.providers = providers;
         this.graphBuilderConfig = graphBuilderConfig;
@@ -63,7 +64,7 @@
             PhaseContext context = new PhaseContext(providers);
             new CanonicalizerPhase().apply(graph, context);
 
-            EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph);
+            EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, architecture);
             graphCache.put(method, encodedGraph);
             return encodedGraph;
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PEGraphDecoder.java	Thu Apr 16 22:38:52 2015 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PEGraphDecoder.java	Thu Apr 16 16:07:34 2015 -0700
@@ -298,7 +298,8 @@
         }
     }
 
-    public PEGraphDecoder(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, StampProvider stampProvider) {
+    public PEGraphDecoder(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, StampProvider stampProvider, Architecture architecture) {
+        super(architecture);
         this.metaAccess = metaAccess;
         this.constantReflection = constantReflection;
         this.stampProvider = stampProvider;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Thu Apr 16 22:38:52 2015 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Thu Apr 16 16:07:34 2015 -0700
@@ -29,6 +29,7 @@
 import java.lang.invoke.*;
 import java.util.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.compiler.common.*;
@@ -71,6 +72,7 @@
     public static final StableOptionValue<Boolean> GraphPE = new StableOptionValue<>(false);
 
     private final Providers providers;
+    private final Architecture architecture;
     private final CanonicalizerPhase canonicalizer;
     private final SnippetReflectionProvider snippetReflection;
     private final ResolvedJavaMethod callDirectMethod;
@@ -79,8 +81,9 @@
     private final ResolvedJavaMethod callRootMethod;
     private final GraphBuilderConfiguration configForRoot;
 
-    public PartialEvaluator(Providers providers, GraphBuilderConfiguration configForRoot, SnippetReflectionProvider snippetReflection) {
+    public PartialEvaluator(Providers providers, GraphBuilderConfiguration configForRoot, SnippetReflectionProvider snippetReflection, Architecture architecture) {
         this.providers = providers;
+        this.architecture = architecture;
         this.canonicalizer = new CanonicalizerPhase();
         this.snippetReflection = snippetReflection;
         this.callDirectMethod = providers.getMetaAccess().lookupJavaMethod(OptimizedCallTarget.getCallDirectMethod());
@@ -337,7 +340,7 @@
         plugins.setInlineInvokePlugin(new ParsingInlineInvokePlugin((ReplacementsImpl) providers.getReplacements(), parsingInvocationPlugins, loopExplosionPlugin,
                         !PrintTruffleExpansionHistogram.getValue()));
 
-        CachingPEGraphDecoder decoder = new CachingPEGraphDecoder(providers, newConfig, AllowAssumptions.from(graph.getAssumptions() != null));
+        CachingPEGraphDecoder decoder = new CachingPEGraphDecoder(providers, newConfig, AllowAssumptions.from(graph.getAssumptions() != null), architecture);
 
         ParameterPlugin parameterPlugin = new InterceptReceiverPlugin(callTarget);
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Thu Apr 16 22:38:52 2015 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Thu Apr 16 16:07:34 2015 -0700
@@ -99,7 +99,7 @@
         Plugins plugins = new Plugins(phase.getGraphBuilderConfig().getPlugins());
         this.config = GraphBuilderConfiguration.getDefault(plugins).withSkippedExceptionTypes(skippedExceptionTypes);
 
-        this.partialEvaluator = new PartialEvaluator(providers, config, Graal.getRequiredCapability(SnippetReflectionProvider.class));
+        this.partialEvaluator = new PartialEvaluator(providers, config, Graal.getRequiredCapability(SnippetReflectionProvider.class), backend.getTarget().arch);
 
         if (Debug.isEnabled()) {
             DebugEnvironment.initialize(System.out);