# HG changeset patch # User Gilles Duboscq # Date 1327932529 -3600 # Node ID ccbdd90bf35610a69ec9de35de93fd2bacd0f0ff # Parent cd2b68ef8e23f1873705cae06b6c94d0fbfa19b3 Add new arraycopy intrinsics : Object (when no storecheck required), Float and Double diff -r cd2b68ef8e23 -r ccbdd90bf356 graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/ArrayCopySnippets.java --- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/ArrayCopySnippets.java Mon Jan 30 13:06:11 2012 +0100 +++ b/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/ArrayCopySnippets.java Mon Jan 30 15:08:49 2012 +0100 @@ -154,6 +154,29 @@ } @Snippet + public static void arraycopy(float[] src, int srcPos, float[] dest, int destPos, int length) { + if (src == null || dest == null) { + throw new NullPointerException(); + } + if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { + throw new IndexOutOfBoundsException(); + } + if (src == dest && srcPos < destPos) { // bad aliased case + if ((length & 0x01) == 0) { + copyLongsDown(src, srcPos * 4L, dest, destPos * 4L, length >> 1); + } else { + copyIntsDown(src, srcPos * 4L, dest, destPos * 4L, length); + } + } else { + if ((length & 0x01) == 0) { + copyLongsUp(src, srcPos * 4L, dest, destPos * 4L, length >> 1); + } else { + copyIntsUp(src, srcPos * 4L, dest, destPos * 4L, length); + } + } + } + + @Snippet public static void arraycopy(long[] src, int srcPos, long[] dest, int destPos, int length) { if (src == null || dest == null) { throw new NullPointerException(); @@ -169,6 +192,37 @@ } @Snippet + public static void arraycopy(double[] src, int srcPos, double[] dest, int destPos, int length) { + if (src == null || dest == null) { + throw new NullPointerException(); + } + if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { + throw new IndexOutOfBoundsException(); + } + if (src == dest && srcPos < destPos) { // bad aliased case + copyLongsDown(src, srcPos * 8L, dest, destPos * 8L, length); + } else { + copyLongsUp(src, srcPos * 8L, dest, destPos * 8L, length); + } + } + + // Does NOT perform store checks + @Snippet + public static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) { + if (src == null || dest == null) { + throw new NullPointerException(); + } + if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { + throw new IndexOutOfBoundsException(); + } + if (src == dest && srcPos < destPos) { // bad aliased case + copyObjectsDown(src, srcPos * 8L, dest, destPos * 8L, length); + } else { + copyObjectsUp(src, srcPos * 8L, dest, destPos * 8L, length); + } + } + + @Snippet public static void copyBytesDown(Object src, int srcPos, Object dest, int destPos, int length) { long header = ArrayHeaderSizeNode.sizeFor(CiKind.Byte); for (long i = length - 1; i >= 0; i--) { @@ -204,6 +258,16 @@ } } + // Does NOT perform store checks + @Snippet + public static void copyObjectsDown(Object src, long srcOffset, Object dest, long destOffset, int length) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Object); + for (long i = (length - 1) * 8; i >= 0; i -= 8) { + Object a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Object); + UnsafeStoreNode.store(dest, i + (destOffset + header), a, CiKind.Object); + } + } + /** * Copies {@code length} bytes from {@code src} starting at {@code srcPos} to {@code dest} starting at {@code destPos}. * @param src source object @@ -255,4 +319,14 @@ UnsafeStoreNode.store(dest, i + (destOffset + header), a.longValue(), CiKind.Long); } } + + // Does NOT perform store checks + @Snippet + public static void copyObjectsUp(Object src, long srcOffset, Object dest, long destOffset, int length) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Object); + for (long i = 0; i < length * 8L; i += 8) { + Object a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Object); + UnsafeStoreNode.store(dest, i + (destOffset + header), a, CiKind.Object); + } + } } diff -r cd2b68ef8e23 -r ccbdd90bf356 graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/IntrinsifyArrayCopyPhase.java --- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/IntrinsifyArrayCopyPhase.java Mon Jan 30 13:06:11 2012 +0100 +++ b/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/IntrinsifyArrayCopyPhase.java Mon Jan 30 15:08:49 2012 +0100 @@ -24,6 +24,7 @@ import java.lang.reflect.*; +import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; import com.oracle.max.graal.compiler.phases.*; import com.oracle.max.graal.compiler.util.*; @@ -40,6 +41,9 @@ private RiResolvedMethod charArrayCopy; private RiResolvedMethod intArrayCopy; private RiResolvedMethod longArrayCopy; + private RiResolvedMethod floatArrayCopy; + private RiResolvedMethod doubleArrayCopy; + private RiResolvedMethod objectArrayCopy; public IntrinsifyArrayCopyPhase(GraalRuntime runtime) { this.runtime = runtime; @@ -49,6 +53,9 @@ shortArrayCopy = getArrayCopySnippet(runtime, short.class); intArrayCopy = getArrayCopySnippet(runtime, int.class); longArrayCopy = getArrayCopySnippet(runtime, long.class); + floatArrayCopy = getArrayCopySnippet(runtime, float.class); + doubleArrayCopy = getArrayCopySnippet(runtime, double.class); + objectArrayCopy = getArrayCopySnippet(runtime, Object.class); arrayCopy = runtime.getRiMethod(System.class.getDeclaredMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class)); } catch (SecurityException e) { e.printStackTrace(); @@ -78,19 +85,29 @@ if (srcDeclaredType != null && srcDeclaredType.isArrayClass() && destDeclaredType != null - && destDeclaredType.isArrayClass() - && srcDeclaredType.componentType() == destDeclaredType.componentType()) { - Class componentType = srcDeclaredType.componentType().toJava(); - if (componentType.equals(int.class)) { - snippetMethod = intArrayCopy; - } else if (componentType.equals(char.class)) { - snippetMethod = charArrayCopy; - } else if (componentType.equals(long.class)) { - snippetMethod = longArrayCopy; - } else if (componentType.equals(byte.class)) { - snippetMethod = byteArrayCopy; - } else if (componentType.equals(short.class)) { - snippetMethod = shortArrayCopy; + && destDeclaredType.isArrayClass()) { + CiKind componentKind = srcDeclaredType.componentType().kind(false); + if (srcDeclaredType.componentType() == destDeclaredType.componentType()) { + if (componentKind == CiKind.Int) { + snippetMethod = intArrayCopy; + } else if (componentKind == CiKind.Char) { + snippetMethod = charArrayCopy; + } else if (componentKind == CiKind.Long) { + snippetMethod = longArrayCopy; + } else if (componentKind == CiKind.Byte) { + snippetMethod = byteArrayCopy; + } else if (componentKind == CiKind.Short) { + snippetMethod = shortArrayCopy; + } else if (componentKind == CiKind.Float) { + snippetMethod = floatArrayCopy; + } else if (componentKind == CiKind.Double) { + snippetMethod = doubleArrayCopy; + } else if (componentKind == CiKind.Object) { + snippetMethod = objectArrayCopy; + } + } else if (componentKind == CiKind.Object + && srcDeclaredType.componentType().isSubtypeOf(destDeclaredType.componentType())) { + snippetMethod = objectArrayCopy; } } }