# HG changeset patch # User Tom Rodriguez # Date 1401927669 25200 # Node ID bca2ed3b97fd71f0624fefa08791ef113a191e10 # Parent 5da8c17a97675d44541ec533ad6bf1d984b4781e skip initialization and use arraycopy for cloning arrays diff -r 5da8c17a9767 -r bca2ed3b97fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Tue Jun 03 18:15:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Wed Jun 04 17:21:09 2014 -0700 @@ -1390,14 +1390,14 @@ @HotSpotVMField(name = "StubRoutines::_arrayof_jshort_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jshortAlignedArraycopy; @HotSpotVMField(name = "StubRoutines::_arrayof_jint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jintAlignedArraycopy; @HotSpotVMField(name = "StubRoutines::_arrayof_jlong_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jlongAlignedArraycopy; - @HotSpotVMField(name = "StubRoutines::_arrayof_oop_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long alignedOopAlignedArraycopy; - @HotSpotVMField(name = "StubRoutines::_arrayof_oop_arraycopy_uninit", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long alignedOopArraycopyUninit; + @HotSpotVMField(name = "StubRoutines::_arrayof_oop_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long oopAlignedArraycopy; + @HotSpotVMField(name = "StubRoutines::_arrayof_oop_arraycopy_uninit", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long oopAlignedArraycopyUninit; @HotSpotVMField(name = "StubRoutines::_arrayof_jbyte_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jbyteAlignedDisjointArraycopy; @HotSpotVMField(name = "StubRoutines::_arrayof_jshort_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jshortAlignedDisjointArraycopy; @HotSpotVMField(name = "StubRoutines::_arrayof_jint_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jintAlignedDisjointArraycopy; @HotSpotVMField(name = "StubRoutines::_arrayof_jlong_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jlongAlignedDisjointArraycopy; - @HotSpotVMField(name = "StubRoutines::_arrayof_oop_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long alignedOopDisjointArraycopy; - @HotSpotVMField(name = "StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long alignedOopDisjointArraycopyUninit; + @HotSpotVMField(name = "StubRoutines::_arrayof_oop_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long oopAlignedDisjointArraycopy; + @HotSpotVMField(name = "StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long oopAlignedDisjointArraycopyUninit; @HotSpotVMField(name = "StubRoutines::_checkcast_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long checkcastArraycopy; @HotSpotVMField(name = "StubRoutines::_checkcast_arraycopy_uninit", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long checkcastArraycopyUninit; @HotSpotVMField(name = "StubRoutines::_unsafe_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long unsafeArraycopy; diff -r 5da8c17a9767 -r bca2ed3b97fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Tue Jun 03 18:15:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Wed Jun 04 17:21:09 2014 -0700 @@ -64,12 +64,18 @@ stub.getLinkage().setCompiledStub(stub); } - public static ForeignCallDescriptor lookupArraycopyDescriptor(Kind kind, boolean aligned, boolean disjoint) { + public static ForeignCallDescriptor lookupArraycopyDescriptor(Kind kind, boolean aligned, boolean disjoint, boolean uninit) { + if (uninit) { + assert kind == Kind.Object; + return uninitObjectArraycopyDescriptors[aligned ? 1 : 0][disjoint ? 1 : 0]; + } return arraycopyDescriptors[aligned ? 1 : 0][disjoint ? 1 : 0].get(kind); } @SuppressWarnings("unchecked") private static final EnumMap[][] arraycopyDescriptors = new EnumMap[2][2]; + private static final ForeignCallDescriptor[][] uninitObjectArraycopyDescriptors = new ForeignCallDescriptor[2][2]; + static { // Populate the EnumMap instances for (int i = 0; i < arraycopyDescriptors.length; i++) { @@ -79,19 +85,28 @@ } } - private static ForeignCallDescriptor registerArraycopyDescriptor(Kind kind, boolean aligned, boolean disjoint) { - String name = kind + (aligned ? "Aligned" : "") + (disjoint ? "Disjoint" : "") + "Arraycopy"; + private static ForeignCallDescriptor registerArraycopyDescriptor(Kind kind, boolean aligned, boolean disjoint, boolean uninit) { + String name = kind + (aligned ? "Aligned" : "") + (disjoint ? "Disjoint" : "") + (uninit ? "Uninit" : "") + "Arraycopy"; ForeignCallDescriptor desc = new ForeignCallDescriptor(name, void.class, Word.class, Word.class, Word.class); - arraycopyDescriptors[aligned ? 1 : 0][disjoint ? 1 : 0].put(kind, desc); + if (uninit) { + assert kind == Kind.Object; + uninitObjectArraycopyDescriptors[aligned ? 1 : 0][disjoint ? 1 : 0] = desc; + } else { + arraycopyDescriptors[aligned ? 1 : 0][disjoint ? 1 : 0].put(kind, desc); + } return desc; } private void registerArrayCopy(Kind kind, long routine, long alignedRoutine, long disjointRoutine, long alignedDisjointRoutine) { + registerArrayCopy(kind, routine, alignedRoutine, disjointRoutine, alignedDisjointRoutine, false); + } + + private void registerArrayCopy(Kind kind, long routine, long alignedRoutine, long disjointRoutine, long alignedDisjointRoutine, boolean uninit) { LocationIdentity killed = NamedLocationIdentity.getArrayLocation(kind); - registerForeignCall(registerArraycopyDescriptor(kind, false, false), routine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed); - registerForeignCall(registerArraycopyDescriptor(kind, true, false), alignedRoutine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed); - registerForeignCall(registerArraycopyDescriptor(kind, false, true), disjointRoutine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed); - registerForeignCall(registerArraycopyDescriptor(kind, true, true), alignedDisjointRoutine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed); + registerForeignCall(registerArraycopyDescriptor(kind, false, false, uninit), routine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed); + registerForeignCall(registerArraycopyDescriptor(kind, true, false, uninit), alignedRoutine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed); + registerForeignCall(registerArraycopyDescriptor(kind, false, true, uninit), disjointRoutine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed); + registerForeignCall(registerArraycopyDescriptor(kind, true, true, uninit), alignedDisjointRoutine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed); } public void initialize(HotSpotProviders providers, HotSpotVMConfig c) { @@ -155,6 +170,7 @@ registerArrayCopy(Kind.Float, c.jintArraycopy, c.jintAlignedArraycopy, c.jintDisjointArraycopy, c.jintAlignedDisjointArraycopy); registerArrayCopy(Kind.Long, c.jlongArraycopy, c.jlongAlignedArraycopy, c.jlongDisjointArraycopy, c.jlongAlignedDisjointArraycopy); registerArrayCopy(Kind.Double, c.jlongArraycopy, c.jlongAlignedArraycopy, c.jlongDisjointArraycopy, c.jlongAlignedDisjointArraycopy); - registerArrayCopy(Kind.Object, c.oopArraycopy, c.oopArraycopy, c.oopDisjointArraycopy, c.oopDisjointArraycopy); + registerArrayCopy(Kind.Object, c.oopArraycopy, c.oopAlignedArraycopy, c.oopDisjointArraycopy, c.oopAlignedDisjointArraycopy); + registerArrayCopy(Kind.Object, c.oopArraycopyUninit, c.oopAlignedArraycopyUninit, c.oopDisjointArraycopyUninit, c.oopAlignedDisjointArraycopyUninit, true); } } diff -r 5da8c17a9767 -r bca2ed3b97fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java Tue Jun 03 18:15:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java Wed Jun 04 17:21:09 2014 -0700 @@ -40,7 +40,7 @@ import com.oracle.graal.runtime.*; @NodeInfo(allowedUsageTypes = {InputType.Memory}) -public final class ArrayCopyCallNode extends ArrayRangeWriteNode implements Lowerable, MemoryCheckpoint.Single { +public final class ArrayCopyCallNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single { @Input private ValueNode src; @Input private ValueNode srcPos; @@ -49,10 +49,15 @@ @Input private ValueNode length; private Kind elementKind; + + /** + * Aligned means that the offset of the copy is heap word aligned. + */ private boolean aligned; private boolean disjoint; + private boolean uninitialized; - private ArrayCopyCallNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind, boolean aligned, boolean disjoint) { + private ArrayCopyCallNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind, boolean aligned, boolean disjoint, boolean uninitialized) { super(StampFactory.forVoid()); assert elementKind != null; this.src = src; @@ -63,10 +68,11 @@ this.elementKind = elementKind; this.aligned = aligned; this.disjoint = disjoint; + this.uninitialized = uninitialized; } - private ArrayCopyCallNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind) { - this(src, srcPos, dest, destPos, length, elementKind, false, false); + private ArrayCopyCallNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind, boolean disjoint) { + this(src, srcPos, dest, destPos, length, elementKind, false, disjoint, false); } public ValueNode getSource() { @@ -85,31 +91,10 @@ return destPos; } - @Override - public ValueNode getArray() { - return dest; - } - - @Override - public ValueNode getIndex() { - return destPos; - } - - @Override public ValueNode getLength() { return length; } - @Override - public boolean isObjectArray() { - return elementKind == Kind.Object; - } - - @Override - public boolean isInitialization() { - return false; - } - public void addSnippetArguments(Arguments args) { args.add("src", src); args.add("srcPos", srcPos); @@ -137,7 +122,7 @@ public void lower(LoweringTool tool) { if (graph().getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { updateAlignedDisjoint(); - ForeignCallDescriptor desc = HotSpotHostForeignCallsProvider.lookupArraycopyDescriptor(elementKind, isAligned(), isDisjoint()); + ForeignCallDescriptor desc = HotSpotHostForeignCallsProvider.lookupArraycopyDescriptor(elementKind, isAligned(), isDisjoint(), isUninitialized()); StructuredGraph graph = graph(); ValueNode srcAddr = computeBase(getSource(), getSourcePosition()); ValueNode destAddr = computeBase(getDestination(), getDestinationPosition()); @@ -161,11 +146,20 @@ } @NodeIntrinsic - public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantNodeParameter Kind elementKind); + private static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantNodeParameter Kind elementKind, @ConstantNodeParameter boolean aligned, + @ConstantNodeParameter boolean disjoint, @ConstantNodeParameter boolean uninitialized); + + public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantNodeParameter Kind elementKind, boolean aligned, boolean disjoint) { + arraycopy(src, srcPos, dest, destPos, length, elementKind, aligned, disjoint, false); + } - @NodeIntrinsic - public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantNodeParameter Kind elementKind, @ConstantNodeParameter boolean aligned, - @ConstantNodeParameter boolean disjoint); + public static void disjointArraycopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantNodeParameter Kind elementKind) { + arraycopy(src, srcPos, dest, destPos, length, elementKind, false, true, false); + } + + public static void disjointUninitializedArraycopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantNodeParameter Kind elementKind) { + arraycopy(src, srcPos, dest, destPos, length, elementKind, false, true, true); + } public boolean isAligned() { return aligned; @@ -175,6 +169,10 @@ return disjoint; } + public boolean isUninitialized() { + return uninitialized; + } + public void updateAlignedDisjoint() { Kind componentKind = elementKind; if (srcPos == destPos) { diff -r 5da8c17a9767 -r bca2ed3b97fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Tue Jun 03 18:15:43 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Wed Jun 04 17:21:09 2014 -0700 @@ -53,46 +53,36 @@ @Snippet(removeAllFrameStates = true) public static byte[] byteArrayClone(byte[] src) { - byte[] result = new byte[src.length]; - for (int i = 0; i < result.length; i++) { - result[i] = src[i]; - } + byte[] result = (byte[]) NewArrayNode.newUninitializedArray(Byte.TYPE, src.length); + ArrayCopyCallNode.disjointArraycopy(src, 0, result, 0, src.length, Kind.Byte); return result; } @Snippet(removeAllFrameStates = true) public static char[] charArrayClone(char[] src) { - char[] result = new char[src.length]; - for (int i = 0; i < result.length; i++) { - result[i] = src[i]; - } + char[] result = (char[]) NewArrayNode.newUninitializedArray(Character.TYPE, src.length); + ArrayCopyCallNode.disjointArraycopy(src, 0, result, 0, src.length, Kind.Char); return result; } @Snippet(removeAllFrameStates = true) public static int[] intArrayClone(int[] src) { - int[] result = new int[src.length]; - for (int i = 0; i < result.length; i++) { - result[i] = src[i]; - } + int[] result = (int[]) NewArrayNode.newUninitializedArray(Integer.TYPE, src.length); + ArrayCopyCallNode.disjointArraycopy(src, 0, result, 0, src.length, Kind.Int); return result; } @Snippet(removeAllFrameStates = true) public static long[] longArrayClone(long[] src) { - long[] result = new long[src.length]; - for (int i = 0; i < result.length; i++) { - result[i] = src[i]; - } + long[] result = (long[]) NewArrayNode.newUninitializedArray(Long.TYPE, src.length); + ArrayCopyCallNode.disjointArraycopy(src, 0, result, 0, src.length, Kind.Long); return result; } @Snippet(removeAllFrameStates = true) public static Object[] objectArrayClone(Object[] src) { - Object[] result = (Object[]) DynamicNewArrayNode.newArray(GuardingPiNode.guardingNonNull(src.getClass().getComponentType()), src.length); - for (int i = 0; i < result.length; i++) { - result[i] = src[i]; - } + Object[] result = (Object[]) DynamicNewArrayNode.newUninitializedArray(GuardingPiNode.guardingNonNull(src.getClass().getComponentType()), src.length); + ArrayCopyCallNode.disjointUninitializedArraycopy(src, 0, result, 0, src.length, Kind.Object); return result; } } diff -r 5da8c17a9767 -r bca2ed3b97fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java Tue Jun 03 18:15:43 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java Wed Jun 04 17:21:09 2014 -0700 @@ -72,4 +72,12 @@ public static Object newArray(Class componentType, int length) { return Array.newInstance(componentType, length); } + + @NodeIntrinsic + private static native Object newArray(Class componentType, int length, @ConstantNodeParameter boolean fillContents); + + public static Object newUninitializedArray(Class componentType, int length) { + return newArray(componentType, length, false); + } + } diff -r 5da8c17a9767 -r bca2ed3b97fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Tue Jun 03 18:15:43 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Wed Jun 04 17:21:09 2014 -0700 @@ -39,7 +39,7 @@ /** * Constructs a new NewArrayNode. - * + * * @param elementType the the type of the elements of the newly created array (not the type of * the array itself). * @param length the node that produces the length for this allocation. @@ -49,9 +49,16 @@ super(StampFactory.exactNonNull(elementType.getArrayClass()), length, fillContents); } + @NodeIntrinsic + static private native Object newArray(@ConstantNodeParameter Class elementType, int length, @ConstantNodeParameter boolean fillContents); + + public static Object newUninitializedArray(Class elementType, int length) { + return newArray(elementType, length, false); + } + /** * Gets the element type of the array. - * + * * @return the element type of the array */ public ResolvedJavaType elementType() {