changeset 4431:73f56093d824

Merge
author Lukas Stadler <lukas.stadler@jku.at>
date Fri, 03 Feb 2012 10:21:02 +0100
parents be4914c1c799 (current diff) c97f09b8d1ce (diff)
children 12558f571128
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/RemovePlaceholderPhase.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/ArrayCopySnippets.java graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/IntrinsifyArrayCopyPhase.java graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/SystemSnippets.java graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/UnsafeSnippets.java
diffstat 20 files changed, 972 insertions(+), 824 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java	Fri Feb 03 10:17:33 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java	Fri Feb 03 10:21:02 2012 +0100
@@ -181,7 +181,6 @@
                 new ReadEliminationPhase().apply(graph);
             }
         }
-        new RemovePlaceholderPhase().apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
 
         plan.runPhases(PhasePosition.MID_LEVEL, graph);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java	Fri Feb 03 10:21:02 2012 +0100
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012, 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.max.graal.compiler.phases;
+
+import com.oracle.max.graal.nodes.*;
+
+public class InsertStateAfterPlaceholderPhase extends Phase {
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (ReturnNode ret : graph.getNodes(ReturnNode.class)) {
+            PlaceholderNode p = graph.add(new PlaceholderNode());
+            p.setStateAfter(graph.add(new FrameState(null, FrameState.AFTER_BCI, 0, 0, false)));
+            graph.addBeforeFixed(ret, p);
+        }
+    }
+
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/IntrinsificationPhase.java	Fri Feb 03 10:17:33 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/IntrinsificationPhase.java	Fri Feb 03 10:21:02 2012 +0100
@@ -25,6 +25,7 @@
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.cri.*;
+import com.oracle.max.graal.debug.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 
@@ -58,6 +59,7 @@
             intrinsicGraph = runtime.intrinsicGraph(invoke.stateAfter().method(), invoke.bci(), target, invoke.callTarget().arguments());
         }
         if (intrinsicGraph != null) {
+            Debug.log(" > Intrinsify %s", target);
             InliningUtil.inline(invoke, intrinsicGraph, true);
         }
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/RemovePlaceholderPhase.java	Fri Feb 03 10:17:33 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2011, 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.max.graal.compiler.phases;
-
-import com.oracle.max.graal.nodes.*;
-
-public class RemovePlaceholderPhase extends Phase {
-    @Override
-    protected void run(StructuredGraph graph) {
-        for (PlaceholderNode n : graph.getNodes(PlaceholderNode.class)) {
-            graph.removeFixed(n);
-        }
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/SnippetIntrinsificationPhase.java	Fri Feb 03 10:17:33 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/SnippetIntrinsificationPhase.java	Fri Feb 03 10:21:02 2012 +0100
@@ -156,6 +156,7 @@
         Constructor< ? > constructor;
         try {
             constructor = nodeClass.getDeclaredConstructor(parameterTypes);
+            constructor.setAccessible(true);
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/NodePredicates.java	Fri Feb 03 10:17:33 2012 +0100
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/NodePredicates.java	Fri Feb 03 10:21:02 2012 +0100
@@ -142,13 +142,13 @@
     private static final class AndPredicate extends NodePredicate {
         private final NodePredicate a;
         private final NodePredicate b;
-        private AndPredicate(NodePredicate pa, NodePredicate pb) {
-            this.a = pa;
-            this.b = pb;
+        private AndPredicate(NodePredicate a, NodePredicate b) {
+            this.a = a;
+            this.b = b;
         }
         @Override
         public boolean apply(Node n) {
-            return b.apply(n) && a.apply(n);
+            return a.apply(n) && b.apply(n);
         }
     }
 
@@ -166,13 +166,13 @@
     private static final class OrPredicate extends NodePredicate {
         private final NodePredicate a;
         private final NodePredicate b;
-        private OrPredicate(NodePredicate np, NodePredicate thiz) {
-            this.a = np;
-            this.b = thiz;
+        private OrPredicate(NodePredicate a, NodePredicate b) {
+            this.a = a;
+            this.b = b;
         }
         @Override
         public boolean apply(Node n) {
-            return b.apply(n) || a.apply(n);
+            return a.apply(n) || b.apply(n);
         }
     }
 
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java	Fri Feb 03 10:17:33 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java	Fri Feb 03 10:21:02 2012 +0100
@@ -39,6 +39,7 @@
 import com.oracle.max.graal.hotspot.Compiler;
 import com.oracle.max.graal.hotspot.ri.*;
 import com.oracle.max.graal.hotspot.server.*;
+import com.oracle.max.graal.hotspot.snippets.*;
 import com.oracle.max.graal.java.*;
 import com.oracle.max.graal.snippets.*;
 
@@ -49,6 +50,7 @@
 
     private final Compiler compiler;
     private int compiledMethodCount;
+    private IntrinsifyArrayCopyPhase intrinsifyArrayCopy;
 
     public final HotSpotTypePrimitive typeBoolean;
     public final HotSpotTypePrimitive typeChar;
@@ -110,9 +112,11 @@
         // Install intrinsics.
         HotSpotRuntime runtime = (HotSpotRuntime) compiler.getCompiler().runtime;
         if (GraalOptions.Intrinsify) {
+            this.intrinsifyArrayCopy = new IntrinsifyArrayCopyPhase(runtime);
             GraalIntrinsics.installIntrinsics(runtime, runtime.getCompiler().getTarget(), PhasePlan.DEFAULT);
             Snippets.install(runtime, runtime.getCompiler().getTarget(), new SystemSnippets(), PhasePlan.DEFAULT);
             Snippets.install(runtime, runtime.getCompiler().getTarget(), new UnsafeSnippets(), PhasePlan.DEFAULT);
+            Snippets.install(runtime, runtime.getCompiler().getTarget(), new ArrayCopySnippets(), PhasePlan.DEFAULT);
         }
 
         // Create compilation queue.
@@ -247,7 +251,7 @@
 
                 public void run() {
                     try {
-                        PhasePlan plan = new PhasePlan();
+                        PhasePlan plan = getDefaultPhasePlan();
                         GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime());
                         plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
                         long startTime = 0;
@@ -384,4 +388,10 @@
     public CiConstant createCiConstantObject(Object object) {
         return CiConstant.forObject(object);
     }
+
+    private PhasePlan getDefaultPhasePlan() {
+        PhasePlan phasePlan = new PhasePlan();
+        phasePlan.addPhase(PhasePosition.HIGH_LEVEL, intrinsifyArrayCopy);
+        return phasePlan;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/ArrayCopySnippets.java	Fri Feb 03 10:21:02 2012 +0100
@@ -0,0 +1,462 @@
+/*
+ * Copyright (c) 2011, 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.max.graal.hotspot.snippets;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.graal.cri.*;
+import com.oracle.max.graal.hotspot.*;
+import com.oracle.max.graal.nodes.*;
+import com.oracle.max.graal.nodes.extended.*;
+import com.oracle.max.graal.nodes.spi.*;
+import com.oracle.max.graal.nodes.type.*;
+import com.oracle.max.graal.snippets.*;
+import com.oracle.max.graal.snippets.nodes.*;
+
+
+public class ArrayCopySnippets implements SnippetsInterface{
+
+    @Snippet
+    public static void arraycopy(byte[] src, int srcPos, byte[] dest, int destPos, int length) {
+        if (src == null || dest == null) {
+            throw new NullPointerException();
+        }
+        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (src == dest && srcPos < destPos) { // bad aliased case
+            if ((length & 0x01) == 0) {
+                if ((length & 0x02) == 0) {
+                    if ((length & 0x04) == 0) {
+                        copyLongsDown(src, srcPos, dest, destPos, length >> 3);
+                    } else {
+                        copyIntsDown(src, srcPos, dest, destPos, length >> 2);
+                    }
+                } else {
+                    copyShortsDown(src, srcPos, dest, destPos, length >> 1);
+                }
+            } else {
+                copyBytesDown(src, srcPos, dest, destPos, length);
+            }
+        } else {
+            if ((length & 0x01) == 0) {
+                if ((length & 0x02) == 0) {
+                    if ((length & 0x04) == 0) {
+                        copyLongsUp(src, srcPos, dest, destPos, length >> 3);
+                    } else {
+                        copyIntsUp(src, srcPos, dest, destPos, length >> 2);
+                    }
+                } else {
+                    copyShortsUp(src, srcPos, dest, destPos, length >> 1);
+                }
+            } else {
+                copyBytesUp(src, srcPos, dest, destPos, length);
+            }
+        }
+    }
+
+    @Snippet
+    public static void arraycopy(char[] src, int srcPos, char[] dest, int destPos, int length) {
+        if (src == null || dest == null) {
+            throw new NullPointerException();
+        }
+        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (src == dest && srcPos < destPos) { // bad aliased case
+            if ((length & 0x01) == 0) {
+                if ((length & 0x02) == 0) {
+                    copyLongsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 2);
+                } else {
+                    copyIntsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 1);
+                }
+            } else {
+                copyShortsDown(src, srcPos * 2L, dest, destPos * 2L, length);
+            }
+        } else {
+            if ((length & 0x01) == 0) {
+                if ((length & 0x02) == 0) {
+                    copyLongsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 2);
+                } else {
+                    copyIntsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 1);
+                }
+            } else {
+                copyShortsUp(src, srcPos * 2L, dest, destPos * 2L, length);
+            }
+        }
+    }
+
+    @Snippet
+    public static void arraycopy(short[] src, int srcPos, short[] dest, int destPos, int length) {
+        if (src == null || dest == null) {
+            throw new NullPointerException();
+        }
+        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (src == dest && srcPos < destPos) { // bad aliased case
+            if ((length & 0x01) == 0) {
+                if ((length & 0x02) == 0) {
+                    copyLongsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 2);
+                } else {
+                    copyIntsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 1);
+                }
+            } else {
+                copyShortsDown(src, srcPos * 2L, dest, destPos * 2L, length);
+            }
+        } else {
+            if ((length & 0x01) == 0) {
+                if ((length & 0x02) == 0) {
+                    copyLongsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 2);
+                } else {
+                    copyIntsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 1);
+                }
+            } else {
+                copyShortsUp(src, srcPos * 2L, dest, destPos * 2L, length);
+            }
+        }
+    }
+
+    @Snippet
+    public static void arraycopy(int[] src, int srcPos, int[] dest, int destPos, int length) {
+        if (src == null || dest == null) {
+            throw new NullPointerException();
+        }
+        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (src == dest && srcPos < destPos) { // bad aliased case
+            if ((length & 0x01) == 0) {
+                copyLongsDown(src, srcPos * 4L, dest, destPos * 4L, length >> 1);
+            } else {
+                copyIntsDown(src, srcPos * 4L, dest, destPos * 4L, length);
+            }
+        } else {
+            if ((length & 0x01) == 0) {
+                copyLongsUp(src, srcPos * 4L, dest, destPos * 4L, length >> 1);
+            } else {
+                copyIntsUp(src, srcPos * 4L, dest, destPos * 4L, length);
+            }
+        }
+    }
+
+    @Snippet
+    public static void arraycopy(float[] src, int srcPos, float[] dest, int destPos, int length) {
+        if (src == null || dest == null) {
+            throw new NullPointerException();
+        }
+        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (src == dest && srcPos < destPos) { // bad aliased case
+            if ((length & 0x01) == 0) {
+                copyLongsDown(src, srcPos * 4L, dest, destPos * 4L, length >> 1);
+            } else {
+                copyIntsDown(src, srcPos * 4L, dest, destPos * 4L, length);
+            }
+        } else {
+            if ((length & 0x01) == 0) {
+                copyLongsUp(src, srcPos * 4L, dest, destPos * 4L, length >> 1);
+            } else {
+                copyIntsUp(src, srcPos * 4L, dest, destPos * 4L, length);
+            }
+        }
+    }
+
+    @Snippet
+    public static void arraycopy(long[] src, int srcPos, long[] dest, int destPos, int length) {
+        if (src == null || dest == null) {
+            throw new NullPointerException();
+        }
+        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (src == dest && srcPos < destPos) { // bad aliased case
+            copyLongsDown(src, srcPos * 8L, dest, destPos * 8L, length);
+        } else {
+            copyLongsUp(src, srcPos * 8L, dest, destPos * 8L, length);
+        }
+    }
+
+    @Snippet
+    public static void arraycopy(double[] src, int srcPos, double[] dest, int destPos, int length) {
+        if (src == null || dest == null) {
+            throw new NullPointerException();
+        }
+        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (src == dest && srcPos < destPos) { // bad aliased case
+            copyLongsDown(src, srcPos * 8L, dest, destPos * 8L, length);
+        } else {
+            copyLongsUp(src, srcPos * 8L, dest, destPos * 8L, length);
+        }
+    }
+
+    // Does NOT perform store checks
+    @Snippet
+    public static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) {
+        if (src == null || dest == null) {
+            throw new NullPointerException();
+        }
+        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (src == dest && srcPos < destPos) { // bad aliased case
+            copyObjectsDown(src, srcPos * 8L, dest, destPos * 8L, length);
+        } else {
+            copyObjectsUp(src, srcPos * 8L, dest, destPos * 8L, length);
+        }
+        if (length > 0) {
+            long header = ArrayHeaderSizeNode.sizeFor(CiKind.Object);
+            int cardShift = CardTableShiftNode.get();
+            long cardStart = CardTableStartNode.get();
+            long dstAddr = GetObjectAddressNode.get(dest);
+            long start = (dstAddr + header + destPos * 8L) >>> cardShift;
+            long end = (dstAddr + header + (destPos + length - 1) * 8L) >>> cardShift;
+            long count = end - start + 1;
+            while (count-- > 0) {
+                DirectStoreNode.store((start + cardStart) + count, false);
+            }
+        }
+    }
+
+    @Snippet
+    public static void copyBytesDown(Object src, int srcPos, Object dest, int destPos, int length)  {
+        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Byte);
+        for (long i = length - 1; i >= 0; i--) {
+            Byte a = UnsafeLoadNode.load(src, i + (srcPos + header), CiKind.Byte);
+            UnsafeStoreNode.store(dest, i + (destPos + header), a.byteValue(), CiKind.Byte);
+        }
+    }
+
+    @Snippet
+    public static void copyShortsDown(Object src, long srcOffset, Object dest, long destOffset, int length)  {
+        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short);
+        for (long i = (length - 1) * 2; i >= 0; i -= 2) {
+            Character a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Short);
+            UnsafeStoreNode.store(dest, i + (destOffset + header), a.charValue(), CiKind.Short);
+        }
+    }
+
+    @Snippet
+    public static void copyIntsDown(Object src, long srcOffset, Object dest, long destOffset, int length)  {
+        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short);
+        for (long i = (length - 1) * 4; i >= 0; i -= 4) {
+            Integer a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Int);
+            UnsafeStoreNode.store(dest, i + (destOffset + header), a.intValue(), CiKind.Int);
+        }
+    }
+
+    @Snippet
+    public static void copyLongsDown(Object src, long srcOffset, Object dest, long destOffset, int length)  {
+        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short);
+        for (long i = (length - 1) * 8; i >= 0; i -= 8) {
+            Long a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Long);
+            UnsafeStoreNode.store(dest, i + (destOffset + header), a.longValue(), CiKind.Long);
+        }
+    }
+
+    // Does NOT perform store checks
+    @Snippet
+    public static void copyObjectsDown(Object src, long srcOffset, Object dest, long destOffset, int length)  {
+        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Object);
+        for (long i = (length - 1) * 8; i >= 0; i -= 8) {
+            Object a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Object);
+            DirectObjectStoreNode.store(dest, i + (destOffset + header), a);
+        }
+    }
+
+    /**
+     * Copies {@code length} bytes from {@code src} starting at {@code srcPos} to {@code dest} starting at {@code destPos}.
+     * @param src source object
+     * @param srcPos source offset
+     * @param dest destination object
+     * @param destPos destination offset
+     * @param length number of bytes to copy
+     */
+    @Snippet
+    public static void copyBytesUp(Object src, int srcPos, Object dest, int destPos, int length)  {
+        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Byte);
+        for (long i = 0; i < length; i++) {
+            Byte a = UnsafeLoadNode.load(src, i + (srcPos + header), CiKind.Byte);
+            UnsafeStoreNode.store(dest, i + (destPos + header), a.byteValue(), CiKind.Byte);
+        }
+    }
+
+    /**
+     * Copies {@code length} shorts from {@code src} starting at offset {@code srcOffset} (in bytes) to {@code dest} starting at offset {@code destOffset} (in bytes).
+     * @param src
+     * @param srcOffset (in bytes)
+     * @param dest
+     * @param destOffset (in bytes)
+     * @param length  (in shorts)
+     */
+    @Snippet
+    public static void copyShortsUp(Object src, long srcOffset, Object dest, long destOffset, int length)  {
+        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short);
+        for (long i = 0; i < length * 2L; i += 2) {
+            Character a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Short);
+            UnsafeStoreNode.store(dest, i + (destOffset + header), a.charValue(), CiKind.Short);
+        }
+    }
+
+    @Snippet
+    public static void copyIntsUp(Object src, long srcOffset, Object dest, long destOffset, int length)  {
+        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Int);
+        for (long i = 0; i < length * 4L; i += 4) {
+            Integer a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Int);
+            UnsafeStoreNode.store(dest, i + (destOffset + header), a.intValue(), CiKind.Int);
+        }
+    }
+
+    @Snippet
+    public static void copyLongsUp(Object src, long srcOffset, Object dest, long destOffset, int length)  {
+        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Long);
+        for (long i = 0; i < length * 8L; i += 8) {
+            Long a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Long);
+            UnsafeStoreNode.store(dest, i + (destOffset + header), a.longValue(), CiKind.Long);
+        }
+    }
+
+    // Does NOT perform store checks
+    @Snippet
+    public static void copyObjectsUp(Object src, long srcOffset, Object dest, long destOffset, int length)  {
+        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Object);
+        for (long i = 0; i < length * 8L; i += 8) {
+            Object a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Object);
+            DirectObjectStoreNode.store(dest, i + (destOffset + header), a);
+        }
+    }
+
+    private static class GetObjectAddressNode extends FixedWithNextNode implements LIRLowerable {
+        @Input private ValueNode object;
+
+        public GetObjectAddressNode(ValueNode obj) {
+            super(StampFactory.forKind(CiKind.Long));
+            this.object = obj;
+        }
+
+        @SuppressWarnings("unused")
+        @NodeIntrinsic
+        public static long get(Object array) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void generate(LIRGeneratorTool gen) {
+            CiValue obj = gen.newVariable(gen.target().wordKind);
+            gen.emitMove(gen.operand(object), obj);
+            gen.setResult(this, obj);
+        }
+    }
+
+    private static class DirectStoreNode extends FixedWithNextNode implements LIRLowerable {
+        @Input private ValueNode address;
+        @Input private ValueNode value;
+
+        public DirectStoreNode(ValueNode address, ValueNode value) {
+            super(StampFactory.illegal());
+            this.address = address;
+            this.value = value;
+        }
+
+        @SuppressWarnings("unused")
+        @NodeIntrinsic
+        public static void store(long address, long value) {
+            throw new UnsupportedOperationException();
+        }
+
+        @SuppressWarnings("unused")
+        @NodeIntrinsic
+        public static void store(long address, boolean value) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void generate(LIRGeneratorTool gen) {
+            CiValue v = gen.operand(value);
+            gen.emitStore(new CiAddress(v.kind, gen.operand(address)), v, false);
+        }
+    }
+
+    private static class DirectObjectStoreNode extends FixedWithNextNode implements Lowerable {
+        @Input private ValueNode object;
+        @Input private ValueNode value;
+        @Input private ValueNode offset;
+
+        public DirectObjectStoreNode(ValueNode object, ValueNode offset, ValueNode value) {
+            super(StampFactory.illegal());
+            this.object = object;
+            this.value = value;
+            this.offset = offset;
+        }
+
+        @SuppressWarnings("unused")
+        @NodeIntrinsic
+        public static void store(Object obj, long offset, long value) {
+            throw new UnsupportedOperationException();
+        }
+
+        @SuppressWarnings("unused")
+        @NodeIntrinsic
+        public static void store(Object obj, long offset, boolean value) {
+            throw new UnsupportedOperationException();
+        }
+
+        @SuppressWarnings("unused")
+        @NodeIntrinsic
+        public static void store(Object obj, long offset, Object value) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void lower(CiLoweringTool tool) {
+            StructuredGraph graph = (StructuredGraph) this.graph();
+            IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, value.kind(), 0, offset, graph, false);
+            WriteNode write = graph.add(new WriteNode(object, value, location));
+            graph.replaceFixedWithFixed(this, write);
+        }
+    }
+
+    private static class CardTableShiftNode extends ConstantNode {
+        public CardTableShiftNode() {
+            super(CiConstant.forInt(CompilerImpl.getInstance().getConfig().cardtableShift));
+        }
+
+        @NodeIntrinsic
+        public static int get() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    private static class CardTableStartNode extends ConstantNode {
+        public CardTableStartNode() {
+            super(CiConstant.forLong(CompilerImpl.getInstance().getConfig().cardtableStartAddress));
+        }
+
+        @NodeIntrinsic
+        public static long get() {
+            throw new UnsupportedOperationException();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java	Fri Feb 03 10:21:02 2012 +0100
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2011, 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.max.graal.hotspot.snippets;
+
+import java.lang.reflect.*;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
+import com.oracle.max.graal.compiler.phases.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.cri.*;
+import com.oracle.max.graal.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.nodes.*;
+import com.oracle.max.graal.nodes.java.*;
+
+public class IntrinsifyArrayCopyPhase extends Phase {
+    private final GraalRuntime runtime;
+    private RiResolvedMethod arrayCopy;
+    private RiResolvedMethod byteArrayCopy;
+    private RiResolvedMethod shortArrayCopy;
+    private RiResolvedMethod charArrayCopy;
+    private RiResolvedMethod intArrayCopy;
+    private RiResolvedMethod longArrayCopy;
+    private RiResolvedMethod floatArrayCopy;
+    private RiResolvedMethod doubleArrayCopy;
+    private RiResolvedMethod objectArrayCopy;
+
+    public IntrinsifyArrayCopyPhase(GraalRuntime runtime) {
+        this.runtime = runtime;
+        try {
+            byteArrayCopy = getArrayCopySnippet(runtime, byte.class);
+            charArrayCopy = getArrayCopySnippet(runtime, char.class);
+            shortArrayCopy = getArrayCopySnippet(runtime, short.class);
+            intArrayCopy = getArrayCopySnippet(runtime, int.class);
+            longArrayCopy = getArrayCopySnippet(runtime, long.class);
+            floatArrayCopy = getArrayCopySnippet(runtime, float.class);
+            doubleArrayCopy = getArrayCopySnippet(runtime, double.class);
+            objectArrayCopy = getArrayCopySnippet(runtime, Object.class);
+            arrayCopy = runtime.getRiMethod(System.class.getDeclaredMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class));
+        } catch (SecurityException e) {
+            e.printStackTrace();
+        } catch (NoSuchMethodException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private static RiResolvedMethod getArrayCopySnippet(RiRuntime runtime, Class<?> componentClass) throws NoSuchMethodException {
+        Class<?> arrayClass = Array.newInstance(componentClass, 0).getClass();
+        return runtime.getRiMethod(ArrayCopySnippets.class.getDeclaredMethod("arraycopy", arrayClass, int.class, arrayClass, int.class, int.class));
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        boolean hits = false;
+        for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.class)) {
+            RiResolvedMethod targetMethod = methodCallTarget.targetMethod();
+            RiResolvedMethod snippetMethod = null;
+            if (targetMethod == arrayCopy) {
+                ValueNode src = methodCallTarget.arguments().get(0);
+                ValueNode dest = methodCallTarget.arguments().get(2);
+                if (src == null || dest == null) { //TODO (gd) this should never be null : check
+                    return;
+                }
+                RiResolvedType srcDeclaredType = src.declaredType();
+                RiResolvedType destDeclaredType = dest.declaredType();
+                if (srcDeclaredType != null
+                                && srcDeclaredType.isArrayClass()
+                                && destDeclaredType != null
+                                && destDeclaredType.isArrayClass()) {
+                    CiKind componentKind = srcDeclaredType.componentType().kind(false);
+                    if (srcDeclaredType.componentType() == destDeclaredType.componentType()) {
+                        if (componentKind == CiKind.Int) {
+                            snippetMethod = intArrayCopy;
+                        } else if (componentKind == CiKind.Char) {
+                            snippetMethod = charArrayCopy;
+                        } else if (componentKind == CiKind.Long) {
+                            snippetMethod = longArrayCopy;
+                        } else if (componentKind == CiKind.Byte) {
+                            snippetMethod = byteArrayCopy;
+                        } else if (componentKind == CiKind.Short) {
+                            snippetMethod = shortArrayCopy;
+                        } else if (componentKind == CiKind.Float) {
+                            snippetMethod = floatArrayCopy;
+                        } else if (componentKind == CiKind.Double) {
+                            snippetMethod = doubleArrayCopy;
+                        } else if (componentKind == CiKind.Object) {
+                            snippetMethod = objectArrayCopy;
+                        }
+                    } else if (componentKind == CiKind.Object
+                                    && srcDeclaredType.componentType().isSubtypeOf(destDeclaredType.componentType())) {
+                        snippetMethod = objectArrayCopy;
+                    }
+                }
+            }
+
+            if (snippetMethod != null) {
+                StructuredGraph snippetGraph = (StructuredGraph) snippetMethod.compilerStorage().get(Graph.class);
+                assert snippetGraph != null : "ArrayCopySnippets should be installed";
+                hits = true;
+                Debug.log("%s > Intinsify (%s)", Debug.currentScope(), snippetMethod.signature().argumentTypeAt(0, snippetMethod.holder()).componentType());
+                InliningUtil.inline(methodCallTarget.invoke(), snippetGraph, false);
+            }
+        }
+        if (hits) {
+            new CanonicalizerPhase(null, runtime, null).apply(graph);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/SystemSnippets.java	Fri Feb 03 10:21:02 2012 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2011, 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.max.graal.hotspot.snippets;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.graal.nodes.extended.*;
+import com.oracle.max.graal.snippets.*;
+
+/**
+ * Snippets for {@link java.lang.System} methods.
+ */
+@ClassSubstitution(java.lang.System.class)
+public class SystemSnippets implements SnippetsInterface {
+
+    public static long currentTimeMillis() {
+        return RuntimeCallNode.performCall(CiRuntimeCall.JavaTimeMillis);
+    }
+
+    public static long nanoTime() {
+        return RuntimeCallNode.performCall(CiRuntimeCall.JavaTimeNanos);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/UnsafeSnippets.java	Fri Feb 03 10:21:02 2012 +0100
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2011, 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.max.graal.hotspot.snippets;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.util.*;
+import com.oracle.max.graal.nodes.extended.*;
+import com.oracle.max.graal.nodes.java.*;
+import com.oracle.max.graal.snippets.*;
+
+/**
+ * Snippets for {@link sun.misc.Unsafe} methods.
+ */
+@ClassSubstitution(sun.misc.Unsafe.class)
+public class UnsafeSnippets implements SnippetsInterface {
+
+    public boolean compareAndSwapObject(Object o, long offset, Object expected, Object x) {
+        return CompareAndSwapNode.compareAndSwap(o, offset, expected, x);
+    }
+
+    public boolean compareAndSwapInt(Object o, long offset, int expected, int x) {
+        return CompareAndSwapNode.compareAndSwap(o, offset, expected, x);
+    }
+
+    public boolean compareAndSwapLong(Object o, long offset, long expected, long x) {
+        return CompareAndSwapNode.compareAndSwap(o, offset, expected, x);
+    }
+
+    public Object getObject(Object o, long offset) {
+        return UnsafeLoadNode.load(o, offset, CiKind.Object);
+    }
+
+    public Object getObjectVolatile(Object o, long offset) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
+        Object result = getObject(o, offset);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
+        return result;
+    }
+
+    public void putObject(Object o, long offset, Object x) {
+        UnsafeStoreNode.store(o, offset, x, CiKind.Object);
+    }
+
+    public void putObjectVolatile(Object o, long offset, Object x) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
+        putObject(o, offset, x);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
+    }
+
+    public int getInt(Object o, long offset) {
+        Integer value = UnsafeLoadNode.load(o, offset, CiKind.Int);
+        return value;
+    }
+
+    public int getIntVolatile(Object o, long offset) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
+        int result = getInt(o, offset);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
+        return result;
+    }
+
+    public void putInt(Object o, long offset, int x) {
+        UnsafeStoreNode.store(o, offset, x, CiKind.Int);
+    }
+
+    public void putIntVolatile(Object o, long offset, int x) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
+        putInt(o, offset, x);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
+    }
+
+    public boolean getBoolean(Object o, long offset) {
+        @JavacBug(id = 6995200)
+        Boolean result = UnsafeLoadNode.load(o, offset, CiKind.Boolean);
+        return result;
+    }
+
+    public boolean getBooleanVolatile(Object o, long offset) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
+        boolean result = getBoolean(o, offset);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
+        return result;
+    }
+
+    public void putBoolean(Object o, long offset, boolean x) {
+        UnsafeStoreNode.store(o, offset, x, CiKind.Boolean);
+    }
+
+    public void putBooleanVolatile(Object o, long offset, boolean x) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
+        putBoolean(o, offset, x);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
+    }
+
+    public byte getByte(Object o, long offset) {
+        @JavacBug(id = 6995200)
+        Byte result = UnsafeLoadNode.load(o, offset, CiKind.Byte);
+        return result;
+    }
+
+    public byte getByteVolatile(Object o, long offset) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
+        byte result = getByte(o, offset);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
+        return result;
+    }
+
+    public void putByte(Object o, long offset, byte x) {
+        UnsafeStoreNode.store(o, offset, x, CiKind.Byte);
+    }
+
+    public void putByteVolatile(Object o, long offset, byte x) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
+        putByte(o, offset, x);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
+    }
+
+    public short getShort(Object o, long offset) {
+        @JavacBug(id = 6995200)
+        Short result = UnsafeLoadNode.load(o, offset, CiKind.Short);
+        return result;
+    }
+
+    public short getShortVolatile(Object o, long offset) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
+        short result = getShort(o, offset);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
+        return result;
+    }
+
+    public void putShort(Object o, long offset, short x) {
+        UnsafeStoreNode.store(o, offset, x, CiKind.Short);
+    }
+
+    public void putShortVolatile(Object o, long offset, short x) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
+        putShort(o, offset, x);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
+    }
+
+    public char getChar(Object o, long offset) {
+        @JavacBug(id = 6995200)
+        Character result = UnsafeLoadNode.load(o, offset, CiKind.Char);
+        return result;
+    }
+
+    public char getCharVolatile(Object o, long offset) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
+        char result = getChar(o, offset);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
+        return result;
+    }
+
+    public void putChar(Object o, long offset, char x) {
+        UnsafeStoreNode.store(o, offset, x, CiKind.Char);
+    }
+
+    public void putCharVolatile(Object o, long offset, char x) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
+        putChar(o, offset, x);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
+    }
+
+    public long getLong(Object o, long offset) {
+        @JavacBug(id = 6995200)
+        Long result = UnsafeLoadNode.load(o, offset, CiKind.Long);
+        return result;
+    }
+
+    public long getLongVolatile(Object o, long offset) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
+        long result = getLong(o, offset);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
+        return result;
+    }
+
+    public void putLong(Object o, long offset, long x) {
+        UnsafeStoreNode.store(o, offset, x, CiKind.Long);
+    }
+
+    public void putLongVolatile(Object o, long offset, long x) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
+        putLong(o, offset, x);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
+    }
+
+    public float getFloat(Object o, long offset) {
+        @JavacBug(id = 6995200)
+        Float result = UnsafeLoadNode.load(o, offset, CiKind.Float);
+        return result;
+    }
+
+    public float getFloatVolatile(Object o, long offset) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
+        float result = getFloat(o, offset);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
+        return result;
+    }
+
+    public void putFloat(Object o, long offset, float x) {
+        UnsafeStoreNode.store(o, offset, x, CiKind.Float);
+    }
+
+    public void putFloatVolatile(Object o, long offset, float x) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
+        putFloat(o, offset, x);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
+    }
+
+    public double getDouble(Object o, long offset) {
+        @JavacBug(id = 6995200)
+        Double result = UnsafeLoadNode.load(o, offset, CiKind.Double);
+        return result;
+    }
+
+    public double getDoubleVolatile(Object o, long offset) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
+        double result = getDouble(o, offset);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
+        return result;
+    }
+
+    public void putDouble(Object o, long offset, double x) {
+        UnsafeStoreNode.store(o, offset, x, CiKind.Double);
+    }
+
+    public void putDoubleVolatile(Object o, long offset, double x) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
+        putDouble(o, offset, x);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
+    }
+}
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BlockMap.java	Fri Feb 03 10:17:33 2012 +0100
+++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BlockMap.java	Fri Feb 03 10:21:02 2012 +0100
@@ -581,7 +581,7 @@
                 throw new CiBailout("Loop formed by an exception handler");
             }
             if (nextLoop >= Long.SIZE) {
-                // This restriction can be removed by using a fall-back to a BitSet in case we have more than 32 loops
+                // This restriction can be removed by using a fall-back to a BitSet in case we have more than 64 loops
                 // Don't compile such methods for now, until we see a concrete case that allows checking for correctness.
                 throw new CiBailout("Too many loops in method");
             }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/ConstantNode.java	Fri Feb 03 10:17:33 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/ConstantNode.java	Fri Feb 03 10:21:02 2012 +0100
@@ -33,11 +33,11 @@
  * long, float, object reference, address, etc.
  */
 @NodeInfo(shortName = "Const")
-public final class ConstantNode extends BooleanNode implements LIRLowerable {
+public class ConstantNode extends BooleanNode implements LIRLowerable {
 
     @Data public final CiConstant value;
 
-    private ConstantNode(CiConstant value) {
+    protected ConstantNode(CiConstant value) {
         this(value, null);
     }
 
@@ -45,7 +45,7 @@
      * Constructs a new ConstantNode representing the specified constant.
      * @param value the constant
      */
-    private ConstantNode(CiConstant value, RiRuntime runtime) {
+    protected ConstantNode(CiConstant value, RiRuntime runtime) {
         super(StampFactory.forConstant(value, runtime));
         this.value = value;
     }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/FrameState.java	Fri Feb 03 10:17:33 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/FrameState.java	Fri Feb 03 10:21:02 2012 +0100
@@ -75,27 +75,6 @@
 
     @Input private final NodeInputList<Node> virtualObjectMappings;
 
-    public FrameState outerFrameState() {
-        return outerFrameState;
-    }
-
-    public void setOuterFrameState(FrameState x) {
-        updateUsages(this.outerFrameState, x);
-        this.outerFrameState = x;
-    }
-
-    public FrameState outermostFrameState() {
-        FrameState fs = this;
-        while (fs.outerFrameState() != null) {
-            fs = fs.outerFrameState();
-        }
-        return fs;
-    }
-
-    public void setValueAt(int i, ValueNode x) {
-        values.set(i, x);
-    }
-
     /**
      * The bytecode index to which this frame state applies. This will be {@code -1}
      * iff this state is mutable.
@@ -143,6 +122,27 @@
         assert !rethrowException || stackSize == 1 : "must have exception on top of the stack";
     }
 
+    public FrameState outerFrameState() {
+        return outerFrameState;
+    }
+
+    public void setOuterFrameState(FrameState x) {
+        updateUsages(this.outerFrameState, x);
+        this.outerFrameState = x;
+    }
+
+    public FrameState outermostFrameState() {
+        FrameState fs = this;
+        while (fs.outerFrameState() != null) {
+            fs = fs.outerFrameState();
+        }
+        return fs;
+    }
+
+    public void setValueAt(int i, ValueNode x) {
+        values.set(i, x);
+    }
+
     public boolean rethrowException() {
         return rethrowException;
     }
--- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/ArrayCopySnippets.java	Fri Feb 03 10:17:33 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,332 +0,0 @@
-/*
- * Copyright (c) 2011, 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.max.graal.snippets;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.nodes.extended.*;
-import com.oracle.max.graal.snippets.nodes.*;
-
-
-public class ArrayCopySnippets implements SnippetsInterface{
-
-    @Snippet
-    public static void arraycopy(byte[] src, int srcPos, byte[] dest, int destPos, int length) {
-        if (src == null || dest == null) {
-            throw new NullPointerException();
-        }
-        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
-            throw new IndexOutOfBoundsException();
-        }
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            if ((length & 0x01) == 0) {
-                if ((length & 0x02) == 0) {
-                    if ((length & 0x04) == 0) {
-                        copyLongsDown(src, srcPos, dest, destPos, length >> 3);
-                    } else {
-                        copyIntsDown(src, srcPos, dest, destPos, length >> 2);
-                    }
-                } else {
-                    copyShortsDown(src, srcPos, dest, destPos, length >> 1);
-                }
-            } else {
-                copyBytesDown(src, srcPos, dest, destPos, length);
-            }
-        } else {
-            if ((length & 0x01) == 0) {
-                if ((length & 0x02) == 0) {
-                    if ((length & 0x04) == 0) {
-                        copyLongsUp(src, srcPos, dest, destPos, length >> 3);
-                    } else {
-                        copyIntsUp(src, srcPos, dest, destPos, length >> 2);
-                    }
-                } else {
-                    copyShortsUp(src, srcPos, dest, destPos, length >> 1);
-                }
-            } else {
-                copyBytesUp(src, srcPos, dest, destPos, length);
-            }
-        }
-    }
-
-    @Snippet
-    public static void arraycopy(char[] src, int srcPos, char[] dest, int destPos, int length) {
-        if (src == null || dest == null) {
-            throw new NullPointerException();
-        }
-        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
-            throw new IndexOutOfBoundsException();
-        }
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            if ((length & 0x01) == 0) {
-                if ((length & 0x02) == 0) {
-                    copyLongsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 2);
-                } else {
-                    copyIntsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 1);
-                }
-            } else {
-                copyShortsDown(src, srcPos * 2L, dest, destPos * 2L, length);
-            }
-        } else {
-            if ((length & 0x01) == 0) {
-                if ((length & 0x02) == 0) {
-                    copyLongsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 2);
-                } else {
-                    copyIntsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 1);
-                }
-            } else {
-                copyShortsUp(src, srcPos * 2L, dest, destPos * 2L, length);
-            }
-        }
-    }
-
-    @Snippet
-    public static void arraycopy(short[] src, int srcPos, short[] dest, int destPos, int length) {
-        if (src == null || dest == null) {
-            throw new NullPointerException();
-        }
-        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
-            throw new IndexOutOfBoundsException();
-        }
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            if ((length & 0x01) == 0) {
-                if ((length & 0x02) == 0) {
-                    copyLongsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 2);
-                } else {
-                    copyIntsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 1);
-                }
-            } else {
-                copyShortsDown(src, srcPos * 2L, dest, destPos * 2L, length);
-            }
-        } else {
-            if ((length & 0x01) == 0) {
-                if ((length & 0x02) == 0) {
-                    copyLongsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 2);
-                } else {
-                    copyIntsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 1);
-                }
-            } else {
-                copyShortsUp(src, srcPos * 2L, dest, destPos * 2L, length);
-            }
-        }
-    }
-
-    @Snippet
-    public static void arraycopy(int[] src, int srcPos, int[] dest, int destPos, int length) {
-        if (src == null || dest == null) {
-            throw new NullPointerException();
-        }
-        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
-            throw new IndexOutOfBoundsException();
-        }
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            if ((length & 0x01) == 0) {
-                copyLongsDown(src, srcPos * 4L, dest, destPos * 4L, length >> 1);
-            } else {
-                copyIntsDown(src, srcPos * 4L, dest, destPos * 4L, length);
-            }
-        } else {
-            if ((length & 0x01) == 0) {
-                copyLongsUp(src, srcPos * 4L, dest, destPos * 4L, length >> 1);
-            } else {
-                copyIntsUp(src, srcPos * 4L, dest, destPos * 4L, length);
-            }
-        }
-    }
-
-    @Snippet
-    public static void arraycopy(float[] src, int srcPos, float[] dest, int destPos, int length) {
-        if (src == null || dest == null) {
-            throw new NullPointerException();
-        }
-        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
-            throw new IndexOutOfBoundsException();
-        }
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            if ((length & 0x01) == 0) {
-                copyLongsDown(src, srcPos * 4L, dest, destPos * 4L, length >> 1);
-            } else {
-                copyIntsDown(src, srcPos * 4L, dest, destPos * 4L, length);
-            }
-        } else {
-            if ((length & 0x01) == 0) {
-                copyLongsUp(src, srcPos * 4L, dest, destPos * 4L, length >> 1);
-            } else {
-                copyIntsUp(src, srcPos * 4L, dest, destPos * 4L, length);
-            }
-        }
-    }
-
-    @Snippet
-    public static void arraycopy(long[] src, int srcPos, long[] dest, int destPos, int length) {
-        if (src == null || dest == null) {
-            throw new NullPointerException();
-        }
-        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
-            throw new IndexOutOfBoundsException();
-        }
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            copyLongsDown(src, srcPos * 8L, dest, destPos * 8L, length);
-        } else {
-            copyLongsUp(src, srcPos * 8L, dest, destPos * 8L, length);
-        }
-    }
-
-    @Snippet
-    public static void arraycopy(double[] src, int srcPos, double[] dest, int destPos, int length) {
-        if (src == null || dest == null) {
-            throw new NullPointerException();
-        }
-        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
-            throw new IndexOutOfBoundsException();
-        }
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            copyLongsDown(src, srcPos * 8L, dest, destPos * 8L, length);
-        } else {
-            copyLongsUp(src, srcPos * 8L, dest, destPos * 8L, length);
-        }
-    }
-
-    // Does NOT perform store checks
-    @Snippet
-    public static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) {
-        if (src == null || dest == null) {
-            throw new NullPointerException();
-        }
-        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
-            throw new IndexOutOfBoundsException();
-        }
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            copyObjectsDown(src, srcPos * 8L, dest, destPos * 8L, length);
-        } else {
-            copyObjectsUp(src, srcPos * 8L, dest, destPos * 8L, length);
-        }
-    }
-
-    @Snippet
-    public static void copyBytesDown(Object src, int srcPos, Object dest, int destPos, int length)  {
-        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Byte);
-        for (long i = length - 1; i >= 0; i--) {
-            Byte a = UnsafeLoadNode.load(src, i + (srcPos + header), CiKind.Byte);
-            UnsafeStoreNode.store(dest, i + (destPos + header), a.byteValue(), CiKind.Byte);
-        }
-    }
-
-    @Snippet
-    public static void copyShortsDown(Object src, long srcOffset, Object dest, long destOffset, int length)  {
-        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short);
-        for (long i = (length - 1) * 2; i >= 0; i -= 2) {
-            Character a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Short);
-            UnsafeStoreNode.store(dest, i + (destOffset + header), a.charValue(), CiKind.Short);
-        }
-    }
-
-    @Snippet
-    public static void copyIntsDown(Object src, long srcOffset, Object dest, long destOffset, int length)  {
-        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short);
-        for (long i = (length - 1) * 4; i >= 0; i -= 4) {
-            Integer a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Int);
-            UnsafeStoreNode.store(dest, i + (destOffset + header), a.intValue(), CiKind.Int);
-        }
-    }
-
-    @Snippet
-    public static void copyLongsDown(Object src, long srcOffset, Object dest, long destOffset, int length)  {
-        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short);
-        for (long i = (length - 1) * 8; i >= 0; i -= 8) {
-            Long a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Long);
-            UnsafeStoreNode.store(dest, i + (destOffset + header), a.longValue(), CiKind.Long);
-        }
-    }
-
-    // Does NOT perform store checks
-    @Snippet
-    public static void copyObjectsDown(Object src, long srcOffset, Object dest, long destOffset, int length)  {
-        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Object);
-        for (long i = (length - 1) * 8; i >= 0; i -= 8) {
-            Object a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Object);
-            UnsafeStoreNode.store(dest, i + (destOffset + header), a, CiKind.Object);
-        }
-    }
-
-    /**
-     * Copies {@code length} bytes from {@code src} starting at {@code srcPos} to {@code dest} starting at {@code destPos}.
-     * @param src source object
-     * @param srcPos source offset
-     * @param dest destination object
-     * @param destPos destination offset
-     * @param length number of bytes to copy
-     */
-    @Snippet
-    public static void copyBytesUp(Object src, int srcPos, Object dest, int destPos, int length)  {
-        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Byte);
-        for (long i = 0; i < length; i++) {
-            Byte a = UnsafeLoadNode.load(src, i + (srcPos + header), CiKind.Byte);
-            UnsafeStoreNode.store(dest, i + (destPos + header), a.byteValue(), CiKind.Byte);
-        }
-    }
-
-    /**
-     * Copies {@code length} shorts from {@code src} starting at offset {@code srcOffset} (in bytes) to {@code dest} starting at offset {@code destOffset} (in bytes).
-     * @param src
-     * @param srcOffset (in bytes)
-     * @param dest
-     * @param destOffset (in bytes)
-     * @param length  (in shorts)
-     */
-    @Snippet
-    public static void copyShortsUp(Object src, long srcOffset, Object dest, long destOffset, int length)  {
-        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short);
-        for (long i = 0; i < length * 2L; i += 2) {
-            Character a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Short);
-            UnsafeStoreNode.store(dest, i + (destOffset + header), a.charValue(), CiKind.Short);
-        }
-    }
-
-    @Snippet
-    public static void copyIntsUp(Object src, long srcOffset, Object dest, long destOffset, int length)  {
-        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Int);
-        for (long i = 0; i < length * 4L; i += 4) {
-            Integer a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Int);
-            UnsafeStoreNode.store(dest, i + (destOffset + header), a.intValue(), CiKind.Int);
-        }
-    }
-
-    @Snippet
-    public static void copyLongsUp(Object src, long srcOffset, Object dest, long destOffset, int length)  {
-        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Long);
-        for (long i = 0; i < length * 8L; i += 8) {
-            Long a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Long);
-            UnsafeStoreNode.store(dest, i + (destOffset + header), a.longValue(), CiKind.Long);
-        }
-    }
-
-    // Does NOT perform store checks
-    @Snippet
-    public static void copyObjectsUp(Object src, long srcOffset, Object dest, long destOffset, int length)  {
-        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Object);
-        for (long i = 0; i < length * 8L; i += 8) {
-            Object a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Object);
-            UnsafeStoreNode.store(dest, i + (destOffset + header), a, CiKind.Object);
-        }
-    }
-}
--- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/GraalIntrinsics.java	Fri Feb 03 10:17:33 2012 +0100
+++ b/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/GraalIntrinsics.java	Fri Feb 03 10:21:02 2012 +0100
@@ -25,7 +25,6 @@
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.phases.*;
-import com.oracle.max.graal.compiler.phases.PhasePlan.PhasePosition;
 import com.oracle.max.graal.cri.*;
 
 /**
@@ -38,8 +37,6 @@
             Snippets.install(runtime, target, new DoubleSnippets(), plan);
             Snippets.install(runtime, target, new FloatSnippets(), plan);
             Snippets.install(runtime, target, new NodeClassSnippets(), plan);
-            Snippets.install(runtime, target, new ArrayCopySnippets(), plan);
-            plan.addPhase(PhasePosition.HIGH_LEVEL, new IntrinsifyArrayCopyPhase(runtime));
         }
     }
 }
--- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/IntrinsifyArrayCopyPhase.java	Fri Feb 03 10:17:33 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2011, 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.max.graal.snippets;
-
-import java.lang.reflect.*;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ri.*;
-import com.oracle.max.graal.compiler.phases.*;
-import com.oracle.max.graal.compiler.util.*;
-import com.oracle.max.graal.cri.*;
-import com.oracle.max.graal.graph.*;
-import com.oracle.max.graal.nodes.*;
-import com.oracle.max.graal.nodes.java.*;
-
-public class IntrinsifyArrayCopyPhase extends Phase {
-    private final GraalRuntime runtime;
-    private RiResolvedMethod arrayCopy;
-    private RiResolvedMethod byteArrayCopy;
-    private RiResolvedMethod shortArrayCopy;
-    private RiResolvedMethod charArrayCopy;
-    private RiResolvedMethod intArrayCopy;
-    private RiResolvedMethod longArrayCopy;
-    private RiResolvedMethod floatArrayCopy;
-    private RiResolvedMethod doubleArrayCopy;
-    private RiResolvedMethod objectArrayCopy;
-
-    public IntrinsifyArrayCopyPhase(GraalRuntime runtime) {
-        this.runtime = runtime;
-        try {
-            byteArrayCopy = getArrayCopySnippet(runtime, byte.class);
-            charArrayCopy = getArrayCopySnippet(runtime, char.class);
-            shortArrayCopy = getArrayCopySnippet(runtime, short.class);
-            intArrayCopy = getArrayCopySnippet(runtime, int.class);
-            longArrayCopy = getArrayCopySnippet(runtime, long.class);
-            floatArrayCopy = getArrayCopySnippet(runtime, float.class);
-            doubleArrayCopy = getArrayCopySnippet(runtime, double.class);
-            objectArrayCopy = getArrayCopySnippet(runtime, Object.class);
-            arrayCopy = runtime.getRiMethod(System.class.getDeclaredMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class));
-        } catch (SecurityException e) {
-            e.printStackTrace();
-        } catch (NoSuchMethodException e) {
-            e.printStackTrace();
-        }
-    }
-
-    private static RiResolvedMethod getArrayCopySnippet(RiRuntime runtime, Class<?> componentClass) throws NoSuchMethodException {
-        Class<?> arrayClass = Array.newInstance(componentClass, 0).getClass();
-        return runtime.getRiMethod(ArrayCopySnippets.class.getDeclaredMethod("arraycopy", arrayClass, int.class, arrayClass, int.class, int.class));
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.class)) {
-            RiResolvedMethod targetMethod = methodCallTarget.targetMethod();
-            RiResolvedMethod snippetMethod = null;
-            if (targetMethod == arrayCopy) {
-                ValueNode src = methodCallTarget.arguments().get(0);
-                ValueNode dest = methodCallTarget.arguments().get(2);
-                if (src == null || dest == null) { //TODO (gd) this should never be null : check
-                    return;
-                }
-                RiResolvedType srcDeclaredType = src.declaredType();
-                RiResolvedType destDeclaredType = dest.declaredType();
-                if (srcDeclaredType != null
-                                && srcDeclaredType.isArrayClass()
-                                && destDeclaredType != null
-                                && destDeclaredType.isArrayClass()) {
-                    CiKind componentKind = srcDeclaredType.componentType().kind(false);
-                    if (srcDeclaredType.componentType() == destDeclaredType.componentType()) {
-                        if (componentKind == CiKind.Int) {
-                            snippetMethod = intArrayCopy;
-                        } else if (componentKind == CiKind.Char) {
-                            snippetMethod = charArrayCopy;
-                        } else if (componentKind == CiKind.Long) {
-                            snippetMethod = longArrayCopy;
-                        } else if (componentKind == CiKind.Byte) {
-                            snippetMethod = byteArrayCopy;
-                        } else if (componentKind == CiKind.Short) {
-                            snippetMethod = shortArrayCopy;
-                        } else if (componentKind == CiKind.Float) {
-                            snippetMethod = floatArrayCopy;
-                        } else if (componentKind == CiKind.Double) {
-                            snippetMethod = doubleArrayCopy;
-                        } else if (componentKind == CiKind.Object) {
-                            snippetMethod = objectArrayCopy;
-                        }
-                    } else if (componentKind == CiKind.Object
-                                    && srcDeclaredType.componentType().isSubtypeOf(destDeclaredType.componentType())) {
-                        snippetMethod = objectArrayCopy;
-                    }
-                }
-            }
-
-            if (snippetMethod != null) {
-                StructuredGraph snippetGraph = (StructuredGraph) snippetMethod.compilerStorage().get(Graph.class);
-                assert snippetGraph != null : "ArrayCopySnippets should be installed";
-                //TTY.println("  >  Intinsify");
-                InliningUtil.inline(methodCallTarget.invoke(), snippetGraph, false);
-            }
-        }
-        new CanonicalizerPhase(null, runtime, null).apply(graph);
-    }
-}
--- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/Snippets.java	Fri Feb 03 10:17:33 2012 +0100
+++ b/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/Snippets.java	Fri Feb 03 10:21:02 2012 +0100
@@ -121,6 +121,7 @@
         for (LoopEndNode end : graph.getNodes(LoopEndNode.class)) {
             end.setSafepointPolling(false);
         }
+        new InsertStateAfterPlaceholderPhase().apply(graph);
 
         Debug.dump(graph, "%s: Final", snippetRiMethod.name());
 
@@ -128,5 +129,4 @@
 
         return graph;
     }
-
 }
--- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/SystemSnippets.java	Fri Feb 03 10:17:33 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2011, 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.max.graal.snippets;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.nodes.extended.*;
-
-/**
- * Snippets for {@link java.lang.System} methods.
- */
-@ClassSubstitution(java.lang.System.class)
-public class SystemSnippets implements SnippetsInterface {
-
-    // TODO: public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) { }
-
-    public static long currentTimeMillis() {
-        return RuntimeCallNode.performCall(CiRuntimeCall.JavaTimeMillis);
-    }
-
-    public static long nanoTime() {
-        return RuntimeCallNode.performCall(CiRuntimeCall.JavaTimeNanos);
-    }
-
-}
--- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/UnsafeSnippets.java	Fri Feb 03 10:17:33 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,251 +0,0 @@
-/*
- * Copyright (c) 2011, 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.max.graal.snippets;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.util.*;
-import com.oracle.max.graal.nodes.extended.*;
-import com.oracle.max.graal.nodes.java.*;
-
-/**
- * Snippets for {@link sun.misc.Unsafe} methods.
- */
-@ClassSubstitution(sun.misc.Unsafe.class)
-public class UnsafeSnippets implements SnippetsInterface {
-
-    public boolean compareAndSwapObject(Object o, long offset, Object expected, Object x) {
-        return CompareAndSwapNode.compareAndSwap(o, offset, expected, x);
-    }
-
-    public boolean compareAndSwapInt(Object o, long offset, int expected, int x) {
-        return CompareAndSwapNode.compareAndSwap(o, offset, expected, x);
-    }
-
-    public boolean compareAndSwapLong(Object o, long offset, long expected, long x) {
-        return CompareAndSwapNode.compareAndSwap(o, offset, expected, x);
-    }
-
-    public Object getObject(Object o, long offset) {
-        return UnsafeLoadNode.load(o, offset, CiKind.Object);
-    }
-
-    public Object getObjectVolatile(Object o, long offset) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
-        Object result = getObject(o, offset);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
-        return result;
-    }
-
-    public void putObject(Object o, long offset, Object x) {
-        UnsafeStoreNode.store(o, offset, x, CiKind.Object);
-    }
-
-    public void putObjectVolatile(Object o, long offset, Object x) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
-        putObject(o, offset, x);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
-    }
-
-    public int getInt(Object o, long offset) {
-        Integer value = UnsafeLoadNode.load(o, offset, CiKind.Int);
-        return value;
-    }
-
-    public int getIntVolatile(Object o, long offset) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
-        int result = getInt(o, offset);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
-        return result;
-    }
-
-    public void putInt(Object o, long offset, int x) {
-        UnsafeStoreNode.store(o, offset, x, CiKind.Int);
-    }
-
-    public void putIntVolatile(Object o, long offset, int x) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
-        putInt(o, offset, x);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
-    }
-
-    public boolean getBoolean(Object o, long offset) {
-        @JavacBug(id = 6995200)
-        Boolean result = UnsafeLoadNode.load(o, offset, CiKind.Boolean);
-        return result;
-    }
-
-    public boolean getBooleanVolatile(Object o, long offset) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
-        boolean result = getBoolean(o, offset);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
-        return result;
-    }
-
-    public void putBoolean(Object o, long offset, boolean x) {
-        UnsafeStoreNode.store(o, offset, x, CiKind.Boolean);
-    }
-
-    public void putBooleanVolatile(Object o, long offset, boolean x) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
-        putBoolean(o, offset, x);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
-    }
-
-    public byte getByte(Object o, long offset) {
-        @JavacBug(id = 6995200)
-        Byte result = UnsafeLoadNode.load(o, offset, CiKind.Byte);
-        return result;
-    }
-
-    public byte getByteVolatile(Object o, long offset) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
-        byte result = getByte(o, offset);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
-        return result;
-    }
-
-    public void putByte(Object o, long offset, byte x) {
-        UnsafeStoreNode.store(o, offset, x, CiKind.Byte);
-    }
-
-    public void putByteVolatile(Object o, long offset, byte x) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
-        putByte(o, offset, x);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
-    }
-
-    public short getShort(Object o, long offset) {
-        @JavacBug(id = 6995200)
-        Short result = UnsafeLoadNode.load(o, offset, CiKind.Short);
-        return result;
-    }
-
-    public short getShortVolatile(Object o, long offset) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
-        short result = getShort(o, offset);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
-        return result;
-    }
-
-    public void putShort(Object o, long offset, short x) {
-        UnsafeStoreNode.store(o, offset, x, CiKind.Short);
-    }
-
-    public void putShortVolatile(Object o, long offset, short x) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
-        putShort(o, offset, x);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
-    }
-
-    public char getChar(Object o, long offset) {
-        @JavacBug(id = 6995200)
-        Character result = UnsafeLoadNode.load(o, offset, CiKind.Char);
-        return result;
-    }
-
-    public char getCharVolatile(Object o, long offset) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
-        char result = getChar(o, offset);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
-        return result;
-    }
-
-    public void putChar(Object o, long offset, char x) {
-        UnsafeStoreNode.store(o, offset, x, CiKind.Char);
-    }
-
-    public void putCharVolatile(Object o, long offset, char x) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
-        putChar(o, offset, x);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
-    }
-
-    public long getLong(Object o, long offset) {
-        @JavacBug(id = 6995200)
-        Long result = UnsafeLoadNode.load(o, offset, CiKind.Long);
-        return result;
-    }
-
-    public long getLongVolatile(Object o, long offset) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
-        long result = getLong(o, offset);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
-        return result;
-    }
-
-    public void putLong(Object o, long offset, long x) {
-        UnsafeStoreNode.store(o, offset, x, CiKind.Long);
-    }
-
-    public void putLongVolatile(Object o, long offset, long x) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
-        putLong(o, offset, x);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
-    }
-
-    public float getFloat(Object o, long offset) {
-        @JavacBug(id = 6995200)
-        Float result = UnsafeLoadNode.load(o, offset, CiKind.Float);
-        return result;
-    }
-
-    public float getFloatVolatile(Object o, long offset) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
-        float result = getFloat(o, offset);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
-        return result;
-    }
-
-    public void putFloat(Object o, long offset, float x) {
-        UnsafeStoreNode.store(o, offset, x, CiKind.Float);
-    }
-
-    public void putFloatVolatile(Object o, long offset, float x) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
-        putFloat(o, offset, x);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
-    }
-
-    public double getDouble(Object o, long offset) {
-        @JavacBug(id = 6995200)
-        Double result = UnsafeLoadNode.load(o, offset, CiKind.Double);
-        return result;
-    }
-
-    public double getDoubleVolatile(Object o, long offset) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
-        double result = getDouble(o, offset);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
-        return result;
-    }
-
-    public void putDouble(Object o, long offset, double x) {
-        UnsafeStoreNode.store(o, offset, x, CiKind.Double);
-    }
-
-    public void putDoubleVolatile(Object o, long offset, double x) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
-        putDouble(o, offset, x);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
-    }
-}