# HG changeset patch # User Christos Kotselidis # Date 1364389383 -3600 # Node ID ebf95eed9eef69b9dd7c378810754802ebfaf107 # Parent cc433555c5a3347a868ea198b46bbceafe4e8f78 -ArrayCopy WB Intrinsics diff -r cc433555c5a3 -r ebf95eed9eef graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPost.java --- 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); } diff -r cc433555c5a3 -r ebf95eed9eef graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java --- 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;