changeset 16028:bca2ed3b97fd

skip initialization and use arraycopy for cloning arrays
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Wed, 04 Jun 2014 17:21:09 -0700
parents 5da8c17a9767
children 8bbfddf8483f
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java
diffstat 6 files changed, 84 insertions(+), 65 deletions(-) [+]
line wrap: on
line diff
--- 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;
--- 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<Kind, ForeignCallDescriptor>[][] 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);
     }
 }
--- 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) {
--- 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;
     }
 }
--- 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);
+    }
+
 }
--- 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() {