# HG changeset patch # User Doug Simon # Date 1357913131 -3600 # Node ID 8f7be0c45a82f71798ecdc5cb9ddff43ca132ba1 # Parent 13d5545e24e237aa24fd327c9da58e00715f3ae5 arraycopy cannot be intrinsified if the destination array type is not exact diff -r 13d5545e24e2 -r 8f7be0c45a82 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/ArrayCopyIntrinsificationTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/ArrayCopyIntrinsificationTest.java Fri Jan 11 12:47:37 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/ArrayCopyIntrinsificationTest.java Fri Jan 11 15:05:31 2013 +0100 @@ -153,9 +153,24 @@ } @Test - public void testObject() { + public void testObjectExact() { Object[] src = {"one", "two", "three", new ArrayList<>(), new HashMap<>()}; - testHelper("objectArraycopy", src); + test("exactObjectArraycopy", (Object) src); + } + + @Test + public void testString() { + String[] src = {"one", "two", "three"}; + test("stringArraycopy", src, 0, new String[src.length], 0, src.length); + } + + @Test + public void testObject() { + mustIntrinsify = false; // a call to arraycopy where dest is not an exact type will not be intrinsified + Object[] src = {"one", "two", "three", new ArrayList<>(), new HashMap<>()}; + test("objectArraycopy", src, 0, new Object[src.length], 0, src.length); + // Expect ArrayStoreException + test("objectArraycopy", src, 0, new String[src.length], 0, src.length); } private static Object newArray(Object proto, int length) { @@ -188,6 +203,17 @@ return dst; } + public static Object[] exactObjectArraycopy(Object[] src) { + Object[] dst = new Object[src.length]; + System.arraycopy(src, 0, dst, 0, src.length); + return dst; + } + + public static Object[] stringArraycopy(String[] src, int srcPos, String[] dst, int dstPos, int length) { + System.arraycopy(src, srcPos, dst, dstPos, length); + return dst; + } + public static boolean[] booleanArraycopy(boolean[] src, int srcPos, boolean[] dst, int dstPos, int length) { System.arraycopy(src, srcPos, dst, dstPos, length); return dst; diff -r 13d5545e24e2 -r 8f7be0c45a82 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java Fri Jan 11 12:47:37 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java Fri Jan 11 15:05:31 2013 +0100 @@ -31,6 +31,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; @@ -82,34 +83,37 @@ ValueNode src = methodCallTarget.arguments().get(0); ValueNode dest = methodCallTarget.arguments().get(2); assert src != null && dest != null; - ResolvedJavaType srcType = src.objectStamp().type(); - ResolvedJavaType destType = dest.objectStamp().type(); + ObjectStamp srcStamp = src.objectStamp(); + ObjectStamp destStamp = dest.objectStamp(); + ResolvedJavaType srcType = srcStamp.type(); + ResolvedJavaType destType = destStamp.type(); if (srcType != null && srcType.isArray() && destType != null && destType.isArray()) { Kind componentKind = srcType.getComponentType().getKind(); - if (srcType.getComponentType() == destType.getComponentType()) { - if (componentKind == Kind.Int) { - snippetMethod = intArrayCopy; - } else if (componentKind == Kind.Char) { - snippetMethod = charArrayCopy; - } else if (componentKind == Kind.Long) { - snippetMethod = longArrayCopy; - } else if (componentKind == Kind.Byte) { - snippetMethod = byteArrayCopy; - } else if (componentKind == Kind.Short) { - snippetMethod = shortArrayCopy; - } else if (componentKind == Kind.Float) { - snippetMethod = floatArrayCopy; - } else if (componentKind == Kind.Double) { - snippetMethod = doubleArrayCopy; - } else if (componentKind == Kind.Object) { + if (componentKind != Kind.Object) { + if (srcType.getComponentType() == destType.getComponentType()) { + if (componentKind == Kind.Int) { + snippetMethod = intArrayCopy; + } else if (componentKind == Kind.Char) { + snippetMethod = charArrayCopy; + } else if (componentKind == Kind.Long) { + snippetMethod = longArrayCopy; + } else if (componentKind == Kind.Byte) { + snippetMethod = byteArrayCopy; + } else if (componentKind == Kind.Short) { + snippetMethod = shortArrayCopy; + } else if (componentKind == Kind.Float) { + snippetMethod = floatArrayCopy; + } else if (componentKind == Kind.Double) { + snippetMethod = doubleArrayCopy; + } + } + } else if (destType.getComponentType().isAssignableFrom(srcType.getComponentType())) { + if (destStamp.isExactType()) { snippetMethod = objectArrayCopy; } - } else if (componentKind == Kind.Object - && destType.getComponentType().isAssignableFrom(srcType.getComponentType())) { - snippetMethod = objectArrayCopy; } } }