changeset 10441:6447890af1bf

Merge.
author Doug Simon <doug.simon@oracle.com>
date Thu, 20 Jun 2013 21:11:06 +0200
parents 7a0d4d95f84c (current diff) b724895db5c0 (diff)
children 7381d7427f0f 3754634b49a7 e799aba89b5d a46c3180faed
files graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GenericArrayRangeWriteBarrier.java
diffstat 17 files changed, 701 insertions(+), 218 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Thu Jun 20 17:38:53 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Thu Jun 20 21:11:06 2013 +0200
@@ -37,5 +37,7 @@
         appendPhase(new ExpandLogicPhase());
 
         appendPhase(new DeadCodeEliminationPhase());
+
+        appendPhase(new RemoveValueProxyPhase());
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu Jun 20 17:38:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu Jun 20 21:11:06 2013 +0200
@@ -51,6 +51,8 @@
 import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.Log.*;
 import static com.oracle.graal.replacements.MathSubstitutionsX86.*;
+import static com.oracle.graal.hotspot.nodes.G1PostWriteBarrierStubCall.*;
+import static com.oracle.graal.hotspot.nodes.G1PreWriteBarrierStubCall.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -294,7 +296,8 @@
         linkForeignCall(r, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
         linkForeignCall(r, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
         linkForeignCall(r, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, NOT_REEXECUTABLE, NO_LOCATIONS);
-
+        linkForeignCall(r, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(r, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
         if (IntrinsifyObjectMethods.getValue()) {
             r.registerSubstitutions(ObjectSubstitutions.class);
         }
@@ -325,6 +328,8 @@
         writeBarrierSnippets = new WriteBarrierSnippets.Templates(this, r, graalRuntime.getTarget());
         boxingSnippets = new BoxingSnippets.Templates(this, r, graalRuntime.getTarget());
         exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(this, r, graalRuntime.getTarget());
+
+        r.registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(this, r, graalRuntime.getTarget()));
     }
 
     public HotSpotGraalRuntime getGraalRuntime() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrierStubCall.java	Thu Jun 20 21:11:06 2013 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.nodes;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.word.*;
+
+public class G1PostWriteBarrierStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
+
+    @Input private ValueNode cardAddress;
+    public static final ForeignCallDescriptor G1WBPOSTCALL = new ForeignCallDescriptor("write_barrier_post", void.class, Word.class);
+
+    public G1PostWriteBarrierStubCall(ValueNode cardAddress) {
+        super(StampFactory.forVoid());
+        this.cardAddress = cardAddress;
+    }
+
+    @Override
+    public void generate(LIRGenerator gen) {
+        ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(G1PostWriteBarrierStubCall.G1WBPOSTCALL);
+        gen.emitForeignCall(linkage, this, gen.operand(cardAddress));
+    }
+
+    @NodeIntrinsic
+    public static native void call(Word cardAddress);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrierStubCall.java	Thu Jun 20 21:11:06 2013 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
++ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.nodes;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+
+public class G1PreWriteBarrierStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
+
+    @Input private ValueNode object;
+    public static final ForeignCallDescriptor G1WBPRECALL = new ForeignCallDescriptor("write_barrier_pre", void.class, Object.class);
+
+    public G1PreWriteBarrierStubCall(ValueNode object) {
+        super(StampFactory.forVoid());
+        this.object = object;
+    }
+
+    @Override
+    public void generate(LIRGenerator gen) {
+        ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(G1PreWriteBarrierStubCall.G1WBPRECALL);
+        gen.emitForeignCall(linkage, this, gen.operand(object));
+    }
+
+    @NodeIntrinsic
+    public static native void call(Object hub);
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Thu Jun 20 17:38:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Thu Jun 20 21:11:06 2013 +0200
@@ -41,8 +41,10 @@
         for (CompareAndSwapNode node : graph.getNodes(CompareAndSwapNode.class)) {
             addCASBarriers(node, graph);
         }
-        for (GenericArrayRangeWriteBarrier node : graph.getNodes(GenericArrayRangeWriteBarrier.class)) {
-            addArrayRangeBarriers(node, graph);
+        for (ArrayRangeWriteNode node : graph.getNodes(ArrayRangeWriteNode.class)) {
+            if (node.isObjectArray()) {
+                addArrayRangeBarriers(node, graph);
+            }
         }
     }
 
@@ -69,9 +71,9 @@
         }
     }
 
-    private static void addArrayRangeBarriers(GenericArrayRangeWriteBarrier node, StructuredGraph graph) {
-        SerialArrayRangeWriteBarrier serialArrayRangeWriteBarrier = graph.add(new SerialArrayRangeWriteBarrier(node.getDstObject(), node.getDstPos(), node.getLength()));
-        graph.replaceFixedWithFixed(node, serialArrayRangeWriteBarrier);
+    private static void addArrayRangeBarriers(ArrayRangeWriteNode node, StructuredGraph graph) {
+        SerialArrayRangeWriteBarrier serialArrayRangeWriteBarrier = graph.add(new SerialArrayRangeWriteBarrier(node.getArray(), node.getIndex(), node.getLength()));
+        graph.addAfterFixed(node, serialArrayRangeWriteBarrier);
     }
 
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Thu Jun 20 17:38:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Thu Jun 20 21:11:06 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -76,35 +76,11 @@
     private static final Kind VECTOR_KIND = Kind.Long;
     private static final long VECTOR_SIZE = arrayIndexScale(Kind.Long);
 
-    private static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind) {
+    private static void checkedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind) {
         checkNonNull(src);
         checkNonNull(dest);
         checkLimits(src, srcPos, dest, destPos, length);
-        int header = arrayBaseOffset(baseKind);
-        int elementSize = arrayIndexScale(baseKind);
-        long byteLength = (long) length * elementSize;
-        long nonVectorBytes = byteLength % VECTOR_SIZE;
-        long srcOffset = (long) srcPos * elementSize;
-        long destOffset = (long) destPos * elementSize;
-        if (probability(NOT_FREQUENT_PROBABILITY, src == dest) && probability(NOT_FREQUENT_PROBABILITY, srcPos < destPos)) {
-            // bad aliased case
-            for (long i = byteLength - elementSize; i >= byteLength - nonVectorBytes; i -= elementSize) {
-                UnsafeStoreNode.store(dest, header, i + destOffset, UnsafeLoadNode.load(src, header, i + srcOffset, baseKind), baseKind);
-            }
-            long vectorLength = byteLength - nonVectorBytes;
-            for (long i = vectorLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
-                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
-            }
-        } else {
-            for (long i = 0; i < nonVectorBytes; i += elementSize) {
-                UnsafeStoreNode.store(dest, header, i + destOffset, UnsafeLoadNode.load(src, header, i + srcOffset, baseKind), baseKind);
-            }
-            for (long i = nonVectorBytes; i < byteLength; i += VECTOR_SIZE) {
-                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
-            }
-        }
+        UnsafeArrayCopyNode.arraycopy(src, srcPos, dest, destPos, length, baseKind);
     }
 
     public static void checkNonNull(Object obj) {
@@ -149,85 +125,49 @@
     @Snippet
     public static void arraycopy(byte[] src, int srcPos, byte[] dest, int destPos, int length) {
         byteCounter.inc();
-        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Byte);
+        checkedCopy(src, srcPos, dest, destPos, length, Kind.Byte);
     }
 
     @Snippet
     public static void arraycopy(boolean[] src, int srcPos, boolean[] dest, int destPos, int length) {
         booleanCounter.inc();
-        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Byte);
+        checkedCopy(src, srcPos, dest, destPos, length, Kind.Boolean);
     }
 
     @Snippet
     public static void arraycopy(char[] src, int srcPos, char[] dest, int destPos, int length) {
         charCounter.inc();
-        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Char);
+        checkedCopy(src, srcPos, dest, destPos, length, Kind.Char);
     }
 
     @Snippet
     public static void arraycopy(short[] src, int srcPos, short[] dest, int destPos, int length) {
         shortCounter.inc();
-        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Short);
+        checkedCopy(src, srcPos, dest, destPos, length, Kind.Short);
     }
 
     @Snippet
     public static void arraycopy(int[] src, int srcPos, int[] dest, int destPos, int length) {
         intCounter.inc();
-        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Int);
+        checkedCopy(src, srcPos, dest, destPos, length, Kind.Int);
     }
 
     @Snippet
     public static void arraycopy(float[] src, int srcPos, float[] dest, int destPos, int length) {
         floatCounter.inc();
-        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Float);
+        checkedCopy(src, srcPos, dest, destPos, length, Kind.Float);
     }
 
     @Snippet
     public static void arraycopy(long[] src, int srcPos, long[] dest, int destPos, int length) {
         longCounter.inc();
-        checkNonNull(src);
-        checkNonNull(dest);
-        checkLimits(src, srcPos, dest, destPos, length);
-        Kind baseKind = Kind.Long;
-        int header = arrayBaseOffset(baseKind);
-        long byteLength = (long) length * arrayIndexScale(baseKind);
-        long srcOffset = (long) srcPos * arrayIndexScale(baseKind);
-        long destOffset = (long) destPos * arrayIndexScale(baseKind);
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            for (long i = byteLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
-                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
-            }
-        } else {
-            for (long i = 0; i < byteLength; i += VECTOR_SIZE) {
-                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
-            }
-        }
+        checkedCopy(src, srcPos, dest, destPos, length, Kind.Long);
     }
 
     @Snippet
     public static void arraycopy(double[] src, int srcPos, double[] dest, int destPos, int length) {
         doubleCounter.inc();
-        checkNonNull(src);
-        checkNonNull(dest);
-        checkLimits(src, srcPos, dest, destPos, length);
-        Kind baseKind = Kind.Double;
-        int header = arrayBaseOffset(baseKind);
-        long byteLength = (long) length * arrayIndexScale(baseKind);
-        long srcOffset = (long) srcPos * arrayIndexScale(baseKind);
-        long destOffset = (long) destPos * arrayIndexScale(baseKind);
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            for (long i = byteLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
-                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
-            }
-        } else {
-            for (long i = 0; i < byteLength; i += VECTOR_SIZE) {
-                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
-            }
-        }
+        checkedCopy(src, srcPos, dest, destPos, length, Kind.Double);
     }
 
     @Snippet
@@ -239,48 +179,25 @@
     @Snippet
     public static void arrayObjectCopy(Object src, int srcPos, Object dest, int destPos, int length) {
         objectCounter.inc();
-        checkNonNull(src);
-        checkNonNull(dest);
-        checkLimits(src, srcPos, dest, destPos, length);
-        final int scale = arrayIndexScale(Kind.Object);
-        int header = arrayBaseOffset(Kind.Object);
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            long start = (long) (length - 1) * scale;
-            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);
-            }
-        } else {
-            long end = (long) length * scale;
-            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) {
-            GenericArrayRangeWriteBarrier.insertWriteBarrier(dest, destPos, length);
-        }
+        checkedCopy(src, srcPos, dest, destPos, length, Kind.Object);
     }
 
     @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 (probability(FAST_PATH_PROBABILITY, srcHub.equal(destHub)) && probability(FAST_PATH_PROBABILITY, src != dest)) {
+            int layoutHelper = checkArrayType(srcHub);
+            final boolean isObjectArray = ((layoutHelper & layoutHelperElementTypePrimitiveInPlace()) == 0);
 
-        if (probability(FAST_PATH_PROBABILITY, srcHub.equal(destHub)) && probability(FAST_PATH_PROBABILITY, src != dest)) {
             checkLimits(src, srcPos, dest, destPos, length);
             if (probability(FAST_PATH_PROBABILITY, isObjectArray)) {
                 genericObjectExactCallCounter.inc();
                 arrayObjectCopy(src, srcPos, dest, destPos, length);
             } else {
                 genericPrimitiveCallCounter.inc();
-                arraycopyInnerloop(src, srcPos, dest, destPos, length, layoutHelper);
+                UnsafeArrayCopyNode.arraycopyPrimitive(src, srcPos, dest, destPos, length, layoutHelper);
             }
         } else {
             genericObjectCallCounter.inc();
@@ -288,33 +205,6 @@
         }
     }
 
-    public static void arraycopyInnerloop(Object src, int srcPos, Object dest, int destPos, int length, int layoutHelper) {
-        int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
-        int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask();
-
-        Word memory = (Word) Word.fromObject(src);
-
-        Word srcOffset = (Word) Word.fromObject(src).add(headerSize).add(srcPos << log2ElementSize);
-        Word destOffset = (Word) Word.fromObject(dest).add(headerSize).add(destPos << log2ElementSize);
-        Word destStart = destOffset;
-        long sizeInBytes = ((long) length) << log2ElementSize;
-        Word destEnd = destOffset.add(Word.unsigned(length).shiftLeft(log2ElementSize));
-
-        int nonVectorBytes = (int) (sizeInBytes % VECTOR_SIZE);
-        Word destNonVectorEnd = destStart.add(nonVectorBytes);
-
-        while (destOffset.belowThan(destNonVectorEnd)) {
-            destOffset.writeByte(0, srcOffset.readByte(0, ANY_LOCATION), ANY_LOCATION);
-            destOffset = destOffset.add(1);
-            srcOffset = srcOffset.add(1);
-        }
-        while (destOffset.belowThan(destEnd)) {
-            destOffset.writeWord(0, srcOffset.readWord(0, ANY_LOCATION), ANY_LOCATION);
-            destOffset = destOffset.add(wordSize());
-            srcOffset = srcOffset.add(wordSize());
-        }
-    }
-
     private static final SnippetCounter.Group checkCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("System.arraycopy checkInputs") : null;
     private static final SnippetCounter checkSuccessCounter = new SnippetCounter(checkCounters, "checkSuccess", "checkSuccess");
     private static final SnippetCounter checkNPECounter = new SnippetCounter(checkCounters, "checkNPE", "checkNPE");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java	Thu Jun 20 21:11:06 2013 +0200
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.replacements;
+
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+
+public final class UnsafeArrayCopyNode extends ArrayRangeWriteNode implements Lowerable, MemoryCheckpoint.Single {
+
+    @Input private ValueNode src;
+    @Input private ValueNode srcPos;
+    @Input private ValueNode dest;
+    @Input private ValueNode destPos;
+    @Input private ValueNode length;
+    @Input private ValueNode layoutHelper;
+
+    private Kind elementKind;
+
+    private UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode layoutHelper, Kind elementKind) {
+        super(StampFactory.forVoid());
+        assert layoutHelper == null || elementKind == null;
+        this.src = src;
+        this.srcPos = srcPos;
+        this.dest = dest;
+        this.destPos = destPos;
+        this.length = length;
+        this.layoutHelper = layoutHelper;
+        this.elementKind = elementKind;
+    }
+
+    private UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind) {
+        this(src, srcPos, dest, destPos, length, null, elementKind);
+    }
+
+    private UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode layoutHelper) {
+        this(src, srcPos, dest, destPos, length, layoutHelper, null);
+    }
+
+    @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;
+    }
+
+    public Kind getElementKind() {
+        return elementKind;
+    }
+
+    @Override
+    public void lower(LoweringTool tool, LoweringType loweringType) {
+        if (loweringType == LoweringType.AFTER_GUARDS) {
+            UnsafeArrayCopySnippets.Templates templates = tool.getReplacements().getSnippetTemplateCache(UnsafeArrayCopySnippets.Templates.class);
+            templates.lower(this);
+        }
+    }
+
+    public void addSnippetArguments(Arguments args) {
+        args.add("src", src);
+        args.add("srcPos", srcPos);
+        args.add("dest", dest);
+        args.add("destPos", destPos);
+        args.add("length", length);
+        if (layoutHelper != null) {
+            args.add("layoutHelper", layoutHelper);
+        }
+    }
+
+    @Override
+    public LocationIdentity getLocationIdentity() {
+        if (elementKind == null) {
+            return ANY_LOCATION;
+        } else {
+            return NamedLocationIdentity.getArrayLocation(elementKind);
+        }
+    }
+
+    @NodeIntrinsic
+    public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantNodeParameter Kind elementKind);
+
+    @NodeIntrinsic
+    public static native void arraycopyPrimitive(Object src, int srcPos, Object dest, int destPos, int length, int layoutHelper);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java	Thu Jun 20 21:11:06 2013 +0200
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.replacements;
+
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+import static com.oracle.graal.replacements.SnippetTemplate.*;
+import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.replacements.*;
+import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
+import com.oracle.graal.replacements.nodes.*;
+import com.oracle.graal.word.*;
+
+public class UnsafeArrayCopySnippets implements Snippets {
+
+    private static final Kind VECTOR_KIND = Kind.Long;
+    private static final long VECTOR_SIZE = arrayIndexScale(Kind.Long);
+
+    private static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind) {
+        int header = arrayBaseOffset(baseKind);
+        int elementSize = arrayIndexScale(baseKind);
+        long byteLength = (long) length * elementSize;
+        long nonVectorBytes = byteLength % VECTOR_SIZE;
+        long srcOffset = (long) srcPos * elementSize;
+        long destOffset = (long) destPos * elementSize;
+        if (probability(NOT_FREQUENT_PROBABILITY, src == dest) && probability(NOT_FREQUENT_PROBABILITY, srcPos < destPos)) {
+            // bad aliased case
+            for (long i = byteLength - elementSize; i >= byteLength - nonVectorBytes; i -= elementSize) {
+                UnsafeStoreNode.store(dest, header, i + destOffset, UnsafeLoadNode.load(src, header, i + srcOffset, baseKind), baseKind);
+            }
+            long vectorLength = byteLength - nonVectorBytes;
+            for (long i = vectorLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
+                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
+            }
+        } else {
+            for (long i = 0; i < nonVectorBytes; i += elementSize) {
+                UnsafeStoreNode.store(dest, header, i + destOffset, UnsafeLoadNode.load(src, header, i + srcOffset, baseKind), baseKind);
+            }
+            for (long i = nonVectorBytes; i < byteLength; i += VECTOR_SIZE) {
+                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
+            }
+        }
+    }
+
+    @Snippet
+    public static void arraycopyByte(byte[] src, int srcPos, byte[] dest, int destPos, int length) {
+        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Byte);
+    }
+
+    @Snippet
+    public static void arraycopyBoolean(boolean[] src, int srcPos, boolean[] dest, int destPos, int length) {
+        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Byte);
+    }
+
+    @Snippet
+    public static void arraycopyChar(char[] src, int srcPos, char[] dest, int destPos, int length) {
+        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Char);
+    }
+
+    @Snippet
+    public static void arraycopyShort(short[] src, int srcPos, short[] dest, int destPos, int length) {
+        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Short);
+    }
+
+    @Snippet
+    public static void arraycopyInt(int[] src, int srcPos, int[] dest, int destPos, int length) {
+        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Int);
+    }
+
+    @Snippet
+    public static void arraycopyFloat(float[] src, int srcPos, float[] dest, int destPos, int length) {
+        vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Float);
+    }
+
+    @Snippet
+    public static void arraycopyLong(long[] src, int srcPos, long[] dest, int destPos, int length) {
+        Kind baseKind = Kind.Long;
+        int header = arrayBaseOffset(baseKind);
+        long byteLength = (long) length * arrayIndexScale(baseKind);
+        long srcOffset = (long) srcPos * arrayIndexScale(baseKind);
+        long destOffset = (long) destPos * arrayIndexScale(baseKind);
+        if (src == dest && srcPos < destPos) { // bad aliased case
+            for (long i = byteLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
+                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
+            }
+        } else {
+            for (long i = 0; i < byteLength; i += VECTOR_SIZE) {
+                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
+            }
+        }
+    }
+
+    @Snippet
+    public static void arraycopyDouble(double[] src, int srcPos, double[] dest, int destPos, int length) {
+        Kind baseKind = Kind.Double;
+        int header = arrayBaseOffset(baseKind);
+        long byteLength = (long) length * arrayIndexScale(baseKind);
+        long srcOffset = (long) srcPos * arrayIndexScale(baseKind);
+        long destOffset = (long) destPos * arrayIndexScale(baseKind);
+        if (src == dest && srcPos < destPos) { // bad aliased case
+            for (long i = byteLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
+                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
+            }
+        } else {
+            for (long i = 0; i < byteLength; i += VECTOR_SIZE) {
+                Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
+            }
+        }
+    }
+
+    /**
+     * Does NOT perform store checks.
+     */
+    @Snippet
+    public static void arraycopyObject(Object[] src, int srcPos, Object[] dest, int destPos, int length) {
+        final int scale = arrayIndexScale(Kind.Object);
+        int header = arrayBaseOffset(Kind.Object);
+        if (src == dest && srcPos < destPos) { // bad aliased case
+            long start = (long) (length - 1) * scale;
+            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);
+            }
+        } else {
+            long end = (long) length * scale;
+            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);
+            }
+        }
+    }
+
+    @Snippet
+    public static void arraycopyPrimitive(Object src, int srcPos, Object dest, int destPos, int length, int layoutHelper) {
+        int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
+        int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask();
+
+        Word srcOffset = (Word) Word.fromObject(src).add(headerSize).add(srcPos << log2ElementSize);
+        Word destOffset = (Word) Word.fromObject(dest).add(headerSize).add(destPos << log2ElementSize);
+        Word destStart = destOffset;
+        long sizeInBytes = ((long) length) << log2ElementSize;
+        Word destEnd = destOffset.add(Word.unsigned(length).shiftLeft(log2ElementSize));
+
+        int nonVectorBytes = (int) (sizeInBytes % VECTOR_SIZE);
+        Word destNonVectorEnd = destStart.add(nonVectorBytes);
+
+        while (destOffset.belowThan(destNonVectorEnd)) {
+            destOffset.writeByte(0, srcOffset.readByte(0, ANY_LOCATION), ANY_LOCATION);
+            destOffset = destOffset.add(1);
+            srcOffset = srcOffset.add(1);
+        }
+        while (destOffset.belowThan(destEnd)) {
+            destOffset.writeWord(0, srcOffset.readWord(0, ANY_LOCATION), ANY_LOCATION);
+            destOffset = destOffset.add(wordSize());
+            srcOffset = srcOffset.add(wordSize());
+        }
+    }
+
+    public static class Templates extends AbstractTemplates {
+
+        private final SnippetInfo[] arraycopySnippets;
+        private final SnippetInfo genericPrimitiveSnippet;
+
+        public Templates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) {
+            super(runtime, replacements, target);
+
+            arraycopySnippets = new SnippetInfo[Kind.values().length];
+            arraycopySnippets[Kind.Boolean.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyBoolean");
+            arraycopySnippets[Kind.Byte.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyByte");
+            arraycopySnippets[Kind.Short.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyShort");
+            arraycopySnippets[Kind.Char.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyChar");
+            arraycopySnippets[Kind.Int.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyInt");
+            arraycopySnippets[Kind.Long.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyLong");
+            arraycopySnippets[Kind.Float.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyFloat");
+            arraycopySnippets[Kind.Double.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyDouble");
+            arraycopySnippets[Kind.Object.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyObject");
+
+            genericPrimitiveSnippet = snippet(UnsafeArrayCopySnippets.class, "arraycopyPrimitive");
+        }
+
+        public void lower(UnsafeArrayCopyNode node) {
+            Kind elementKind = node.getElementKind();
+            SnippetInfo snippet;
+            if (elementKind == null) {
+                // primitive array of unknown kind
+                snippet = genericPrimitiveSnippet;
+            } else {
+                snippet = arraycopySnippets[elementKind.ordinal()];
+                assert snippet != null : "arraycopy snippet for " + elementKind.name() + " not found";
+            }
+
+            Arguments args = new Arguments(snippet);
+            node.addSnippetArguments(args);
+
+            SnippetTemplate template = template(args);
+            template.instantiate(runtime, node, DEFAULT_REPLACER, args);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1PostWriteBarrier.java	Thu Jun 20 21:11:06 2013 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.nodes.extended.*;
+
+public class G1PostWriteBarrier extends WriteBarrier {
+
+    @Input private ValueNode value;
+
+    public ValueNode getValue() {
+        return value;
+    }
+
+    public G1PostWriteBarrier(ValueNode object, ValueNode value, LocationNode location, boolean precise) {
+        super(object, location, precise);
+        this.value = value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1PreWriteBarrier.java	Thu Jun 20 21:11:06 2013 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.nodes.extended.*;
+
+public class G1PreWriteBarrier extends WriteBarrier {
+
+    @Input private ValueNode expectedObject;
+    private final boolean doLoad;
+
+    public ValueNode getExpectedObject() {
+        return expectedObject;
+    }
+
+    public boolean doLoad() {
+        return doLoad;
+    }
+
+    public G1PreWriteBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad) {
+        super(object, location, true);
+        this.doLoad = doLoad;
+        this.expectedObject = expectedObject;
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GenericArrayRangeWriteBarrier.java	Thu Jun 20 17:38:53 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes;
-
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.type.*;
-
-public final class GenericArrayRangeWriteBarrier extends FixedWithNextNode implements Node.IterableNodeType {
-
-    @Input private ValueNode dstObject;
-    @Input private ValueNode dstPos;
-    @Input private ValueNode length;
-
-    public ValueNode getDstObject() {
-        return dstObject;
-    }
-
-    public ValueNode getDstPos() {
-        return dstPos;
-    }
-
-    public ValueNode getLength() {
-        return length;
-    }
-
-    public GenericArrayRangeWriteBarrier(ValueNode dstObject, ValueNode dstPos, ValueNode length) {
-        super(StampFactory.forVoid());
-        this.dstObject = dstObject;
-        this.dstPos = dstPos;
-        this.length = length;
-
-    }
-
-    @NodeIntrinsic
-    public static native void insertWriteBarrier(Object dstObject, int dstPos, int length);
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialWriteBarrier.java	Thu Jun 20 17:38:53 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialWriteBarrier.java	Thu Jun 20 21:11:06 2013 +0200
@@ -22,39 +22,11 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-
-public final class SerialWriteBarrier extends FixedWithNextNode implements Lowerable, Node.IterableNodeType {
-
-    @Input private ValueNode object;
-    @Input private LocationNode location;
-    private final boolean precise;
 
-    public ValueNode getObject() {
-        return object;
-    }
-
-    public LocationNode getLocation() {
-        return location;
-    }
-
-    public boolean usePrecise() {
-        return precise;
-    }
+public class SerialWriteBarrier extends WriteBarrier {
 
     public SerialWriteBarrier(ValueNode object, LocationNode location, boolean precise) {
-        super(StampFactory.forVoid());
-        this.object = object;
-        this.location = location;
-        this.precise = precise;
-    }
-
-    @Override
-    public void lower(LoweringTool generator, LoweringType loweringType) {
-        assert loweringType == LoweringType.AFTER_GUARDS;
-        generator.getRuntime().lower(this, generator);
+        super(object, location, precise);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/WriteBarrier.java	Thu Jun 20 21:11:06 2013 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+public class WriteBarrier extends FixedWithNextNode implements Lowerable, Node.IterableNodeType {
+
+    @Input private ValueNode object;
+    @Input private LocationNode location;
+    private final boolean precise;
+
+    public ValueNode getObject() {
+        return object;
+    }
+
+    public LocationNode getLocation() {
+        return location;
+    }
+
+    public boolean usePrecise() {
+        return precise;
+    }
+
+    public WriteBarrier(ValueNode object, LocationNode location, boolean precise) {
+        super(StampFactory.forVoid());
+        this.object = object;
+        this.location = location;
+        this.precise = precise;
+    }
+
+    @Override
+    public void lower(LoweringTool generator, LoweringType loweringType) {
+        assert loweringType == LoweringType.AFTER_GUARDS;
+        generator.getRuntime().lower(this, generator);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java	Thu Jun 20 21:11:06 2013 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.extended;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Base class for nodes that modify a range of an array.
+ */
+public abstract class ArrayRangeWriteNode extends AbstractStateSplit implements Node.IterableNodeType {
+
+    protected ArrayRangeWriteNode(Stamp stamp) {
+        super(stamp);
+    }
+
+    /**
+     * The array that is written to.
+     */
+    public abstract ValueNode getArray();
+
+    /**
+     * The first modified index.
+     */
+    public abstract ValueNode getIndex();
+
+    /**
+     * The length of the modified range.
+     */
+    public abstract ValueNode getLength();
+
+    /**
+     * Return true if the written array is an object array, false if it is a primitive array.
+     */
+    public abstract boolean isObjectArray();
+}
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Thu Jun 20 17:38:53 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Thu Jun 20 21:11:06 2013 +0200
@@ -871,6 +871,8 @@
   set_int("g1SATBQueueMarkingOffset", in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_active()));
   set_int("g1SATBQueueIndexOffset", in_bytes(JavaThread::satb_mark_queue_offset() +  PtrQueue::byte_offset_of_index()));
   set_int("g1SATBQueueBufferOffset", in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_buf()));
+  set_address("writeBarrierPreAddress", GraalRuntime::write_barrier_pre);
+  set_address("writeBarrierPostAddress", GraalRuntime::write_barrier_post);
 
   BarrierSet* bs = Universe::heap()->barrier_set();
   switch (bs->kind()) {
--- a/src/share/vm/graal/graalRuntime.cpp	Thu Jun 20 17:38:53 2013 +0200
+++ b/src/share/vm/graal/graalRuntime.cpp	Thu Jun 20 21:11:06 2013 +0200
@@ -358,6 +358,14 @@
   }
 JRT_END
 
+JRT_LEAF(void, GraalRuntime::write_barrier_pre(JavaThread* thread, oopDesc* obj))
+  thread->satb_mark_queue().enqueue(obj);
+JRT_END
+
+JRT_LEAF(void, GraalRuntime::write_barrier_post(JavaThread* thread, void* card_addr))
+  thread->dirty_card_queue().enqueue(card_addr);
+JRT_END
+
 JRT_ENTRY(void, GraalRuntime::vm_error(JavaThread* thread, oop where, oop format, jlong value))
   ResourceMark rm;
   assert(where == NULL || java_lang_String::is_instance(where), "must be");
--- a/src/share/vm/graal/graalRuntime.hpp	Thu Jun 20 17:38:53 2013 +0200
+++ b/src/share/vm/graal/graalRuntime.hpp	Thu Jun 20 21:11:06 2013 +0200
@@ -52,6 +52,8 @@
     LOG_OBJECT_ADDRESS = 0x04
   };
   static void log_object(JavaThread* thread, oop msg, jint flags);
+  static void write_barrier_pre(JavaThread* thread, oopDesc* obj);
+  static void write_barrier_post(JavaThread* thread, void* card);
 };
 
 #endif // SHARE_VM_GRAAL_GRAAL_RUNTIME_HPP