# HG changeset patch # User Christian Wimmer # Date 1429225654 25200 # Node ID acc86d08e1ccbc5732aad27bf59ef6ed3b8a149b # Parent fdf55f1ffc590c77408c4594195b1d719cdc42a6 Support Sparc without the need of a temporary ByteBuffer for every memory access diff -r fdf55f1ffc59 -r acc86d08e1cc 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 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; } diff -r fdf55f1ffc59 -r acc86d08e1cc 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 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)); + } +} diff -r fdf55f1ffc59 -r acc86d08e1cc graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraphEncoderTest.java --- 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); } } } diff -r fdf55f1ffc59 -r acc86d08e1cc graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeWriterTest.java --- 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)); } } diff -r fdf55f1ffc59 -r acc86d08e1cc graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java --- 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); diff -r fdf55f1ffc59 -r acc86d08e1cc graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphEncoder.java --- 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(); diff -r fdf55f1ffc59 -r acc86d08e1cc graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CachingPEGraphDecoder.java --- 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 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; diff -r fdf55f1ffc59 -r acc86d08e1cc graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PEGraphDecoder.java --- 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; diff -r fdf55f1ffc59 -r acc86d08e1cc graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- 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 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); diff -r fdf55f1ffc59 -r acc86d08e1cc graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java --- 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);