changeset 8523:ebf95eed9eef

-ArrayCopy WB Intrinsics
author Christos Kotselidis <christos.kotselidis@oracle.com>
date Wed, 27 Mar 2013 14:03:03 +0100
parents cc433555c5a3
children ecb2446232ac 0d91be9af2bc
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPost.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java
diffstat 2 files changed, 57 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPost.java	Tue Mar 26 18:32:58 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPost.java	Wed Mar 27 14:03:03 2013 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -32,6 +34,7 @@
     @Input private ValueNode object;
     @Input private ValueNode value;
     @Input private LocationNode location;
+    @Input private ValueNode length;
     private final boolean precise;
 
     public ValueNode getObject() {
@@ -42,6 +45,10 @@
         return value;
     }
 
+    public ValueNode getLength() {
+        return length;
+    }
+
     public LocationNode getLocation() {
         return location;
     }
@@ -56,9 +63,33 @@
         this.value = value;
         this.location = location;
         this.precise = precise;
+        this.length = null;
+
+    }
+
+    public WriteBarrierPost(ValueNode array, ValueNode value, ValueNode index, ValueNode length) {
+        super(StampFactory.forVoid());
+        this.object = array;
+        this.location = IndexedLocationNode.create(LocationNode.getArrayLocation(Kind.Object), Kind.Object, arrayBaseOffset(Kind.Object), index, array.graph(), arrayIndexScale(Kind.Object));
+        this.length = length;
+        this.value = value;
+        this.precise = true;
     }
 
+    @Override
     public void lower(LoweringTool generator) {
-        generator.getRuntime().lower(this, generator);
+        if (getLength() == null) {
+            generator.getRuntime().lower(this, generator);
+        } else {
+            StructuredGraph graph = (StructuredGraph) this.graph();
+            if (useG1GC()) {
+                graph.replaceFixedWithFixed(this, graph().add(new WriteBarrierPost(getObject(), getValue(), getLocation(), usePrecise())));
+            } else {
+                graph.replaceFixedWithFixed(this, graph().add(new ArrayWriteBarrier(getObject(), getLocation())));
+            }
+        }
     }
+
+    @NodeIntrinsic
+    public static native void arrayCopyWriteBarrier(Object array, Object value, int index, int length);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Tue Mar 26 18:32:58 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Wed Mar 27 14:03:03 2013 +0100
@@ -236,9 +236,8 @@
         }
     }
 
-    // Does NOT perform store checks
     @Snippet
-    public static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) {
+    private static void arrayObjectCopy(Object src, int srcPos, Object dest, int destPos, int length) {
         objectCounter.inc();
         checkNonNull(src);
         checkNonNull(dest);
@@ -247,44 +246,49 @@
         int header = arrayBaseOffset(Kind.Object);
         if (src == dest && srcPos < destPos) { // bad aliased case
             long start = (long) (length - 1) * scale;
+            int j = length - 1;
             for (long i = start; i >= 0; i -= scale) {
                 Object a = UnsafeLoadNode.load(src, header, i + (long) srcPos * scale, Kind.Object);
                 DirectObjectStoreNode.storeObject(dest, header, i + (long) destPos * scale, a);
+                WriteBarrierPost.arrayCopyWriteBarrier(dest, a, j, length);
+                j--;
             }
         } else {
             long end = (long) length * scale;
+            int j = 0;
             for (long i = 0; i < end; i += scale) {
                 Object a = UnsafeLoadNode.load(src, header, i + (long) srcPos * scale, Kind.Object);
                 DirectObjectStoreNode.storeObject(dest, header, i + (long) destPos * scale, a);
-            }
-        }
-        if (length > 0) {
-            int cardShift = cardTableShift();
-            long cardStart = cardTableStart();
-            long dstAddr = GetObjectAddressNode.get(dest);
-            long start = (dstAddr + header + (long) destPos * scale) >>> cardShift;
-            long end = (dstAddr + header + ((long) destPos + length - 1) * scale) >>> cardShift;
-            long count = end - start + 1;
-            while (count-- > 0) {
-                DirectStoreNode.store((start + cardStart) + count, false, Kind.Boolean);
+                WriteBarrierPost.arrayCopyWriteBarrier(dest, a, j, length);
+                j++;
             }
         }
     }
 
+    // Does NOT perform store checks
+    @Snippet
+    public static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) {
+        arrayObjectCopy(src, srcPos, dest, destPos, length);
+    }
+
     @Snippet
     public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) {
-
-        // loading the hubs also checks for nullness
         Word srcHub = loadHub(src);
         Word destHub = loadHub(dest);
-
         int layoutHelper = checkArrayType(srcHub);
+        int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
+        final boolean isObjectArray = ((layoutHelper & layoutHelperElementTypePrimitiveInPlace()) == 0);
         if (srcHub.equal(destHub) && src != dest) {
             probability(FAST_PATH_PROBABILITY);
-
             checkLimits(src, srcPos, dest, destPos, length);
-
-            arraycopyInnerloop(src, srcPos, dest, destPos, length, layoutHelper);
+            if (isObjectArray) {
+                genericObjectExactCallCounter.inc();
+                probability(FAST_PATH_PROBABILITY);
+                arrayObjectCopy(src, srcPos, dest, destPos, length);
+            } else {
+                genericPrimitiveCallCounter.inc();
+                arraycopyInnerloop(src, srcPos, dest, destPos, length, layoutHelper);
+            }
         } else {
             genericObjectCallCounter.inc();
             System.arraycopy(src, srcPos, dest, destPos, length);
@@ -312,29 +316,11 @@
             srcOffset = srcOffset.add(1);
         }
         while (destOffset.belowThan(destEnd)) {
-            destOffset.writeWord(0, srcOffset.readWord(0, UNKNOWN_LOCATION), ANY_LOCATION);
+            Word word = srcOffset.readWord(0, UNKNOWN_LOCATION);
+            destOffset.writeWord(0, word, ANY_LOCATION);
             destOffset = destOffset.add(wordSize());
             srcOffset = srcOffset.add(wordSize());
         }
-
-        if ((layoutHelper & layoutHelperElementTypePrimitiveInPlace()) != 0) {
-            genericPrimitiveCallCounter.inc();
-
-        } else {
-            probability(LIKELY_PROBABILITY);
-            genericObjectExactCallCounter.inc();
-
-            if (length > 0) {
-                int cardShift = cardTableShift();
-                long cardStart = cardTableStart();
-                Word destCardOffset = destStart.unsignedShiftRight(cardShift).add(Word.unsigned(cardStart));
-                Word destCardEnd = destEnd.subtract(1).unsignedShiftRight(cardShift).add(Word.unsigned(cardStart));
-                while (destCardOffset.belowOrEqual(destCardEnd)) {
-                    DirectStoreNode.store(destCardOffset.rawValue(), false, Kind.Boolean);
-                    destCardOffset = destCardOffset.add(1);
-                }
-            }
-        }
     }
 
     private static final SnippetCounter.Group checkCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("System.arraycopy checkInputs") : null;