changeset 9114:01958088b87d

Merge.
author Christian Haeubl <haeubl@ssw.jku.at>
date Mon, 15 Apr 2013 08:49:14 +0200
parents 6c33b2076d7c (current diff) 58f9750afcab (diff)
children 79b098d44d20
files graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfBoxingEliminationTest.java graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TestNodeInterface.java graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TypedNodeIteratorTest.java graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TypedNodeIteratorTest2.java graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/ArrayCopyIntrinsificationTest.java graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/HotSpotMethodSubstitutionTest.java graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/InstalledCodeExecuteHelperTest.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayWriteBarrier.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/FieldWriteBarrier.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxingMethodPool.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/BoxingEliminationPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandBoxingNodesPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IdentifyBoxingPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/PushNodesThroughPi.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/CheckCastTest.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/CompiledExceptionHandlerTest.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/InstanceOfDynamicTest.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/InstanceOfTest.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/InvokeTest.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/MethodSubstitutionTest.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/MonitorTest.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/NewArrayTest.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/NewInstanceTest.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/NewMultiArrayTest.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/PointerTest.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/StandardMethodSubstitutionsTest.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/TypeCheckTest.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/WordTest.java src/cpu/x86/vm/sharedRuntime_x86_64.cpp test/gc/6941923/test6941923.sh test/gc/TestVerifyBeforeGCDuringStartup.java test/runtime/NMT/AllocTestType.java
diffstat 424 files changed, 14658 insertions(+), 8834 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Mon Apr 08 17:48:46 2013 +0200
+++ b/.hgignore	Mon Apr 15 08:49:14 2013 +0200
@@ -4,6 +4,7 @@
 ^mx/ecj.jar
 ^mx/includes
 ^build/
+^build-nograal/
 ^dist/
 ^java/
 ^lib/
--- a/.hgtags	Mon Apr 08 17:48:46 2013 +0200
+++ b/.hgtags	Mon Apr 15 08:49:14 2013 +0200
@@ -330,3 +330,6 @@
 8d0f263a370c5f3e61791bb06054560804117288 hs25-b25
 af788b85010ebabbc1e8f52c6766e08c7a95cf99 jdk8-b84
 a947f40fb536e5b9e0aa210cf26abb430f80887a hs25-b26
+42fe530cd478744a4d12a0cbf803f0fc804bab1a jdk8-b85
+09b0d3e9ba6cdf7da07d4010d2d1df14596f6864 hs25-b27
+6d88a566d369f6a1f86912cad7d0912686b2fda1 hs25-b28
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java	Mon Apr 15 08:49:14 2013 +0200
@@ -25,6 +25,7 @@
 import static com.oracle.graal.api.meta.MetaUtil.*;
 
 import java.io.*;
+import java.lang.invoke.*;
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
@@ -44,6 +45,40 @@
         private static final long serialVersionUID = -1936652569665112915L;
     }
 
+    public static final class NoFinalizableSubclass extends Assumption {
+
+        private static final long serialVersionUID = 6451169735564055081L;
+
+        private ResolvedJavaType receiverType;
+
+        public NoFinalizableSubclass(ResolvedJavaType receiverType) {
+            this.receiverType = receiverType;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + receiverType.hashCode();
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof NoFinalizableSubclass) {
+                NoFinalizableSubclass other = (NoFinalizableSubclass) obj;
+                return other.receiverType == receiverType;
+            }
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            return "NoFinalizableSubclass[receiverType=" + toJavaName(receiverType) + "]";
+        }
+
+    }
+
     /**
      * An assumption about a unique subtype of a given type.
      */
@@ -182,6 +217,45 @@
     }
 
     /**
+     * Assumption that a call site's method handle did not change.
+     */
+    public static final class CallSiteTargetValue extends Assumption {
+
+        private static final long serialVersionUID = 1732459941784550371L;
+
+        public final CallSite callSite;
+        public final MethodHandle methodHandle;
+
+        public CallSiteTargetValue(CallSite callSite, MethodHandle methodHandle) {
+            this.callSite = callSite;
+            this.methodHandle = methodHandle;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + callSite.hashCode();
+            result = prime * result + methodHandle.hashCode();
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof CallSiteTargetValue) {
+                CallSiteTargetValue other = (CallSiteTargetValue) obj;
+                return other.callSite == callSite && other.methodHandle == methodHandle;
+            }
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            return "CallSiteTargetValue[callSite=" + callSite + ", methodHandle=" + methodHandle + "]";
+        }
+    }
+
+    /**
      * Array with the assumptions. This field is directly accessed from C++ code in the
      * Graal/HotSpot implementation.
      */
@@ -233,12 +307,10 @@
      * Records an assumption that the specified type has no finalizable subclasses.
      * 
      * @param receiverType the type that is assumed to have no finalizable subclasses
-     * @return {@code true} if the assumption was recorded and can be assumed; {@code false}
-     *         otherwise
      */
-    public boolean recordNoFinalizableSubclassAssumption(ResolvedJavaType receiverType) {
+    public void recordNoFinalizableSubclassAssumption(ResolvedJavaType receiverType) {
         assert useOptimisticAssumptions;
-        return false;
+        record(new NoFinalizableSubclass(receiverType));
     }
 
     /**
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Mon Apr 15 08:49:14 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -52,42 +52,45 @@
     }
 
     /**
-     * Represents a safepoint with associated debug info.
+     * Represents an infopoint with associated debug info. Note that safepoints are also infopoints.
      */
-    public static class Safepoint extends Site implements Comparable<Safepoint> {
+    public static class Infopoint extends Site implements Comparable<Infopoint> {
 
         private static final long serialVersionUID = 2479806696381720162L;
         public final DebugInfo debugInfo;
 
-        public Safepoint(int pcOffset, DebugInfo debugInfo) {
+        public final InfopointReason reason;
+
+        public Infopoint(int pcOffset, DebugInfo debugInfo, InfopointReason reason) {
             super(pcOffset);
             this.debugInfo = debugInfo;
+            this.reason = reason;
         }
 
         @Override
         public String toString() {
             StringBuilder sb = new StringBuilder();
             sb.append(pcOffset);
-            sb.append("[<safepoint>]");
+            sb.append("[<infopoint>]");
             appendDebugInfo(sb, debugInfo);
             return sb.toString();
         }
 
         @Override
-        public int compareTo(Safepoint o) {
+        public int compareTo(Infopoint o) {
             if (pcOffset < o.pcOffset) {
                 return -1;
             } else if (pcOffset > o.pcOffset) {
                 return 1;
             }
-            return 0;
+            return this.reason.compareTo(o.reason);
         }
     }
 
     /**
      * Represents a call in the code.
      */
-    public static final class Call extends Safepoint {
+    public static final class Call extends Infopoint {
 
         private static final long serialVersionUID = 1440741241631046954L;
 
@@ -109,7 +112,7 @@
         public final boolean direct;
 
         public Call(InvokeTarget target, int pcOffset, int size, boolean direct, DebugInfo debugInfo) {
-            super(pcOffset, debugInfo);
+            super(pcOffset, debugInfo, InfopointReason.CALL);
             this.size = size;
             this.target = target;
             this.direct = direct;
@@ -284,7 +287,7 @@
         }
     }
 
-    private final List<Safepoint> safepoints = new ArrayList<>();
+    private final List<Infopoint> infopoints = new ArrayList<>();
     private final List<DataPatch> dataReferences = new ArrayList<>();
     private final List<ExceptionHandler> exceptionHandlers = new ArrayList<>();
     private final List<Mark> marks = new ArrayList<>();
@@ -377,7 +380,7 @@
      */
     public void recordCall(int codePos, int size, InvokeTarget target, DebugInfo debugInfo, boolean direct) {
         final Call call = new Call(target, codePos, size, direct, debugInfo);
-        addSafepoint(call);
+        addInfopoint(call);
     }
 
     /**
@@ -391,22 +394,22 @@
     }
 
     /**
-     * Records a safepoint in the code array.
+     * Records an infopoint in the code array.
      * 
-     * @param codePos the position of the safepoint in the code array
-     * @param debugInfo the debug info for the safepoint
+     * @param codePos the position of the infopoint in the code array
+     * @param debugInfo the debug info for the infopoint
      */
-    public void recordSafepoint(int codePos, DebugInfo debugInfo) {
-        addSafepoint(new Safepoint(codePos, debugInfo));
+    public void recordInfopoint(int codePos, DebugInfo debugInfo, InfopointReason reason) {
+        addInfopoint(new Infopoint(codePos, debugInfo, reason));
     }
 
-    private void addSafepoint(Safepoint safepoint) {
-        // The safepoints list must always be sorted
-        if (!getSafepoints().isEmpty() && getSafepoints().get(getSafepoints().size() - 1).pcOffset >= safepoint.pcOffset) {
+    private void addInfopoint(Infopoint infopoint) {
+        // The infopoints list must always be sorted
+        if (!getInfopoints().isEmpty() && getInfopoints().get(getInfopoints().size() - 1).pcOffset >= infopoint.pcOffset) {
             // This re-sorting should be very rare
-            Collections.sort(getSafepoints());
+            Collections.sort(getInfopoints());
         }
-        getSafepoints().add(safepoint);
+        getInfopoints().add(infopoint);
     }
 
     /**
@@ -522,10 +525,10 @@
     }
 
     /**
-     * @return the list of safepoints, sorted by {@link Site#pcOffset}
+     * @return the list of infopoints, sorted by {@link Site#pcOffset}
      */
-    public List<Safepoint> getSafepoints() {
-        return safepoints;
+    public List<Infopoint> getInfopoints() {
+        return infopoints;
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InfopointReason.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,32 @@
+/*
+ * 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.api.code;
+
+/**
+ * A reason for infopoint insertion.
+ */
+public enum InfopointReason {
+
+    UNKNOWN, SAFEPOINT, CALL, IMPLICIT_EXCEPTION, METHOD_START, METHOD_END, LINE_NUMBER;
+
+}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -31,14 +31,6 @@
 public interface InstalledCode {
 
     /**
-     * Exception thrown by the runtime in case an invalidated machine code is called.
-     */
-    public abstract class MethodInvalidatedException extends RuntimeException {
-
-        private static final long serialVersionUID = -3540232440794244844L;
-    }
-
-    /**
      * Returns the method (if any) to which the installed code belongs.
      */
     ResolvedJavaMethod getMethod();
@@ -61,6 +53,12 @@
     boolean isValid();
 
     /**
+     * Invalidates this installed code such that any subsequent invocation will throw an
+     * {@link InvalidInstalledCodeException}.
+     */
+    void invalidate();
+
+    /**
      * Executes the installed code with three object arguments.
      * 
      * @param arg1 the first argument
@@ -68,7 +66,7 @@
      * @param arg3 the third argument
      * @return the value returned by the executed code
      */
-    Object execute(Object arg1, Object arg2, Object arg3);
+    Object execute(Object arg1, Object arg2, Object arg3) throws InvalidInstalledCodeException;
 
     /**
      * Executes the installed code with a variable number of arguments.
@@ -76,5 +74,5 @@
      * @param args the array of object arguments
      * @return the value returned by the executed code
      */
-    Object executeVarargs(Object... args);
+    Object executeVarargs(Object... args) throws InvalidInstalledCodeException;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InvalidInstalledCodeException.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,31 @@
+/*
+ * 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.api.code;
+
+/**
+ * Exception thrown by the runtime in case an invalidated machine code is called.
+ */
+public final class InvalidInstalledCodeException extends Exception {
+
+    private static final long serialVersionUID = -3540232440794244844L;
+}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java	Mon Apr 15 08:49:14 2013 +0200
@@ -114,4 +114,6 @@
     long getMaxCallTargetOffset();
 
     Descriptor getDescriptor();
+
+    boolean preservesRegisters();
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java	Mon Apr 15 08:49:14 2013 +0200
@@ -36,10 +36,31 @@
  */
 public class TypeCheckHints {
 
-    private static final ResolvedJavaType[] NO_TYPES = {};
+    /**
+     * A receiver type profiled in a type check instruction.
+     */
+    public static class Hint {
+
+        /**
+         * A type seen while profiling a type check instruction.
+         */
+        public final ResolvedJavaType type;
+
+        /**
+         * Specifies if {@link #type} was a sub-type of the checked type.
+         */
+        public final boolean positive;
+
+        Hint(ResolvedJavaType type, boolean positive) {
+            this.type = type;
+            this.positive = positive;
+        }
+    }
+
+    private static final Hint[] NO_HINTS = {};
 
     /**
-     * If true, then {@link #types} contains the only possible type that could pass the type check
+     * If true, then {@link #hints} contains the only possible type that could pass the type check
      * because the target of the type check is a final class or has been speculated to be a final
      * class.
      */
@@ -48,63 +69,63 @@
     /**
      * The most likely types that the type check instruction will see.
      */
-    public final ResolvedJavaType[] types;
+    public final Hint[] hints;
 
     /**
      * Derives hint information for use when generating the code for a type check instruction.
      * 
-     * @param type the target type of the type check
+     * @param targetType the target type of the type check
      * @param profile the profiling information available for the instruction (if any)
      * @param assumptions the object in which speculations are recorded. This is null if
      *            speculations are not supported.
      * @param minHintHitProbability if the probability that the type check will hit one of the
-     *            profiled types (up to {@code maxHints}) is below this value, then {@link #types}
+     *            profiled types (up to {@code maxHints}) is below this value, then {@link #hints}
      *            will be null
-     * @param maxHints the maximum length of {@link #types}
+     * @param maxHints the maximum length of {@link #hints}
      */
-    public TypeCheckHints(ResolvedJavaType type, JavaTypeProfile profile, Assumptions assumptions, double minHintHitProbability, int maxHints) {
-        if (type != null && !canHaveSubtype(type)) {
-            types = new ResolvedJavaType[]{type};
+    public TypeCheckHints(ResolvedJavaType targetType, JavaTypeProfile profile, Assumptions assumptions, double minHintHitProbability, int maxHints) {
+        if (targetType != null && !canHaveSubtype(targetType)) {
+            hints = new Hint[]{new Hint(targetType, true)};
             exact = true;
         } else {
-            ResolvedJavaType uniqueSubtype = type == null ? null : type.findUniqueConcreteSubtype();
+            ResolvedJavaType uniqueSubtype = targetType == null ? null : targetType.findUniqueConcreteSubtype();
             if (uniqueSubtype != null) {
-                types = new ResolvedJavaType[]{uniqueSubtype};
+                hints = new Hint[]{new Hint(uniqueSubtype, true)};
                 if (assumptions.useOptimisticAssumptions()) {
-                    assumptions.recordConcreteSubtype(type, uniqueSubtype);
+                    assumptions.recordConcreteSubtype(targetType, uniqueSubtype);
                     exact = true;
                 } else {
                     exact = false;
                 }
             } else {
                 exact = false;
-                ResolvedJavaType[] hintTypes = NO_TYPES;
+                Hint[] hintsBuf = NO_HINTS;
                 JavaTypeProfile typeProfile = profile;
                 if (typeProfile != null) {
                     double notRecordedTypes = typeProfile.getNotRecordedProbability();
                     ProfiledType[] ptypes = typeProfile.getTypes();
                     if (notRecordedTypes < (1D - minHintHitProbability) && ptypes != null && ptypes.length > 0) {
-                        hintTypes = new ResolvedJavaType[ptypes.length];
+                        hintsBuf = new Hint[ptypes.length];
                         int hintCount = 0;
                         double totalHintProbability = 0.0d;
                         for (ProfiledType ptype : ptypes) {
-                            ResolvedJavaType hint = ptype.getType();
-                            if (type != null && type.isAssignableFrom(hint)) {
-                                hintTypes[hintCount++] = hint;
+                            if (targetType != null) {
+                                ResolvedJavaType hintType = ptype.getType();
+                                hintsBuf[hintCount++] = new Hint(hintType, targetType.isAssignableFrom(hintType));
                                 totalHintProbability += ptype.getProbability();
                             }
                         }
                         if (totalHintProbability >= minHintHitProbability) {
-                            if (hintTypes.length != hintCount || hintCount > maxHints) {
-                                hintTypes = Arrays.copyOf(hintTypes, Math.min(maxHints, hintCount));
+                            if (hintsBuf.length != hintCount || hintCount > maxHints) {
+                                hintsBuf = Arrays.copyOf(hintsBuf, Math.min(maxHints, hintCount));
                             }
                         } else {
-                            hintTypes = NO_TYPES;
+                            hintsBuf = NO_HINTS;
                         }
 
                     }
                 }
-                this.types = hintTypes;
+                this.hints = hintsBuf;
             }
         }
     }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java	Mon Apr 15 08:49:14 2013 +0200
@@ -89,13 +89,19 @@
     }
 
     public static Register asIntReg(Value value) {
-        assert value.getKind() == Kind.Int;
-        return asRegister(value);
+        if (value.getKind() != Kind.Int) {
+            throw new InternalError("needed Int got: " + value.getKind());
+        } else {
+            return asRegister(value);
+        }
     }
 
     public static Register asLongReg(Value value) {
-        assert value.getKind() == Kind.Long : value.getKind();
-        return asRegister(value);
+        if (value.getKind() != Kind.Long) {
+            throw new InternalError("needed Long got: " + value.getKind());
+        } else {
+            return asRegister(value);
+        }
     }
 
     public static Register asObjectReg(Value value) {
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java	Mon Apr 15 08:49:14 2013 +0200
@@ -402,7 +402,7 @@
                 if (!isStatic(m.getModifiers()) && !isPrivate(m.getModifiers())) {
                     Method overridden = vtable.methods.put(new NameAndSignature(m), m);
                     if (overridden != null) {
-                        // System.out.println(m + " overrides " + overridden);
+                        // println(m + " overrides " + overridden);
                     }
                 }
             }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java	Mon Apr 15 08:49:14 2013 +0200
@@ -30,6 +30,13 @@
 public interface ConstantPool {
 
     /**
+     * Returns the number of entries the constant pool.
+     * 
+     * @return number of entries in the constant pool
+     */
+    int length();
+
+    /**
      * Ensures that the type referenced by the specified constant pool entry is loaded and
      * initialized. This can be used to compile time resolve a type. It works for field, method, or
      * type constant pool entries.
@@ -93,4 +100,14 @@
      *         entry
      */
     Object lookupConstant(int cpi);
+
+    /**
+     * Looks up the appendix at the specified index.
+     * 
+     * @param cpi the constant pool index
+     * @param opcode the opcode of the instruction for which the lookup is being performed or
+     *            {@code -1}
+     * @return the appendix if it exists and is resolved or {@code null}
+     */
+    Object lookupAppendix(int cpi, int opcode);
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java	Mon Apr 15 08:49:14 2013 +0200
@@ -122,7 +122,9 @@
     }
 
     /**
-     * A list of types for which the runtime has recorded probability information.
+     * A list of types for which the runtime has recorded probability information. Note that this
+     * includes both positive and negative types where a positive type is a subtype of the checked
+     * type and a negative type is not.
      */
     public ProfiledType[] getTypes() {
         return ptypes;
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Mon Apr 15 08:49:14 2013 +0200
@@ -47,6 +47,17 @@
     }
 
     /**
+     * Calls {@link JavaType#resolve(ResolvedJavaType)} on an array of types.
+     */
+    public static ResolvedJavaType[] resolveJavaTypes(JavaType[] types, ResolvedJavaType accessingClass) {
+        ResolvedJavaType[] result = new ResolvedJavaType[types.length];
+        for (int i = 0; i < result.length; i++) {
+            result[i] = types[i].resolve(accessingClass);
+        }
+        return result;
+    }
+
+    /**
      * Calls {@link MetaAccessProvider#lookupJavaType(Class)} on an array of classes.
      */
     public static ResolvedJavaType[] lookupJavaTypes(MetaAccessProvider metaAccess, Class[] classes) {
@@ -58,54 +69,6 @@
     }
 
     /**
-     * Gets the {@link Class} mirror for a given resolved type.
-     * 
-     * @param type the type for which the Java mirror is requested
-     * @param loader class loader from which the class must be loaded (null means use the class
-     *            loader of the {@link MetaUtil} class)
-     * @return the mirror for {@code type}
-     * @throws NoClassDefFoundError if the mirror is not available
-     */
-    public static Class getMirrorOrFail(ResolvedJavaType type, ClassLoader loader) throws NoClassDefFoundError {
-        ResolvedJavaType elementalType = getElementalType(type);
-        Class elementalClass;
-        if (elementalType.isPrimitive()) {
-            elementalClass = elementalType.getKind().toJavaClass();
-        } else {
-            try {
-                elementalClass = Class.forName(toJavaName(elementalType), true, loader);
-            } catch (ClassNotFoundException e) {
-                throw (NoClassDefFoundError) new NoClassDefFoundError().initCause(e);
-            }
-        }
-        if (type.isArray()) {
-            ResolvedJavaType t = type;
-            while (t.getComponentType() != null) {
-                elementalClass = Array.newInstance(elementalClass, 0).getClass();
-                t = t.getComponentType();
-            }
-        }
-        assert elementalClass != null : toJavaName(type);
-        return elementalClass;
-    }
-
-    /**
-     * Gets the {@link Class} mirror for a given resolved type.
-     * 
-     * @param type the type for which the Java mirror is requested
-     * @param loader class loader from which the class must be loaded (null means use the class
-     *            loader of the {@link MetaUtil} class)
-     * @return the mirror for {@code type} or null if it is not available
-     */
-    public static Class getMirror(ResolvedJavaType type, ClassLoader loader) {
-        try {
-            return getMirrorOrFail(type, loader);
-        } catch (NoClassDefFoundError e) {
-            return null;
-        }
-    }
-
-    /**
      * Gets the elemental type for a given type. The elemental type of an array type is the
      * corresponding zero dimensional (e.g., the elemental type of {@code int[][][]} is {@code int}
      * ). A non-array type is its own elemental type.
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Mon Apr 15 08:49:14 2013 +0200
@@ -180,4 +180,26 @@
      * Returns the localvariable table of this method.
      */
     LocalVariableTable getLocalVariableTable();
+
+    /**
+     * Invokes the underlying method represented by this object, on the specified object with the
+     * specified parameters. This method is similar to a reflective method invocation by
+     * {@link Method#invoke}.
+     * 
+     * @param receiver The receiver for the invocation, or {@code null} if it is a static method.
+     * @param arguments The arguments for the invocation.
+     * @return The value returned by the method invocation, or {@code null} if the return type is
+     *         {@code void}.
+     */
+    Constant invoke(Constant receiver, Constant[] arguments);
+
+    /**
+     * Uses the constructor represented by this object to create and initialize a new instance of
+     * the constructor's declaring class, with the specified initialization parameters. This method
+     * is similar to a reflective instantiation by {@link Constructor#newInstance}.
+     * 
+     * @param arguments The arguments for the constructor.
+     * @return The newly created and initialized object.
+     */
+    Constant newInstance(Constant[] arguments);
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Mon Apr 15 08:49:14 2013 +0200
@@ -274,4 +274,22 @@
      * Returns the enclosing type of this type, if it exists, or {@code null}.
      */
     ResolvedJavaType getEnclosingType();
+
+    /**
+     * Returns an array reflecting all the constructors declared by this type. This method is
+     * similar to {@link Class#getDeclaredConstructors()} in terms of returned constructors.
+     */
+    ResolvedJavaMethod[] getDeclaredConstructors();
+
+    /**
+     * Returns an array reflecting all the methods declared by this type. This method is similar to
+     * {@link Class#getDeclaredMethods()} in terms of returned methods.
+     */
+    ResolvedJavaMethod[] getDeclaredMethods();
+
+    /**
+     * Creates a new array with this type as the component type and the specified length. This
+     * method is similar to {@link Array#newInstance(Class, int)}.
+     */
+    Constant newArray(int length);
 }
--- a/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MethodSubstitution.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MethodSubstitution.java	Mon Apr 15 08:49:14 2013 +0200
@@ -54,4 +54,20 @@
      * is the same as the substitute method.
      */
     String signature() default "";
+
+    /**
+     * Determines if this method should be substituted in all cases, even if inlining thinks it is
+     * not important.
+     * 
+     * Not that this is still depending on whether inlining sees the correct call target, so it's
+     * only a hard guarantee for static and special invocations.
+     */
+    boolean forced() default false;
+
+    /**
+     * Determines if the substitution is for a method that may not be part of the runtime. For
+     * example, a method introduced in a later JDK version. Substitutions for such methods are
+     * omitted if the original method cannot be found.
+     */
+    boolean optional() default false;
 }
--- a/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/ServiceProvider.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/ServiceProvider.java	Mon Apr 15 08:49:14 2013 +0200
@@ -24,7 +24,7 @@
 
 import java.lang.annotation.*;
 
-@Retention(RetentionPolicy.SOURCE)
+@Retention(RetentionPolicy.CLASS)
 @Target(ElementType.TYPE)
 public @interface ServiceProvider {
 
--- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Mon Apr 15 08:49:14 2013 +0200
@@ -26,8 +26,7 @@
 
 public class PTXAssembler extends AbstractPTXAssembler {
 
-    @SuppressWarnings("unused")
-    public PTXAssembler(TargetDescription target, RegisterConfig registerConfig) {
+    public PTXAssembler(TargetDescription target, @SuppressWarnings("unused") RegisterConfig registerConfig) {
         super(target);
     }
 
@@ -35,6 +34,18 @@
         emitString("@%p" + " " + "");
     }
 
+    public final void atq() {
+        emitString("@%q" + " " + "");
+    }
+
+    public final void add_f32(Register d, Register a, Register b) {
+        emitString("add.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void add_f64(Register d, Register a, Register b) {
+        emitString("add.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
     public final void add_s16(Register d, Register a, Register b) {
         emitString("add.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
@@ -59,6 +70,14 @@
         emitString("add.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + "");
     }
 
+    public final void add_f32(Register d, Register a, float f32) {
+        emitString("add.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + "");
+    }
+
+    public final void add_f64(Register d, Register a, double f64) {
+        emitString("add.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + "");
+    }
+
     public final void add_u16(Register d, Register a, Register b) {
         emitString("add.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
@@ -123,7 +142,63 @@
         emitString("bra.uni" + " " + tgt + ";" + "");
     }
 
-    public final void div_s16(Register d, Register a, Register b) {
+    public final void cvt_s32_f32(Register d, Register a) {
+        emitString("cvt.s32.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void cvt_s64_f32(Register d, Register a) {
+        emitString("cvt.s64.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void cvt_f64_f32(Register d, Register a) {
+        emitString("cvt.f64.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void cvt_f32_f64(Register d, Register a) {
+        emitString("cvt.f32.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void cvt_s32_f64(Register d, Register a) {
+        emitString("cvt.s32.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void cvt_s64_f64(Register d, Register a) {
+        emitString("cvt.s64.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void cvt_f32_s32(Register d, Register a) {
+        emitString("cvt.f32.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void cvt_f64_s32(Register d, Register a) {
+        emitString("cvt.f64.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void cvt_s8_s32(Register d, Register a) {
+        emitString("cvt.s8.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void cvt_b16_s32(Register d, Register a) {
+        emitString("cvt.b16.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void cvt_s64_s32(Register d, Register a) {
+        emitString("cvt.s64.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void cvt_s32_s64(Register d, Register a) {
+        emitString("cvt.s32.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void div_f32(Register d, Register a, Register b) {
+        emitString("div.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void div_f64(Register d, Register a, Register b) {
+        emitString("div.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+   public final void div_s16(Register d, Register a, Register b) {
         emitString("div.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
 
@@ -143,10 +218,30 @@
         emitString("div.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + "");
     }
 
+    public final void div_s32(Register d, int s32, Register b) {
+        emitString("div.s32" + " " + "%r" + d.encoding() + ", " + s32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void div_f32(Register d, float f32, Register b) {
+        emitString("div.f32" + " " + "%r" + d.encoding() + ", " + f32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void div_f64(Register d, double f64, Register b) {
+        emitString("div.f64" + " " + "%r" + d.encoding() + ", " + f64 + ", %r" + b.encoding() + ";" + "");
+    }
+
     public final void div_s64(Register d, Register a, long s64) {
         emitString("div.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + "");
     }
 
+    public final void div_f32(Register d, Register a, float f32) {
+        emitString("div.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + "");
+    }
+
+    public final void div_f64(Register d, Register a, double f64) {
+        emitString("div.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + "");
+    }
+
     public final void div_u16(Register d, Register a, Register b) {
         emitString("div.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
@@ -255,6 +350,11 @@
         emitString("mov.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
     }
 
+    public final void mov_u64(@SuppressWarnings("unused") Register d,
+                              @SuppressWarnings("unused") AbstractAddress a) {
+        // emitString("mov.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
     public final void mov_s16(Register d, Register a) {
         emitString("mov.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
     }
@@ -319,6 +419,14 @@
         emitString("mov.f64" + " " + "%r" + d.encoding() + ", " + f64 + ";" + "");
     }
 
+    public final void mul_f32(Register d, Register a, Register b) {
+        emitString("mul.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void mul_f64(Register d, Register a, Register b) {
+        emitString("smul.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
     public final void mul_s16(Register d, Register a, Register b) {
         emitString("mul.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
@@ -343,6 +451,14 @@
         emitString("mul.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + "");
     }
 
+    public final void mul_f32(Register d, Register a, float f32) {
+        emitString("mul.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + "");
+    }
+
+    public final void mul_f64(Register d, Register a, double f64) {
+        emitString("mul.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + "");
+    }
+
     public final void mul_u16(Register d, Register a, Register b) {
         emitString("mul.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
@@ -367,6 +483,14 @@
         emitString("mul.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + "");
     }
 
+    public final void neg_f32(Register d, Register a) {
+        emitString("neg.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void neg_f64(Register d, Register a) {
+        emitString("neg.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
     public final void neg_s16(Register d, Register a) {
         emitString("neg.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
     }
@@ -379,6 +503,42 @@
         emitString("neg.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
     }
 
+    public final void not_s16(Register d, Register a) {
+        emitString("not.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void not_s32(Register d, Register a) {
+        emitString("not.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void not_s64(Register d, Register a) {
+        emitString("not.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void or_b16(Register d, Register a, Register b) {
+        emitString("or.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void or_b32(Register d, Register a, Register b) {
+        emitString("or.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void or_b64(Register d, Register a, Register b) {
+        emitString("or.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void or_b16(Register d, Register a, short b16) {
+        emitString("or.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b16 + ";" + "");
+    }
+
+    public final void or_b32(Register d, Register a, int b32) {
+        emitString("or.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b32 + ";" + "");
+    }
+
+    public final void or_b64(Register d, Register a, long b64) {
+        emitString("or.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b64 + ";" + "");
+    }
+
     public final void popc_b32(Register d, Register a) {
         emitString("popc.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
     }
@@ -443,6 +603,86 @@
         emitString("ret.uni;" + " " + "");
     }
 
+    public final void setp_eq_f32(Register a, Register b) {
+        emitString("setp.eq.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_ne_f32(Register a, Register b) {
+        emitString("setp.ne.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_lt_f32(Register a, Register b) {
+        emitString("setp.lt.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_le_f32(Register a, Register b) {
+        emitString("setp.le.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_gt_f32(Register a, Register b) {
+        emitString("setp.gt.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_ge_f32(Register a, Register b) {
+        emitString("setp.ge.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_eq_f32(float f32, Register b) {
+        emitString("setp.eq.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_ne_f32(float f32, Register b) {
+        emitString("setp.ne.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_lt_f32(float f32, Register b) {
+        emitString("setp.lt.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_le_f32(float f32, Register b) {
+        emitString("setp.le.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_gt_f32(float f32, Register b) {
+        emitString("setp.gt.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_ge_f32(float f32, Register b) {
+        emitString("setp.ge.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_eq_f64(double f64, Register b) {
+        emitString("setp.eq.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_ne_f64(double f64, Register b) {
+        emitString("setp.ne.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_lt_f64(double f64, Register b) {
+        emitString("setp.lt.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_le_f64(double f64, Register b) {
+        emitString("setp.le.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_gt_f64(double f64, Register b) {
+        emitString("setp.gt.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_ge_f64(double f64, Register b) {
+        emitString("setp.ge.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_eq_s64(Register a, Register b) {
+        emitString("setp.eq.s64" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_eq_s64(long s64, Register b) {
+        emitString("setp.eq.s64" + " " + "%p" + ", " + s64 + ", %r" + b.encoding() + ";" + "");
+    }
+
     public final void setp_eq_s32(Register a, Register b) {
         emitString("setp.eq.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
@@ -587,6 +827,54 @@
         emitString("setp.ge.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + "");
     }
 
+    public final void shl_s16(Register d, Register a, Register b) {
+        emitString("shl.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void shl_s32(Register d, Register a, Register b) {
+        emitString("shl.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void shl_s64(Register d, Register a, Register b) {
+        emitString("shl.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void shl_s16(Register d, Register a, int u32) {
+        emitString("shl.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void shl_s32(Register d, Register a, int u32) {
+        emitString("shl.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void shl_s64(Register d, Register a, int u32) {
+        emitString("shl.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void shl_u16(Register d, Register a, Register b) {
+        emitString("shl.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void shl_u32(Register d, Register a, Register b) {
+        emitString("shl.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void shl_u64(Register d, Register a, Register b) {
+        emitString("shl.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void shl_u16(Register d, Register a, int u32) {
+        emitString("shl.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void shl_u32(Register d, Register a, int u32) {
+        emitString("shl.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void shl_u64(Register d, Register a, int u32) {
+        emitString("shl.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
     public final void shr_s16(Register d, Register a, Register b) {
         emitString("shr.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
@@ -631,8 +919,8 @@
         emitString("shr.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
     }
 
-    public final void shr_u64(Register d, Register a, int u32) {
-        emitString("shr.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    public final void shr_u64(Register d, Register a, long u64) {
+        emitString("shr.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + "");
     }
 
     public final void st_global_b8(Register a, long immOff, Register b) {
@@ -691,6 +979,14 @@
         emitString("st.global.f64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
     }
 
+    public final void sub_f32(Register d, Register a, Register b) {
+        emitString("sub.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void sub_f64(Register d, Register a, Register b) {
+        emitString("sub.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
     public final void sub_s16(Register d, Register a, Register b) {
         emitString("sub.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
@@ -711,10 +1007,22 @@
         emitString("sub.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + "");
     }
 
+    public final void sub_s64(Register d, Register a, int s32) {
+        emitString("sub.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + "");
+    }
+
     public final void sub_s64(Register d, Register a, long s64) {
         emitString("sub.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + "");
     }
 
+    public final void sub_f32(Register d, Register a, float f32) {
+        emitString("sub.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + "");
+    }
+
+    public final void sub_f64(Register d, Register a, double f64) {
+        emitString("sub.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + "");
+    }
+
     public final void sub_s16(Register d, short s16, Register b) {
         emitString("sub.s16" + " " + "%r" + d.encoding() + ", " + s16 + ", %r" + b.encoding() + ";" + "");
     }
@@ -727,6 +1035,14 @@
         emitString("sub.s64" + " " + "%r" + d.encoding() + ", " + s64 + ", %r" + b.encoding() + ";" + "");
     }
 
+    public final void sub_f32(Register d, float f32, Register b) {
+        emitString("sub.f32" + " " + "%r" + d.encoding() + ", %r" + b.encoding() + ", " + f32 + ";" + "");
+    }
+
+    public final void sub_f64(Register d, double f64, Register b) {
+        emitString("sub.f64" + " " + "%r" + d.encoding() + ", %r" + b.encoding() + ", " + f64 + ";" + "");
+    }
+
     public final void sub_sat_s32(Register d, Register a, Register b) {
         emitString("sub.sat.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
@@ -739,6 +1055,30 @@
         emitString("sub.sat.s32" + " " + "%r" + d.encoding() + ", " + s32 + ", %r" + b.encoding() + ";" + "");
     }
 
+    public final void xor_b16(Register d, Register a, Register b) {
+        emitString("xor.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void xor_b32(Register d, Register a, Register b) {
+        emitString("xor.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void xor_b64(Register d, Register a, Register b) {
+        emitString("xor.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void xor_b16(Register d, Register a, short b16) {
+        emitString("xor.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b16 + ";" + "");
+    }
+
+    public final void xor_b32(Register d, Register a, int b32) {
+        emitString("xor.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b32 + ";" + "");
+    }
+
+    public final void xor_b64(Register d, Register a, long b64) {
+        emitString("xor.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b64 + ";" + "");
+    }
+
     @Override
     public PTXAddress makeAddress(Register base, int displacement) {
         return new PTXAddress(base, displacement);
--- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -67,7 +67,11 @@
     protected Object runTest(String methodName, CodeGenTest test, Object... args) {
         Method method = getMethod(methodName);
         InstalledCode code = assembleMethod(method, test);
-        return code.executeVarargs(args);
+        try {
+            return code.executeVarargs(args);
+        } catch (InvalidInstalledCodeException e) {
+            throw new RuntimeException(e);
+        }
     }
 
     protected void assertReturn(String methodName, CodeGenTest test, Object expected, Object... args) {
--- a/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeStream.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeStream.java	Mon Apr 15 08:49:14 2013 +0200
@@ -168,6 +168,16 @@
     }
 
     /**
+     * Reads a constant pool index for an invokedynamic instruction.
+     * 
+     * @return the constant pool index
+     */
+    public int readCPI4() {
+        assert opcode == Bytecodes.INVOKEDYNAMIC;
+        return Bytes.beS4(code, curBCI + 1);
+    }
+
+    /**
      * Reads a signed, 1-byte value for the current instruction (e.g. BIPUSH).
      * 
      * @return the byte
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon Apr 15 08:49:14 2013 +0200
@@ -926,4 +926,9 @@
         Value[] parameters = visitInvokeArguments(cc, node.arguments);
         append(new AMD64BreakpointOp(parameters));
     }
+
+    @Override
+    public void visitInfopointNode(InfopointNode i) {
+        append(new InfopointOp(stateFor(i.stateAfter(), DeoptimizationReason.None), i.reason));
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,116 @@
+/*
+ * 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.compiler.ptx.test;
+
+import java.lang.reflect.Method;
+
+import org.junit.Test;
+
+public class ArrayTest extends PTXTestBase {
+
+    @Test
+    public void testArray() {
+        compile("testArray1I");
+        compile("testArray1J");
+        compile("testArray1B");
+        compile("testArray1S");
+        compile("testArray1C");
+        compile("testArray1F");
+        compile("testArray1D");
+        compile("testArray1L");
+        compile("testStoreArray1I");
+        compile("testStoreArray1J");
+        compile("testStoreArray1B");
+        compile("testStoreArray1S");
+        compile("testStoreArray1F");
+        compile("testStoreArray1D");
+    }
+
+    public static int testArray1I(int[] array, int i) {
+        return array[i];
+    }
+
+    public static long testArray1J(long[] array, int i) {
+        return array[i];
+    }
+
+    public static byte testArray1B(byte[] array, int i) {
+        return array[i];
+    }
+
+    public static short testArray1S(short[] array, int i) {
+        return array[i];
+    }
+
+    public static char testArray1C(char[] array, int i) {
+        return array[i];
+    }
+
+    public static float testArray1F(float[] array, int i) {
+        return array[i];
+    }
+
+    public static double testArray1D(double[] array, int i) {
+        return array[i];
+    }
+
+    public static Object testArray1L(Object[] array, int i) {
+        return array[i];
+    }
+
+    public static void testStoreArray1I(int[] array, int i, int val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1B(byte[] array, int i, byte val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1S(short[] array, int i, short val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1J(long[] array, int i, long val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1F(float[] array, int i, float val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1D(double[] array, int i, double val) {
+        array[i] = val;
+    }
+
+    public static void main(String[] args) {
+        ArrayTest test = new ArrayTest();
+        for (Method m : ArrayTest.class.getMethods()) {
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -22,81 +22,33 @@
  */
 package com.oracle.graal.compiler.ptx.test;
 
-import java.lang.reflect.*;
-
-import org.junit.*;
+import java.lang.reflect.Method;
 
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.ptx.*;
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.java.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.PhasePlan.PhasePosition;
-import com.oracle.graal.ptx.*;
+import org.junit.Test;
 
 /**
  * Test class for small Java methods compiled to PTX kernels.
  */
-public class BasicPTXTest extends GraalCompilerTest {
+public class BasicPTXTest extends PTXTestBase {
 
     @Test
     public void testAdd() {
-        test("testAddSnippet");
+        compile("testAddConst1I");
     }
 
-    public static int testAddSnippet(int a) {
+    public static int testAddConst1I(int a) {
         return a + 1;
     }
 
-    @Test
-    public void testArray() {
-        test("testArraySnippet");
-    }
-
-    public static int testArraySnippet(int[] array) {
-        return array[0];
-    }
-
-    private CompilationResult test(String snippet) {
-        StructuredGraph graph = parse(snippet);
-        Debug.dump(graph, "Graph");
-        TargetDescription target = new TargetDescription(new PTX(), true, 1, 0, true);
-        PTXBackend ptxBackend = new PTXBackend(Graal.getRequiredCapability(CodeCacheProvider.class), target);
-        PhasePlan phasePlan = new PhasePlan();
-        GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.NONE);
-        phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
-        phasePlan.addPhase(PhasePosition.AFTER_PARSING, new PTXPhase());
-        new PTXPhase().apply(graph);
-        CompilationResult result = GraalCompiler.compileMethod(runtime, replacements, ptxBackend, target, graph.method(), graph, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog());
-        return result;
-    }
-
-    private static class PTXPhase extends Phase {
-
-        @Override
-        protected void run(StructuredGraph graph) {
-            for (LocalNode local : graph.getNodes(LocalNode.class)) {
-                if (local.kind() == Kind.Object) {
-                    local.setStamp(StampFactory.declaredNonNull(local.objectStamp().type()));
-                }
-            }
-        }
-
-    }
-
     public static void main(String[] args) {
-        BasicPTXTest basicPTXTest = new BasicPTXTest();
+        BasicPTXTest test = new BasicPTXTest();
         Method[] methods = BasicPTXTest.class.getMethods();
         for (Method m : methods) {
-            if (m.getAnnotation(Test.class) != null) {
-                String name = m.getName() + "Snippet";
-                System.out.println(name + ": \n" + new String(basicPTXTest.test(name).getTargetCode()));
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
             }
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,95 @@
+/*
+ * 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.compiler.ptx.test;
+
+import org.junit.Test;
+
+import java.lang.reflect.Method;
+
+public class ControlTest extends PTXTestBase {
+
+    @Test
+    public void testControl() {
+        compile("testSwitch1I");
+        compile("testStatic");
+        compile("testCall");
+        compile("testLookupSwitch1I");
+    }
+
+    public static int testSwitch1I(int a) {
+        switch (a) {
+        case 1:
+            return 2;
+        case 2:
+            return 3;
+        default:
+            return 4;
+        }
+    }
+
+    public static int testLookupSwitch1I(int a) {
+        switch (a) {
+        case 0:  return 1;
+        case 1:  return 2;
+        case 2:  return 3;
+        case 3:  return 1;
+        case 4:  return 2;
+        case 5:  return 3;
+        case 6:  return 1;
+        case 7:  return 2;
+        case 8:  return 3;
+        case 9:  return 1;
+        case 10: return 2;
+        case 11: return 3;
+        default: return -1;
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private static Object foo = null;
+
+    public static boolean testStatic(Object o) {
+        foo = o;
+        return true;
+    }
+
+    private static int method(int a, int b) {
+        return a + b;
+    }
+
+    public static int testCall(@SuppressWarnings("unused") Object o, int a, int b) {
+        return method(a, b);
+    }
+
+    public static void main(String[] args) {
+        ControlTest test = new ControlTest();
+        for (Method m : ControlTest.class.getMethods()) {
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/FloatPTXTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,245 @@
+/*
+ * 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.compiler.ptx.test;
+
+import java.lang.reflect.Method;
+
+import org.junit.*;
+
+
+/* PTX ISA 3.1 - 8.7.3 Floating-Point Instructions */
+public class FloatPTXTest extends PTXTestBase {
+
+    @Test
+    public void testAdd() {
+        compile("testAdd2F");
+        compile("testAdd2D");
+        compile("testAddFConst");
+        compile("testAddConstF");
+        compile("testAddDConst");
+        compile("testAddConstD");
+    }
+
+    public static float testAdd2F(float a, float b) {
+        return a + b;
+    }
+
+    public static double testAdd2D(double a, double b) {
+        return a + b;
+    }
+
+    public static float testAddFConst(float a) {
+        return a + 32.0F;
+    }
+
+    public static float testAddConstF(float a) {
+        return 32.0F + a;
+    }
+
+    public static double testAddDConst(double a) {
+        return a + 32.0;
+    }
+
+    public static double testAddConstD(double a) {
+        return 32.0 + a;
+    }
+
+    @Test
+    public void testSub() {
+        compile("testSub2F");
+        compile("testSub2D");
+        compile("testSubFConst");
+        compile("testSubConstF");
+        compile("testSubDConst");
+        compile("testSubConstD");
+    }
+
+    public static float testSub2F(float a, float b) {
+        return a - b;
+    }
+
+    public static double testSub2D(double a, double b) {
+        return a - b;
+    }
+
+    public static float testSubFConst(float a) {
+        return a - 32.0F;
+    }
+
+    public static float testSubConstF(float a) {
+        return 32.0F - a;
+    }
+
+    public static double testSubDConst(double a) {
+        return a - 32.0;
+    }
+
+    public static double testSubConstD(double a) {
+        return 32.0 - a;
+    }
+
+    @Test
+    public void testMul() {
+        compile("testMul2F");
+        compile("testMul2D");
+        compile("testMulFConst");
+        compile("testMulConstF");
+        compile("testMulDConst");
+        compile("testMulConstD");
+    }
+
+    public static float testMul2F(float a, float b) {
+        return a * b;
+    }
+
+    public static double testMul2D(double a, double b) {
+        return a * b;
+    }
+
+    public static float testMulFConst(float a) {
+        return a * 32.0F;
+    }
+
+    public static float testMulConstF(float a) {
+        return 32.0F * a;
+    }
+
+    public static double testMulDConst(double a) {
+        return a * 32.0;
+    }
+
+    public static double testMulConstD(double a) {
+        return 32.0 * a;
+    }
+
+    @Test
+    public void testDiv() {
+        compile("testDiv2F");
+        compile("testDiv2D");
+        compile("testDivFConst");
+        compile("testDivConstF");
+        compile("testDivDConst");
+        compile("testDivConstD");
+    }
+
+    public static float testDiv2F(float a, float b) {
+        return a / b;
+    }
+
+    public static double testDiv2D(double a, double b) {
+        return a / b;
+    }
+
+    public static float testDivFConst(float a) {
+        return a / 32.0F;
+    }
+
+    public static float testDivConstF(float a) {
+        return 32.0F / a;
+    }
+
+    public static double testDivDConst(double a) {
+        return a / 32.0;
+    }
+
+    public static double testDivConstD(double a) {
+        return 32.0 / a;
+    }
+
+    @Test
+    public void testNeg() {
+        compile("testNeg2F");
+        compile("testNeg2D");
+    }
+
+    public static float testNeg2F(float a) {
+        return -a;
+    }
+
+    public static double testNeg2D(double a) {
+        return -a;
+    }
+
+    @Test
+    public void testRem() {
+        // need linkage to PTX remainder()
+        // compile("testRem2F");
+        // compile("testRem2D");
+    }
+
+    public static float testRem2F(float a, float b) {
+        return a % b;
+    }
+
+    public static double testRem2D(double a, double b) {
+        return a % b;
+    }
+
+    @Test
+    public void testFloatConversion() {
+        compile("testF2I");
+        compile("testF2L");
+        compile("testF2D");
+        compile("testD2I");
+        compile("testD2L");
+        compile("testD2F");
+    }
+
+    public static int testF2I(float a) {
+        return (int) a;
+    }
+
+    public static long testF2L(float a) {
+        return (long) a;
+    }
+
+    public static double testF2D(float a) {
+        return a;
+    }
+
+    public static int testD2I(double a) {
+        return (int) a;
+    }
+
+    public static long testD2L(double a) {
+        return (long) a;
+    }
+
+    public static float testD2F(double a) {
+        return (float) a;
+    }
+
+    public static void main(String[] args) {
+        FloatPTXTest test = new FloatPTXTest();
+        for (Method m : FloatPTXTest.class.getMethods()) {
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null &&
+                    name.startsWith("test") &&
+                    name.startsWith("testRem") == false) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/IntegerPTXTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,192 @@
+/*
+ * 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.compiler.ptx.test;
+
+import org.junit.Test;
+
+import java.lang.reflect.Method;
+
+
+public class IntegerPTXTest extends PTXTestBase {
+
+    @Test
+    public void testAdd() {
+        compile("testAdd2I");
+        compile("testAdd2L");
+        compile("testAdd2B");
+        compile("testAddIConst");
+        compile("testAddConstI");
+    }
+
+    public static int testAdd2I(int a, int b) {
+        return a + b;
+    }
+
+    public static long testAdd2L(long a, long b) {
+        return a + b;
+    }
+
+    public static int testAdd2B(byte a, byte b) {
+        return a + b;
+    }
+
+    public static int testAddIConst(int a) {
+        return a + 32;
+    }
+
+    public static int testAddConstI(int a) {
+        return 32 + a;
+    }
+
+    @Test
+    public void testSub() {
+        compile("testSub2I");
+        compile("testSub2L");
+        compile("testSubIConst");
+        compile("testSubConstI");
+    }
+
+    public static int testSub2I(int a, int b) {
+        return a - b;
+    }
+
+    public static long testSub2L(long a, long b) {
+        return a - b;
+    }
+
+    public static int testSubIConst(int a) {
+        return a - 32;
+    }
+
+    public static int testSubConstI(int a) {
+        return 32 - a;
+    }
+
+    @Test
+    public void testMul() {
+        compile("testMul2I");
+        compile("testMul2L");
+        compile("testMulIConst");
+        compile("testMulConstI");
+    }
+
+    public static int testMul2I(int a, int b) {
+        return a * b;
+    }
+
+    public static long testMul2L(long a, long b) {
+        return a * b;
+    }
+
+    public static int testMulIConst(int a) {
+        return a * 32;
+    }
+
+    public static int testMulConstI(int a) {
+        return 32 * a;
+    }
+
+    @Test
+    public void testDiv() {
+        compile("testDiv2I");
+        compile("testDiv2L");
+        compile("testDivIConst");
+        compile("testDivConstI");
+    }
+
+    public static int testDiv2I(int a, int b) {
+        return a / b;
+    }
+
+    public static long testDiv2L(long a, long b) {
+        return a / b;
+    }
+
+    public static int testDivIConst(int a) {
+        return a / 32;
+    }
+
+    public static int testDivConstI(int a) {
+        return 32 / a;
+    }
+
+    @Test
+    public void testRem() {
+        compile("testRem2I");
+        compile("testRem2L");
+    }
+
+    public static int testRem2I(int a, int b) {
+        return a % b;
+    }
+
+    public static long testRem2L(long a, long b) {
+        return a % b;
+    }
+
+    @Test
+    public void testIntConversion() {
+        compile("testI2L");
+        compile("testL2I");
+        compile("testI2C");
+        compile("testI2B");
+        compile("testI2F");
+        compile("testI2D");
+    }
+
+    public static long testI2L(int a) {
+        return a;
+    }
+
+    public static char testI2C(int a) {
+        return (char) a;
+    }
+
+    public static byte testI2B(int a) {
+        return (byte) a;
+    }
+
+    public static float testI2F(int a) {
+        return a;
+    }
+
+    public static double testI2D(int a) {
+        return a;
+    }
+
+    public static int testL2I(long a) {
+        return (int) a;
+    }
+
+    public static void main(String[] args) {
+        IntegerPTXTest test = new IntegerPTXTest();
+        for (Method m : IntegerPTXTest.class.getMethods()) {
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/LogicPTXTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,138 @@
+/*
+ * 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.compiler.ptx.test;
+
+import java.lang.reflect.Method;
+
+import org.junit.Test;
+
+
+/* PTX ISA 3.1 - 8.7.5 Logic and Shift Instructions */
+public class LogicPTXTest extends PTXTestBase {
+
+    @Test
+    public void testAnd() {
+        compile("testAnd2I");
+        compile("testAnd2L");
+    }
+
+    public static int testAnd2I(int a, int b) {
+        return a & b;
+    }
+
+    public static long testAnd2L(long a, long b) {
+        return a & b;
+    }
+
+    @Test
+    public void testOr() {
+        compile("testOr2I");
+        compile("testOr2L");
+    }
+
+    public static int testOr2I(int a, int b) {
+        return a | b;
+    }
+
+    public static long testOr2L(long a, long b) {
+        return a | b;
+    }
+
+    @Test
+    public void testXor() {
+        compile("testXor2I");
+        compile("testXor2L");
+    }
+
+    public static int testXor2I(int a, int b) {
+        return a ^ b;
+    }
+
+    public static long testXor2L(long a, long b) {
+        return a ^ b;
+    }
+
+    @Test
+    public void testNot() {
+        compile("testNot1I");
+        compile("testNot1L");
+    }
+
+    public static int testNot1I(int a) {
+        return ~a;
+    }
+
+    public static long testNot1L(long a) {
+        return ~a;
+    }
+
+    @Test
+    public void testShiftLeft() {
+        compile("testShiftLeft2I");
+        compile("testShiftLeft2L");
+    }
+
+    public static int testShiftLeft2I(int a, int b) {
+        return a << b;
+    }
+
+    public static long testShiftLeft2L(long a, int b) {
+        return a << b;
+    }
+
+    @Test
+    public void testShiftRight() {
+        compile("testShiftRight2I");
+        compile("testShiftRight2L");
+        compile("testUnsignedShiftRight2I");
+        compile("testUnsignedShiftRight2L");
+    }
+
+    public static int testShiftRight2I(int a, int b) {
+        return a >> b;
+    }
+
+    public static long testShiftRight2L(long a, int b) {
+        return a >> b;
+    }
+
+    public static int testUnsignedShiftRight2I(int a, int b) {
+        return a >>> b;
+    }
+
+    public static long testUnsignedShiftRight2L(long a, long b) {
+        return a >>> b;
+    }
+
+    public static void main(String[] args) {
+        LogicPTXTest test = new LogicPTXTest();
+        for (Method m : LogicPTXTest.class.getMethods()) {
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXPhase.java	Mon Apr 15 08:49:14 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.compiler.ptx.test;
+
+import com.oracle.graal.api.meta.Kind;
+import com.oracle.graal.nodes.LocalNode;
+import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.type.StampFactory;
+import com.oracle.graal.phases.Phase;
+
+
+public class PTXPhase extends Phase {
+    @Override
+    protected void run(StructuredGraph graph) {
+        /*
+         * Assume that null checks would be done on the CPU caller side prior
+         * to copying data onto the GPU.
+         */
+        for (LocalNode local : graph.getNodes(LocalNode.class)) {
+            if (local.kind() == Kind.Object) {
+                local.setStamp(StampFactory.declaredNonNull(local.objectStamp().type()));
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,62 @@
+/*
+ * 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.compiler.ptx.test;
+
+import com.oracle.graal.api.code.CodeCacheProvider;
+import com.oracle.graal.api.code.CompilationResult;
+import com.oracle.graal.api.code.SpeculationLog;
+import com.oracle.graal.api.code.TargetDescription;
+import com.oracle.graal.api.runtime.Graal;
+import com.oracle.graal.compiler.GraalCompiler;
+import com.oracle.graal.compiler.ptx.PTXBackend;
+import com.oracle.graal.compiler.test.GraalCompilerTest;
+import com.oracle.graal.debug.Debug;
+import com.oracle.graal.java.GraphBuilderConfiguration;
+import com.oracle.graal.java.GraphBuilderPhase;
+import com.oracle.graal.hotspot.HotSpotGraalRuntime;
+import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.phases.OptimisticOptimizations;
+import com.oracle.graal.phases.PhasePlan;
+import com.oracle.graal.phases.PhasePlan.PhasePosition;
+import com.oracle.graal.ptx.PTX;
+
+public abstract class PTXTestBase extends GraalCompilerTest {
+
+    protected CompilationResult compile(String test) {
+        StructuredGraph graph = parse(test);
+        Debug.dump(graph, "Graph");
+        TargetDescription target = new TargetDescription(new PTX(), true, 1, 0, true);
+        PTXBackend ptxBackend = new PTXBackend(Graal.getRequiredCapability(CodeCacheProvider.class), target);
+        PhasePlan phasePlan = new PhasePlan();
+        GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(),
+                                                                    OptimisticOptimizations.NONE);
+        phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
+        phasePlan.addPhase(PhasePosition.AFTER_PARSING, new PTXPhase());
+        new PTXPhase().apply(graph);
+        CompilationResult result = GraalCompiler.compileMethod(runtime, HotSpotGraalRuntime.getInstance().getReplacements(),
+                                                               ptxBackend, target, graph.method(), graph, null, phasePlan,
+                                                               OptimisticOptimizations.NONE, new SpeculationLog());
+        return result;
+    }
+
+}
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java	Mon Apr 15 08:49:14 2013 +0200
@@ -94,7 +94,7 @@
         codeBuffer.emitString("");
 
         // XXX For now declare one predicate and all registers
-        codeBuffer.emitString("  .reg .pred %p;");
+        codeBuffer.emitString("  .reg .pred %p,%q;");
         codeBuffer.emitString("  .reg .u32 %r<16>;");
 
         // Emit code for the LIR
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Mon Apr 15 08:49:14 2013 +0200
@@ -28,35 +28,59 @@
 import static com.oracle.graal.lir.ptx.PTXBitManipulationOp.IntrinsicOpcode.*;
 import static com.oracle.graal.lir.ptx.PTXCompare.*;
 
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.asm.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.*;
+import com.oracle.graal.api.code.AllocatableValue;
+import com.oracle.graal.api.code.CodeCacheProvider;
+import com.oracle.graal.api.code.DeoptimizationAction;
+import com.oracle.graal.api.code.RuntimeCallTarget;
+import com.oracle.graal.api.code.StackSlot;
+import com.oracle.graal.api.code.TargetDescription;
+import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
+import com.oracle.graal.api.meta.Constant;
+import com.oracle.graal.api.meta.Kind;
+import com.oracle.graal.api.meta.ResolvedJavaMethod;
+import com.oracle.graal.api.meta.Value;
+import com.oracle.graal.asm.NumUtil;
+import com.oracle.graal.compiler.gen.LIRGenerator;
+import com.oracle.graal.compiler.target.LIRGenLowerable;
+import com.oracle.graal.graph.GraalInternalError;
+import com.oracle.graal.lir.FrameMap;
+import com.oracle.graal.lir.LIR;
+import com.oracle.graal.lir.LIRFrameState;
+import com.oracle.graal.lir.LIRInstruction;
+import com.oracle.graal.lir.LIRValueUtil;
+import com.oracle.graal.lir.LabelRef;
 import com.oracle.graal.lir.StandardOp.JumpOp;
-import com.oracle.graal.lir.ptx.*;
+import com.oracle.graal.lir.Variable;
+import com.oracle.graal.lir.ptx.PTXAddressValue;
 import com.oracle.graal.lir.ptx.PTXArithmetic.Op1Stack;
 import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Reg;
 import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Stack;
 import com.oracle.graal.lir.ptx.PTXArithmetic.ShiftOp;
+import com.oracle.graal.lir.ptx.PTXBitManipulationOp;
 import com.oracle.graal.lir.ptx.PTXCompare.CompareOp;
 import com.oracle.graal.lir.ptx.PTXControlFlow.BranchOp;
+import com.oracle.graal.lir.ptx.PTXControlFlow.CondMoveOp;
+import com.oracle.graal.lir.ptx.PTXControlFlow.FloatCondMoveOp;
 import com.oracle.graal.lir.ptx.PTXControlFlow.ReturnOp;
+import com.oracle.graal.lir.ptx.PTXControlFlow.SequentialSwitchOp;
+import com.oracle.graal.lir.ptx.PTXControlFlow.TableSwitchOp;
 import com.oracle.graal.lir.ptx.PTXMove.LoadOp;
 import com.oracle.graal.lir.ptx.PTXMove.MoveFromRegOp;
 import com.oracle.graal.lir.ptx.PTXMove.MoveToRegOp;
 import com.oracle.graal.lir.ptx.PTXMove.StoreOp;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.calc.Condition;
+import com.oracle.graal.nodes.calc.ConvertNode;
+import com.oracle.graal.nodes.java.CompareAndSwapNode;
 
 /**
  * This class implements the PTX specific portion of the LIR generator.
  */
 public class PTXLIRGenerator extends LIRGenerator {
 
+    public static final Descriptor ARITHMETIC_FREM = new Descriptor("arithmeticFrem", false, float.class, float.class, float.class);
+    public static final Descriptor ARITHMETIC_DREM = new Descriptor("arithmeticDrem", false, double.class, double.class, double.class);
+
     public static class PTXSpillMoveFactory implements LIR.SpillMoveFactory {
 
         @Override
@@ -131,7 +155,7 @@
             baseRegister = asAllocatable(base);
         }
 
-        if (index != Value.ILLEGAL) {
+        if (index != Value.ILLEGAL && scale != 0) {
             if (isConstant(index)) {
                 finalDisp += asConstant(index).asLong() * scale;
             } else {
@@ -145,6 +169,9 @@
                 if (baseRegister == AllocatableValue.UNUSED) {
                     baseRegister = asAllocatable(indexRegister);
                 } else {
+                    Variable newBase = newVariable(Kind.Int);
+                    emitMove(newBase, baseRegister);
+                    baseRegister = newBase;
                     baseRegister = emitAdd(baseRegister, indexRegister);
                 }
             }
@@ -190,6 +217,18 @@
                 append(new CompareOp(ICMP, cond, left, right));
                 append(new BranchOp(cond, label));
                 break;
+            case Long:
+                append(new CompareOp(LCMP, cond, left, right));
+                append(new BranchOp(cond, label));
+                break;
+            case Float:
+                append(new CompareOp(FCMP, cond, left, right));
+                append(new BranchOp(cond, label));
+                break;
+            case Double:
+                append(new CompareOp(DCMP, cond, left, right));
+                append(new BranchOp(cond, label));
+                break;
             case Object:
                 append(new CompareOp(ACMP, cond, left, right));
                 append(new BranchOp(cond, label));
@@ -211,7 +250,67 @@
 
     @Override
     public Variable emitConditionalMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
-        throw new InternalError("NYI");
+        boolean mirrored = emitCompare(cond, left, right);
+        Condition finalCondition = mirrored ? cond.mirror() : cond;
+
+        Variable result = newVariable(trueValue.getKind());
+        switch (left.getKind().getStackKind()) {
+            case Int:
+            case Long:
+            case Object:
+                append(new CondMoveOp(result, finalCondition, load(trueValue), loadNonConst(falseValue)));
+                break;
+            case Float:
+            case Double:
+                append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: " + left.getKind());
+        }
+        return result;
+    }
+
+    /**
+     * This method emits the compare instruction, and may reorder the operands. It returns true if
+     * it did so.
+     * 
+     * @param a the left operand of the comparison
+     * @param b the right operand of the comparison
+     * @return true if the left and right operands were switched, false otherwise
+     */
+    private boolean emitCompare(Condition cond, Value a, Value b) {
+        Variable left;
+        Value right;
+        boolean mirrored;
+        if (LIRValueUtil.isVariable(b)) {
+            left = load(b);
+            right = loadNonConst(a);
+            mirrored = true;
+        } else {
+            left = load(a);
+            right = loadNonConst(b);
+            mirrored = false;
+        }
+        switch (left.getKind().getStackKind()) {
+            case Int:
+                append(new CompareOp(ICMP, cond, left, right));
+                break;
+            case Long:
+                append(new CompareOp(LCMP, cond, left, right));
+                break;
+            case Object:
+                append(new CompareOp(ACMP, cond, left, right));
+                break;
+            case Float:
+                append(new CompareOp(FCMP, cond, left, right));
+                break;
+            case Double:
+                append(new CompareOp(DCMP, cond, left, right));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        return mirrored;
     }
 
     @Override
@@ -226,6 +325,12 @@
             case Int:
                 append(new Op1Stack(INEG, result, input));
                 break;
+            case Float:
+                append(new Op1Stack(FNEG, result, input));
+                break;
+            case Double:
+                append(new Op1Stack(DNEG, result, input));
+                break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
@@ -239,8 +344,17 @@
             case Int:
                 append(new Op2Stack(IADD, result, a, loadNonConst(b)));
                 break;
+            case Long:
+                append(new Op2Stack(LADD, result, a, loadNonConst(b)));
+                break;
+            case Float:
+                append(new Op2Stack(FADD, result, a, loadNonConst(b)));
+                break;
+            case Double:
+                append(new Op2Stack(DADD, result, a, loadNonConst(b)));
+                break;
             default:
-                throw GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind() + " prim: " + a.getKind().isPrimitive());
         }
         return result;
     }
@@ -252,8 +366,17 @@
             case Int:
                 append(new Op2Stack(ISUB, result, a, loadNonConst(b)));
                 break;
+            case Long:
+                append(new Op2Stack(LSUB, result, a, loadNonConst(b)));
+                break;
+            case Float:
+                append(new Op2Stack(FSUB, result, a, loadNonConst(b)));
+                break;
+            case Double:
+                append(new Op2Stack(DSUB, result, a, loadNonConst(b)));
+                break;
             default:
-                throw GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
         }
         return result;
     }
@@ -265,8 +388,17 @@
             case Int:
                 append(new Op2Reg(IMUL, result, a, loadNonConst(b)));
                 break;
+            case Long:
+                append(new Op2Reg(LMUL, result, a, loadNonConst(b)));
+                break;
+            case Float:
+                append(new Op2Stack(FMUL, result, a, loadNonConst(b)));
+                break;
+            case Double:
+                append(new Op2Stack(DMUL, result, a, loadNonConst(b)));
+                break;
             default:
-                throw GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
         }
         return result;
     }
@@ -279,12 +411,40 @@
 
     @Override
     public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) {
-        throw new InternalError("NYI");
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Reg(IDIV, result, a, loadNonConst(b)));
+                break;
+            case Long:
+                append(new Op2Reg(LDIV, result, a, loadNonConst(b)));
+                break;
+            case Float:
+                append(new Op2Stack(FDIV, result, a, loadNonConst(b)));
+                break;
+            case Double:
+                append(new Op2Stack(DDIV, result, a, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
+        }
+        return result;
     }
 
     @Override
     public Value emitRem(Value a, Value b, DeoptimizingNode deopting) {
-        throw new InternalError("NYI");
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Reg(IREM, result, a, loadNonConst(b)));
+                break;
+            case Long:
+                append(new Op2Reg(LREM, result, a, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
+        }
+        return result;
     }
 
     @Override
@@ -304,6 +464,42 @@
             case Int:
                 append(new Op2Stack(IAND, result, a, loadNonConst(b)));
                 break;
+            case Long:
+                append(new Op2Stack(LAND, result, a, loadNonConst(b)));
+                break;
+
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
+        }
+        return result;
+    }
+
+    @Override
+    public Variable emitOr(Value a, Value b) {
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Stack(IOR, result, a, loadNonConst(b)));
+                break;
+            case Long:
+                append(new Op2Stack(LOR, result, a, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
+        }
+        return result;
+    }
+
+    @Override
+    public Variable emitXor(Value a, Value b) {
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Stack(IXOR, result, a, loadNonConst(b)));
+                break;
+            case Long:
+                append(new Op2Stack(LXOR, result, a, loadNonConst(b)));
+                break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
@@ -311,23 +507,35 @@
     }
 
     @Override
-    public Variable emitOr(Value a, Value b) {
-        throw new InternalError("NYI");
-    }
-
-    @Override
-    public Variable emitXor(Value a, Value b) {
-        throw new InternalError("NYI");
-    }
-
-    @Override
     public Variable emitShl(Value a, Value b) {
-        throw new InternalError("NYI");
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Stack(ISHL, result, a, loadNonConst(b)));
+                break;
+            case Long:
+                append(new Op1Stack(LSHL, result, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        return result;
     }
 
     @Override
     public Variable emitShr(Value a, Value b) {
-        throw new InternalError("NYI");
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Stack(ISHR, result, a, loadNonConst(b)));
+                break;
+            case Long:
+                append(new Op1Stack(LSHR, result, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        return result;
     }
 
     @Override
@@ -337,15 +545,87 @@
             case Int:
                 append(new ShiftOp(IUSHR, result, a, b));
                 break;
+            case Long:
+                append(new ShiftOp(LUSHR, result, a, b));
+                break;
             default:
-                GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere();
         }
         return result;
     }
 
     @Override
     public Variable emitConvert(ConvertNode.Op opcode, Value inputVal) {
-        throw new InternalError("NYI");
+        Variable input = load(inputVal);
+        Variable result = newVariable(opcode.to);
+        switch (opcode) {
+            case I2L:
+                append(new Unary2Op(I2L, result, input));
+                break;
+            case L2I:
+                append(new Unary1Op(L2I, result, input));
+                break;
+            case I2B:
+                append(new Unary2Op(I2B, result, input));
+                break;
+            case I2C:
+                append(new Unary1Op(I2C, result, input));
+                break;
+            case I2S:
+                append(new Unary2Op(I2S, result, input));
+                break;
+            case F2D:
+                append(new Unary2Op(F2D, result, input));
+                break;
+            case D2F:
+                append(new Unary2Op(D2F, result, input));
+                break;
+            case I2F:
+                append(new Unary2Op(I2F, result, input));
+                break;
+            case I2D:
+                append(new Unary2Op(I2D, result, input));
+                break;
+            case F2I:
+                append(new Unary2Op(F2I, result, input));
+                break;
+            case D2I:
+                append(new Unary2Op(D2I, result, input));
+                break;
+            case L2F:
+                append(new Unary2Op(L2F, result, input));
+                break;
+            case L2D:
+                append(new Unary2Op(L2D, result, input));
+                break;
+            case F2L:
+                append(new Unary2Op(F2L, result, input));
+                break;
+            case D2L:
+                append(new Unary2Op(D2L, result, input));
+                break;
+            case MOV_I2F:
+                append(new Unary2Op(MOV_I2F, result, input));
+                break;
+            case MOV_L2D:
+                append(new Unary2Op(MOV_L2D, result, input));
+                break;
+            case MOV_F2I:
+                append(new Unary2Op(MOV_F2I, result, input));
+                break;
+            case MOV_D2L:
+                append(new Unary2Op(MOV_D2L, result, input));
+                break;
+            case UNSIGNED_I2L:
+                // Instructions that move or generate 32-bit register values also set the upper 32
+                // bits of the register to zero.
+                // Consequently, there is no need for a special zero-extension move.
+                emitMove(result, input);
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        return result;
     }
 
     @Override
@@ -434,7 +714,14 @@
 
     @Override
     protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) {
-        throw new InternalError("NYI");
+        // Making a copy of the switch value is necessary because jump table destroys the input
+        // value
+        if (key.getKind() == Kind.Int || key.getKind() == Kind.Long) {
+            append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, Value.ILLEGAL));
+        } else {
+            assert key.getKind() == Kind.Object : key.getKind();
+            append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, newVariable(Kind.Object)));
+        }
     }
 
     @Override
@@ -444,7 +731,10 @@
 
     @Override
     protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) {
-        throw new InternalError("NYI");
+        // Making a copy of the switch value is necessary because jump table destroys the input
+        // value
+        Variable tmp = emitMove(key);
+        append(new TableSwitchOp(lowKey, defaultTarget, targets, tmp, newVariable(target.wordKind)));
     }
 
     @Override
@@ -459,17 +749,23 @@
 
     @Override
     public void visitSafepointNode(SafepointNode i) {
+        // LIRFrameState info = state();
+        // append(new PTXSafepointOp(info, runtime().config, this));
         throw new InternalError("NYI");
     }
 
     @Override
     public void emitUnwind(Value operand) {
-        // TODO Auto-generated method stub
-
+        throw new InternalError("NYI");
     }
 
     @Override
     public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) {
         throw new InternalError("NYI");
     }
+
+    @Override
+    public void visitInfopointNode(InfopointNode i) {
+        throw new InternalError("NYI");
+    }
 }
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Apr 15 08:49:14 2013 +0200
@@ -368,4 +368,10 @@
         // SPARC: Auto-generated method stub
 
     }
+
+    @Override
+    public void visitInfopointNode(InfopointNode i) {
+        // SPARC: Auto-generated method stub
+
+    }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -22,17 +22,17 @@
  */
 package com.oracle.graal.compiler.test;
 
-import java.util.*;
-
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.PhasePlan.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+import com.oracle.graal.virtual.nodes.*;
+import com.oracle.graal.virtual.phases.ea.*;
 
 /**
  * In the following tests, the usages of local variable "a" are replaced with the integer constant
@@ -57,17 +57,25 @@
         return 1;
     }
 
-    public static Object boxedObject() {
+    public static Object boxedObjectShort() {
         return (short) 1;
     }
 
+    public static Object boxedObjectInteger() {
+        return (int) 1;
+    }
+
+    public static Integer boxedInteger() {
+        return 2;
+    }
+
     public static Short constantBoxedShort() {
         return s;
     }
 
     @Test
     public void test1() {
-        test("test1Snippet", "referenceSnippet1");
+        compareGraphs("test1Snippet", "referenceSnippet1");
     }
 
     @SuppressWarnings("all")
@@ -77,17 +85,17 @@
 
     @Test
     public void test2() {
-        test("test2Snippet", "referenceSnippet1");
+        compareGraphs("test2Snippet", "referenceSnippet1");
     }
 
     @SuppressWarnings("all")
     public static short test2Snippet() {
-        return (Short) boxedObject();
+        return (Short) boxedObjectShort();
     }
 
     @Test
     public void test3() {
-        test("test3Snippet", "referenceSnippet1");
+        compareGraphs("test3Snippet", "referenceSnippet1");
     }
 
     @SuppressWarnings("all")
@@ -101,7 +109,7 @@
 
     @Test
     public void test4() {
-        test("test4Snippet", "referenceSnippet2");
+        compareGraphs("test4Snippet", "referenceSnippet2");
     }
 
     @SuppressWarnings("all")
@@ -109,33 +117,238 @@
         return constantBoxedShort();
     }
 
-    private void test(final String snippet, final String referenceSnippet) {
-        Debug.scope("BoxingEliminationTest", new DebugDumpScope(snippet), new Runnable() {
+    @Test
+    public void testLoop() {
+        compareGraphs("testLoopSnippet", "referenceLoopSnippet", false, true);
+    }
+
+    public static int testLoopSnippet(int n, int a) {
+        Integer sum = a;
+        for (Integer i = 0; i < n; i++) {
+            sum += i;
+        }
+        return sum;
+    }
+
+    public static int referenceLoopSnippet(int n, int a) {
+        int sum = a;
+        for (int i = 0; i < n; i++) {
+            sum += i;
+        }
+        return sum;
+    }
+
+    @Test
+    public void testLoop2() {
+        compareGraphs("testLoop2Snippet", "referenceLoop2Snippet", true, true);
+    }
+
+    public static int testLoop2Snippet(int n, Integer a) {
+        Integer sum = a;
+        for (Integer i = 0; i < n; i++) {
+            sum += i;
+        }
+        return sum;
+    }
+
+    public static int referenceLoop2Snippet(int n, Integer a) {
+        Integer sum0;
+        if (n <= 0) {
+            sum0 = a;
+        } else {
+            int sum = a;
+            for (int i = 0; i < n; i++) {
+                sum += i;
+            }
+            sum0 = sum;
+        }
+        return sum0;
+    }
+
+    public static int referenceIfSnippet(int a) {
+        int result;
+        if (a < 0) {
+            result = 2;
+        } else {
+            result = 1;
+        }
+        return result;
+    }
+
+    @Test
+    public void testIf() {
+        compareGraphs("testIfSnippet", "referenceIfSnippet");
+    }
+
+    public static int testIfSnippet(int a) {
+        Integer result;
+        if (a < 0) {
+            result = boxedInteger();
+        } else {
+            result = (Integer) boxedObjectInteger();
+        }
+        return result;
+    }
+
+    @Test
+    public void testComparison() {
+        compareGraphs("testComparison1Snippet", "referenceComparisonSnippet");
+        compareGraphs("testComparison2Snippet", "referenceComparisonSnippet");
+    }
+
+    @SuppressWarnings("cast")
+    public static boolean testComparison1Snippet(int a, int b) {
+        return ((Integer) a) == b;
+    }
+
+    public static boolean testComparison2Snippet(int a, int b) {
+        Integer x = a;
+        Integer y = b;
+        return x == y;
+    }
+
+    public static boolean referenceComparisonSnippet(int a, int b) {
+        return a == b;
+    }
+
+    @Test
+    public void testLateCanonicalization() {
+        compareGraphs("testLateCanonicalizationSnippet", "referenceLateCanonicalizationSnippet");
+    }
+
+    public static boolean testLateCanonicalizationSnippet(int a) {
+        Integer x = a;
+        Integer y = 1000;
+        return x == y;
+    }
+
+    public static boolean referenceLateCanonicalizationSnippet(int a) {
+        return a == 1000;
+    }
+
+    private StructuredGraph graph;
+
+    public static Integer materializeReferenceSnippet(int a) {
+        return Integer.valueOf(a);
+    }
+
+    public static Integer materializeTest1Snippet(int a) {
+        Integer v = a;
+
+        if (v == a) {
+            return v;
+        } else {
+            return null;
+        }
+    }
+
+    @Test
+    public void materializeTest1() {
+        test("materializeTest1Snippet", 1);
+    }
+
+    public static int intTest1Snippet() {
+        return Integer.valueOf(1);
+    }
+
+    @Test
+    public void intTest1() {
+        ValueNode result = getResult("intTest1Snippet");
+        Assert.assertTrue(result.isConstant());
+        Assert.assertEquals(1, result.asConstant().asInt());
+    }
+
+    public static int mergeTest1Snippet(boolean d, int a, int b) {
+        Integer v;
+        if (d) {
+            v = a;
+        } else {
+            v = b;
+        }
+        return v;
+    }
+
+    @Test
+    public void mergeTest1() {
+        processMethod("mergeTest1Snippet");
+    }
+
+    public static boolean equalsTest1Snippet(int x, int y) {
+        Integer a = x;
+        Integer b = y;
+        return a == b;
+    }
+
+    @Test
+    public void equalsTest1() {
+        processMethod("equalsTest1Snippet");
+    }
+
+    public static int loopTest1Snippet(int n, int v) {
+        Integer sum = 0;
+        for (int i = 0; i < n; i++) {
+            sum += v;
+        }
+        return sum;
+    }
+
+    @Test
+    public void loopTest1() {
+        processMethod("loopTest1Snippet");
+
+    }
+
+    final ValueNode getResult(String snippet) {
+        processMethod(snippet);
+        assertEquals(1, graph.getNodes(ReturnNode.class).count());
+        return graph.getNodes(ReturnNode.class).first().result();
+    }
+
+    private void processMethod(final String snippet) {
+        graph = parse(snippet);
+        new ComputeProbabilityPhase().apply(graph);
+        Assumptions assumptions = new Assumptions(false);
+        HighTierContext context = new HighTierContext(runtime(), assumptions);
+        new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+        new PartialEscapeAnalysisPhase(false, false).apply(graph, context);
+        new CullFrameStatesPhase().apply(graph);
+    }
+
+    private void compareGraphs(final String snippet, final String referenceSnippet) {
+        compareGraphs(snippet, referenceSnippet, false, false);
+    }
+
+    private void compareGraphs(final String snippet, final String referenceSnippet, final boolean loopPeeling, final boolean excludeVirtual) {
+        Debug.scope("BoxingEliminationTest " + snippet, new DebugDumpScope(snippet), new Runnable() {
 
             @Override
             public void run() {
-                StructuredGraph graph = parse(snippet);
-                BoxingMethodPool pool = new BoxingMethodPool(runtime());
-                IdentifyBoxingPhase identifyBoxingPhase = new IdentifyBoxingPhase(pool);
-                PhasePlan phasePlan = getDefaultPhasePlan();
-                phasePlan.addPhase(PhasePosition.AFTER_PARSING, identifyBoxingPhase);
-                identifyBoxingPhase.apply(graph);
-                Map<Invoke, Double> hints = new HashMap<>();
-                for (Invoke invoke : graph.getInvokes()) {
-                    hints.put(invoke, 1000d);
+                graph = parse(snippet);
+
+                new ComputeProbabilityPhase().apply(graph);
+                Assumptions assumptions = new Assumptions(false);
+                HighTierContext context = new HighTierContext(runtime(), assumptions);
+                new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+                if (loopPeeling) {
+                    new LoopTransformHighPhase().apply(graph);
+                }
+                new DeadCodeEliminationPhase().apply(graph);
+                new CanonicalizerPhase().apply(graph, context);
+                new PartialEscapeAnalysisPhase(false, false).apply(graph, context);
+
+                for (MaterializeObjectNode materialize : graph.getNodes(MaterializeObjectNode.class)) {
+                    materialize.getVirtualObject().materializeAt(materialize, materialize.getValues(), false, materialize.getLockCount());
                 }
 
-                Assumptions assumptions = new Assumptions(false);
-                new InliningPhase(runtime(), hints, replacements, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
-                new CanonicalizerPhase(runtime(), assumptions).apply(graph);
-                Debug.dump(graph, "Graph");
-                new BoxingEliminationPhase(runtime()).apply(graph);
-                Debug.dump(graph, "Graph");
-                new ExpandBoxingNodesPhase(pool).apply(graph);
-                new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+                new CullFrameStatesPhase().apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
+                new CanonicalizerPhase().apply(graph, context);
+
                 StructuredGraph referenceGraph = parse(referenceSnippet);
-                assertEquals(referenceGraph, graph);
+                new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(referenceGraph);
+                new DeadCodeEliminationPhase().apply(referenceGraph);
+                new CanonicalizerPhase().apply(referenceGraph, context);
+                assertEquals(referenceGraph, graph, excludeVirtual);
             }
         });
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -35,7 +35,7 @@
 
     private StructuredGraph getCanonicalizedGraph(String name) {
         StructuredGraph graph = parse(name);
-        new CanonicalizerPhase(runtime(), null).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), null).apply(graph);
         return graph;
     }
 
@@ -53,7 +53,7 @@
             assertEquals(referenceGraph, graph);
         }
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(referenceGraph);
         for (int i = 1; i < 4; i++) {
             StructuredGraph graph = getCanonicalizedGraph("canonicalCompare" + i);
             assertEquals(referenceGraph, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -82,7 +82,7 @@
             public void run() {
                 StructuredGraph graph = parse(snippet);
                 new InliningPhase(runtime(), null, replacements, new Assumptions(false), null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-                new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph);
+                new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph);
                 Debug.dump(graph, "Graph");
                 StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
                 Debug.dump(referenceGraph, "ReferenceGraph");
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -40,11 +40,13 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.printer.*;
 import com.oracle.graal.test.*;
+import com.oracle.graal.hotspot.phases.WriteBarrierAdditionPhase;
 
 /**
  * Base class for Graal compiler unit tests.
@@ -83,11 +85,15 @@
     }
 
     protected void assertEquals(StructuredGraph expected, StructuredGraph graph) {
-        String expectedString = getCanonicalGraphString(expected);
-        String actualString = getCanonicalGraphString(graph);
+        assertEquals(expected, graph, false);
+    }
+
+    protected void assertEquals(StructuredGraph expected, StructuredGraph graph, boolean excludeVirtual) {
+        String expectedString = getCanonicalGraphString(expected, excludeVirtual);
+        String actualString = getCanonicalGraphString(graph, excludeVirtual);
         String mismatchString = "mismatch in graphs:\n========= expected =========\n" + expectedString + "\n\n========= actual =========\n" + actualString;
 
-        if (expected.getNodeCount() != graph.getNodeCount()) {
+        if (!excludeVirtual && expected.getNodeCount() != graph.getNodeCount()) {
             Debug.dump(expected, "Node count not matching - expected");
             Debug.dump(graph, "Node count not matching - actual");
             Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount() + "\n" + mismatchString);
@@ -100,7 +106,7 @@
     }
 
     protected void assertConstantReturn(StructuredGraph graph, int value) {
-        String graphString = getCanonicalGraphString(graph);
+        String graphString = getCanonicalGraphString(graph, false);
         Assert.assertEquals("unexpected number of ReturnNodes: " + graphString, graph.getNodes(ReturnNode.class).count(), 1);
         ValueNode result = graph.getNodes(ReturnNode.class).first().result();
         Assert.assertTrue("unexpected ReturnNode result node: " + graphString, result.isConstant());
@@ -108,7 +114,7 @@
         Assert.assertEquals("unexpected ReturnNode result: " + graphString, result.asConstant().asInt(), value);
     }
 
-    protected static String getCanonicalGraphString(StructuredGraph graph) {
+    protected static String getCanonicalGraphString(StructuredGraph graph, boolean excludeVirtual) {
         SchedulePhase schedule = new SchedulePhase();
         schedule.apply(graph);
 
@@ -127,15 +133,17 @@
             }
             result.append("\n");
             for (Node node : schedule.getBlockToNodesMap().get(block)) {
-                int id;
-                if (canonicalId.get(node) != null) {
-                    id = canonicalId.get(node);
-                } else {
-                    id = nextId++;
-                    canonicalId.set(node, id);
+                if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode)) {
+                    int id;
+                    if (canonicalId.get(node) != null) {
+                        id = canonicalId.get(node);
+                    } else {
+                        id = nextId++;
+                        canonicalId.set(node, id);
+                    }
+                    String name = node instanceof ConstantNode ? node.toString(Verbosity.Name) : node.getClass().getSimpleName();
+                    result.append("  " + id + "|" + name + (excludeVirtual ? "\n" : "    (" + node.usages().count() + ")\n"));
                 }
-                String name = node instanceof ConstantNode ? node.toString(Verbosity.Name) : node.getClass().getSimpleName();
-                result.append("  " + id + "|" + name + "    (" + node.usages().count() + ")\n");
             }
         }
         return result.toString();
@@ -397,14 +405,17 @@
                 }
                 long start = System.currentTimeMillis();
                 PhasePlan phasePlan = new PhasePlan();
+                StructuredGraph graphCopy = graph.copy();
                 GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
                 phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
+                phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierAdditionPhase());
                 editPhasePlan(method, graph, phasePlan);
-                CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), method, graph, null, phasePlan, OptimisticOptimizations.ALL, new SpeculationLog());
+                CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), method, graph, null, phasePlan, OptimisticOptimizations.ALL,
+                                new SpeculationLog());
                 if (printCompilation) {
                     TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize()));
                 }
-                return addMethod(method, compResult);
+                return addMethod(method, compResult, graphCopy);
             }
         });
 
@@ -414,12 +425,12 @@
         return installedCode;
     }
 
-    protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult) {
+    protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult, final StructuredGraph graph) {
         return Debug.scope("CodeInstall", new Object[]{runtime, method}, new Callable<InstalledCode>() {
 
             @Override
             public InstalledCode call() throws Exception {
-                InstalledCode installedCode = runtime.addMethod(method, compResult);
+                InstalledCode installedCode = runtime.addMethod(method, compResult, graph);
                 if (Debug.isDumpEnabled()) {
                     Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
                 }
@@ -442,25 +453,41 @@
      * Parses a Java method to produce a graph.
      */
     protected StructuredGraph parse(Method m) {
-        ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(m);
-        StructuredGraph graph = new StructuredGraph(javaMethod);
-        new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
-        return graph;
+        return parse0(m, GraphBuilderConfiguration.getEagerDefault());
     }
 
     /**
      * Parses a Java method to produce a graph.
      */
     protected StructuredGraph parseProfiled(Method m) {
+        return parse0(m, GraphBuilderConfiguration.getDefault());
+    }
+
+    /**
+     * Parses a Java method in debug mode to produce a graph with extra infopoints.
+     */
+    protected StructuredGraph parseDebug(Method m) {
+        GraphBuilderConfiguration gbConf = GraphBuilderConfiguration.getEagerDefault();
+        gbConf.setEagerInfopointMode(true);
+        return parse0(m, gbConf);
+    }
+
+    private StructuredGraph parse0(Method m, GraphBuilderConfiguration conf) {
         ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(m);
         StructuredGraph graph = new StructuredGraph(javaMethod);
-        new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL).apply(graph);
+        new GraphBuilderPhase(runtime, conf, OptimisticOptimizations.ALL).apply(graph);
         return graph;
     }
 
     protected PhasePlan getDefaultPhasePlan() {
+        return getDefaultPhasePlan(false);
+    }
+
+    protected PhasePlan getDefaultPhasePlan(boolean eagerInfopointMode) {
         PhasePlan plan = new PhasePlan();
-        plan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL));
+        GraphBuilderConfiguration gbConf = GraphBuilderConfiguration.getEagerDefault();
+        gbConf.setEagerInfopointMode(eagerInfopointMode);
+        plan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(runtime, gbConf, OptimisticOptimizations.ALL));
         return plan;
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfBoxingEliminationTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +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.graal.compiler.test;
-
-import java.util.*;
-
-import org.junit.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.PhasePlan.PhasePosition;
-import com.oracle.graal.phases.common.*;
-
-public class IfBoxingEliminationTest extends GraalCompilerTest {
-
-    private static final String REFERENCE_SNIPPET = "referenceSnippet";
-
-    public static int referenceSnippet(int a) {
-        int result;
-        if (a < 0) {
-            result = 1;
-        } else {
-            result = 2;
-        }
-        return result;
-    }
-
-    public static Integer boxedInteger() {
-        return 1;
-    }
-
-    public static Object boxedObject() {
-        return 2;
-    }
-
-    @Test
-    public void test1() {
-        test("test1Snippet");
-    }
-
-    public static int test1Snippet(int a) {
-        Integer result;
-        if (a < 0) {
-            result = boxedInteger();
-        } else {
-            result = (Integer) boxedObject();
-        }
-        return result;
-    }
-
-    private void test(final String snippet) {
-        Debug.scope("IfBoxingEliminationTest", new DebugDumpScope(snippet), new Runnable() {
-
-            @Override
-            public void run() {
-                StructuredGraph graph = parse(snippet);
-                BoxingMethodPool pool = new BoxingMethodPool(runtime());
-                IdentifyBoxingPhase identifyBoxingPhase = new IdentifyBoxingPhase(pool);
-                PhasePlan phasePlan = getDefaultPhasePlan();
-                phasePlan.addPhase(PhasePosition.AFTER_PARSING, identifyBoxingPhase);
-                phasePlan.addPhase(PhasePosition.AFTER_PARSING, new PhiStampPhase());
-                identifyBoxingPhase.apply(graph);
-                Map<Invoke, Double> hints = new HashMap<>();
-                for (Invoke invoke : graph.getInvokes()) {
-                    hints.put(invoke, 1000d);
-                }
-
-                Assumptions assumptions = new Assumptions(false);
-                new InliningPhase(runtime(), hints, replacements, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
-                new CanonicalizerPhase(runtime(), assumptions).apply(graph);
-                new PhiStampPhase().apply(graph);
-                new CanonicalizerPhase(runtime(), assumptions).apply(graph);
-                Debug.dump(graph, "Graph");
-                new BoxingEliminationPhase(runtime()).apply(graph);
-                Debug.dump(graph, "Graph");
-                new ExpandBoxingNodesPhase(pool).apply(graph);
-                new CanonicalizerPhase(runtime(), assumptions).apply(graph);
-                new CanonicalizerPhase(runtime(), assumptions).apply(graph);
-                new DeadCodeEliminationPhase().apply(graph);
-                StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
-                new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph);
-                new DeadCodeEliminationPhase().apply(referenceGraph);
-
-                assertEquals(referenceGraph, graph);
-            }
-        });
-    }
-}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -144,7 +144,7 @@
             n.replaceFirstInput(local, constant);
         }
         Debug.dump(graph, "Graph");
-        new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph);
         StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
         assertEquals(referenceGraph, graph);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,92 @@
+/*
+ * 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.compiler.test;
+
+import static org.junit.Assert.*;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CompilationResult.Call;
+import com.oracle.graal.api.code.CompilationResult.Infopoint;
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.test.*;
+
+/**
+ * Test that infopoints in {@link CompilationResult}s have correctly assigned reasons.
+ */
+public class InfopointReasonTest extends GraalCompilerTest {
+
+    public static final String[] STRINGS = new String[]{"world", "everyone", "you"};
+
+    public String testMethod() {
+        StringBuilder sb = new StringBuilder("Hello ");
+        for (String s : STRINGS) {
+            sb.append(s).append(", ");
+        }
+        sb.replace(sb.length() - 2, sb.length(), "!");
+        return sb.toString();
+    }
+
+    @Test
+    public void callInfopoints() {
+        final Method method = getMethod("testMethod");
+        final StructuredGraph graph = parse(method);
+        final CompilationResult cr = GraalCompiler.compileMethod(runtime, replacements, backend, runtime.getTarget(), runtime.lookupJavaMethod(method), graph, null, getDefaultPhasePlan(),
+                        OptimisticOptimizations.ALL, new SpeculationLog());
+        for (Infopoint sp : cr.getInfopoints()) {
+            assertNotNull(sp.reason);
+            if (sp instanceof Call) {
+                assertEquals(InfopointReason.CALL, sp.reason);
+            }
+        }
+    }
+
+    @LongTest
+    public void lineInfopoints() {
+        final Method method = getMethod("testMethod");
+        final StructuredGraph graph = parseDebug(method);
+        int graphLineSPs = 0;
+        for (InfopointNode ipn : graph.getNodes(InfopointNode.class)) {
+            if (ipn.reason == InfopointReason.LINE_NUMBER) {
+                ++graphLineSPs;
+            }
+        }
+        assertTrue(graphLineSPs > 0);
+        final CompilationResult cr = GraalCompiler.compileMethod(runtime, replacements, backend, runtime.getTarget(), runtime.lookupJavaMethod(method), graph, null, getDefaultPhasePlan(true),
+                        OptimisticOptimizations.ALL, new SpeculationLog());
+        int lineSPs = 0;
+        for (Infopoint sp : cr.getInfopoints()) {
+            assertNotNull(sp.reason);
+            if (sp.reason == InfopointReason.LINE_NUMBER) {
+                ++lineSPs;
+            }
+        }
+        assertTrue(lineSPs > 0);
+    }
+
+}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -66,7 +66,7 @@
         }
         Assumptions assumptions = new Assumptions(false);
         new InliningPhase(runtime(), hints, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -77,7 +77,7 @@
 
         Assumptions assumptions = new Assumptions(false);
         new InliningPhase(runtime(), hints, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
         StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
         assertEquals(referenceGraph, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -133,8 +133,8 @@
         }
 
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
-        new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(referenceGraph);
         Debug.scope("Test", new DebugDumpScope("Test:" + snippet), new Runnable() {
 
             @Override
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -94,7 +94,7 @@
         }
         Assumptions assumptions = new Assumptions(false);
         new InliningPhase(runtime(), hints, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
         return graph;
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -83,9 +83,9 @@
     private StructuredGraph compileTestSnippet(final String snippet) {
         StructuredGraph graph = parse(snippet);
         new LoweringPhase(null, runtime(), replacements, new Assumptions(false)).apply(graph);
-        new CanonicalizerPhase(runtime(), null).apply(graph);
-        new PushNodesThroughPi().apply(graph);
-        new CanonicalizerPhase(runtime(), null).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), null).apply(graph);
+        new PushThroughPiPhase().apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), null).apply(graph);
 
         return graph;
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCast.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCast.java	Mon Apr 15 08:49:14 2013 +0200
@@ -89,7 +89,7 @@
                 new FloatingReadPhase().apply(graph);
                 new EliminatePartiallyRedundantGuardsPhase(true, false).apply(graph);
                 new ReadEliminationPhase().apply(graph);
-                new CanonicalizerPhase(runtime(), null).apply(graph);
+                new CanonicalizerPhase.Instance(runtime(), null).apply(graph);
 
                 Debug.dump(graph, "After lowering");
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -244,9 +244,9 @@
     private <T extends Node & Node.IterableNodeType> void test(String test, String ref) {
         StructuredGraph testGraph = parse(test);
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase(runtime(), assumptions).apply(testGraph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(testGraph);
         StructuredGraph refGraph = parse(ref);
-        new CanonicalizerPhase(runtime(), assumptions).apply(refGraph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(refGraph);
         assertEquals(testGraph, refGraph);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -166,9 +166,9 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
         StructuredGraph referenceGraph = parse(referenceSnippet);
         assertEquals(referenceGraph, graph);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -98,7 +98,7 @@
 
     private void testZeroReturn(String methodName) {
         StructuredGraph graph = parse(methodName);
-        new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
         assertConstantReturn(graph, 0);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -89,7 +89,7 @@
         // No debug scope to reduce console noise for @Test(expected = ...) tests
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
-        new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph);
         StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
         assertEquals(referenceGraph, graph);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -186,13 +186,13 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
         // a second canonicalizer is needed to process nested MaterializeNodes
-        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
         StructuredGraph referenceGraph = parse(referenceSnippet);
-        new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(referenceGraph);
         assertEquals(referenceGraph, graph);
     }
 
@@ -206,19 +206,19 @@
     }
 
     public static void outputGraph(StructuredGraph graph, String message) {
-        System.out.println("========================= " + message);
+        TTY.println("========================= " + message);
         SchedulePhase schedule = new SchedulePhase();
         schedule.apply(graph);
         for (Block block : schedule.getCFG().getBlocks()) {
-            System.out.print("Block " + block + " ");
+            TTY.print("Block " + block + " ");
             if (block == schedule.getCFG().getStartBlock()) {
-                System.out.print("* ");
+                TTY.print("* ");
             }
-            System.out.print("-> ");
+            TTY.print("-> ");
             for (Block succ : block.getSuccessors()) {
-                System.out.print(succ + " ");
+                TTY.print(succ + " ");
             }
-            System.out.println();
+            TTY.println();
             for (Node node : schedule.getBlockToNodesMap().get(block)) {
                 outputNode(node);
             }
@@ -226,11 +226,11 @@
     }
 
     private static void outputNode(Node node) {
-        System.out.print("  " + node + "    (usage count: " + node.usages().count() + ") (inputs:");
+        TTY.print("  " + node + "    (usage count: " + node.usages().count() + ") (inputs:");
         for (Node input : node.inputs()) {
-            System.out.print(" " + input.toString(Verbosity.Id));
+            TTY.print(" " + input.toString(Verbosity.Id));
         }
-        System.out.println(")");
+        TTY.println(")");
         if (node instanceof MergeNode) {
             for (PhiNode phi : ((MergeNode) node).phis()) {
                 outputNode(phi);
@@ -242,9 +242,9 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
         Debug.dump(graph, "Graph");
         Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes(clazz).iterator().hasNext());
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -27,13 +27,10 @@
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.InstalledCode.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.test.*;
 
@@ -58,7 +55,7 @@
     public void test1() {
         Method method = getMethod("testMethod");
         final StructuredGraph graph = parse(method);
-        new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
 
         for (Node node : graph.getNodes()) {
@@ -75,7 +72,7 @@
         try {
             Object result = compiledMethod.execute("1", "2", "3");
             Assert.assertEquals("1-2-3", result);
-        } catch (MethodInvalidatedException t) {
+        } catch (InvalidInstalledCodeException t) {
             Assert.fail("method invalidated");
         }
     }
@@ -89,7 +86,7 @@
         try {
             Object result = compiledMethod.executeVarargs("1", "2", "3");
             Assert.assertEquals("1 2 3", result);
-        } catch (MethodInvalidatedException t) {
+        } catch (InvalidInstalledCodeException t) {
             Assert.fail("method invalidated");
         }
     }
@@ -104,98 +101,8 @@
             f1 = "0";
             Object result = compiledMethod.executeVarargs(this, "1", "2", "3");
             Assert.assertEquals("0 1 2 3", result);
-        } catch (MethodInvalidatedException t) {
+        } catch (InvalidInstalledCodeException t) {
             Assert.fail("method invalidated");
         }
     }
-
-    @LongTest
-    public void test2() throws NoSuchMethodException, SecurityException {
-        Method method = CompilableObjectImpl.class.getDeclaredMethod("executeHelper", ObjectCompiler.class, String.class);
-        ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method);
-        StructuredGraph graph = new StructuredGraph(javaMethod);
-        new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.NONE).apply(graph);
-        new CanonicalizerPhase(runtime, new Assumptions(false)).apply(graph);
-        new DeadCodeEliminationPhase().apply(graph);
-
-        for (Node node : graph.getNodes()) {
-            if (node instanceof ConstantNode) {
-                ConstantNode constant = (ConstantNode) node;
-                if (constant.kind() == Kind.Object && "1 ".equals(constant.value.asObject())) {
-                    graph.replaceFloating(constant, ConstantNode.forObject("1-", runtime, graph));
-                }
-            }
-        }
-
-        InstalledCode compiledMethod = getCode(javaMethod, graph);
-        final CompilableObject compilableObject = new CompilableObjectImpl(0);
-
-        Object result;
-        result = compilableObject.execute(new ObjectCompilerImpl(compiledMethod), "3");
-        Assert.assertEquals("1-3", result);
-    }
-
-    public abstract class CompilableObject {
-
-        private CompiledObject compiledObject;
-        private final int compileThreshold;
-        private int counter;
-
-        public CompilableObject(int compileThreshold) {
-            this.compileThreshold = compileThreshold;
-        }
-
-        public final Object execute(ObjectCompiler compiler, String args) {
-            if (counter++ < compileThreshold || compiler == null) {
-                return executeHelper(compiler, args);
-            } else {
-                compiledObject = compiler.compile(this);
-                return compiledObject.execute(compiler, args);
-            }
-        }
-
-        protected abstract Object executeHelper(ObjectCompiler context, String args);
-    }
-
-    private final class CompilableObjectImpl extends CompilableObject {
-
-        private CompilableObjectImpl(int compileThreshold) {
-            super(compileThreshold);
-        }
-
-        @Override
-        protected Object executeHelper(ObjectCompiler compiler, String args) {
-            return "1 " + args;
-        }
-    }
-
-    public interface CompiledObject {
-
-        Object execute(ObjectCompiler context, String args);
-    }
-
-    public interface ObjectCompiler {
-
-        CompiledObject compile(CompilableObject node);
-    }
-
-    private final class ObjectCompilerImpl implements ObjectCompiler {
-
-        private final InstalledCode compiledMethod;
-
-        private ObjectCompilerImpl(InstalledCode compiledMethod) {
-            this.compiledMethod = compiledMethod;
-        }
-
-        @Override
-        public CompiledObject compile(final CompilableObject node) {
-            return new CompiledObject() {
-
-                @Override
-                public Object execute(ObjectCompiler compiler, String args) {
-                    return compiledMethod.execute(node, compiler, args);
-                }
-            };
-        }
-    }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/SynchronizedMethodDeoptimizationTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/SynchronizedMethodDeoptimizationTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -27,7 +27,6 @@
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.InstalledCode.MethodInvalidatedException;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.nodes.*;
@@ -59,7 +58,7 @@
         try {
             Object result = compiledMethod.executeVarargs(testString);
             Assert.assertEquals(testString, result);
-        } catch (MethodInvalidatedException t) {
+        } catch (InvalidInstalledCodeException t) {
             Assert.fail("method invalidated");
         }
 
@@ -67,7 +66,7 @@
             Object result = compiledMethod.executeVarargs(new Object[]{null});
             Assert.assertEquals(null, result);
             Assert.assertFalse(compiledMethod.isValid());
-        } catch (MethodInvalidatedException t) {
+        } catch (InvalidInstalledCodeException t) {
             Assert.fail("method invalidated");
         }
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -22,7 +22,8 @@
  */
 package com.oracle.graal.compiler.test.ea;
 
-import junit.framework.*;
+import java.util.concurrent.*;
+
 import junit.framework.Assert;
 
 import org.junit.Test;
@@ -30,10 +31,13 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.virtual.nodes.*;
 import com.oracle.graal.virtual.phases.ea.*;
 
@@ -83,8 +87,8 @@
 
     public static int testMonitorSnippet() {
         Integer x = new Integer(0);
-        Integer[] y = new Integer[0];
-        Integer[] z = new Integer[1];
+        Double y = new Double(0);
+        Object z = new Object();
         synchronized (x) {
             synchronized (y) {
                 synchronized (z) {
@@ -106,8 +110,8 @@
      */
     public static int testMonitor2Snippet() {
         Integer x = new Integer(0);
-        Integer[] y = new Integer[0];
-        Integer[] z = new Integer[1];
+        Double y = new Double(0);
+        Object z = new Object();
         synchronized (x) {
             synchronized (y) {
                 synchronized (z) {
@@ -161,6 +165,20 @@
         return obj.x;
     }
 
+    @Test
+    public void testModifyingLoop() {
+        testEscapeAnalysis("testModifyingLoopSnippet", Constant.forInt(1), false);
+    }
+
+    public int testModifyingLoopSnippet(int a) {
+        TestObject obj = new TestObject(1, 2);
+        for (int i = 0; i < a; i++) {
+            obj.x = 3;
+            notInlineable();
+        }
+        return obj.x <= 3 ? 1 : 0;
+    }
+
     public static class TestObject2 {
 
         Object o;
@@ -192,28 +210,33 @@
         return obj2.o instanceof TestObject2;
     }
 
-    private ReturnNode testEscapeAnalysis(String snippet, Constant expectedConstantResult, boolean iterativeEscapeAnalysis) {
-        StructuredGraph graph = parse(snippet);
-        try {
-            for (Invoke n : graph.getInvokes()) {
-                n.setInliningRelevance(1);
-            }
+    private ReturnNode testEscapeAnalysis(String snippet, final Constant expectedConstantResult, final boolean iterativeEscapeAnalysis) {
+        ResolvedJavaMethod method = runtime.lookupJavaMethod(getMethod(snippet));
+        final StructuredGraph graph = new StructuredGraph(method);
+
+        return Debug.scope("GraalCompiler", new Object[]{graph, method, runtime}, new Callable<ReturnNode>() {
+
+            public ReturnNode call() {
+                new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
+                for (Invoke n : graph.getInvokes()) {
+                    n.setInliningRelevance(1);
+                }
 
-            Assumptions assumptions = new Assumptions(false);
-            new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-            new DeadCodeEliminationPhase().apply(graph);
-            new PartialEscapeAnalysisPhase(runtime(), assumptions, iterativeEscapeAnalysis, false).apply(graph);
-            Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count());
-            ReturnNode returnNode = graph.getNodes(ReturnNode.class).first();
-            if (expectedConstantResult != null) {
-                Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant());
-                Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant());
+                Assumptions assumptions = new Assumptions(false);
+                HighTierContext context = new HighTierContext(runtime(), assumptions);
+                new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+                new DeadCodeEliminationPhase().apply(graph);
+                new PartialEscapeAnalysisPhase(iterativeEscapeAnalysis, false).apply(graph, context);
+                Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count());
+                ReturnNode returnNode = graph.getNodes(ReturnNode.class).first();
+                if (expectedConstantResult != null) {
+                    Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant());
+                    Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant());
+                }
+                int newInstanceCount = graph.getNodes(NewInstanceNode.class).count() + graph.getNodes(NewArrayNode.class).count() + graph.getNodes(MaterializeObjectNode.class).count();
+                Assert.assertEquals(0, newInstanceCount);
+                return returnNode;
             }
-            int newInstanceCount = graph.getNodes(NewInstanceNode.class).count() + graph.getNodes(NewArrayNode.class).count() + graph.getNodes(MaterializeObjectNode.class).count();
-            Assert.assertEquals(0, newInstanceCount);
-            return returnNode;
-        } catch (AssertionFailedError t) {
-            throw new RuntimeException(t.getMessage() + "\n" + getCanonicalGraphString(graph), t);
-        }
+        });
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -34,6 +34,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.virtual.phases.ea.*;
 
 public class IterativeInliningTest extends GraalCompilerTest {
@@ -102,6 +103,7 @@
         graph = parse(snippet);
         new ComputeProbabilityPhase().apply(graph);
         GraalOptions.OptEarlyReadElimination = true;
-        new IterativeInliningPhase(runtime(), replacements, new Assumptions(false), null, getDefaultPhasePlan(), OptimisticOptimizations.ALL, false).apply(graph);
+        HighTierContext context = new HighTierContext(runtime(), new Assumptions(false));
+        new IterativeInliningPhase(replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL, false).apply(graph, context);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -34,6 +34,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.virtual.phases.ea.*;
 
 public class PEAReadEliminationTest extends GraalCompilerTest {
@@ -143,10 +144,11 @@
     }
 
     @SuppressWarnings("all")
-    public static int testBadLoopSnippet(TestObject obj, int a, int b) {
+    public static int testBadLoopSnippet(TestObject obj, TestObject obj2, int a, int b) {
         obj.x = a;
         for (int i = 0; i < 10; i++) {
             staticField = obj;
+            obj2.x = 10;
             obj.x = 0;
         }
         return obj.x;
@@ -155,6 +157,24 @@
     @Test
     public void testBadLoop() {
         ValueNode result = getReturn("testBadLoopSnippet").result();
+        assertEquals(0, graph.getNodes(LoadFieldNode.class).count());
+        assertTrue(result instanceof ProxyNode);
+        assertTrue(((ProxyNode) result).value() instanceof PhiNode);
+    }
+
+    @SuppressWarnings("all")
+    public static int testBadLoop2Snippet(TestObject obj, TestObject obj2, int a, int b) {
+        obj.x = a;
+        for (int i = 0; i < 10; i++) {
+            obj.x = 0;
+            obj2.x = 10;
+        }
+        return obj.x;
+    }
+
+    @Test
+    public void testBadLoop2() {
+        ValueNode result = getReturn("testBadLoop2Snippet").result();
         assertEquals(1, graph.getNodes(LoadFieldNode.class).count());
         assertTrue(result instanceof LoadFieldNode);
     }
@@ -203,7 +223,8 @@
         graph = parse(snippet);
         new ComputeProbabilityPhase().apply(graph);
         Assumptions assumptions = new Assumptions(false);
+        HighTierContext context = new HighTierContext(runtime(), assumptions);
         new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-        new PartialEscapeAnalysisPhase(runtime(), assumptions, false, true).apply(graph);
+        new PartialEscapeAnalysisPhase(false, true).apply(graph, context);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -22,18 +22,21 @@
  */
 package com.oracle.graal.compiler.test.ea;
 
-import junit.framework.*;
+import java.util.concurrent.*;
+
 import junit.framework.Assert;
 
 import org.junit.Test;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.virtual.nodes.*;
 import com.oracle.graal.virtual.phases.ea.*;
 
@@ -72,8 +75,8 @@
     }
 
     @SuppressWarnings("all")
-    public static Object test1Snippet(int a, int b) {
-        TestObject obj = new TestObject(1, 2);
+    public static Object test1Snippet(int a, int b, Object x, Object y) {
+        TestObject2 obj = new TestObject2(x, y);
         if (a < 0) {
             if (b < 0) {
                 return obj;
@@ -90,9 +93,9 @@
         testMaterialize("test2Snippet", 1.5, 3, LoadIndexedNode.class);
     }
 
-    public static Object test2Snippet(int a) {
-        TestObject2 obj = new TestObject2(1, 2);
-        obj.x = new TestObject2(obj, 3);
+    public static Object test2Snippet(int a, Object x, Object y, Object z) {
+        TestObject2 obj = new TestObject2(x, y);
+        obj.x = new TestObject2(obj, z);
         if (a < 0) {
             ((TestObject2) obj.x).y = null;
             obj.y = null;
@@ -125,42 +128,50 @@
     @SafeVarargs
     final void testMaterialize(final String snippet, double expectedProbability, int expectedCount, Class<? extends Node>... invalidNodeClasses) {
         StructuredGraph result = processMethod(snippet);
-        Assert.assertTrue("partial escape analysis should have removed all NewInstanceNode allocations", result.getNodes(NewInstanceNode.class).isEmpty());
-        Assert.assertTrue("partial escape analysis should have removed all NewArrayNode allocations", result.getNodes(NewArrayNode.class).isEmpty());
-        double probabilitySum = 0;
-        int materializeCount = 0;
-        for (MaterializeObjectNode materialize : result.getNodes(MaterializeObjectNode.class)) {
-            probabilitySum += materialize.probability();
-            materializeCount++;
-        }
-        Assert.assertEquals("unexpected number of MaterializeObjectNodes", expectedCount, materializeCount);
-        Assert.assertEquals("unexpected probability of MaterializeObjectNodes", expectedProbability, probabilitySum, 0.01);
-        for (Node node : result.getNodes()) {
-            for (Class<? extends Node> clazz : invalidNodeClasses) {
-                Assert.assertFalse("instance of invalid class: " + clazz.getSimpleName(), clazz.isInstance(node) && node.usages().isNotEmpty());
+        try {
+            Assert.assertTrue("partial escape analysis should have removed all NewInstanceNode allocations", result.getNodes(NewInstanceNode.class).isEmpty());
+            Assert.assertTrue("partial escape analysis should have removed all NewArrayNode allocations", result.getNodes(NewArrayNode.class).isEmpty());
+            double probabilitySum = 0;
+            int materializeCount = 0;
+            for (MaterializeObjectNode materialize : result.getNodes(MaterializeObjectNode.class)) {
+                probabilitySum += materialize.probability();
+                materializeCount++;
             }
+            Assert.assertEquals("unexpected number of MaterializeObjectNodes", expectedCount, materializeCount);
+            Assert.assertEquals("unexpected probability of MaterializeObjectNodes", expectedProbability, probabilitySum, 0.01);
+            for (Node node : result.getNodes()) {
+                for (Class<? extends Node> clazz : invalidNodeClasses) {
+                    Assert.assertFalse("instance of invalid class: " + clazz.getSimpleName(), clazz.isInstance(node) && node.usages().isNotEmpty());
+                }
+            }
+        } catch (AssertionError e) {
+            TypeSystemTest.outputGraph(result, snippet + ": " + e.getMessage());
+            throw e;
         }
     }
 
     private StructuredGraph processMethod(final String snippet) {
-        StructuredGraph graph = parse(snippet);
-        try {
-            new ComputeProbabilityPhase().apply(graph);
-            for (Invoke n : graph.getInvokes()) {
-                n.node().setProbability(100000);
+        return Debug.scope("PartialEscapeAnalysisTest " + snippet, new DebugDumpScope(snippet), new Callable<StructuredGraph>() {
+
+            @Override
+            public StructuredGraph call() {
+                StructuredGraph graph = parse(snippet);
+                new ComputeProbabilityPhase().apply(graph);
+                for (Invoke n : graph.getInvokes()) {
+                    n.asNode().setProbability(100000);
+                }
+                Assumptions assumptions = new Assumptions(false);
+                HighTierContext context = new HighTierContext(runtime(), assumptions);
+                new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+                new DeadCodeEliminationPhase().apply(graph);
+                new CanonicalizerPhase().apply(graph, context);
+                new PartialEscapeAnalysisPhase(false, false).apply(graph, context);
+
+                new CullFrameStatesPhase().apply(graph);
+                new DeadCodeEliminationPhase().apply(graph);
+                new CanonicalizerPhase().apply(graph, context);
+                return graph;
             }
-            Assumptions assumptions = new Assumptions(false);
-            new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-            new DeadCodeEliminationPhase().apply(graph);
-            new CanonicalizerPhase(runtime(), assumptions).apply(graph);
-            new PartialEscapeAnalysisPhase(runtime(), assumptions, false, false).apply(graph);
-
-            new CullFrameStatesPhase().apply(graph);
-            new DeadCodeEliminationPhase().apply(graph);
-            new CanonicalizerPhase(runtime(), assumptions).apply(graph);
-            return graph;
-        } catch (AssertionFailedError t) {
-            throw new RuntimeException(t.getMessage() + "\n" + getCanonicalGraphString(graph), t);
-        }
+        });
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -24,6 +24,7 @@
 
 import static org.junit.Assert.*;
 
+import java.lang.reflect.*;
 import java.util.concurrent.*;
 
 import org.junit.*;
@@ -35,14 +36,15 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.test.*;
 
 @SuppressWarnings("unused")
 public class InliningTest extends GraalCompilerTest {
 
     @Test
     public void testInvokeStaticInlining() {
-        assertInlined(getGraph("invokeStaticSnippet"));
-        assertInlined(getGraph("invokeStaticOnInstanceSnippet"));
+        assertInlined(getGraph("invokeStaticSnippet", false));
+        assertInlined(getGraph("invokeStaticOnInstanceSnippet", false));
     }
 
     @SuppressWarnings("all")
@@ -57,9 +59,16 @@
 
     @Test
     public void testStaticBindableInlining() {
-        assertInlined(getGraph("invokeConstructorSnippet"));
-        assertInlined(getGraph("invokeFinalMethodSnippet"));
-        assertInlined(getGraph("invokeMethodOnFinalClassSnippet"));
+        assertInlined(getGraph("invokeConstructorSnippet", false));
+        assertInlined(getGraph("invokeFinalMethodSnippet", false));
+        assertInlined(getGraph("invokeMethodOnFinalClassSnippet", false));
+    }
+
+    @LongTest
+    public void testStaticBindableInliningIP() {
+        assertManyMethodInfopoints(assertInlined(getGraph("invokeConstructorSnippet", true)));
+        assertManyMethodInfopoints(assertInlined(getGraph("invokeFinalMethodSnippet", true)));
+        assertManyMethodInfopoints(assertInlined(getGraph("invokeMethodOnFinalClassSnippet", true)));
     }
 
     @SuppressWarnings("all")
@@ -81,14 +90,28 @@
 
     @Test
     public void testClassHierarchyAnalysis() {
-        assertInlined(getGraph("invokeLeafClassMethodSnippet"));
-        assertInlined(getGraph("invokeConcreteMethodSnippet"));
-        assertInlined(getGraph("invokeSingleImplementorInterfaceSnippet"));
-        // assertInlined(getGraph("invokeConcreteInterfaceMethodSnippet"));
+        assertInlined(getGraph("invokeLeafClassMethodSnippet", false));
+        assertInlined(getGraph("invokeConcreteMethodSnippet", false));
+        assertInlined(getGraph("invokeSingleImplementorInterfaceSnippet", false));
+        // assertInlined(getGraph("invokeConcreteInterfaceMethodSnippet", false));
+
+        assertNotInlined(getGraph("invokeOverriddenPublicMethodSnippet", false));
+        assertNotInlined(getGraph("invokeOverriddenProtectedMethodSnippet", false));
+        assertNotInlined(getGraph("invokeOverriddenInterfaceMethodSnippet", false));
+    }
 
-        assertNotInlined(getGraph("invokeOverriddenPublicMethodSnippet"));
-        assertNotInlined(getGraph("invokeOverriddenProtectedMethodSnippet"));
-        assertNotInlined(getGraph("invokeOverriddenInterfaceMethodSnippet"));
+    @LongTest
+    public void testClassHierarchyAnalysisIP() {
+        assertManyMethodInfopoints(assertInlined(getGraph("invokeLeafClassMethodSnippet", true)));
+        assertManyMethodInfopoints(assertInlined(getGraph("invokeConcreteMethodSnippet", true)));
+        assertManyMethodInfopoints(assertInlined(getGraph("invokeSingleImplementorInterfaceSnippet", true)));
+        //@formatter:off
+        // assertInlineInfopoints(assertInlined(getGraph("invokeConcreteInterfaceMethodSnippet", true)));
+        //@formatter:on
+
+        assertFewMethodInfopoints(assertNotInlined(getGraph("invokeOverriddenPublicMethodSnippet", true)));
+        assertFewMethodInfopoints(assertNotInlined(getGraph("invokeOverriddenProtectedMethodSnippet", true)));
+        assertFewMethodInfopoints(assertNotInlined(getGraph("invokeOverriddenInterfaceMethodSnippet", true)));
     }
 
     @SuppressWarnings("all")
@@ -126,19 +149,20 @@
         return superClass.protectedOverriddenMethod();
     }
 
-    private StructuredGraph getGraph(final String snippet) {
+    private StructuredGraph getGraph(final String snippet, final boolean eagerInfopointMode) {
         return Debug.scope("InliningTest", new DebugDumpScope(snippet), new Callable<StructuredGraph>() {
 
             @Override
             public StructuredGraph call() {
-                StructuredGraph graph = parse(snippet);
-                PhasePlan phasePlan = getDefaultPhasePlan();
+                Method method = getMethod(snippet);
+                StructuredGraph graph = eagerInfopointMode ? parseDebug(method) : parse(method);
+                PhasePlan phasePlan = getDefaultPhasePlan(eagerInfopointMode);
                 Assumptions assumptions = new Assumptions(true);
                 new ComputeProbabilityPhase().apply(graph);
                 Debug.dump(graph, "Graph");
                 new InliningPhase(runtime(), null, replacements, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
                 Debug.dump(graph, "Graph");
-                new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+                new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
                 return graph;
             }
@@ -172,6 +196,35 @@
         return graph;
     }
 
+    private static int[] countMethodInfopoints(StructuredGraph graph) {
+        int start = 0;
+        int end = 0;
+        for (InfopointNode ipn : graph.getNodes(InfopointNode.class)) {
+            if (ipn.reason == InfopointReason.METHOD_START) {
+                ++start;
+            } else if (ipn.reason == InfopointReason.METHOD_END) {
+                ++end;
+            }
+        }
+        return new int[]{start, end};
+    }
+
+    private static StructuredGraph assertManyMethodInfopoints(StructuredGraph graph) {
+        int[] counts = countMethodInfopoints(graph);
+        if (counts[0] <= 1 || counts[1] <= 1) {
+            fail(String.format("Graph contains too few required method boundary infopoints: %d starts, %d ends.", counts[0], counts[1]));
+        }
+        return graph;
+    }
+
+    private static StructuredGraph assertFewMethodInfopoints(StructuredGraph graph) {
+        int[] counts = countMethodInfopoints(graph);
+        if (counts[0] > 1 || counts[1] > 1) {
+            fail(String.format("Graph contains too many method boundary infopoints: %d starts, %d ends.", counts[0], counts[1]));
+        }
+        return graph;
+    }
+
     // some interfaces and classes for testing
     private interface MultipleImplementorsInterface {
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/DebugFilter.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/DebugFilter.java	Mon Apr 15 08:49:14 2013 +0200
@@ -132,9 +132,6 @@
                 }
             }
         }
-        // if (match) {
-        // System.out.println(this + " matches " + input);
-        // }
         return match;
     }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Apr 15 08:49:14 2013 +0200
@@ -31,11 +31,11 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.alloc.*;
 import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.spi.*;
@@ -43,6 +43,7 @@
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.virtual.phases.ea.*;
 
 public class GraalCompiler {
@@ -118,78 +119,42 @@
         }
 
         if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase(runtime, assumptions).apply(graph);
+            new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
         }
 
+        HighTierContext highTierContext = new HighTierContext(runtime, assumptions);
+
         if (GraalOptions.Inline && !plan.isPhaseDisabled(InliningPhase.class)) {
             if (GraalOptions.IterativeInlining) {
-                new IterativeInliningPhase(runtime, replacements, assumptions, cache, plan, optimisticOpts, GraalOptions.OptEarlyReadElimination).apply(graph);
+                new IterativeInliningPhase(replacements, cache, plan, optimisticOpts, GraalOptions.OptEarlyReadElimination).apply(graph, highTierContext);
             } else {
                 new InliningPhase(runtime, null, replacements, assumptions, cache, plan, optimisticOpts).apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
 
                 if (GraalOptions.ConditionalElimination && GraalOptions.OptCanonicalizer) {
-                    new CanonicalizerPhase(runtime, assumptions).apply(graph);
+                    new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
                     new IterativeConditionalEliminationPhase(runtime, assumptions).apply(graph);
                 }
             }
         }
 
-        // new ConvertUnreachedToGuardPhase(optimisticOpts).apply(graph);
-
         plan.runPhases(PhasePosition.HIGH_LEVEL, graph);
 
-        if (GraalOptions.FullUnroll) {
-            new LoopFullUnrollPhase(runtime, assumptions).apply(graph);
-            if (GraalOptions.OptCanonicalizer) {
-                new CanonicalizerPhase(runtime, assumptions).apply(graph);
-            }
-        }
-
-        if (GraalOptions.OptTailDuplication) {
-            new TailDuplicationPhase().apply(graph);
-            if (GraalOptions.OptCanonicalizer) {
-                new CanonicalizerPhase(runtime, assumptions).apply(graph);
-            }
-        }
-
-        if (GraalOptions.PartialEscapeAnalysis && !plan.isPhaseDisabled(PartialEscapeAnalysisPhase.class)) {
-            new PartialEscapeAnalysisPhase(runtime, assumptions, true, GraalOptions.OptEarlyReadElimination).apply(graph);
-        }
-
-        if (GraalOptions.OptConvertDeoptsToGuards) {
-            new ConvertDeoptimizeToGuardPhase().apply(graph);
-        }
-
-        new LockEliminationPhase().apply(graph);
-
-        if (GraalOptions.OptLoopTransform) {
-            new LoopTransformHighPhase().apply(graph);
-            new LoopTransformLowPhase().apply(graph);
-        }
-        new RemoveValueProxyPhase().apply(graph);
-
-        if (GraalOptions.CullFrameStates) {
-            new CullFrameStatesPhase().apply(graph);
-        }
-
-        if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase(runtime, assumptions).apply(graph);
-        }
+        Suites.HIGH_TIER.apply(graph, highTierContext);
 
         new LoweringPhase(target, runtime, replacements, assumptions).apply(graph);
 
         if (GraalOptions.OptPushThroughPi) {
-            new PushNodesThroughPi().apply(graph);
+            new PushThroughPiPhase().apply(graph);
             if (GraalOptions.OptCanonicalizer) {
-                new CanonicalizerPhase(runtime, assumptions).apply(graph);
+                new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
             }
         }
 
         if (GraalOptions.OptFloatingReads) {
             int mark = graph.getMark();
             new FloatingReadPhase().apply(graph);
-            new CanonicalizerPhase(runtime, assumptions, mark, null).apply(graph);
+            new CanonicalizerPhase.Instance(runtime, assumptions, mark, null).apply(graph);
             if (GraalOptions.OptReadElimination) {
                 new ReadEliminationPhase().apply(graph);
             }
@@ -197,7 +162,7 @@
         new RemoveValueProxyPhase().apply(graph);
 
         if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase(runtime, assumptions).apply(graph);
+            new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
         }
 
         if (GraalOptions.OptEliminatePartiallyRedundantGuards) {
@@ -213,18 +178,24 @@
         }
 
         if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase(runtime, assumptions).apply(graph);
+            new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
         }
 
         plan.runPhases(PhasePosition.MID_LEVEL, graph);
 
-        plan.runPhases(PhasePosition.LOW_LEVEL, graph);
-
         // Add safepoints to loops
         new SafepointInsertionPhase().apply(graph);
 
         new GuardLoweringPhase(target).apply(graph);
 
+        plan.runPhases(PhasePosition.LOW_LEVEL, graph);
+
+        new LoweringPhase(target, runtime, replacements, assumptions).apply(graph);
+
+        new FrameStateAssignmentPhase().apply(graph);
+
+        new DeadCodeEliminationPhase().apply(graph);
+
         final SchedulePhase schedule = new SchedulePhase();
         schedule.apply(graph);
         Debug.dump(schedule, "final schedule");
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Mon Apr 15 08:49:14 2013 +0200
@@ -82,21 +82,16 @@
                 for (Entry<VirtualObjectNode, VirtualObject> entry : virtualObjectsCopy.entrySet()) {
                     if (entry.getValue().getValues() == null) {
                         VirtualObjectNode vobj = entry.getKey();
-                        if (vobj instanceof BoxedVirtualObjectNode) {
-                            BoxedVirtualObjectNode boxedVirtualObjectNode = (BoxedVirtualObjectNode) vobj;
-                            entry.getValue().setValues(new Value[]{toValue(boxedVirtualObjectNode.getUnboxedValue())});
-                        } else {
-                            Value[] values = new Value[vobj.entryCount()];
-                            if (values.length > 0) {
-                                changed = true;
-                                VirtualObjectState currentField = (VirtualObjectState) objectStates.get(vobj);
-                                assert currentField != null;
-                                for (int i = 0; i < vobj.entryCount(); i++) {
-                                    values[i] = toValue(currentField.fieldValues().get(i));
-                                }
+                        Value[] values = new Value[vobj.entryCount()];
+                        if (values.length > 0) {
+                            changed = true;
+                            VirtualObjectState currentField = (VirtualObjectState) objectStates.get(vobj);
+                            assert currentField != null;
+                            for (int i = 0; i < vobj.entryCount(); i++) {
+                                values[i] = toValue(currentField.fieldValues().get(i));
                             }
-                            entry.getValue().setValues(values);
                         }
+                        entry.getValue().setValues(values);
                     }
                 }
             } while (changed);
@@ -127,7 +122,7 @@
         if (state.outerFrameState() != null) {
             caller = computeFrameForState(state.outerFrameState());
         }
-        assert state.bci >= 0 || state.bci == FrameState.BEFORE_BCI : "bci == " + state.bci;
+        assert state.bci != FrameState.UNKNOWN_BCI : "bci == " + state.bci;
         return new BytecodeFrame(caller, state.method(), state.bci, state.rethrowException(), state.duringCall(), values, numLocals, numStack, numLocks);
     }
 
@@ -165,7 +160,7 @@
         if (value instanceof VirtualObjectNode) {
             VirtualObjectNode obj = (VirtualObjectNode) value;
             EscapeObjectState state = objectStates.get(obj);
-            if (state == null && obj.entryCount() > 0 && !(obj instanceof BoxedVirtualObjectNode)) {
+            if (state == null && obj.entryCount() > 0) {
                 // null states occur for objects with 0 fields
                 throw new GraalInternalError("no mapping found for virtual object %s", obj);
             }
@@ -173,7 +168,7 @@
                 assert !(((MaterializedObjectState) state).materializedValue() instanceof VirtualObjectNode);
                 return toValue(((MaterializedObjectState) state).materializedValue());
             } else {
-                assert obj.entryCount() == 0 || state instanceof VirtualObjectState || obj instanceof BoxedVirtualObjectNode;
+                assert obj.entryCount() == 0 || state instanceof VirtualObjectState;
                 VirtualObject vobject = virtualObjects.get(value);
                 if (vobject == null) {
                     vobject = VirtualObject.get(obj.type(), null, virtualObjects.size());
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Mon Apr 15 08:49:14 2013 +0200
@@ -225,6 +225,13 @@
         return stateFor(deopt.getDeoptimizationState(), deopt.getDeoptimizationReason());
     }
 
+    public LIRFrameState stateWithExceptionEdge(DeoptimizingNode deopt, LabelRef exceptionEdge) {
+        if (!deopt.canDeoptimize()) {
+            return null;
+        }
+        return stateForWithExceptionEdge(deopt.getDeoptimizationState(), deopt.getDeoptimizationReason(), exceptionEdge);
+    }
+
     public LIRFrameState stateFor(FrameState state, DeoptimizationReason reason) {
         return stateForWithExceptionEdge(state, reason, null);
     }
@@ -233,6 +240,7 @@
         if (needOnlyOopMaps()) {
             return new LIRFrameState(null, null, null, (short) -1);
         }
+        assert state != null;
         return debugInfoBuilder.build(state, lir.getDeoptimizationReasons().addSpeculation(reason), exceptionEdge);
     }
 
@@ -327,17 +335,10 @@
                 TTY.println("LIRGen for " + instr);
             }
             FrameState stateAfter = null;
-            if (instr instanceof StateSplit) {
+            if (instr instanceof StateSplit && !(instr instanceof InfopointNode)) {
                 stateAfter = ((StateSplit) instr).stateAfter();
             }
-            if (instr instanceof DeoptimizingNode) {
-                DeoptimizingNode deopt = (DeoptimizingNode) instr;
-                if (deopt.canDeoptimize() && deopt.getDeoptimizationState() == null) {
-                    deopt.setDeoptimizationState(lastState);
-                }
-            }
             if (instr instanceof ValueNode) {
-
                 ValueNode valueNode = (ValueNode) instr;
                 if (operand(valueNode) == null) {
                     if (!peephole(valueNode)) {
@@ -598,18 +599,18 @@
     @Override
     public void emitInvoke(Invoke x) {
         AbstractCallTargetNode callTarget = (AbstractCallTargetNode) x.callTarget();
-        CallingConvention cc = frameMap.registerConfig.getCallingConvention(callTarget.callType(), x.node().stamp().javaType(runtime), callTarget.signature(), target(), false);
+        CallingConvention cc = frameMap.registerConfig.getCallingConvention(callTarget.callType(), x.asNode().stamp().javaType(runtime), callTarget.signature(), target(), false);
         frameMap.callsMethod(cc);
 
         Value[] parameters = visitInvokeArguments(cc, callTarget.arguments());
 
-        LIRFrameState callState = null;
-        if (x.stateAfter() != null) {
-            callState = stateForWithExceptionEdge(x.stateDuring(), null, x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null);
+        LabelRef exceptionEdge = null;
+        if (x instanceof InvokeWithExceptionNode) {
+            exceptionEdge = getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge());
         }
+        LIRFrameState callState = stateWithExceptionEdge(x, exceptionEdge);
 
         Value result = cc.getReturn();
-
         if (callTarget instanceof DirectCallTargetNode) {
             emitDirectCall((DirectCallTargetNode) callTarget, result, parameters, cc.getTemporaries(), callState);
         } else if (callTarget instanceof IndirectCallTargetNode) {
@@ -619,7 +620,7 @@
         }
 
         if (isLegal(result)) {
-            setResult(x.node(), emitMove(result));
+            setResult(x.asNode(), emitMove(result));
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/Suites.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,80 @@
+/*
+ * 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.compiler.phases;
+
+import java.util.*;
+
+import com.oracle.graal.loop.phases.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+import com.oracle.graal.virtual.phases.ea.*;
+
+public class Suites {
+
+    public static final PhaseSuite<HighTierContext> HIGH_TIER = createHighTier();
+
+    private static PhaseSuite<HighTierContext> createHighTier() {
+        ArrayList<BasePhase<? super HighTierContext>> phases = new ArrayList<>();
+
+        if (GraalOptions.FullUnroll) {
+            phases.add(new LoopFullUnrollPhase());
+            if (GraalOptions.OptCanonicalizer) {
+                phases.add(new CanonicalizerPhase());
+            }
+        }
+
+        if (GraalOptions.OptTailDuplication) {
+            phases.add(new TailDuplicationPhase());
+            if (GraalOptions.OptCanonicalizer) {
+                phases.add(new CanonicalizerPhase());
+            }
+        }
+
+        if (GraalOptions.PartialEscapeAnalysis) {
+            phases.add(new PartialEscapeAnalysisPhase(true, GraalOptions.OptEarlyReadElimination));
+        }
+
+        if (GraalOptions.OptConvertDeoptsToGuards) {
+            phases.add(new ConvertDeoptimizeToGuardPhase());
+        }
+
+        phases.add(new LockEliminationPhase());
+
+        if (GraalOptions.OptLoopTransform) {
+            phases.add(new LoopTransformHighPhase());
+            phases.add(new LoopTransformLowPhase());
+        }
+        phases.add(new RemoveValueProxyPhase());
+
+        if (GraalOptions.CullFrameStates) {
+            phases.add(new CullFrameStatesPhase());
+        }
+
+        if (GraalOptions.OptCanonicalizer) {
+            phases.add(new CanonicalizerPhase());
+        }
+
+        return new PhaseSuite<>("HighTier", phases);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugHistogramTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2013, 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.debug.test;
+
+import java.io.*;
+
+import org.junit.*;
+
+import com.oracle.graal.debug.*;
+
+public class DebugHistogramTest {
+
+    @Test
+    public void testEmptyHistogram() {
+        DebugHistogram histogram = Debug.createHistogram("TestHistogram");
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        histogram.print(new PrintStream(outputStream));
+        Assert.assertEquals("TestHistogram is empty.\n", outputStream.toString());
+    }
+
+    @Test
+    public void testSingleEntryHistogram() {
+        DebugHistogram histogram = Debug.createHistogram("TestHistogram");
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        histogram.add(new Integer(1));
+        histogram.add(new Integer(1));
+        histogram.print(new PrintStream(outputStream));
+        String[] lines = outputStream.toString().split("\n");
+        Assert.assertEquals(4, lines.length);
+        Assert.assertEquals("TestHistogram has 1 unique elements and 2 total elements:", lines[0]);
+        Assert.assertEquals(
+                        "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------",
+                        lines[1]);
+        Assert.assertEquals(
+                        "| 1                                                  | 2          | ==================================================================================================== |",
+                        lines[2]);
+        Assert.assertEquals(
+                        "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------",
+                        lines[3]);
+    }
+
+    @Test
+    public void testMultipleEntryHistogram() {
+        DebugHistogram histogram = Debug.createHistogram("TestHistogram");
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        histogram.add(new Integer(1));
+        histogram.add(new Integer(2));
+        histogram.add(new Integer(2));
+        histogram.print(new PrintStream(outputStream));
+        String[] lines = outputStream.toString().split("\n");
+        Assert.assertEquals(5, lines.length);
+        Assert.assertEquals("TestHistogram has 2 unique elements and 3 total elements:", lines[0]);
+        Assert.assertEquals(
+                        "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------",
+                        lines[1]);
+        Assert.assertEquals(
+                        "| 2                                                  | 2          | ==================================================================================================== |",
+                        lines[2]);
+        Assert.assertEquals(
+                        "| 1                                                  | 1          | ==================================================                                                   |",
+                        lines[3]);
+        Assert.assertEquals(
+                        "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------",
+                        lines[4]);
+    }
+
+    @Test
+    public void testTooLongValueString() {
+        DebugHistogram histogram = Debug.createHistogram("TestHistogram");
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        histogram.add("MyCustomValue");
+        histogram.print(new PrintStream(outputStream), Integer.MAX_VALUE, 10, 10);
+        String[] lines = outputStream.toString().split("\n");
+        Assert.assertEquals(4, lines.length);
+        Assert.assertEquals("TestHistogram has 1 unique elements and 1 total elements:", lines[0]);
+        Assert.assertEquals("----------------------------------------", lines[1]);
+        Assert.assertEquals("| MyCusto... | 1          | ========== |", lines[2]);
+        Assert.assertEquals("----------------------------------------", lines[3]);
+    }
+}
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Mon Apr 15 08:49:14 2013 +0200
@@ -189,6 +189,10 @@
         }
     }
 
+    public static DebugHistogram createHistogram(String name) {
+        return new DebugHistogramImpl(name);
+    }
+
     public static DebugConfig fixedConfig(final boolean isLogEnabled, final boolean isDumpEnabled, final boolean isMeterEnabled, final boolean isTimerEnabled,
                     final Collection<DebugDumpHandler> dumpHandlers, final PrintStream output) {
         return new DebugConfig() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugHistogram.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,36 @@
+/*
+ * 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.debug;
+
+import java.io.*;
+
+public interface DebugHistogram {
+
+    String getName();
+
+    void add(Object value);
+
+    void print(PrintStream os);
+
+    void print(PrintStream os, int limit, int nameSize, int barSize);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramImpl.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,110 @@
+/*
+ * 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.debug.internal;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.graal.debug.*;
+
+public class DebugHistogramImpl implements DebugHistogram {
+
+    public static final int NumberSize = 10;
+    public static final int DefaultNameSize = 50;
+    public static final int DefaultBarSize = 100;
+    private final String name;
+    private HashMap<Object, Integer> map = new HashMap<>();
+
+    public DebugHistogramImpl(String name) {
+        this.name = name;
+    }
+
+    public void add(Object value) {
+        if (!map.containsKey(value)) {
+            map.put(value, 1);
+        } else {
+            map.put(value, map.get(value) + 1);
+        }
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public void print(PrintStream os) {
+        print(os, Integer.MAX_VALUE, DefaultNameSize, DefaultBarSize);
+    }
+
+    public void print(PrintStream os, int limit, int nameSize, int barSize) {
+
+        List<Object> list = new ArrayList<>(map.keySet());
+        if (list.size() == 0) {
+            // No elements in the histogram.
+            os.printf("%s is empty.\n", name);
+            return;
+        }
+
+        // Sort from highest to smallest.
+        Collections.sort(list, new Comparator<Object>() {
+
+            @Override
+            public int compare(Object o1, Object o2) {
+                return map.get(o2) - map.get(o1);
+            }
+        });
+
+        // Sum up the total number of elements.
+        int total = 0;
+        for (Object o : list) {
+            total += map.get(o);
+        }
+
+        // Print header.
+        os.printf("%s has %d unique elements and %d total elements:\n", name, list.size(), total);
+
+        int max = map.get(list.get(0));
+        final int lineSize = nameSize + NumberSize + barSize + 10;
+        printLine(os, '-', lineSize);
+        String formatString = "| %-" + nameSize + "s | %-" + NumberSize + "d | %-" + barSize + "s |\n";
+        for (int i = 0; i < list.size() && i < limit; ++i) {
+            Object o = list.get(i);
+            int value = map.get(o);
+            char[] bar = new char[(int) (((double) value / (double) max) * barSize)];
+            Arrays.fill(bar, '=');
+            String objectString = o.toString();
+            if (objectString.length() > nameSize) {
+                objectString = objectString.substring(0, nameSize - 3) + "...";
+            }
+            os.printf(formatString, objectString, value, new String(bar));
+        }
+        printLine(os, '-', lineSize);
+    }
+
+    private static void printLine(PrintStream printStream, char c, int lineSize) {
+        char[] charArr = new char[lineSize];
+        Arrays.fill(charArr, c);
+        printStream.printf("%s\n", new String(charArr));
+    }
+}
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TestNodeInterface.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +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.graal.graph;
-
-public interface TestNodeInterface {
-
-    String getName();
-}
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TypedNodeIteratorTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,166 +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.graal.graph;
-
-import static org.junit.Assert.*;
-
-import java.util.*;
-
-import org.junit.*;
-
-public class TypedNodeIteratorTest {
-
-    private static class TestNode extends Node implements Node.IterableNodeType, TestNodeInterface {
-
-        private final String name;
-
-        public TestNode(String name) {
-            this.name = name;
-        }
-
-        public String getName() {
-            return name;
-        }
-    }
-
-    @Test
-    public void singleNodeTest() {
-        Graph graph = new Graph();
-        graph.add(new TestNode("a"));
-        assertTrue(graph.hasNode(TestNode.class));
-        assertEquals("a", toString(graph.getNodes(TestNode.class)));
-    }
-
-    @Test
-    public void deletingNodeTest() {
-        TestNode testNode = new TestNode("a");
-        Graph graph = new Graph();
-        graph.add(testNode);
-        testNode.safeDelete();
-        assertEquals("", toString(graph.getNodes(TestNode.class)));
-    }
-
-    @Test
-    public void deleteAndAddTest() {
-        TestNode testNode = new TestNode("b");
-        Graph graph = new Graph();
-        graph.add(new TestNode("a"));
-        graph.add(testNode);
-        testNode.safeDelete();
-        assertEquals("a", toString(graph.getNodes(TestNode.class)));
-        graph.add(new TestNode("c"));
-        assertEquals("ac", toString(graph.getNodes(TestNode.class)));
-    }
-
-    @Test
-    public void iteratorBehaviorTest() {
-        Graph graph = new Graph();
-        graph.add(new TestNode("a"));
-        Iterator<TestNode> iterator = graph.getNodes(TestNode.class).iterator();
-        assertTrue(iterator.hasNext());
-        assertEquals("a", iterator.next().getName());
-        assertFalse(iterator.hasNext());
-        graph.add(new TestNode("b"));
-        assertTrue(iterator.hasNext());
-        assertEquals("b", iterator.next().getName());
-        assertFalse(iterator.hasNext());
-        TestNode c = new TestNode("c");
-        graph.add(c);
-        assertTrue(iterator.hasNext());
-        c.safeDelete();
-        assertFalse(iterator.hasNext());
-    }
-
-    @Test
-    public void complicatedIterationTest() {
-        Graph graph = new Graph();
-        graph.add(new TestNode("a"));
-        for (TestNode tn : graph.getNodes(TestNode.class)) {
-            String name = tn.getName();
-            for (int i = 0; i < name.length(); ++i) {
-                char c = name.charAt(i);
-                if (c == 'a') {
-                    tn.safeDelete();
-                    graph.add(new TestNode("b"));
-                    graph.add(new TestNode("c"));
-                } else if (c == 'b') {
-                    tn.safeDelete();
-                } else if (c == 'c') {
-                    graph.add(new TestNode("d"));
-                    graph.add(new TestNode("e"));
-                    graph.add(new TestNode("d"));
-                    graph.add(new TestNode("e"));
-                    graph.add(new TestNode("e"));
-                    graph.add(new TestNode("d"));
-                    graph.add(new TestNode("e"));
-                    graph.add(new TestNode("d"));
-                } else if (c == 'd') {
-                    for (TestNode tn2 : graph.getNodes(TestNode.class)) {
-                        if (tn2.getName().equals("e")) {
-                            tn2.safeDelete();
-                        } else if (tn2.getName().equals("c")) {
-                            tn2.safeDelete();
-                        }
-                    }
-                } else if (c == 'e') {
-                    fail("All e nodes must have been deleted by visiting the d node");
-                }
-            }
-        }
-        assertEquals("dddd", toString(graph.getNodes(TestNode.class)));
-    }
-
-    @Test
-    public void addingNodeDuringIterationTest() {
-        Graph graph = new Graph();
-        graph.add(new TestNode("a"));
-        StringBuilder sb = new StringBuilder();
-        int z = 0;
-        for (TestNode tn : graph.getNodes(TestNode.class)) {
-            if (z == 0) {
-                graph.add(new TestNode("b"));
-            }
-            sb.append(tn.getName());
-            z++;
-        }
-        assertEquals(2, z);
-        assertEquals("ab", sb.toString());
-        z = 0;
-        for (TestNode tn : graph.getNodes(TestNode.class)) {
-            if (z == 0) {
-                graph.add(new TestNode("c"));
-            }
-            assertNotNull(tn);
-            z++;
-        }
-        assertEquals(3, z);
-    }
-
-    public static String toString(Iterable<? extends TestNodeInterface> nodes) {
-        StringBuilder sb = new StringBuilder();
-        for (TestNodeInterface tn : nodes) {
-            sb.append(tn.getName());
-        }
-        return sb.toString();
-    }
-}
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TypedNodeIteratorTest2.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +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.graph;
-
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-public class TypedNodeIteratorTest2 {
-
-    private static class NodeA extends Node implements TestNodeInterface {
-
-        private final String name;
-
-        public NodeA(String name) {
-            this.name = name;
-        }
-
-        public String getName() {
-            return name;
-        }
-    }
-
-    private static class NodeB extends NodeA implements Node.IterableNodeType {
-
-        public NodeB(String name) {
-            super(name);
-        }
-    }
-
-    private static class NodeC extends NodeB {
-
-        public NodeC(String name) {
-            super(name);
-        }
-    }
-
-    private static class NodeD extends NodeC {
-
-        public NodeD(String name) {
-            super(name);
-        }
-    }
-
-    @Test
-    public void simpleSubclassTest() {
-        Graph graph = new Graph();
-        graph.add(new NodeB("b"));
-        graph.add(new NodeD("d"));
-
-        Assert.assertEquals("bd", TypedNodeIteratorTest.toString(graph.getNodes(NodeB.class)));
-        Assert.assertEquals("d", TypedNodeIteratorTest.toString(graph.getNodes(NodeD.class)));
-    }
-
-    @Test
-    public void addingNodeDuringIterationTest() {
-        Graph graph = new Graph();
-        graph.add(new NodeB("b1"));
-        NodeD d1 = graph.add(new NodeD("d1"));
-        StringBuilder sb = new StringBuilder();
-        for (NodeB tn : graph.getNodes(NodeB.class)) {
-            if (tn == d1) {
-                graph.add(new NodeB("b2"));
-            }
-            sb.append(tn.getName());
-        }
-        assertEquals("b1d1b2", sb.toString());
-        for (NodeB tn : graph.getNodes(NodeB.class)) {
-            if (tn == d1) {
-                graph.add(new NodeB("b3"));
-            }
-            assertNotNull(tn);
-        }
-        assertEquals(4, graph.getNodes(NodeB.class).count());
-        assertEquals(1, graph.getNodes(NodeD.class).count());
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TestNodeInterface.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,28 @@
+/*
+ * 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.graal.graph.test;
+
+public interface TestNodeInterface {
+
+    String getName();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,168 @@
+/*
+ * 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.graal.graph.test;
+
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.graal.graph.*;
+
+public class TypedNodeIteratorTest {
+
+    private static class TestNode extends Node implements Node.IterableNodeType, TestNodeInterface {
+
+        private final String name;
+
+        public TestNode(String name) {
+            this.name = name;
+        }
+
+        public String getName() {
+            return name;
+        }
+    }
+
+    @Test
+    public void singleNodeTest() {
+        Graph graph = new Graph();
+        graph.add(new TestNode("a"));
+        assertTrue(graph.hasNode(TestNode.class));
+        assertEquals("a", toString(graph.getNodes(TestNode.class)));
+    }
+
+    @Test
+    public void deletingNodeTest() {
+        TestNode testNode = new TestNode("a");
+        Graph graph = new Graph();
+        graph.add(testNode);
+        testNode.safeDelete();
+        assertEquals("", toString(graph.getNodes(TestNode.class)));
+    }
+
+    @Test
+    public void deleteAndAddTest() {
+        TestNode testNode = new TestNode("b");
+        Graph graph = new Graph();
+        graph.add(new TestNode("a"));
+        graph.add(testNode);
+        testNode.safeDelete();
+        assertEquals("a", toString(graph.getNodes(TestNode.class)));
+        graph.add(new TestNode("c"));
+        assertEquals("ac", toString(graph.getNodes(TestNode.class)));
+    }
+
+    @Test
+    public void iteratorBehaviorTest() {
+        Graph graph = new Graph();
+        graph.add(new TestNode("a"));
+        Iterator<TestNode> iterator = graph.getNodes(TestNode.class).iterator();
+        assertTrue(iterator.hasNext());
+        assertEquals("a", iterator.next().getName());
+        assertFalse(iterator.hasNext());
+        graph.add(new TestNode("b"));
+        assertTrue(iterator.hasNext());
+        assertEquals("b", iterator.next().getName());
+        assertFalse(iterator.hasNext());
+        TestNode c = new TestNode("c");
+        graph.add(c);
+        assertTrue(iterator.hasNext());
+        c.safeDelete();
+        assertFalse(iterator.hasNext());
+    }
+
+    @Test
+    public void complicatedIterationTest() {
+        Graph graph = new Graph();
+        graph.add(new TestNode("a"));
+        for (TestNode tn : graph.getNodes(TestNode.class)) {
+            String name = tn.getName();
+            for (int i = 0; i < name.length(); ++i) {
+                char c = name.charAt(i);
+                if (c == 'a') {
+                    tn.safeDelete();
+                    graph.add(new TestNode("b"));
+                    graph.add(new TestNode("c"));
+                } else if (c == 'b') {
+                    tn.safeDelete();
+                } else if (c == 'c') {
+                    graph.add(new TestNode("d"));
+                    graph.add(new TestNode("e"));
+                    graph.add(new TestNode("d"));
+                    graph.add(new TestNode("e"));
+                    graph.add(new TestNode("e"));
+                    graph.add(new TestNode("d"));
+                    graph.add(new TestNode("e"));
+                    graph.add(new TestNode("d"));
+                } else if (c == 'd') {
+                    for (TestNode tn2 : graph.getNodes(TestNode.class)) {
+                        if (tn2.getName().equals("e")) {
+                            tn2.safeDelete();
+                        } else if (tn2.getName().equals("c")) {
+                            tn2.safeDelete();
+                        }
+                    }
+                } else if (c == 'e') {
+                    fail("All e nodes must have been deleted by visiting the d node");
+                }
+            }
+        }
+        assertEquals("dddd", toString(graph.getNodes(TestNode.class)));
+    }
+
+    @Test
+    public void addingNodeDuringIterationTest() {
+        Graph graph = new Graph();
+        graph.add(new TestNode("a"));
+        StringBuilder sb = new StringBuilder();
+        int z = 0;
+        for (TestNode tn : graph.getNodes(TestNode.class)) {
+            if (z == 0) {
+                graph.add(new TestNode("b"));
+            }
+            sb.append(tn.getName());
+            z++;
+        }
+        assertEquals(2, z);
+        assertEquals("ab", sb.toString());
+        z = 0;
+        for (TestNode tn : graph.getNodes(TestNode.class)) {
+            if (z == 0) {
+                graph.add(new TestNode("c"));
+            }
+            assertNotNull(tn);
+            z++;
+        }
+        assertEquals(3, z);
+    }
+
+    public static String toString(Iterable<? extends TestNodeInterface> nodes) {
+        StringBuilder sb = new StringBuilder();
+        for (TestNodeInterface tn : nodes) {
+            sb.append(tn.getName());
+        }
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest2.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,100 @@
+/*
+ * 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.graph.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.graal.graph.*;
+
+public class TypedNodeIteratorTest2 {
+
+    private static class NodeA extends Node implements TestNodeInterface {
+
+        private final String name;
+
+        public NodeA(String name) {
+            this.name = name;
+        }
+
+        public String getName() {
+            return name;
+        }
+    }
+
+    private static class NodeB extends NodeA implements Node.IterableNodeType {
+
+        public NodeB(String name) {
+            super(name);
+        }
+    }
+
+    private static class NodeC extends NodeB {
+
+        public NodeC(String name) {
+            super(name);
+        }
+    }
+
+    private static class NodeD extends NodeC {
+
+        public NodeD(String name) {
+            super(name);
+        }
+    }
+
+    @Test
+    public void simpleSubclassTest() {
+        Graph graph = new Graph();
+        graph.add(new NodeB("b"));
+        graph.add(new NodeD("d"));
+
+        Assert.assertEquals("bd", TypedNodeIteratorTest.toString(graph.getNodes(NodeB.class)));
+        Assert.assertEquals("d", TypedNodeIteratorTest.toString(graph.getNodes(NodeD.class)));
+    }
+
+    @Test
+    public void addingNodeDuringIterationTest() {
+        Graph graph = new Graph();
+        graph.add(new NodeB("b1"));
+        NodeD d1 = graph.add(new NodeD("d1"));
+        StringBuilder sb = new StringBuilder();
+        for (NodeB tn : graph.getNodes(NodeB.class)) {
+            if (tn == d1) {
+                graph.add(new NodeB("b2"));
+            }
+            sb.append(tn.getName());
+        }
+        assertEquals("b1d1b2", sb.toString());
+        for (NodeB tn : graph.getNodes(NodeB.class)) {
+            if (tn == d1) {
+                graph.add(new NodeB("b3"));
+            }
+            assertNotNull(tn);
+        }
+        assertEquals(4, graph.getNodes(NodeB.class).count());
+        assertEquals(1, graph.getNodes(NodeD.class).count());
+    }
+
+}
--- a/graal/com.oracle.graal.graph/.checkstyle_checks.xml	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.graph/.checkstyle_checks.xml	Mon Apr 15 08:49:14 2013 +0200
@@ -1,15 +1,15 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
 
-<!--
-    This configuration file was written by the eclipse-cs plugin configuration editor
+<!--
+    This configuration file was written by the eclipse-cs plugin configuration editor
 -->
-<!--
-    Checkstyle-Configuration: Maxine Checks
-    Description: none
+<!--
+    Checkstyle-Configuration: Maxine Checks
+    Description: none
 -->
 <module name="Checker">
-  <property name="severity" value="warning"/>
+  <property name="severity" value="error"/>
   <module name="TreeWalker">
     <property name="tabWidth" value="4"/>
     <module name="FileContentsHolder"/>
@@ -197,4 +197,14 @@
     <property name="format" value="\r\n"/>
     <property name="message" value="illegal Windows line ending"/>
   </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: stop system..print check"/>
+    <property name="onCommentFormat" value="CheckStyle: resume system..print check"/>
+    <property name="checkFormat" value="RegexpSingleline"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable System.(out|err).print checks"/>
+  </module>
+  <module name="RegexpSingleline">
+    <property name="format" value="System\.(out|err)\.print"/>
+    <property name="fileExtensions" value="java"/>
+  </module>
 </module>
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraphEvent.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraphEvent.java	Mon Apr 15 08:49:14 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.graph;
 
+import java.io.*;
+
 public abstract class GraphEvent {
 
     private Exception exceptionContext;
@@ -43,9 +45,9 @@
         }
 
         @Override
-        public StackTraceElement[] print(StackTraceElement[] last) {
-            System.out.println(type.toString() + ", " + nodeString);
-            return super.print(last);
+        public StackTraceElement[] print(StackTraceElement[] last, PrintStream stream) {
+            stream.println(type.toString() + ", " + nodeString);
+            return super.print(last, stream);
         }
     }
 
@@ -72,7 +74,7 @@
         exceptionContext = new Exception();
     }
 
-    public StackTraceElement[] print(StackTraceElement[] last) {
+    public StackTraceElement[] print(StackTraceElement[] last, PrintStream stream) {
         StackTraceElement[] stackTrace = exceptionContext.getStackTrace();
 
         boolean atTop = true;
@@ -90,7 +92,7 @@
                     continue;
                 }
             }
-            System.out.println(String.format("%s.%s(%s:%d)", elem.getClassName(), elem.getMethodName(), elem.getFileName(), elem.getLineNumber()));
+            stream.println(String.format("%s.%s(%s:%d)", elem.getClassName(), elem.getMethodName(), elem.getFileName(), elem.getLineNumber()));
         }
         return stackTrace;
     }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraphEventLog.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraphEventLog.java	Mon Apr 15 08:49:14 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.graph;
 
+import java.io.*;
 import java.util.*;
 
 public class GraphEventLog {
@@ -32,10 +33,10 @@
         this.events.add(e);
     }
 
-    public void printEvents() {
+    public void printEvents(PrintStream stream) {
         StackTraceElement[] last = new StackTraceElement[0];
         for (GraphEvent e : events) {
-            last = e.print(last);
+            last = e.print(last, stream);
         }
     }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Mon Apr 15 08:49:14 2013 +0200
@@ -44,6 +44,7 @@
 import static com.oracle.graal.hotspot.replacements.CipherBlockChainingSubstitutions.DecryptAESCryptStubCall.*;
 import static com.oracle.graal.hotspot.replacements.CipherBlockChainingSubstitutions.EncryptAESCryptStubCall.*;
 
+import com.oracle.graal.amd64.*;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
@@ -71,13 +72,13 @@
                 /*             ret */ ret(Kind.Void));
 
         addRuntimeCall(ARITHMETIC_FREM, config.arithmeticFremStub,
-                /*           temps */ null,
+                /*           temps */ new Register[]{AMD64.rax},
                 /*             ret */ ret(Kind.Float),
                 /* arg0:         a */ javaCallingConvention(Kind.Float,
                 /* arg1:         b */                       Kind.Float));
 
         addRuntimeCall(ARITHMETIC_DREM, config.arithmeticDremStub,
-                /*           temps */ null,
+                /*           temps */ new Register[]{AMD64.rax},
                 /*             ret */ ret(Kind.Double),
                 /* arg0:         a */ javaCallingConvention(Kind.Double,
                 /* arg1:         b */                       Kind.Double));
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java	Mon Apr 15 08:49:14 2013 +0200
@@ -52,7 +52,7 @@
 
     @Use({REG}) protected Value metaspaceMethod;
 
-    AMD64IndirectCallOp(InvokeTarget targetMethod, Value result, Value[] parameters, Value[] temps, Value metaspaceMethod, Value targetAddress, LIRFrameState state) {
+    AMD64IndirectCallOp(ResolvedJavaMethod targetMethod, Value result, Value[] parameters, Value[] temps, Value metaspaceMethod, Value targetAddress, LIRFrameState state) {
         super(targetMethod, result, parameters, temps, targetAddress, state);
         this.metaspaceMethod = metaspaceMethod;
     }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java	Mon Apr 15 08:49:14 2013 +0200
@@ -63,11 +63,11 @@
         if (config.isPollingPageFar) {
             asm.movq(scratch.getRegister(), config.safepointPollingAddress + offset);
             tasm.recordMark(Marks.MARK_POLL_FAR);
-            tasm.recordSafepoint(pos, state);
+            tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
             asm.movq(scratch.getRegister(), new AMD64Address(scratch.getRegister()));
         } else {
             tasm.recordMark(Marks.MARK_POLL_NEAR);
-            tasm.recordSafepoint(pos, state);
+            tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
             // The C++ code transforms the polling page offset into an RIP displacement
             // to the real address at that offset in the polling page.
             asm.movq(scratch.getRegister(), new AMD64Address(rip, offset));
--- a/graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/InvocationSocket.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/InvocationSocket.java	Mon Apr 15 08:49:14 2013 +0200
@@ -38,6 +38,7 @@
  */
 public class InvocationSocket {
 
+    // CheckStyle: stop system..print check
     private static final boolean DEBUG = false;
     private static final boolean COUNT_CALLS = false;
 
@@ -279,4 +280,5 @@
         output.writeObject(new Result(obj));
         output.flush();
     }
+    // CheckStyle: resume system..print check
 }
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/ArrayCopyIntrinsificationTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,238 +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.graal.hotspot;
-
-import static org.junit.Assert.*;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import org.junit.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-
-/**
- * Tests intrinsification of {@link System#arraycopy(Object, int, Object, int, int)}.
- */
-public class ArrayCopyIntrinsificationTest extends GraalCompilerTest {
-
-    @Override
-    protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph) {
-        int nodeCount = graph.getNodeCount();
-        InstalledCode result = super.getCode(method, graph);
-        boolean graphWasProcessed = nodeCount != graph.getNodeCount();
-        if (graphWasProcessed) {
-            if (mustIntrinsify) {
-                for (Node node : graph.getNodes()) {
-                    if (node instanceof Invoke) {
-                        Invoke invoke = (Invoke) node;
-                        Assert.assertTrue(invoke.callTarget() instanceof DirectCallTargetNode);
-                        AbstractCallTargetNode directCall = (AbstractCallTargetNode) invoke.callTarget();
-                        JavaMethod callee = directCall.target();
-                        Assert.assertTrue(callee.getName().equals("<init>"));
-                        Assert.assertTrue(runtime.lookupJavaType(ArrayIndexOutOfBoundsException.class).equals(callee.getDeclaringClass()) ||
-                                        runtime.lookupJavaType(NullPointerException.class).equals(callee.getDeclaringClass()));
-                    }
-                }
-            } else {
-                boolean found = false;
-                for (Node node : graph.getNodes()) {
-                    if (node instanceof Invoke) {
-                        Invoke invoke = (Invoke) node;
-                        AbstractCallTargetNode directCall = (AbstractCallTargetNode) invoke.callTarget();
-                        JavaMethod callee = directCall.target();
-                        if (callee.getDeclaringClass().equals(runtime.lookupJavaType(System.class)) && callee.getName().equals("arraycopy")) {
-                            found = true;
-                        } else {
-                            fail("found invoke to some method other than arraycopy: " + callee);
-                        }
-                    }
-                }
-                Assert.assertTrue("did not find invoke to arraycopy", found);
-            }
-        }
-        return result;
-    }
-
-    boolean mustIntrinsify = true;
-
-    @Test
-    public void test0() {
-        mustIntrinsify = false; // a generic call to arraycopy will not be intrinsified
-        // Array store checks
-        test("genericArraycopy", new Object(), 0, new Object[0], 0, 0);
-        test("genericArraycopy", new Object[0], 0, new Object(), 0, 0);
-
-        mustIntrinsify = true;
-    }
-
-    @Test
-    public void test1() {
-        String name = "intArraycopy";
-        int[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
-        // Null checks
-        test(name, null, 0, src, 0, 0);
-        test(name, src, 0, null, 0, 0);
-        // Bounds checks
-        test(name, src, 0, src, 0, -1);
-        test(name, src, 0, src, 0, src.length + 1);
-    }
-
-    @Test
-    public void testByte() {
-        byte[] src = {-1, 0, 1, 2, 3, 4};
-        testHelper("byteArraycopy", src);
-    }
-
-    @Test
-    public void testChar() {
-        char[] src = "some string of chars".toCharArray();
-        testHelper("charArraycopy", src);
-    }
-
-    @Test
-    public void testShort() {
-        short[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
-        testHelper("shortArraycopy", src);
-    }
-
-    @Test
-    public void testInt() {
-        int[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
-        testHelper("intArraycopy", src);
-    }
-
-    @Test
-    public void testFloat() {
-        float[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
-        testHelper("floatArraycopy", src);
-    }
-
-    @Test
-    public void testLong() {
-        long[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
-        testHelper("longArraycopy", src);
-    }
-
-    @Test
-    public void testDouble() {
-        double[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
-        testHelper("doubleArraycopy", src);
-    }
-
-    @Test
-    public void testObject() {
-        mustIntrinsify = false; // a generic call to arraycopy will not be intrinsified
-
-        Object[] src = {"one", "two", "three", new ArrayList<>(), new HashMap<>()};
-        testHelper("objectArraycopy", src);
-
-        mustIntrinsify = true;
-    }
-
-    @Test
-    public void testObjectExact() {
-        Integer[] src = {1, 2, 3, 4};
-        testHelper("objectArraycopyExact", src);
-    }
-
-    private static Object newArray(Object proto, int length) {
-        assert proto != null;
-        assert proto.getClass().isArray();
-        return Array.newInstance(proto.getClass().getComponentType(), length);
-    }
-
-    private void testHelper(String name, Object src) {
-        int srcLength = Array.getLength(src);
-
-        // Complete array copy
-        test(name, src, 0, newArray(src, srcLength), 0, srcLength);
-
-        for (int length : new int[]{0, 1, srcLength - 1, srcLength}) {
-            // Partial array copying
-            test(name, src, 0, newArray(src, length), 0, length);
-            test(name, src, srcLength - length, newArray(src, length), 0, length);
-            test(name, src, 0, newArray(src, srcLength), 0, length);
-        }
-    }
-
-    public static Object genericArraycopy(Object src, int srcPos, Object dst, int dstPos, int length) {
-        System.arraycopy(src, srcPos, dst, dstPos, length);
-        return dst;
-    }
-
-    public static Object[] objectArraycopy(Object[] src, int srcPos, Object[] dst, int dstPos, int length) {
-        System.arraycopy(src, srcPos, dst, dstPos, length);
-        return dst;
-    }
-
-    public static Object[] objectArraycopyExact(Integer[] src, int srcPos, Integer[] dst, int dstPos, int length) {
-        System.arraycopy(src, srcPos, dst, dstPos, length);
-        return dst;
-    }
-
-    public static boolean[] booleanArraycopy(boolean[] src, int srcPos, boolean[] dst, int dstPos, int length) {
-        System.arraycopy(src, srcPos, dst, dstPos, length);
-        return dst;
-    }
-
-    public static byte[] byteArraycopy(byte[] src, int srcPos, byte[] dst, int dstPos, int length) {
-        System.arraycopy(src, srcPos, dst, dstPos, length);
-        return dst;
-    }
-
-    public static char[] charArraycopy(char[] src, int srcPos, char[] dst, int dstPos, int length) {
-        System.arraycopy(src, srcPos, dst, dstPos, length);
-        return dst;
-    }
-
-    public static short[] shortArraycopy(short[] src, int srcPos, short[] dst, int dstPos, int length) {
-        System.arraycopy(src, srcPos, dst, dstPos, length);
-        return dst;
-    }
-
-    public static int[] intArraycopy(int[] src, int srcPos, int[] dst, int dstPos, int length) {
-        System.arraycopy(src, srcPos, dst, dstPos, length);
-        return dst;
-    }
-
-    public static float[] floatArraycopy(float[] src, int srcPos, float[] dst, int dstPos, int length) {
-        System.arraycopy(src, srcPos, dst, dstPos, length);
-        return dst;
-    }
-
-    public static long[] longArraycopy(long[] src, int srcPos, long[] dst, int dstPos, int length) {
-        System.arraycopy(src, srcPos, dst, dstPos, length);
-        return dst;
-    }
-
-    public static double[] doubleArraycopy(double[] src, int srcPos, double[] dst, int dstPos, int length) {
-        System.arraycopy(src, srcPos, dst, dstPos, length);
-        return dst;
-    }
-
-}
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/HotSpotMethodSubstitutionTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,165 +0,0 @@
-/*
- * 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.graal.hotspot;
-
-import org.junit.*;
-
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.hotspot.replacements.*;
-import com.oracle.graal.replacements.*;
-
-/**
- * Tests HotSpot specific {@link MethodSubstitution}s.
- */
-public class HotSpotMethodSubstitutionTest extends MethodSubstitutionTest {
-
-    @Test
-    public void testObjectSubstitutions() {
-        test("getClass_");
-        test("objectHashCode");
-
-        Object obj = new Object();
-
-        assertEquals("a string".getClass(), ObjectSubstitutions.getClass("a string"));
-        assertEquals(obj.hashCode(), ObjectSubstitutions.hashCode(obj));
-    }
-
-    @SuppressWarnings("all")
-    public static boolean getClass_(Object obj, Class<?> clazz) {
-        return obj.getClass() == clazz;
-    }
-
-    @SuppressWarnings("all")
-    public static int objectHashCode(TestClassA obj) {
-        return obj.hashCode();
-    }
-
-    @Test
-    public void testClassSubstitutions() {
-        test("getModifiers");
-        test("isInstance");
-        test("isInterface");
-        test("isArray");
-        test("isPrimitive");
-        test("getSuperClass");
-        test("getComponentType");
-
-        for (Class c : new Class[]{getClass(), Cloneable.class, int[].class, String[][].class}) {
-            assertEquals(c.getModifiers(), ClassSubstitutions.getModifiers(c));
-            assertEquals(c.isInterface(), ClassSubstitutions.isInterface(c));
-            assertEquals(c.isArray(), ClassSubstitutions.isArray(c));
-            assertEquals(c.isPrimitive(), ClassSubstitutions.isPrimitive(c));
-            assertEquals(c.getSuperclass(), ClassSubstitutions.getSuperclass(c));
-            assertEquals(c.getComponentType(), ClassSubstitutions.getComponentType(c));
-            for (Object o : new Object[]{this, new int[5], new String[2][], new Object()}) {
-                assertEquals(c.isInstance(o), ClassSubstitutions.isInstance(c, o));
-            }
-        }
-    }
-
-    @SuppressWarnings("all")
-    public static int getModifiers(Class<?> clazz) {
-        return clazz.getModifiers();
-    }
-
-    @SuppressWarnings("all")
-    public static boolean isInstance(Class<?> clazz) {
-        return clazz.isInstance(Number.class);
-    }
-
-    @SuppressWarnings("all")
-    public static boolean isInterface(Class<?> clazz) {
-        return clazz.isInterface();
-    }
-
-    @SuppressWarnings("all")
-    public static boolean isArray(Class<?> clazz) {
-        return clazz.isArray();
-    }
-
-    @SuppressWarnings("all")
-    public static boolean isPrimitive(Class<?> clazz) {
-        return clazz.isPrimitive();
-    }
-
-    @SuppressWarnings("all")
-    public static Class<?> getSuperClass(Class<?> clazz) {
-        return clazz.getSuperclass();
-    }
-
-    @SuppressWarnings("all")
-    public static Class<?> getComponentType(Class<?> clazz) {
-        return clazz.getComponentType();
-    }
-
-    @Test
-    public void testThreadSubstitutions() {
-        test("currentThread");
-        test("threadIsInterrupted");
-        test("threadInterrupted");
-
-        Thread currentThread = Thread.currentThread();
-        assertEquals(currentThread, ThreadSubstitutions.currentThread());
-        assertEquals(currentThread.isInterrupted(), ThreadSubstitutions.isInterrupted(currentThread, false));
-    }
-
-    @SuppressWarnings("all")
-    public static Thread currentThread() {
-        return Thread.currentThread();
-    }
-
-    @SuppressWarnings("all")
-    public static boolean threadIsInterrupted(Thread thread) {
-        return thread.isInterrupted();
-    }
-
-    @SuppressWarnings("all")
-    public static boolean threadInterrupted() {
-        return Thread.interrupted();
-    }
-
-    @Test
-    public void testSystemSubstitutions() {
-        test("systemTime");
-        test("systemIdentityHashCode");
-
-        SystemSubstitutions.currentTimeMillis();
-        SystemSubstitutions.nanoTime();
-        for (Object o : new Object[]{this, new int[5], new String[2][], new Object()}) {
-            assertEquals(System.identityHashCode(o), SystemSubstitutions.identityHashCode(o));
-        }
-    }
-
-    @SuppressWarnings("all")
-    public static long systemTime() {
-        return System.currentTimeMillis() + System.nanoTime();
-    }
-
-    @SuppressWarnings("all")
-    public static int systemIdentityHashCode(Object obj) {
-        return System.identityHashCode(obj);
-    }
-
-    private static class TestClassA {
-    }
-}
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/InstalledCodeExecuteHelperTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2012, 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.graal.hotspot;
-
-import java.lang.reflect.*;
-
-import org.junit.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.nodes.spi.*;
-
-public class InstalledCodeExecuteHelperTest extends GraalCompilerTest {
-
-    private static final int ITERATIONS = 100000000;
-
-    @Ignore
-    @Test
-    public void test1() throws NoSuchMethodException, SecurityException {
-
-        final Method benchrMethod = InstalledCodeExecuteHelperTest.class.getMethod("bench", long.class, long.class);
-        final ResolvedJavaMethod benchJavaMethod = Graal.getRequiredCapability(GraalCodeCacheProvider.class).lookupJavaMethod(benchrMethod);
-        HotSpotInstalledCode benchCode = (HotSpotInstalledCode) getCode(benchJavaMethod, parse(benchrMethod));
-
-        final Method wrapperMethod = InstalledCodeExecuteHelperTest.class.getMethod("executeWrapper", long.class, long.class, Object.class, Object.class, Object.class);
-        final ResolvedJavaMethod wrapperJavaMethod = Graal.getRequiredCapability(GraalCodeCacheProvider.class).lookupJavaMethod(wrapperMethod);
-        HotSpotInstalledCode wrapperCode = (HotSpotInstalledCode) getCode(wrapperJavaMethod, parse(wrapperMethod));
-
-        final Method fooMethod = InstalledCodeExecuteHelperTest.class.getMethod("foo", Object.class, Object.class, Object.class);
-        final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) Graal.getRequiredCapability(GraalCodeCacheProvider.class).lookupJavaMethod(fooMethod);
-        HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod));
-
-        System.out.println(wrapperCode.executeVarargs(fooCode.getnmethod(), fooJavaMethod.getMetaspaceMethod(), null, null, null));
-
-        long nmethod = fooCode.getnmethod();
-        long metaspacemethod = fooJavaMethod.getMetaspaceMethod();
-
-        System.out.println("Without replaced InstalledCode.execute:" + bench(nmethod, metaspacemethod));
-
-        System.out.println("WITH replaced InstalledCode.execute:" + benchCode.executeVarargs(nmethod, metaspacemethod));
-
-    }
-
-    public static Long bench(long nmethod, long metaspacemethod) {
-        long start = System.currentTimeMillis();
-
-        for (int i = 0; i < ITERATIONS; i++) {
-            HotSpotInstalledCode.executeHelper(nmethod, metaspacemethod, null, null, null);
-        }
-
-        long end = System.currentTimeMillis();
-        return (end - start);
-    }
-
-    public static Object foo(@SuppressWarnings("unused") Object a1, @SuppressWarnings("unused") Object a2, @SuppressWarnings("unused") Object a3) {
-        return 42;
-    }
-
-    public static Object executeWrapper(long nmethod, long metaspaceMethod, Object arg1, Object arg2, Object arg3) {
-        return HotSpotInstalledCode.executeHelper(nmethod, metaspaceMethod, arg1, arg2, arg3);
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ArrayCopyIntrinsificationTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,238 @@
+/*
+ * 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.graal.hotspot.test;
+
+import static org.junit.Assert.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * Tests intrinsification of {@link System#arraycopy(Object, int, Object, int, int)}.
+ */
+public class ArrayCopyIntrinsificationTest extends GraalCompilerTest {
+
+    @Override
+    protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph) {
+        int nodeCount = graph.getNodeCount();
+        InstalledCode result = super.getCode(method, graph);
+        boolean graphWasProcessed = nodeCount != graph.getNodeCount();
+        if (graphWasProcessed) {
+            if (mustIntrinsify) {
+                for (Node node : graph.getNodes()) {
+                    if (node instanceof Invoke) {
+                        Invoke invoke = (Invoke) node;
+                        Assert.assertTrue(invoke.callTarget() instanceof DirectCallTargetNode);
+                        AbstractCallTargetNode directCall = (AbstractCallTargetNode) invoke.callTarget();
+                        JavaMethod callee = directCall.target();
+                        Assert.assertTrue(callee.getName().equals("<init>"));
+                        Assert.assertTrue(runtime.lookupJavaType(ArrayIndexOutOfBoundsException.class).equals(callee.getDeclaringClass()) ||
+                                        runtime.lookupJavaType(NullPointerException.class).equals(callee.getDeclaringClass()));
+                    }
+                }
+            } else {
+                boolean found = false;
+                for (Node node : graph.getNodes()) {
+                    if (node instanceof Invoke) {
+                        Invoke invoke = (Invoke) node;
+                        AbstractCallTargetNode directCall = (AbstractCallTargetNode) invoke.callTarget();
+                        JavaMethod callee = directCall.target();
+                        if (callee.getDeclaringClass().equals(runtime.lookupJavaType(System.class)) && callee.getName().equals("arraycopy")) {
+                            found = true;
+                        } else {
+                            fail("found invoke to some method other than arraycopy: " + callee);
+                        }
+                    }
+                }
+                Assert.assertTrue("did not find invoke to arraycopy", found);
+            }
+        }
+        return result;
+    }
+
+    boolean mustIntrinsify = true;
+
+    @Test
+    public void test0() {
+        mustIntrinsify = false; // a generic call to arraycopy will not be intrinsified
+        // Array store checks
+        test("genericArraycopy", new Object(), 0, new Object[0], 0, 0);
+        test("genericArraycopy", new Object[0], 0, new Object(), 0, 0);
+
+        mustIntrinsify = true;
+    }
+
+    @Test
+    public void test1() {
+        String name = "intArraycopy";
+        int[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
+        // Null checks
+        test(name, null, 0, src, 0, 0);
+        test(name, src, 0, null, 0, 0);
+        // Bounds checks
+        test(name, src, 0, src, 0, -1);
+        test(name, src, 0, src, 0, src.length + 1);
+    }
+
+    @Test
+    public void testByte() {
+        byte[] src = {-1, 0, 1, 2, 3, 4};
+        testHelper("byteArraycopy", src);
+    }
+
+    @Test
+    public void testChar() {
+        char[] src = "some string of chars".toCharArray();
+        testHelper("charArraycopy", src);
+    }
+
+    @Test
+    public void testShort() {
+        short[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
+        testHelper("shortArraycopy", src);
+    }
+
+    @Test
+    public void testInt() {
+        int[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
+        testHelper("intArraycopy", src);
+    }
+
+    @Test
+    public void testFloat() {
+        float[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
+        testHelper("floatArraycopy", src);
+    }
+
+    @Test
+    public void testLong() {
+        long[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
+        testHelper("longArraycopy", src);
+    }
+
+    @Test
+    public void testDouble() {
+        double[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
+        testHelper("doubleArraycopy", src);
+    }
+
+    @Test
+    public void testObject() {
+        mustIntrinsify = false; // a generic call to arraycopy will not be intrinsified
+
+        Object[] src = {"one", "two", "three", new ArrayList<>(), new HashMap<>()};
+        testHelper("objectArraycopy", src);
+
+        mustIntrinsify = true;
+    }
+
+    @Test
+    public void testObjectExact() {
+        Integer[] src = {1, 2, 3, 4};
+        testHelper("objectArraycopyExact", src);
+    }
+
+    private static Object newArray(Object proto, int length) {
+        assert proto != null;
+        assert proto.getClass().isArray();
+        return Array.newInstance(proto.getClass().getComponentType(), length);
+    }
+
+    private void testHelper(String name, Object src) {
+        int srcLength = Array.getLength(src);
+
+        // Complete array copy
+        test(name, src, 0, newArray(src, srcLength), 0, srcLength);
+
+        for (int length : new int[]{0, 1, srcLength - 1, srcLength}) {
+            // Partial array copying
+            test(name, src, 0, newArray(src, length), 0, length);
+            test(name, src, srcLength - length, newArray(src, length), 0, length);
+            test(name, src, 0, newArray(src, srcLength), 0, length);
+        }
+    }
+
+    public static Object genericArraycopy(Object src, int srcPos, Object dst, int dstPos, int length) {
+        System.arraycopy(src, srcPos, dst, dstPos, length);
+        return dst;
+    }
+
+    public static Object[] objectArraycopy(Object[] src, int srcPos, Object[] dst, int dstPos, int length) {
+        System.arraycopy(src, srcPos, dst, dstPos, length);
+        return dst;
+    }
+
+    public static Object[] objectArraycopyExact(Integer[] src, int srcPos, Integer[] dst, int dstPos, int length) {
+        System.arraycopy(src, srcPos, dst, dstPos, length);
+        return dst;
+    }
+
+    public static boolean[] booleanArraycopy(boolean[] src, int srcPos, boolean[] dst, int dstPos, int length) {
+        System.arraycopy(src, srcPos, dst, dstPos, length);
+        return dst;
+    }
+
+    public static byte[] byteArraycopy(byte[] src, int srcPos, byte[] dst, int dstPos, int length) {
+        System.arraycopy(src, srcPos, dst, dstPos, length);
+        return dst;
+    }
+
+    public static char[] charArraycopy(char[] src, int srcPos, char[] dst, int dstPos, int length) {
+        System.arraycopy(src, srcPos, dst, dstPos, length);
+        return dst;
+    }
+
+    public static short[] shortArraycopy(short[] src, int srcPos, short[] dst, int dstPos, int length) {
+        System.arraycopy(src, srcPos, dst, dstPos, length);
+        return dst;
+    }
+
+    public static int[] intArraycopy(int[] src, int srcPos, int[] dst, int dstPos, int length) {
+        System.arraycopy(src, srcPos, dst, dstPos, length);
+        return dst;
+    }
+
+    public static float[] floatArraycopy(float[] src, int srcPos, float[] dst, int dstPos, int length) {
+        System.arraycopy(src, srcPos, dst, dstPos, length);
+        return dst;
+    }
+
+    public static long[] longArraycopy(long[] src, int srcPos, long[] dst, int dstPos, int length) {
+        System.arraycopy(src, srcPos, dst, dstPos, length);
+        return dst;
+    }
+
+    public static double[] doubleArraycopy(double[] src, int srcPos, double[] dst, int dstPos, int length) {
+        System.arraycopy(src, srcPos, dst, dstPos, length);
+        return dst;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,42 @@
+/*
+ * 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.test;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.hotspot.*;
+
+/**
+ * Tests {@link CompileTheWorld} functionality.
+ */
+public class CompileTheWorldTest extends GraalCompilerTest {
+
+    @Test
+    public void testRtJar() throws Throwable {
+        // Compile a couple classes in rt.jar
+        String file = System.getProperty("java.home") + "/lib/rt.jar";
+        new CompileTheWorld(file, 1, 5).compile();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotInstalledCodeTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2013, 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.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodes.*;
+
+public class HotSpotInstalledCodeTest extends GraalCompilerTest {
+
+    private static final int ITERATION_COUNT = 100000;
+
+    @Test
+    public void testInstallCodeInvalidation() {
+        final ResolvedJavaMethod testJavaMethod = runtime.lookupJavaMethod(getMethod("foo"));
+        final StructuredGraph graph = parse("otherFoo");
+        final HotSpotInstalledCode installedCode = (HotSpotInstalledCode) getCode(testJavaMethod, graph);
+        Assert.assertTrue(installedCode.isValid());
+        Object result;
+        try {
+            result = installedCode.execute("a", "b", "c");
+            assertEquals(43, result);
+        } catch (InvalidInstalledCodeException e) {
+            Assert.fail("Code was invalidated");
+        }
+        Assert.assertTrue(installedCode.isValid());
+        installedCode.invalidate();
+        Assert.assertFalse(installedCode.isValid());
+        try {
+            result = installedCode.execute(null, null, null);
+            Assert.fail("Code was not invalidated");
+        } catch (InvalidInstalledCodeException e) {
+        }
+        Assert.assertFalse(installedCode.isValid());
+    }
+
+    @Test
+    public void testInstalledCodeCalledFromCompiledCode() {
+        final ResolvedJavaMethod testJavaMethod = runtime.lookupJavaMethod(getMethod("foo"));
+        final StructuredGraph graph = parse("otherFoo");
+        final HotSpotInstalledCode installedCode = (HotSpotInstalledCode) getCode(testJavaMethod, graph);
+        Assert.assertTrue(installedCode.isValid());
+        try {
+            for (int i = 0; i < ITERATION_COUNT; ++i) {
+                installedCode.execute("a", "b", "c");
+            }
+        } catch (InvalidInstalledCodeException e) {
+            Assert.fail("Code was invalidated");
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static Object foo(Object a1, Object a2, Object a3) {
+        return 42;
+    }
+
+    @SuppressWarnings("unused")
+    public static Object otherFoo(Object a1, Object a2, Object a3) {
+        return 43;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMethodSubstitutionTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,165 @@
+/*
+ * 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.graal.hotspot.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.replacements.test.*;
+
+/**
+ * Tests HotSpot specific {@link MethodSubstitution}s.
+ */
+public class HotSpotMethodSubstitutionTest extends MethodSubstitutionTest {
+
+    @Test
+    public void testObjectSubstitutions() {
+        test("getClass_");
+        test("objectHashCode");
+
+        Object obj = new Object();
+
+        assertEquals("a string".getClass(), ObjectSubstitutions.getClass("a string"));
+        assertEquals(obj.hashCode(), ObjectSubstitutions.hashCode(obj));
+    }
+
+    @SuppressWarnings("all")
+    public static boolean getClass_(Object obj, Class<?> clazz) {
+        return obj.getClass() == clazz;
+    }
+
+    @SuppressWarnings("all")
+    public static int objectHashCode(TestClassA obj) {
+        return obj.hashCode();
+    }
+
+    @Test
+    public void testClassSubstitutions() {
+        test("getModifiers");
+        test("isInstance");
+        test("isInterface");
+        test("isArray");
+        test("isPrimitive");
+        test("getSuperClass");
+        test("getComponentType");
+
+        for (Class c : new Class[]{getClass(), Cloneable.class, int[].class, String[][].class}) {
+            assertEquals(c.getModifiers(), ClassSubstitutions.getModifiers(c));
+            assertEquals(c.isInterface(), ClassSubstitutions.isInterface(c));
+            assertEquals(c.isArray(), ClassSubstitutions.isArray(c));
+            assertEquals(c.isPrimitive(), ClassSubstitutions.isPrimitive(c));
+            assertEquals(c.getSuperclass(), ClassSubstitutions.getSuperclass(c));
+            assertEquals(c.getComponentType(), ClassSubstitutions.getComponentType(c));
+            for (Object o : new Object[]{this, new int[5], new String[2][], new Object()}) {
+                assertEquals(c.isInstance(o), ClassSubstitutions.isInstance(c, o));
+            }
+        }
+    }
+
+    @SuppressWarnings("all")
+    public static int getModifiers(Class<?> clazz) {
+        return clazz.getModifiers();
+    }
+
+    @SuppressWarnings("all")
+    public static boolean isInstance(Class<?> clazz) {
+        return clazz.isInstance(Number.class);
+    }
+
+    @SuppressWarnings("all")
+    public static boolean isInterface(Class<?> clazz) {
+        return clazz.isInterface();
+    }
+
+    @SuppressWarnings("all")
+    public static boolean isArray(Class<?> clazz) {
+        return clazz.isArray();
+    }
+
+    @SuppressWarnings("all")
+    public static boolean isPrimitive(Class<?> clazz) {
+        return clazz.isPrimitive();
+    }
+
+    @SuppressWarnings("all")
+    public static Class<?> getSuperClass(Class<?> clazz) {
+        return clazz.getSuperclass();
+    }
+
+    @SuppressWarnings("all")
+    public static Class<?> getComponentType(Class<?> clazz) {
+        return clazz.getComponentType();
+    }
+
+    @Test
+    public void testThreadSubstitutions() {
+        test("currentThread");
+        test("threadIsInterrupted");
+        test("threadInterrupted");
+
+        Thread currentThread = Thread.currentThread();
+        assertEquals(currentThread, ThreadSubstitutions.currentThread());
+        assertEquals(currentThread.isInterrupted(), ThreadSubstitutions.isInterrupted(currentThread, false));
+    }
+
+    @SuppressWarnings("all")
+    public static Thread currentThread() {
+        return Thread.currentThread();
+    }
+
+    @SuppressWarnings("all")
+    public static boolean threadIsInterrupted(Thread thread) {
+        return thread.isInterrupted();
+    }
+
+    @SuppressWarnings("all")
+    public static boolean threadInterrupted() {
+        return Thread.interrupted();
+    }
+
+    @Test
+    public void testSystemSubstitutions() {
+        test("systemTime");
+        test("systemIdentityHashCode");
+
+        SystemSubstitutions.currentTimeMillis();
+        SystemSubstitutions.nanoTime();
+        for (Object o : new Object[]{this, new int[5], new String[2][], new Object()}) {
+            assertEquals(System.identityHashCode(o), SystemSubstitutions.identityHashCode(o));
+        }
+    }
+
+    @SuppressWarnings("all")
+    public static long systemTime() {
+        return System.currentTimeMillis() + System.nanoTime();
+    }
+
+    @SuppressWarnings("all")
+    public static int systemIdentityHashCode(Object obj) {
+        return System.identityHashCode(obj);
+    }
+
+    private static class TestClassA {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2012, 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.graal.hotspot.test;
+
+import static com.oracle.graal.api.meta.MetaUtil.*;
+import static java.lang.reflect.Modifier.*;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodes.*;
+
+public class InstalledCodeExecuteHelperTest extends GraalCompilerTest {
+
+    private static final int ITERATIONS = 100000;
+    private final MetaAccessProvider metaAccessProvider;
+    Object[] argsToBind;
+
+    public InstalledCodeExecuteHelperTest() {
+        this.metaAccessProvider = Graal.getRequiredCapability(MetaAccessProvider.class);
+    }
+
+    @Test
+    public void test1() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException {
+        final Method fooMethod = InstalledCodeExecuteHelperTest.class.getMethod("foo", Object.class, Object.class, Object.class);
+        final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) metaAccessProvider.lookupJavaMethod(fooMethod);
+        final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod));
+
+        argsToBind = new Object[]{fooCode};
+
+        final Method benchmarkMethod = InstalledCodeExecuteHelperTest.class.getMethod("benchmark", HotSpotInstalledCode.class);
+        final ResolvedJavaMethod benchmarkJavaMethod = metaAccessProvider.lookupJavaMethod(benchmarkMethod);
+        final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(benchmarkJavaMethod, parse(benchmarkMethod));
+
+        Assert.assertEquals(Integer.valueOf(42), benchmark(fooCode));
+
+        Assert.assertEquals(Integer.valueOf(42), installedBenchmarkCode.executeVarargs(argsToBind[0]));
+
+    }
+
+    public static Integer benchmark(HotSpotInstalledCode code) throws InvalidInstalledCodeException {
+        int val = 0;
+        for (int j = 0; j < 100; j++) {
+            for (int i = 0; i < ITERATIONS; i++) {
+                val = (Integer) code.execute(null, null, null);
+            }
+        }
+        return val;
+    }
+
+    public static Integer foo(@SuppressWarnings("unused") Object a1, @SuppressWarnings("unused") Object a2, @SuppressWarnings("unused") Object a3) {
+        return 42;
+    }
+
+    @Override
+    protected StructuredGraph parse(Method m) {
+        StructuredGraph graph = super.parse(m);
+        if (argsToBind != null) {
+            Object receiver = isStatic(m.getModifiers()) ? null : this;
+            Object[] args = argsWithReceiver(receiver, argsToBind);
+            JavaType[] parameterTypes = signatureToTypes(runtime.lookupJavaMethod(m));
+            assert parameterTypes.length == args.length;
+            for (int i = 0; i < argsToBind.length; i++) {
+                LocalNode local = graph.getLocal(i);
+                Constant c = Constant.forBoxed(parameterTypes[i].getKind(), argsToBind[i]);
+                ConstantNode replacement = ConstantNode.forConstant(c, runtime, graph);
+                local.replaceAtUsages(replacement);
+            }
+        }
+        return graph;
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Mon Apr 15 08:49:14 2013 +0200
@@ -25,6 +25,7 @@
 import static com.oracle.graal.nodes.StructuredGraph.*;
 import static com.oracle.graal.phases.common.InliningUtil.*;
 
+import java.lang.reflect.Modifier;
 import java.util.concurrent.*;
 
 import com.oracle.graal.api.code.*;
@@ -32,6 +33,7 @@
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -133,6 +135,9 @@
                 TTY.println(String.format("%-6d Graal %-70s %-45s %-50s %s...", id, method.getDeclaringClass().getName(), method.getName(), method.getSignature(),
                                 entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + entryBCI + ") "));
             }
+            if (GraalOptions.HotSpotPrintCompilation) {
+                printCompilation();
+            }
 
             CompilationResult result = null;
             TTY.Filter filter = new TTY.Filter(GraalOptions.PrintFilter, method);
@@ -163,7 +168,7 @@
                 }
             }
 
-            installMethod(result);
+            installMethod(result, null);
         } catch (BailoutException bailout) {
             Debug.metric("Bailouts").increment();
             if (GraalOptions.ExitVMOnBailout) {
@@ -183,12 +188,22 @@
         stats.finish(method);
     }
 
-    private void installMethod(final CompilationResult compResult) {
+    /**
+     * Print a HotSpot-style compilation message to the console.
+     */
+    private void printCompilation() {
+        final boolean isOSR = entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI;
+        final int mod = method.getModifiers();
+        TTY.println(String.format("%7d %4d %c%c%c%c%c       %s %s(%d bytes)", 0, id, isOSR ? '%' : ' ', Modifier.isSynchronized(mod) ? 's' : ' ', ' ', ' ', Modifier.isNative(mod) ? 'n' : ' ',
+                        MetaUtil.format("%H::%n(%p)", method), isOSR ? "@ " + entryBCI + " " : "", method.getCodeSize()));
+    }
+
+    private void installMethod(final CompilationResult compResult, final Graph graph) {
         Debug.scope("CodeInstall", new Object[]{new DebugDumpScope(String.valueOf(id), true), graalRuntime.getRuntime(), method}, new Runnable() {
 
             @Override
             public void run() {
-                HotSpotInstalledCode installedCode = graalRuntime.getRuntime().installMethod(method, entryBCI, compResult);
+                HotSpotInstalledCode installedCode = graalRuntime.getRuntime().installMethod(method, graph, entryBCI, compResult);
                 if (Debug.isDumpEnabled()) {
                     Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
                 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,252 @@
+/*
+ * 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;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.net.*;
+import java.util.Enumeration;
+import java.util.jar.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.bytecode.Bytecodes;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.hotspot.bridge.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.replacements.*;
+
+/**
+ * This class implements compile-the-world functionality in Graal.
+ */
+public final class CompileTheWorld {
+
+    /**
+     * This is our magic token to trigger reading files from the boot class path.
+     */
+    public static final String SUN_BOOT_CLASS_PATH = "sun.boot.class.path";
+
+    // Some runtime instances we need.
+    private final HotSpotGraalRuntime graalRuntime = HotSpotGraalRuntime.getInstance();
+    private final VMToCompilerImpl vmToCompiler = (VMToCompilerImpl) graalRuntime.getVMToCompiler();
+
+    /** List of Zip/Jar files to compile (see {@link GraalOptions#CompileTheWorld}. */
+    private final String files;
+
+    /** Class index to start compilation at (see {@link GraalOptions#CompileTheWorldStartAt}. */
+    private final int startAt;
+
+    /** Class index to stop compilation at (see {@link GraalOptions#CompileTheWorldStopAt}. */
+    private final int stopAt;
+
+    // Counters
+    private int classFileCounter = 0;
+    private int compiledMethodsCounter = 0;
+    private long compileTime = 0;
+
+    /**
+     * Create a compile-the-world instance with default values from
+     * {@link GraalOptions#CompileTheWorld}, {@link GraalOptions#CompileTheWorldStartAt} and
+     * {@link GraalOptions#CompileTheWorldStopAt}.
+     */
+    public CompileTheWorld() {
+        this(GraalOptions.CompileTheWorld, GraalOptions.CompileTheWorldStartAt, GraalOptions.CompileTheWorldStopAt);
+    }
+
+    /**
+     * Create a compile-the-world instance.
+     * 
+     * @param files {@link File#pathSeparator} separated list of Zip/Jar files to compile
+     * @param startAt index of the class file to start compilation at
+     * @param stopAt index of the class file to stop compilation at
+     */
+    public CompileTheWorld(String files, int startAt, int stopAt) {
+        this.files = files;
+        this.startAt = startAt;
+        this.stopAt = stopAt;
+
+        // We don't want the VM to exit when a method fails to compile.
+        GraalOptions.ExitVMOnException = false;
+    }
+
+    /**
+     * Compile all methods in all classes in the Zip/Jar files in
+     * {@link GraalOptions#CompileTheWorld}. If the GraalOptions.CompileTheWorld contains the magic
+     * token {@link CompileTheWorld#SUN_BOOT_CLASS_PATH} passed up from HotSpot we take the files
+     * from the boot class path.
+     * 
+     * @throws Throwable
+     */
+    public void compile() throws Throwable {
+        if (SUN_BOOT_CLASS_PATH.equals(files)) {
+            final String[] entries = System.getProperty(SUN_BOOT_CLASS_PATH).split(File.pathSeparator);
+            String bcpFiles = "";
+            for (int i = 0; i < entries.length; i++) {
+                final String entry = entries[i];
+
+                // We stop at rt.jar, unless it is the first boot class path entry.
+                if (entry.endsWith("rt.jar") && (i > 0)) {
+                    break;
+                }
+                if (i > 0) {
+                    bcpFiles += File.pathSeparator;
+                }
+                bcpFiles += entry;
+            }
+            compile(bcpFiles);
+        } else {
+            compile(files);
+        }
+    }
+
+    /**
+     * Compile all methods in all classes in the Zip/Jar files passed.
+     * 
+     * @param fileList {@link File#pathSeparator} separated list of Zip/Jar files to compile
+     * @throws Throwable
+     */
+    private void compile(String fileList) throws Throwable {
+        final String[] entries = fileList.split(File.pathSeparator);
+
+        for (int i = 0; i < entries.length; i++) {
+            final String entry = entries[i];
+
+            // For now we only compile all methods in all classes in zip/jar files.
+            if (!entry.endsWith(".zip") && !entry.endsWith(".jar")) {
+                TTY.println("CompileTheWorld : Skipped classes in " + entry);
+                TTY.println();
+                continue;
+            }
+
+            TTY.println("CompileTheWorld : Compiling all classes in " + entry);
+            TTY.println();
+
+            URL url = new URL("jar", "", "file:" + entry + "!/");
+            ClassLoader loader = new URLClassLoader(new URL[]{url});
+
+            JarFile jarFile = new JarFile(entry);
+            Enumeration<JarEntry> e = jarFile.entries();
+
+            while (e.hasMoreElements()) {
+                JarEntry je = e.nextElement();
+                if (je.isDirectory() || !je.getName().endsWith(".class")) {
+                    continue;
+                }
+
+                // Are we done?
+                if (classFileCounter >= stopAt) {
+                    break;
+                }
+
+                String className = je.getName().substring(0, je.getName().length() - ".class".length());
+                className = className.replace('/', '.');
+                classFileCounter++;
+
+                try {
+                    // Load and initialize class
+                    Class<?> javaClass = Class.forName(className, true, loader);
+
+                    // Pre-load all classes in the constant pool.
+                    try {
+                        HotSpotResolvedObjectType objectType = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(javaClass);
+                        ConstantPool constantPool = objectType.constantPool();
+                        for (int cpi = 1; cpi < constantPool.length(); cpi++) {
+                            constantPool.loadReferencedType(cpi, Bytecodes.LDC);
+                        }
+                    } catch (Throwable t) {
+                        // If something went wrong during pre-loading we just ignore it.
+                        TTY.println("CompileTheWorld (%d) : Preloading failed for %s", classFileCounter, className);
+                    }
+
+                    // Are we compiling this class?
+                    if (classFileCounter >= startAt) {
+                        TTY.println("CompileTheWorld (%d) : %s", classFileCounter, className);
+
+                        // Enqueue each constructor/method in the class for compilation.
+                        for (Constructor<?> constructor : javaClass.getDeclaredConstructors()) {
+                            HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) graalRuntime.getRuntime().lookupJavaConstructor(constructor);
+                            if (canBeCompiled(javaMethod, constructor.getModifiers())) {
+                                compileMethod(javaMethod);
+                            }
+                        }
+                        for (Method method : javaClass.getDeclaredMethods()) {
+                            HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) graalRuntime.getRuntime().lookupJavaMethod(method);
+                            if (canBeCompiled(javaMethod, method.getModifiers())) {
+                                compileMethod(javaMethod);
+                            }
+                        }
+                    }
+                } catch (Throwable t) {
+                    TTY.println("CompileTheWorld (%d) : Skipping %s", classFileCounter, className);
+                }
+            }
+            jarFile.close();
+        }
+
+        TTY.println();
+        TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms)", classFileCounter, compiledMethodsCounter, compileTime);
+    }
+
+    /**
+     * Helper method to schedule a method for compilation and gather some statistics.
+     */
+    private void compileMethod(HotSpotResolvedJavaMethod method) {
+        try {
+            long start = System.currentTimeMillis();
+            vmToCompiler.compileMethod(method, StructuredGraph.INVOCATION_ENTRY_BCI, true, 10);
+            compileTime += (System.currentTimeMillis() - start);
+            compiledMethodsCounter++;
+            method.reprofile();  // makes the method also not-entrant
+        } catch (Throwable t) {
+            // Catch everything and print a message
+            TTY.println("CompileTheWorld (%d) : Error compiling method: %s", classFileCounter, MetaUtil.format("%H.%n(%p):%r", method));
+            t.printStackTrace(TTY.cachedOut);
+        }
+    }
+
+    /**
+     * Helper method for CompileTheWorld to determine if a method should be compiled (Cf.
+     * CompilationPolicy::can_be_compiled).
+     * 
+     * @return true if it can be compiled, false otherwise
+     */
+    private static boolean canBeCompiled(HotSpotResolvedJavaMethod javaMethod, int modifiers) {
+        if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
+            return false;
+        }
+        // This number is from HotSpot:
+        final int hugeMethodLimit = 8000;
+        if (javaMethod.getCodeSize() > hugeMethodLimit) {
+            return false;
+        }
+        // Skip @Snippets for now
+        if (javaMethod.getAnnotation(Snippet.class) != null) {
+            return false;
+        }
+        return true;
+    }
+
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompilationResult.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompilationResult.java	Mon Apr 15 08:49:14 2013 +0200
@@ -67,7 +67,7 @@
     }
 
     private static Site[] getSortedSites(CompilationResult target) {
-        List<?>[] lists = new List<?>[]{target.getSafepoints(), target.getDataReferences(), target.getMarks()};
+        List<?>[] lists = new List<?>[]{target.getInfopoints(), target.getDataReferences(), target.getMarks()};
         int count = 0;
         for (List<?> list : lists) {
             count += list.size();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Mon Apr 15 08:49:14 2013 +0200
@@ -139,6 +139,19 @@
         compilerToVm.initializeConfiguration(config);
         config.check();
 
+        // Set some global options:
+        if (config.compileTheWorld) {
+            GraalOptions.CompileTheWorld = CompileTheWorld.SUN_BOOT_CLASS_PATH;
+        }
+        if (config.compileTheWorldStartAt != 1) {
+            GraalOptions.CompileTheWorldStartAt = config.compileTheWorldStartAt;
+        }
+        if (config.compileTheWorldStopAt != Integer.MAX_VALUE) {
+            GraalOptions.CompileTheWorldStopAt = config.compileTheWorldStopAt;
+        }
+        GraalOptions.HotSpotPrintCompilation = config.printCompilation;
+        GraalOptions.HotSpotPrintInlining = config.printInlining;
+
         if (Boolean.valueOf(System.getProperty("graal.printconfig"))) {
             printConfig(config);
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java	Mon Apr 15 08:49:14 2013 +0200
@@ -25,12 +25,15 @@
 import java.lang.reflect.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.*;
 
 /**
- * Filters certain method substitutions based on whether there is underlying hardware support for them.
+ * Filters certain method substitutions based on whether there is underlying hardware support for
+ * them.
  */
 public class HotSpotReplacementsImpl extends ReplacementsImpl {
 
@@ -42,22 +45,42 @@
     }
 
     @Override
-    protected void registerMethodSubstitution(Member originalMethod, Method substituteMethod) {
+    protected ResolvedJavaMethod registerMethodSubstitution(Member originalMethod, Method substituteMethod) {
         if (substituteMethod.getDeclaringClass() == IntegerSubstitutions.class || substituteMethod.getDeclaringClass() == LongSubstitutions.class) {
             if (substituteMethod.getName().equals("bitCount")) {
                 if (!config.usePopCountInstruction) {
-                    return;
+                    return null;
                 }
             }
         } else if (substituteMethod.getDeclaringClass() == AESCryptSubstitutions.class || substituteMethod.getDeclaringClass() == CipherBlockChainingSubstitutions.class) {
             if (!config.useAESIntrinsics) {
-                return;
+                return null;
             }
             assert config.aescryptEncryptBlockStub != 0L;
             assert config.aescryptDecryptBlockStub != 0L;
             assert config.cipherBlockChainingEncryptAESCryptStub != 0L;
             assert config.cipherBlockChainingDecryptAESCryptStub != 0L;
         }
-        super.registerMethodSubstitution(originalMethod, substituteMethod);
+        return super.registerMethodSubstitution(originalMethod, substituteMethod);
+    }
+
+    @Override
+    public Class<? extends FixedWithNextNode> getMacroSubstitution(ResolvedJavaMethod method) {
+        HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method;
+        int intrinsicId = hsMethod.intrinsicId();
+        if (intrinsicId != 0) {
+            if (intrinsicId == config.vmIntrinsicInvokeBasic) {
+                return MethodHandleInvokeBasicNode.class;
+            } else if (intrinsicId == config.vmIntrinsicLinkToInterface) {
+                return MethodHandleLinkToInterfaceNode.class;
+            } else if (intrinsicId == config.vmIntrinsicLinkToSpecial) {
+                return MethodHandleLinkToSpecialNode.class;
+            } else if (intrinsicId == config.vmIntrinsicLinkToStatic) {
+                return MethodHandleLinkToStaticNode.class;
+            } else if (intrinsicId == config.vmIntrinsicLinkToVirtual) {
+                return MethodHandleLinkToVirtualNode.class;
+            }
+        }
+        return super.getMacroSubstitution(method);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java	Mon Apr 15 08:49:14 2013 +0200
@@ -90,4 +90,9 @@
             address = stub.getAddress(backend);
         }
     }
+
+    @Override
+    public boolean preservesRegisters() {
+        return stub == null;
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Mon Apr 15 08:49:14 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
@@ -37,6 +37,11 @@
     public int codeEntryAlignment;
     public boolean verifyOops;
     public boolean ciTime;
+    public boolean compileTheWorld;
+    public int compileTheWorldStartAt;
+    public int compileTheWorldStopAt;
+    public boolean printCompilation;
+    public boolean printInlining;
     public boolean useFastLocking;
     public boolean useTLAB;
     public boolean useBiasedLocking;
@@ -185,6 +190,11 @@
     public int methodAccessFlagsOffset;
 
     /**
+     * Offset of _intrinsic_id in a metaspace Method object.
+     */
+    public int methodIntrinsicIdOffset;
+
+    /**
      * Offset of _max_locals in a metaspace Method object.
      */
     public int methodMaxLocalsOffset;
@@ -376,6 +386,12 @@
     public int deoptActionMakeNotEntrant;
     public int deoptActionMakeNotCompilable;
 
+    public int vmIntrinsicInvokeBasic;
+    public int vmIntrinsicLinkToVirtual;
+    public int vmIntrinsicLinkToStatic;
+    public int vmIntrinsicLinkToSpecial;
+    public int vmIntrinsicLinkToInterface;
+
     public void check() {
         assert codeEntryAlignment > 0;
         assert stackShadowPages > 0;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Mon Apr 15 08:49:14 2013 +0200
@@ -128,6 +128,8 @@
      */
     JavaType lookupType(String name, HotSpotResolvedObjectType accessingClass, boolean eagerResolve);
 
+    int constantPoolLength(HotSpotResolvedObjectType pool);
+
     Object lookupConstantInPool(HotSpotResolvedObjectType pool, int cpi);
 
     JavaMethod lookupMethodInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode);
@@ -138,6 +140,8 @@
 
     void lookupReferencedTypeInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode);
 
+    Object lookupAppendixInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode);
+
     // Must be kept in sync with enum in graalEnv.hpp
     public enum CodeInstallResult {
         OK, DEPENDENCIES_FAILED, CACHE_FULL
@@ -199,9 +203,9 @@
 
     StackTraceElement getStackTraceElement(long metaspaceMethod, int bci);
 
-    Object executeCompiledMethod(long metaspaceMethod, long nmethod, Object arg1, Object arg2, Object arg3);
+    Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nativeMethod) throws InvalidInstalledCodeException;
 
-    Object executeCompiledMethodVarargs(long metaspaceMethod, long nmethod, Object... args);
+    Object executeCompiledMethodVarargs(Object[] args, long nativeMethod) throws InvalidInstalledCodeException;
 
     int getVtableEntryOffset(long metaspaceMethod);
 
@@ -221,4 +225,8 @@
      * @param metaspaceMethod the metaspace Method object
      */
     void reprofile(long metaspaceMethod);
+
+    void invalidateInstalledCode(long nativeMethod);
+
+    boolean isInstalledCodeValid(long nativeMethod);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Mon Apr 15 08:49:14 2013 +0200
@@ -79,6 +79,9 @@
     public native JavaType lookupType(String name, HotSpotResolvedObjectType accessingClass, boolean eagerResolve);
 
     @Override
+    public native int constantPoolLength(HotSpotResolvedObjectType pool);
+
+    @Override
     public native Object lookupConstantInPool(HotSpotResolvedObjectType pool, int cpi);
 
     @Override
@@ -133,10 +136,7 @@
     public native StackTraceElement getStackTraceElement(long metaspaceMethod, int bci);
 
     @Override
-    public native Object executeCompiledMethod(long metaspaceMethod, long nmethod, Object arg1, Object arg2, Object arg3);
-
-    @Override
-    public native Object executeCompiledMethodVarargs(long metaspaceMethod, long nmethod, Object... args);
+    public native Object executeCompiledMethodVarargs(Object[] args, long nativeMethod);
 
     @Override
     public native int getVtableEntryOffset(long metaspaceMethod);
@@ -158,4 +158,27 @@
 
     @Override
     public native void reprofile(long metaspaceMethod);
+
+    @Override
+    public native Object lookupAppendixInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode);
+
+    @Override
+    public native void invalidateInstalledCode(long nativeMethod);
+
+    @Override
+    public native boolean isInstalledCodeValid(long nativeMethod);
+
+    @Override
+    public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nativeMethod) throws InvalidInstalledCodeException {
+        return executeCompiledMethodIntrinsic(arg1, arg2, arg3, nativeMethod);
+    }
+
+    /**
+     * Direct call to the given nativeMethod with three object arguments and an object return value.
+     * This method does not have an implementation on the C++ side, but its entry points (from
+     * interpreter and from compiled code) are directly pointing to a manually generated assembly
+     * stub that does the necessary argument shuffling and a tail call via an indirect jump to the
+     * verified entry point of the given native method.
+     */
+    private static native Object executeCompiledMethodIntrinsic(Object arg1, Object arg2, Object arg3, long nativeMethod);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/MetricRateInPhase.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/MetricRateInPhase.java	Mon Apr 15 08:49:14 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot.bridge;
 
+import java.io.*;
 import java.util.concurrent.*;
 
 import com.oracle.graal.debug.*;
@@ -65,10 +66,10 @@
         return (int) (v / t);
     }
 
-    public void printAll(String label) {
+    public void printAll(String label, PrintStream stream) {
         MetricRateInPhase rs = this;
         while (rs != null) {
-            System.out.println(label + "@" + rs.phase + ": " + rs.rate());
+            stream.println(label + "@" + rs.phase + ": " + rs.rate());
             rs = rs.previous;
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Mon Apr 15 08:49:14 2013 +0200
@@ -34,8 +34,23 @@
  */
 public interface VMToCompiler {
 
+    /**
+     * Compiles a method to machine code. This method is called from the VM
+     * (VMToCompiler::compileMethod).
+     * 
+     * @return true if the method is in the queue (either added to the queue or already in the
+     *         queue)
+     */
     boolean compileMethod(long metaspaceMethod, HotSpotResolvedObjectType holder, int entryBCI, boolean blocking, int priority) throws Throwable;
 
+    /**
+     * Compiles a method to machine code.
+     * 
+     * @return true if the method is in the queue (either added to the queue or already in the
+     *         queue)
+     */
+    boolean compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, boolean blocking, int priority) throws Throwable;
+
     void shutdownCompiler() throws Throwable;
 
     void startCompiler() throws Throwable;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Mon Apr 15 08:49:14 2013 +0200
@@ -37,6 +37,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.debug.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -152,10 +153,18 @@
 
                 @Override
                 public void run() {
-                    for (ReplacementsProvider provider : ServiceLoader.loadInstalled(ReplacementsProvider.class)) {
+                    ServiceLoader<ReplacementsProvider> serviceLoader = ServiceLoader.loadInstalled(ReplacementsProvider.class);
+                    for (ReplacementsProvider provider : serviceLoader) {
                         provider.registerReplacements(replacements);
                     }
                     runtime.registerReplacements(replacements);
+                    if (GraalOptions.BootstrapReplacements) {
+                        for (ResolvedJavaMethod method : replacements.getAllReplacements()) {
+                            replacements.getMacroSubstitution(method);
+                            replacements.getMethodSubstitution(method);
+                            replacements.getSnippet(method);
+                        }
+                    }
                 }
             });
 
@@ -197,9 +206,22 @@
             t.start();
         }
 
-        if (GraalOptions.BenchmarkDynamicCounters) {
-            System.setErr(new PrintStream(new BenchmarkCountersOutputStream(System.err, " starting =====", " PASSED in ", "\n")));
-            System.setOut(new PrintStream(new BenchmarkCountersOutputStream(System.out, "Iteration ~ (~s) begins: ", "Iteration ~ (~s) ends:   ", "\n")));
+        if (GraalOptions.BenchmarkDynamicCounters != null) {
+            String[] arguments = GraalOptions.BenchmarkDynamicCounters.split(",");
+            if (arguments.length == 0 || (arguments.length % 3) != 0) {
+                throw new GraalInternalError("invalid arguments to BenchmarkDynamicCounters: (err|out),start,end,(err|out),start,end,... (~ matches multiple digits)");
+            }
+            for (int i = 0; i < arguments.length; i += 3) {
+                if (arguments[i].equals("err")) {
+                    System.setErr(new PrintStream(new BenchmarkCountersOutputStream(System.err, arguments[i + 1], arguments[i + 2])));
+                } else if (arguments[i].equals("out")) {
+                    System.setOut(new PrintStream(new BenchmarkCountersOutputStream(System.out, arguments[i + 1], arguments[i + 2])));
+                } else {
+                    throw new GraalInternalError("invalid arguments to BenchmarkDynamicCounters: err|out");
+                }
+                // dacapo: "err, starting =====, PASSED in "
+                // specjvm2008: "out,Iteration ~ (~s) begins: ,Iteration ~ (~s) ends:   "
+            }
             DynamicCounterNode.excludedClassPrefix = "Lcom/oracle/graal/";
             DynamicCounterNode.enabled = true;
         }
@@ -214,8 +236,8 @@
         private long startTime;
         private boolean waitingForEnd;
 
-        private BenchmarkCountersOutputStream(PrintStream delegate, String... patterns) {
-            super(delegate, patterns);
+        private BenchmarkCountersOutputStream(PrintStream delegate, String start, String end) {
+            super(delegate, new String[]{start, end, "\n"});
         }
 
         @Override
@@ -371,6 +393,10 @@
         System.gc();
         phaseTransition("bootstrap2");
 
+        if (GraalOptions.CompileTheWorld != null) {
+            new CompileTheWorld().compile();
+            System.exit(0);
+        }
     }
 
     private MetricRateInPhase parsedBytecodesPerSecond;
@@ -438,8 +464,8 @@
         phaseTransition("final");
 
         if (graalRuntime.getConfig().ciTime) {
-            parsedBytecodesPerSecond.printAll("ParsedBytecodesPerSecond");
-            inlinedBytecodesPerSecond.printAll("InlinedBytecodesPerSecond");
+            parsedBytecodesPerSecond.printAll("ParsedBytecodesPerSecond", System.out);
+            inlinedBytecodesPerSecond.printAll("InlinedBytecodesPerSecond", System.out);
         }
 
         SnippetCounter.printGroups(TTY.out().out());
@@ -713,6 +739,7 @@
         if (onStackReplacement) {
             phasePlan.addPhase(PhasePosition.AFTER_PARSING, new OnStackReplacementPhase());
         }
+        phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierAdditionPhase());
         return phasePlan;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/CountingProxy.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/CountingProxy.java	Mon Apr 15 08:49:14 2013 +0200
@@ -41,7 +41,9 @@
 
     public CountingProxy(T delegate) {
         assert ENABLED;
+        // CheckStyle: stop system..print check
         System.out.println("Counting proxy for " + delegate.getClass().getSimpleName() + " created");
+        // CheckStyle: resume system..print check
         this.delegate = delegate;
         proxies.add(this);
     }
@@ -92,6 +94,7 @@
         }
     }
 
+    // CheckStyle: stop system..print check
     protected void print() {
         long sum = 0;
         for (Map.Entry<Method, AtomicLong> entry : calls.entrySet()) {
@@ -102,4 +105,5 @@
         }
         System.out.println(delegate.getClass().getSimpleName() + " calls: " + sum);
     }
+    // CheckStyle: resume system..print check
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/Logger.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/Logger.java	Mon Apr 15 08:49:14 2013 +0200
@@ -70,6 +70,7 @@
         }
     }
 
+    // CheckStyle: stop system..print check
     public static void info(String message) {
         if (ENABLED) {
             log(message);
@@ -124,6 +125,8 @@
         }
     }
 
+    // CheckStyle: resume system..print check
+
     private static String[] spaces = new String[50];
 
     private static String space(int count) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java	Mon Apr 15 08:49:14 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot.meta;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.bytecode.*;
 import com.oracle.graal.hotspot.*;
 
 /**
@@ -39,6 +40,11 @@
     }
 
     @Override
+    public int length() {
+        return HotSpotGraalRuntime.getInstance().getCompilerToVM().constantPoolLength(type);
+    }
+
+    @Override
     public Object lookupConstant(int cpi) {
         assert cpi != 0;
         Object constant = HotSpotGraalRuntime.getInstance().getCompilerToVM().lookupConstantInPool(type, cpi);
@@ -51,6 +57,12 @@
     }
 
     @Override
+    public Object lookupAppendix(int cpi, int opcode) {
+        assert Bytecodes.isInvoke(opcode);
+        return HotSpotGraalRuntime.getInstance().getCompilerToVM().lookupAppendixInPool(type, cpi, (byte) opcode);
+    }
+
+    @Override
     public JavaMethod lookupMethod(int cpi, int opcode) {
         return HotSpotGraalRuntime.getInstance().getCompilerToVM().lookupMethodInPool(type, cpi, (byte) opcode);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -26,6 +26,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 
 /**
@@ -39,11 +40,13 @@
 
     private final HotSpotResolvedJavaMethod method;
     private final boolean isDefault;
+    private final Graph graph;
     long nmethod;
     long start;
 
-    public HotSpotInstalledCode(HotSpotResolvedJavaMethod method, boolean isDefault) {
+    public HotSpotInstalledCode(HotSpotResolvedJavaMethod method, Graph graph, boolean isDefault) {
         this.method = method;
+        this.graph = graph;
         this.isDefault = isDefault;
     }
 
@@ -51,10 +54,14 @@
         return isDefault;
     }
 
-    public long getnmethod() {
+    public long getMethodAddress() {
         return nmethod;
     }
 
+    public Graph getGraph() {
+        return graph;
+    }
+
     @Override
     public ResolvedJavaMethod getMethod() {
         return method;
@@ -62,7 +69,12 @@
 
     @Override
     public boolean isValid() {
-        return nmethod != 0;
+        return HotSpotGraalRuntime.getInstance().getCompilerToVM().isInstalledCodeValid(nmethod);
+    }
+
+    @Override
+    public void invalidate() {
+        HotSpotGraalRuntime.getInstance().getCompilerToVM().invalidateInstalledCode(nmethod);
     }
 
     @Override
@@ -71,12 +83,12 @@
     }
 
     @Override
-    public Object execute(Object arg1, Object arg2, Object arg3) {
+    public Object execute(Object arg1, Object arg2, Object arg3) throws InvalidInstalledCodeException {
         assert method.getSignature().getParameterCount(!Modifier.isStatic(method.getModifiers())) == 3;
         assert method.getSignature().getParameterKind(0) == Kind.Object;
         assert method.getSignature().getParameterKind(1) == Kind.Object;
         assert !Modifier.isStatic(method.getModifiers()) || method.getSignature().getParameterKind(2) == Kind.Object;
-        return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(method.metaspaceMethod, nmethod, arg1, arg2, arg3);
+        return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(arg1, arg2, arg3, nmethod);
     }
 
     private boolean checkArgs(Object... args) {
@@ -94,9 +106,9 @@
     }
 
     @Override
-    public Object executeVarargs(Object... args) {
+    public Object executeVarargs(Object... args) throws InvalidInstalledCodeException {
         assert checkArgs(args);
-        return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethodVarargs(method.metaspaceMethod, nmethod, args);
+        return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethodVarargs(args, nmethod);
     }
 
     @Override
@@ -108,8 +120,4 @@
     public byte[] getCode() {
         return HotSpotGraalRuntime.getInstance().getCompilerToVM().getCode(nmethod);
     }
-
-    public static Object executeHelper(long nmethod, long metaspaceMethod, Object arg1, Object arg2, Object arg3) {
-        return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(metaspaceMethod, nmethod, arg1, arg2, arg3);
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodUnresolved.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodUnresolved.java	Mon Apr 15 08:49:14 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.meta;
 
+import static com.oracle.graal.api.meta.MetaUtil.*;
+
 import com.oracle.graal.api.meta.*;
 
 /**
@@ -51,6 +53,6 @@
 
     @Override
     public String toString() {
-        return "HotSpotMethod<" + holder.getName() + ". " + name + ", unresolved>";
+        return format("HotSpotMethod<%H.%n(%p), unresolved>", this);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Mon Apr 15 08:49:14 2013 +0200
@@ -23,6 +23,8 @@
 
 package com.oracle.graal.hotspot.meta;
 
+import static com.oracle.graal.api.meta.MetaUtil.*;
+
 import java.lang.annotation.*;
 import java.lang.reflect.*;
 
@@ -150,7 +152,7 @@
 
     @Override
     public String toString() {
-        return "HotSpotField<" + MetaUtil.format("%h.%n", this) + ":" + offset + ">";
+        return format("HotSpotField<%H.%n %t:", this) + offset + ">";
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Mon Apr 15 08:49:14 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot.meta;
 
+import static com.oracle.graal.api.meta.MetaUtil.*;
 import static com.oracle.graal.graph.FieldIntrospection.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
@@ -186,7 +187,7 @@
 
     @Override
     public String toString() {
-        return "HotSpotMethod<" + MetaUtil.format("%h.%n", this) + ">";
+        return format("HotSpotMethod<%H.%n(%p)>", this);
     }
 
     public int getCompiledCodeSize() {
@@ -361,4 +362,51 @@
         }
         return speculationLog;
     }
+
+    public int intrinsicId() {
+        HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig();
+        return unsafe.getByte(metaspaceMethod + config.methodIntrinsicIdOffset) & 0xff;
+    }
+
+    @Override
+    public Constant invoke(Constant receiver, Constant[] arguments) {
+        assert !isConstructor();
+        Method javaMethod = toJava();
+        javaMethod.setAccessible(true);
+
+        Object[] objArguments = new Object[arguments.length];
+        for (int i = 0; i < arguments.length; i++) {
+            objArguments[i] = arguments[i].asBoxedValue();
+        }
+        Object objReceiver = receiver != null ? receiver.asObject() : null;
+
+        try {
+            Object objResult = javaMethod.invoke(objReceiver, objArguments);
+            return javaMethod.getReturnType() == void.class ? null : Constant.forBoxed(getSignature().getReturnKind(), objResult);
+
+        } catch (IllegalAccessException | InvocationTargetException ex) {
+            throw new IllegalArgumentException(ex);
+        }
+    }
+
+    @Override
+    public Constant newInstance(Constant[] arguments) {
+        assert isConstructor();
+        Constructor javaConstructor = toJavaConstructor();
+        javaConstructor.setAccessible(true);
+
+        Object[] objArguments = new Object[arguments.length];
+        for (int i = 0; i < arguments.length; i++) {
+            objArguments[i] = arguments[i].asBoxedValue();
+        }
+
+        try {
+            Object objResult = javaConstructor.newInstance(objArguments);
+            assert objResult != null;
+            return Constant.forObject(objResult);
+
+        } catch (IllegalAccessException | InvocationTargetException | InstantiationException ex) {
+            throw new IllegalArgumentException(ex);
+        }
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Mon Apr 15 08:49:14 2013 +0200
@@ -135,7 +135,6 @@
         assert name.charAt(0) != '[' || sizeOrSpecies == ARRAY_SPECIES_VALUE : name + " " + Long.toHexString(sizeOrSpecies);
         assert javaMirror.isArray() == isArray();
         assert javaMirror.isInterface() == isInterface();
-        // System.out.println("0x" + Long.toHexString(metaspaceKlass) + ": " + name);
     }
 
     @Override
@@ -520,4 +519,31 @@
         final Class<?> encl = mirror().getEnclosingClass();
         return encl == null ? null : fromClass(encl);
     }
+
+    @Override
+    public ResolvedJavaMethod[] getDeclaredConstructors() {
+        Constructor[] constructors = javaMirror.getDeclaredConstructors();
+        ResolvedJavaMethod[] result = new ResolvedJavaMethod[constructors.length];
+        for (int i = 0; i < constructors.length; i++) {
+            result[i] = HotSpotGraalRuntime.getInstance().getRuntime().lookupJavaConstructor(constructors[i]);
+            assert result[i].isConstructor();
+        }
+        return result;
+    }
+
+    @Override
+    public ResolvedJavaMethod[] getDeclaredMethods() {
+        Method[] methods = javaMirror.getDeclaredMethods();
+        ResolvedJavaMethod[] result = new ResolvedJavaMethod[methods.length];
+        for (int i = 0; i < methods.length; i++) {
+            result[i] = HotSpotGraalRuntime.getInstance().getRuntime().lookupJavaMethod(methods[i]);
+            assert !result[i].isConstructor();
+        }
+        return result;
+    }
+
+    @Override
+    public Constant newArray(int length) {
+        return Constant.forObject(Array.newInstance(javaMirror, length));
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java	Mon Apr 15 08:49:14 2013 +0200
@@ -210,4 +210,19 @@
     public ResolvedJavaType getEnclosingType() {
         return null;
     }
+
+    @Override
+    public ResolvedJavaMethod[] getDeclaredConstructors() {
+        return new ResolvedJavaMethod[0];
+    }
+
+    @Override
+    public ResolvedJavaMethod[] getDeclaredMethods() {
+        return new ResolvedJavaMethod[0];
+    }
+
+    @Override
+    public Constant newArray(int length) {
+        return Constant.forObject(Array.newInstance(javaMirror, length));
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Mon Apr 15 08:49:14 2013 +0200
@@ -48,7 +48,7 @@
 import com.oracle.graal.api.code.CompilationResult.Call;
 import com.oracle.graal.api.code.CompilationResult.DataPatch;
 import com.oracle.graal.api.code.CompilationResult.Mark;
-import com.oracle.graal.api.code.CompilationResult.Safepoint;
+import com.oracle.graal.api.code.CompilationResult.Infopoint;
 import com.oracle.graal.api.code.Register.RegisterFlag;
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
 import com.oracle.graal.api.meta.*;
@@ -64,6 +64,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
@@ -89,6 +90,7 @@
     private NewObjectSnippets.Templates newObjectSnippets;
     private MonitorSnippets.Templates monitorSnippets;
     private WriteBarrierSnippets.Templates writeBarrierSnippets;
+    private BoxingSnippets.Templates boxingSnippets;
     private LoadExceptionObjectSnippets.Templates exceptionObjectSnippets;
 
     private final Map<Descriptor, HotSpotRuntimeCallTarget> runtimeCalls = new HashMap<>();
@@ -223,25 +225,25 @@
                         /* arg0:     index */ javaCallingConvention(Kind.Int));
 
         addRuntimeCall(JAVA_TIME_MILLIS, config.javaTimeMillisStub,
-                        /*           temps */ null,
+                        /*           temps */ this.regConfig.getCallerSaveRegisters(),
                         /*             ret */ ret(Kind.Long));
 
         addRuntimeCall(JAVA_TIME_NANOS, config.javaTimeNanosStub,
-                        /*           temps */ null,
+                        /*           temps */ this.regConfig.getCallerSaveRegisters(),
                         /*             ret */ ret(Kind.Long));
 
         addRuntimeCall(ARITHMETIC_SIN, config.arithmeticSinStub,
-                        /*           temps */ null,
+                        /*           temps */ this.regConfig.getCallerSaveRegisters(),
                         /*             ret */ ret(Kind.Double),
                         /* arg0:     index */ javaCallingConvention(Kind.Double));
 
         addRuntimeCall(ARITHMETIC_COS, config.arithmeticCosStub,
-                        /*           temps */ null,
+                        /*           temps */ this.regConfig.getCallerSaveRegisters(),
                         /*             ret */ ret(Kind.Double),
                         /* arg0:     index */ javaCallingConvention(Kind.Double));
 
         addRuntimeCall(ARITHMETIC_TAN, config.arithmeticTanStub,
-                        /*           temps */ null,
+                        /*           temps */ this.regConfig.getCallerSaveRegisters(),
                         /*             ret */ ret(Kind.Double),
                         /* arg0:     index */ javaCallingConvention(Kind.Double));
 
@@ -277,7 +279,7 @@
      * @param ret where the call returns its result
      * @param args where arguments are passed to the call
      */
-    protected void addRuntimeCall(Descriptor descriptor, long address, Register[] tempRegs, Value ret, Value... args) {
+    protected RuntimeCallTarget addRuntimeCall(Descriptor descriptor, long address, Register[] tempRegs, Value ret, Value... args) {
         Value[] temps = tempRegs == null || tempRegs.length == 0 ? Value.NONE : new Value[tempRegs.length];
         for (int i = 0; i < temps.length; i++) {
             temps[i] = tempRegs[i].asValue();
@@ -290,6 +292,7 @@
         }
         HotSpotRuntimeCallTarget runtimeCall = new HotSpotRuntimeCallTarget(descriptor, address, new CallingConvention(temps, 0, ret, args), graalRuntime.getCompilerToVM());
         runtimeCalls.put(descriptor, runtimeCall);
+        return runtimeCall;
     }
 
     private boolean checkAssignable(Class spec, Value value) {
@@ -325,18 +328,13 @@
             replacements.registerSubstitutions(AESCryptSubstitutions.class);
             replacements.registerSubstitutions(CipherBlockChainingSubstitutions.class);
         }
-        if (GraalOptions.IntrinsifyArrayCopy) {
-            replacements.registerSnippets(ArrayCopySnippets.class);
-        }
-        if (GraalOptions.IntrinsifyObjectClone) {
-            replacements.registerSnippets(ObjectCloneSnippets.class);
-        }
 
         checkcastSnippets = new CheckCastSnippets.Templates(this, replacements, graalRuntime.getTarget());
         instanceofSnippets = new InstanceOfSnippets.Templates(this, replacements, graalRuntime.getTarget());
         newObjectSnippets = new NewObjectSnippets.Templates(this, replacements, graalRuntime.getTarget(), config.useTLAB);
         monitorSnippets = new MonitorSnippets.Templates(this, replacements, graalRuntime.getTarget(), config.useFastLocking);
         writeBarrierSnippets = new WriteBarrierSnippets.Templates(this, replacements, graalRuntime.getTarget());
+        boxingSnippets = new BoxingSnippets.Templates(this, replacements, graalRuntime.getTarget());
         exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(this, replacements, graalRuntime.getTarget());
 
         registerStub(new NewInstanceStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(NEW_INSTANCE)));
@@ -373,18 +371,18 @@
             addExceptionHandlersComment(compResult, hcf);
             Register fp = regConfig.getFrameRegister();
             RefMapFormatter slotFormatter = new RefMapFormatter(target.arch, target.wordSize, fp, 0);
-            for (Safepoint safepoint : compResult.getSafepoints()) {
-                if (safepoint instanceof Call) {
-                    Call call = (Call) safepoint;
+            for (Infopoint infopoint : compResult.getInfopoints()) {
+                if (infopoint instanceof Call) {
+                    Call call = (Call) infopoint;
                     if (call.debugInfo != null) {
                         hcf.addComment(call.pcOffset + call.size, CodeUtil.append(new StringBuilder(100), call.debugInfo, slotFormatter).toString());
                     }
                     addOperandComment(hcf, call.pcOffset, "{" + getTargetName(call) + "}");
                 } else {
-                    if (safepoint.debugInfo != null) {
-                        hcf.addComment(safepoint.pcOffset, CodeUtil.append(new StringBuilder(100), safepoint.debugInfo, slotFormatter).toString());
+                    if (infopoint.debugInfo != null) {
+                        hcf.addComment(infopoint.pcOffset, CodeUtil.append(new StringBuilder(100), infopoint.debugInfo, slotFormatter).toString());
                     }
-                    addOperandComment(hcf, safepoint.pcOffset, "{safepoint}");
+                    addOperandComment(hcf, infopoint.pcOffset, "{infopoint: " + infopoint.reason + "}");
                 }
             }
             for (DataPatch site : compResult.getDataReferences()) {
@@ -508,7 +506,7 @@
                 NodeInputList<ValueNode> parameters = callTarget.arguments();
                 ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0);
                 if (!callTarget.isStatic() && receiver.kind() == Kind.Object && !receiver.objectStamp().nonNull()) {
-                    invoke.node().dependencies().add(tool.createNullCheckGuard(receiver));
+                    invoke.asNode().dependencies().add(tool.createNullCheckGuard(receiver));
                 }
                 JavaType[] signature = MetaUtil.signatureToTypes(callTarget.targetMethod().getSignature(), callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass());
 
@@ -528,10 +526,10 @@
                             ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, LocationNode.create(LocationNode.ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph),
                                             StampFactory.forKind(wordKind())));
 
-                            loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.node().stamp(), signature, callTarget.targetMethod(),
+                            loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(),
                                             CallingConvention.Type.JavaCall));
 
-                            graph.addBeforeFixed(invoke.node(), hub);
+                            graph.addBeforeFixed(invoke.asNode(), hub);
                             graph.addAfterFixed(hub, metaspaceMethod);
                             graph.addAfterFixed(metaspaceMethod, compiledEntry);
                         }
@@ -539,7 +537,7 @@
                 }
 
                 if (loweredCallTarget == null) {
-                    loweredCallTarget = graph.add(new HotSpotDirectCallTargetNode(parameters, invoke.node().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall,
+                    loweredCallTarget = graph.add(new HotSpotDirectCallTargetNode(parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall,
                                     callTarget.invokeKind()));
                 }
                 callTarget.replaceAndDelete(loweredCallTarget);
@@ -548,16 +546,11 @@
             LoadFieldNode loadField = (LoadFieldNode) n;
             HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) loadField.field();
             ValueNode object = loadField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), this, graph) : loadField.object();
-            LocationNode location = LocationNode.create(field, field.getKind(), field.offset(), graph);
             assert loadField.kind() != Kind.Illegal;
             ReadNode memoryRead = graph.add(new ReadNode(object, LocationNode.create(field, field.getKind(), field.offset(), graph), loadField.stamp()));
             memoryRead.dependencies().add(tool.createNullCheckGuard(object));
 
             graph.replaceFixedWithFixed(loadField, memoryRead);
-            if (config.useG1GC && field.getKind() == Kind.Object && field.getDeclaringClass().getName().toString().equals("Ljava/lang/ref/Reference;") && field.getName().equals("referent")) {
-                WriteBarrierPre writeBarrierPre = graph.add(new WriteBarrierPre(memoryRead.object(), memoryRead, location, false));
-                graph.addAfterFixed(memoryRead, writeBarrierPre);
-            }
 
             if (loadField.isVolatile()) {
                 MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ));
@@ -570,27 +563,14 @@
             HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field();
             ValueNode object = storeField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), this, graph) : storeField.object();
             LocationNode location = LocationNode.create(field, field.getKind(), field.offset(), graph);
-            WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), location));
+            WriteBarrierType barrierType = getFieldStoreBarrier(storeField);
+            WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), location, barrierType));
             memoryWrite.dependencies().add(tool.createNullCheckGuard(object));
             memoryWrite.setStateAfter(storeField.stateAfter());
             graph.replaceFixedWithFixed(storeField, memoryWrite);
             FixedWithNextNode last = memoryWrite;
             FixedWithNextNode first = memoryWrite;
 
-            if (field.getKind() == Kind.Object && !memoryWrite.value().objectStamp().alwaysNull()) {
-                if (config.useG1GC) {
-                    WriteBarrierPre writeBarrierPre = graph.add(new WriteBarrierPre(memoryWrite.object(), null, memoryWrite.location(), true));
-                    WriteBarrierPost writeBarrierPost = graph.add(new WriteBarrierPost(memoryWrite.object(), memoryWrite.value(), memoryWrite.location(), false));
-                    graph.addBeforeFixed(memoryWrite, writeBarrierPre);
-                    graph.addAfterFixed(memoryWrite, writeBarrierPost);
-                    first = writeBarrierPre;
-                    last = writeBarrierPost;
-                } else {
-                    FieldWriteBarrier writeBarrier = graph.add(new FieldWriteBarrier(memoryWrite.object()));
-                    graph.addAfterFixed(memoryWrite, writeBarrier);
-                    last = writeBarrier;
-                }
-            }
             if (storeField.isVolatile()) {
                 MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE));
                 graph.addBeforeFixed(first, preMembar);
@@ -600,31 +580,7 @@
         } else if (n instanceof CompareAndSwapNode) {
             // Separate out GC barrier semantics
             CompareAndSwapNode cas = (CompareAndSwapNode) n;
-            ValueNode expected = cas.expected();
-            LocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, 1);
-            if (expected.kind() == Kind.Object && !cas.newValue().objectStamp().alwaysNull()) {
-                ResolvedJavaType type = cas.object().objectStamp().type();
-                if (type != null && !type.isArray() && !MetaUtil.isJavaLangObject(type)) {
-                    // Use a field write barrier since it's not an array store
-                    if (config.useG1GC) {
-                        WriteBarrierPre writeBarrierPre = graph.add(new WriteBarrierPre(cas.object(), null, location, true));
-                        WriteBarrierPost writeBarrierPost = graph.add(new WriteBarrierPost(cas.object(), cas.newValue(), location, false));
-                        graph.addBeforeFixed(cas, writeBarrierPre);
-                        graph.addAfterFixed(cas, writeBarrierPost);
-                    } else {
-                        graph.addAfterFixed(cas, graph.add(new FieldWriteBarrier(cas.object())));
-                    }
-                } else {
-                    // This may be an array store so use an array write barrier
-                    if (config.useG1GC) {
-                        WriteBarrierPre writeBarrierPre = graph.add(new WriteBarrierPre(cas.object(), null, location, true));
-                        graph.addBeforeFixed(cas, writeBarrierPre);
-                        graph.addAfterFixed(cas, graph.add(new WriteBarrierPost(cas.object(), cas.newValue(), location, true)));
-                    } else {
-                        graph.addAfterFixed(cas, graph.add(new ArrayWriteBarrier(cas.object(), location)));
-                    }
-                }
-            }
+            cas.setWriteBarrierType(getCompareAndSwapBarrier(cas));
         } else if (n instanceof LoadIndexedNode) {
             LoadIndexedNode loadIndexed = (LoadIndexedNode) n;
             ValueNode boundsCheck = createBoundsCheck(loadIndexed, tool);
@@ -660,21 +616,12 @@
                     value = checkcast;
                 }
             }
-            WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation));
+            WriteBarrierType barrierType = getArrayStoreBarrier(storeIndexed);
+            WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation, barrierType));
             memoryWrite.dependencies().add(boundsCheck);
             memoryWrite.setStateAfter(storeIndexed.stateAfter());
             graph.replaceFixedWithFixed(storeIndexed, memoryWrite);
 
-            if (elementKind == Kind.Object && !value.objectStamp().alwaysNull()) {
-                if (config.useG1GC) {
-                    WriteBarrierPre writeBarrierPre = graph.add(new WriteBarrierPre(array, null, arrayLocation, true));
-                    graph.addBeforeFixed(memoryWrite, writeBarrierPre);
-                    WriteBarrierPost writeBarrierPost = graph.add(new WriteBarrierPost(array, value, arrayLocation, true));
-                    graph.addAfterFixed(memoryWrite, writeBarrierPost);
-                } else {
-                    graph.addAfterFixed(memoryWrite, graph.add(new ArrayWriteBarrier(array, arrayLocation)));
-                }
-            }
         } else if (n instanceof UnsafeLoadNode) {
             UnsafeLoadNode load = (UnsafeLoadNode) n;
             assert load.kind() != Kind.Illegal;
@@ -688,32 +635,11 @@
             UnsafeStoreNode store = (UnsafeStoreNode) n;
             IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, store.accessKind(), store.displacement(), store.offset(), graph, 1);
             ValueNode object = store.object();
-            WriteNode write = graph.add(new WriteNode(object, store.value(), location));
+            WriteBarrierType barrierType = getUnsafeStoreBarrier(store);
+            WriteNode write = graph.add(new WriteNode(object, store.value(), location, barrierType));
             write.setStateAfter(store.stateAfter());
             graph.replaceFixedWithFixed(store, write);
-            if (write.value().kind() == Kind.Object && !write.value().objectStamp().alwaysNull()) {
-                ResolvedJavaType type = object.objectStamp().type();
-                // WriteBarrier writeBarrier;
-                if (type != null && !type.isArray() && !MetaUtil.isJavaLangObject(type)) {
-                    // Use a field write barrier since it's not an array store
-                    if (config.useG1GC) {
-                        WriteBarrierPre writeBarrierPre = new WriteBarrierPre(object, null, location, true);
-                        graph.addBeforeFixed(write, graph.add(writeBarrierPre));
-                        graph.addAfterFixed(write, graph.add(new WriteBarrierPost(object, write.value(), location, false)));
-                    } else {
-                        graph.addAfterFixed(write, graph.add(new FieldWriteBarrier(object)));
-                    }
-                } else {
-                    // This may be an array store so use an array write barrier
-                    if (config.useG1GC) {
-                        WriteBarrierPre writeBarrierPre = graph.add(new WriteBarrierPre(object, null, location, true));
-                        graph.addBeforeFixed(write, writeBarrierPre);
-                        graph.addAfterFixed(write, graph.add(new WriteBarrierPost(object, write.value(), location, true)));
-                    } else {
-                        graph.addAfterFixed(write, graph.add(new ArrayWriteBarrier(object, location)));
-                    }
-                }
-            }
+
         } else if (n instanceof LoadHubNode) {
             LoadHubNode loadHub = (LoadHubNode) n;
             assert loadHub.kind() == wordKind;
@@ -744,14 +670,10 @@
             monitorSnippets.lower((MonitorEnterNode) n, tool);
         } else if (n instanceof MonitorExitNode) {
             monitorSnippets.lower((MonitorExitNode) n, tool);
-        } else if (n instanceof FieldWriteBarrier) {
-            writeBarrierSnippets.lower((FieldWriteBarrier) n, tool);
-        } else if (n instanceof ArrayWriteBarrier) {
-            writeBarrierSnippets.lower((ArrayWriteBarrier) n, tool);
-        } else if (n instanceof WriteBarrierPre) {
-            writeBarrierSnippets.lower((WriteBarrierPre) n, tool);
-        } else if (n instanceof WriteBarrierPost) {
-            writeBarrierSnippets.lower((WriteBarrierPost) n, tool);
+        } else if (n instanceof SerialWriteBarrier) {
+            writeBarrierSnippets.lower((SerialWriteBarrier) n, tool);
+        } else if (n instanceof SerialArrayRangeWriteBarrier) {
+            writeBarrierSnippets.lower((SerialArrayRangeWriteBarrier) n, tool);
         } else if (n instanceof TLABAllocateNode) {
             newObjectSnippets.lower((TLABAllocateNode) n, tool);
         } else if (n instanceof InitializeObjectNode) {
@@ -765,14 +687,60 @@
         } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) {
             // Nothing to do for division nodes. The HotSpot signal handler catches divisions by
             // zero and the MIN_VALUE / -1 cases.
-        } else if (n instanceof UnwindNode) {
+        } else if (n instanceof UnwindNode || n instanceof DeoptimizeNode) {
             // Nothing to do, using direct LIR lowering for these nodes.
+        } else if (n instanceof BoxNode) {
+            boxingSnippets.lower((BoxNode) n);
+        } else if (n instanceof UnboxNode) {
+            boxingSnippets.lower((UnboxNode) n);
         } else {
             assert false : "Node implementing Lowerable not handled: " + n;
             throw GraalInternalError.shouldNotReachHere();
         }
     }
 
+    private static WriteBarrierType getFieldStoreBarrier(StoreFieldNode storeField) {
+        WriteBarrierType barrierType = WriteBarrierType.NONE;
+        if (storeField.field().getKind() == Kind.Object && !storeField.value().objectStamp().alwaysNull()) {
+            barrierType = WriteBarrierType.IMPRECISE;
+        }
+        return barrierType;
+    }
+
+    private static WriteBarrierType getArrayStoreBarrier(StoreIndexedNode store) {
+        WriteBarrierType barrierType = WriteBarrierType.NONE;
+        if (store.elementKind() == Kind.Object && !store.value().objectStamp().alwaysNull()) {
+            barrierType = WriteBarrierType.PRECISE;
+        }
+        return barrierType;
+    }
+
+    private static WriteBarrierType getUnsafeStoreBarrier(UnsafeStoreNode store) {
+        WriteBarrierType barrierType = WriteBarrierType.NONE;
+        if (store.value().kind() == Kind.Object && !store.value().objectStamp().alwaysNull()) {
+            ResolvedJavaType type = store.object().objectStamp().type();
+            if ((type != null && type.isArray() && !MetaUtil.isJavaLangObject(type))) {
+                barrierType = WriteBarrierType.PRECISE;
+            } else {
+                barrierType = WriteBarrierType.IMPRECISE;
+            }
+        }
+        return barrierType;
+    }
+
+    private static WriteBarrierType getCompareAndSwapBarrier(CompareAndSwapNode cas) {
+        WriteBarrierType barrierType = WriteBarrierType.NONE;
+        if (cas.expected().kind() == Kind.Object && !cas.newValue().objectStamp().alwaysNull()) {
+            ResolvedJavaType type = cas.object().objectStamp().type();
+            if ((type != null && type.isArray() && !MetaUtil.isJavaLangObject(type))) {
+                barrierType = WriteBarrierType.PRECISE;
+            } else {
+                barrierType = WriteBarrierType.IMPRECISE;
+            }
+        }
+        return barrierType;
+    }
+
     private IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index) {
         int scale = this.graalRuntime.getTarget().sizeInBytes(elementKind);
         return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, getArrayBaseOffset(elementKind), index, graph, scale);
@@ -828,16 +796,21 @@
         return graalRuntime.getCompilerToVM().getJavaField(reflectionField);
     }
 
-    public HotSpotInstalledCode installMethod(HotSpotResolvedJavaMethod method, int entryBCI, CompilationResult compResult) {
-        HotSpotInstalledCode installedCode = new HotSpotInstalledCode(method, true);
+    public HotSpotInstalledCode installMethod(HotSpotResolvedJavaMethod method, Graph graph, int entryBCI, CompilationResult compResult) {
+        HotSpotInstalledCode installedCode = new HotSpotInstalledCode(method, graph, true);
         graalRuntime.getCompilerToVM().installCode(new HotSpotCompilationResult(method, entryBCI, compResult), installedCode, method.getSpeculationLog());
         return installedCode;
     }
 
     @Override
     public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) {
+        return addMethod(method, compResult, null);
+    }
+
+    @Override
+    public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, Graph graph) {
         HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method;
-        HotSpotInstalledCode code = new HotSpotInstalledCode(hotspotMethod, false);
+        HotSpotInstalledCode code = new HotSpotInstalledCode(hotspotMethod, graph, false);
         CodeInstallResult result = graalRuntime.getCompilerToVM().installCode(new HotSpotCompilationResult(hotspotMethod, -1, compResult), code, null);
         if (result != CodeInstallResult.OK) {
             return null;
@@ -956,7 +929,7 @@
 
     public String disassemble(InstalledCode code) {
         if (code.isValid()) {
-            long nmethod = ((HotSpotInstalledCode) code).nmethod;
+            long nmethod = ((HotSpotInstalledCode) code).getMethodAddress();
             return graalRuntime.getCompilerToVM().disassembleNMethod(nmethod);
         }
         return null;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotUnresolvedField.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotUnresolvedField.java	Mon Apr 15 08:49:14 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.meta;
 
+import static com.oracle.graal.api.meta.MetaUtil.*;
+
 import com.oracle.graal.api.meta.*;
 
 /**
@@ -60,6 +62,6 @@
      */
     @Override
     public String toString() {
-        return MetaUtil.format("%H.%n [unresolved]", this);
+        return format("HotSpotField<%H.%n %t, unresolved>", this);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayWriteBarrier.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * 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.graal.hotspot.nodes;
-
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-
-public final class ArrayWriteBarrier extends FixedWithNextNode implements Lowerable {
-
-    @Input private ValueNode object;
-    @Input private LocationNode location;
-
-    public ValueNode getObject() {
-        return object;
-    }
-
-    public LocationNode getLocation() {
-        return location;
-    }
-
-    public ArrayWriteBarrier(ValueNode object, LocationNode location) {
-        super(StampFactory.forVoid());
-        this.object = object;
-        this.location = location;
-    }
-
-    public void lower(LoweringTool generator) {
-        generator.getRuntime().lower(this, generator);
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -70,7 +70,6 @@
     @Override
     public void generate(LIRGenerator gen) {
         assert lockDepth != -1;
-        assert stateAfter() != null;
         HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen;
         StackSlot slot = hsGen.getLockSlot(lockDepth);
         if (!eliminated) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/FieldWriteBarrier.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * 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.graal.hotspot.nodes;
-
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-
-public final class FieldWriteBarrier extends FixedWithNextNode implements Lowerable {
-
-    @Input private ValueNode object;
-
-    public ValueNode getObject() {
-        return object;
-    }
-
-    public FieldWriteBarrier(ValueNode object) {
-        super(StampFactory.forVoid());
-        this.object = object;
-    }
-
-    public void lower(LoweringTool generator) {
-        generator.getRuntime().lower(this, generator);
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -24,22 +24,24 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.word.*;
+import com.oracle.graal.phases.common.*;
 
 public class HotSpotInstalledCodeExecuteNode extends AbstractCallNode implements Lowerable {
 
-    @Input private final ValueNode targetAddress;
-    @Input private final ValueNode metaspaceObject;
+    @Input private final ValueNode code;
     private final Class[] signature;
 
-    public HotSpotInstalledCodeExecuteNode(Kind kind, ValueNode targetAddress, ValueNode metaspaceObject, Class[] signature, ValueNode arg1, ValueNode arg2, ValueNode arg3) {
+    public HotSpotInstalledCodeExecuteNode(Kind kind, Class[] signature, ValueNode code, ValueNode arg1, ValueNode arg2, ValueNode arg3) {
         super(StampFactory.forKind(kind), new ValueNode[]{arg1, arg2, arg3});
-        this.targetAddress = targetAddress;
-        this.metaspaceObject = metaspaceObject;
+        this.code = code;
         this.signature = signature;
     }
 
@@ -50,30 +52,57 @@
 
     @Override
     public void lower(LoweringTool tool) {
-        replaceWithInvoke(tool);
+        if (code.isConstant() && code.asConstant().asObject() instanceof HotSpotInstalledCode) {
+            HotSpotInstalledCode hsCode = (HotSpotInstalledCode) code.asConstant().asObject();
+            InvokeNode invoke = replaceWithInvoke(tool.getRuntime());
+            StructuredGraph graph = (StructuredGraph) hsCode.getGraph();
+            if (graph != null) {
+                InliningUtil.inline(invoke, (StructuredGraph) hsCode.getGraph(), false);
+            }
+        } else {
+            replaceWithInvoke(tool.getRuntime());
+        }
     }
 
-    private InvokeNode replaceWithInvoke(LoweringTool tool) {
-        InvokeNode invoke = createInvoke(tool);
-        ((StructuredGraph) graph()).replaceFixedWithFixed(this, invoke);
-        return invoke;
-    }
-
-    protected InvokeNode createInvoke(LoweringTool tool) {
+    protected InvokeNode replaceWithInvoke(MetaAccessProvider tool) {
         ResolvedJavaMethod method = null;
+        ResolvedJavaField methodField = null;
+        ResolvedJavaField metaspaceMethodField = null;
+        ResolvedJavaField nmethodField = null;
         try {
-            method = tool.getRuntime().lookupJavaMethod(HotSpotInstalledCodeExecuteNode.class.getMethod("placeholder", Object.class, Object.class, Object.class));
-        } catch (NoSuchMethodException | SecurityException e) {
-            throw new IllegalStateException();
+            method = tool.lookupJavaMethod(HotSpotInstalledCodeExecuteNode.class.getMethod("placeholder", Object.class, Object.class, Object.class));
+            methodField = tool.lookupJavaField(HotSpotInstalledCode.class.getDeclaredField("method"));
+            nmethodField = tool.lookupJavaField(HotSpotInstalledCode.class.getDeclaredField("nmethod"));
+            metaspaceMethodField = tool.lookupJavaField(HotSpotResolvedJavaMethod.class.getDeclaredField("metaspaceMethod"));
+        } catch (NoSuchMethodException | SecurityException | NoSuchFieldException e) {
+            throw new IllegalStateException(e);
         }
         ResolvedJavaType[] signatureTypes = new ResolvedJavaType[signature.length];
         for (int i = 0; i < signature.length; i++) {
-            signatureTypes[i] = tool.getRuntime().lookupJavaType(signature[i]);
+            signatureTypes[i] = tool.lookupJavaType(signature[i]);
         }
-        HotSpotIndirectCallTargetNode callTarget = graph().add(
-                        new HotSpotIndirectCallTargetNode(metaspaceObject, targetAddress, arguments, stamp(), signatureTypes, method, CallingConvention.Type.JavaCall));
-        InvokeNode invoke = graph().add(new InvokeNode(callTarget, 0));
+        final int verifiedEntryPointOffset = HotSpotSnippetUtils.verifiedEntryPointOffset();
+
+        StructuredGraph g = (StructuredGraph) graph();
+
+        LoadFieldNode loadnmethod = g.add(new LoadFieldNode(code, nmethodField));
+        UnsafeLoadNode load = g.add(new UnsafeLoadNode(loadnmethod, verifiedEntryPointOffset, ConstantNode.forLong(0, graph()), HotSpotGraalRuntime.getInstance().getTarget().wordKind));
+
+        LoadFieldNode loadMethod = g.add(new LoadFieldNode(code, methodField));
+        LoadFieldNode loadmetaspaceMethod = g.add(new LoadFieldNode(loadMethod, metaspaceMethodField));
+
+        HotSpotIndirectCallTargetNode callTarget = g.add(new HotSpotIndirectCallTargetNode(loadmetaspaceMethod, load, arguments, stamp(), signatureTypes, method, CallingConvention.Type.JavaCall));
+
+        InvokeNode invoke = g.add(new InvokeNode(callTarget, 0));
+
         invoke.setStateAfter(stateAfter());
+        g.replaceFixedWithFixed(this, invoke);
+
+        g.addBeforeFixed(invoke, loadmetaspaceMethod);
+        g.addBeforeFixed(loadmetaspaceMethod, loadMethod);
+        g.addBeforeFixed(invoke, load);
+        g.addBeforeFixed(load, loadnmethod);
+
         return invoke;
     }
 
@@ -82,6 +111,6 @@
     }
 
     @NodeIntrinsic
-    public static native <T> T call(@ConstantNodeParameter Kind kind, Word targetAddress, long metaspaceObject, @ConstantNodeParameter Class[] signature, Object arg1, Object arg2, Object arg3);
+    public static native <T> T call(@ConstantNodeParameter Kind kind, @ConstantNodeParameter Class[] signature, Object code, Object arg1, Object arg2, Object arg3);
 
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.hotspot.nodes;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -75,7 +74,7 @@
     public boolean fillContents() {
         // We fill contents when G1 GC is used since we want to record
         // the original field values prior to stores
-        return HotSpotSnippetUtils.useG1GC() ? true : fillContents;
+        return fillContents;
     }
 
     public boolean locked() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeObjectNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeObjectNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.hotspot.nodes;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -57,7 +56,7 @@
     }
 
     public boolean fillContents() {
-        return HotSpotSnippetUtils.useG1GC() ? true : fillContents;
+        return fillContents;
     }
 
     public boolean locked() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013, 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.phases;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.*;
+
+public class WriteBarrierAdditionPhase extends Phase {
+
+    public WriteBarrierAdditionPhase() {
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (WriteNode node : graph.getNodes(WriteNode.class)) {
+            addWriteNodeBarriers(node, graph);
+        }
+        for (CompareAndSwapNode node : graph.getNodes(CompareAndSwapNode.class)) {
+            addCASBarriers(node, graph);
+        }
+        for (GenericArrayRangeWriteBarrier node : graph.getNodes(GenericArrayRangeWriteBarrier.class)) {
+            addArrayRangeBarriers(node, graph);
+        }
+    }
+
+    private static void addWriteNodeBarriers(WriteNode node, StructuredGraph graph) {
+        WriteBarrierType barrierType = node.getWriteBarrierType();
+        if (barrierType == WriteBarrierType.PRECISE) {
+            graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.location(), true)));
+        } else if (barrierType == WriteBarrierType.IMPRECISE) {
+            graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.location(), false)));
+        } else {
+            assert barrierType == WriteBarrierType.NONE;
+        }
+
+    }
+
+    private static void addCASBarriers(CompareAndSwapNode node, StructuredGraph graph) {
+        WriteBarrierType barrierType = node.getWriteBarrierType();
+        if (barrierType == WriteBarrierType.PRECISE) {
+            LocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, node.expected().kind(), node.displacement(), node.offset(), graph, 1);
+            graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), location, true)));
+        } else if (barrierType == WriteBarrierType.IMPRECISE) {
+            LocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, node.expected().kind(), node.displacement(), node.offset(), graph, 1);
+            graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), location, false)));
+        } else {
+            assert barrierType == WriteBarrierType.NONE;
+        }
+    }
+
+    private static void addArrayRangeBarriers(GenericArrayRangeWriteBarrier node, StructuredGraph graph) {
+        SerialArrayRangeWriteBarrier serialArrayRangeWriteBarrier = graph.add(new SerialArrayRangeWriteBarrier(node.getDstObject(), node.getDstPos(), node.getLength()));
+        graph.replaceFixedWithFixed(node, serialArrayRangeWriteBarrier);
+    }
+
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -31,6 +31,7 @@
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.replacements.nodes.*;
 
 public class ArrayCopyNode extends MacroNode implements Virtualizable, IterableNodeType, Lowerable {
@@ -81,9 +82,10 @@
         }
         // the canonicalization before loop unrolling is needed to propagate the length into
         // additions, etc.
-        new CanonicalizerPhase(tool.getRuntime(), tool.assumptions()).apply(snippetGraph);
-        new LoopFullUnrollPhase(tool.getRuntime(), tool.assumptions()).apply(snippetGraph);
-        new CanonicalizerPhase(tool.getRuntime(), tool.assumptions()).apply(snippetGraph);
+        HighTierContext context = new HighTierContext(tool.getRuntime(), tool.assumptions());
+        new CanonicalizerPhase().apply(snippetGraph, context);
+        new LoopFullUnrollPhase().apply(snippetGraph, context);
+        new CanonicalizerPhase().apply(snippetGraph, context);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Mon Apr 15 08:49:14 2013 +0200
@@ -37,7 +37,6 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
 
@@ -75,7 +74,7 @@
     private static final Kind VECTOR_KIND = Kind.Long;
     private static final long VECTOR_SIZE = arrayIndexScale(Kind.Long);
 
-    public static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter("baseKind") Kind baseKind) {
+    private static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind) {
         checkNonNull(src);
         checkNonNull(dest);
         checkLimits(src, srcPos, dest, destPos, length);
@@ -236,9 +235,14 @@
         }
     }
 
+    @Snippet
+    public static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) {
+        arrayObjectCopy(src, srcPos, dest, destPos, length);
+    }
+
     // Does NOT perform store checks
     @Snippet
-    public static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) {
+    public static void arrayObjectCopy(Object src, int srcPos, Object dest, int destPos, int length) {
         objectCounter.inc();
         checkNonNull(src);
         checkNonNull(dest);
@@ -260,15 +264,7 @@
             }
         }
         if (length > 0) {
-            int cardShift = cardTableShift();
-            long cardStart = cardTableStart();
-            long dstAddr = GetObjectAddressNode.get(dest);
-            long start = (dstAddr + header + (long) destPos * scale) >>> cardShift;
-            long end = (dstAddr + header + ((long) destPos + length - 1) * scale) >>> cardShift;
-            long count = end - start + 1;
-            while (count-- > 0) {
-                DirectStoreNode.store((start + cardStart) + count, false, Kind.Boolean);
-            }
+            GenericArrayRangeWriteBarrier.insertWriteBarrier(dest, destPos, length);
         }
     }
 
@@ -278,14 +274,22 @@
         // 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);
 
-        int layoutHelper = checkArrayType(srcHub);
         if (srcHub.equal(destHub) && src != dest) {
             probability(FAST_PATH_PROBABILITY);
 
             checkLimits(src, srcPos, dest, destPos, length);
-
-            arraycopyInnerloop(src, srcPos, dest, destPos, length, layoutHelper);
+            if (isObjectArray) {
+                genericObjectExactCallCounter.inc();
+                probability(FAST_PATH_PROBABILITY);
+                arrayObjectCopy(src, srcPos, dest, destPos, length);
+            } else {
+                genericPrimitiveCallCounter.inc();
+                arraycopyInnerloop(src, srcPos, dest, destPos, length, layoutHelper);
+            }
         } else {
             genericObjectCallCounter.inc();
             System.arraycopy(src, srcPos, dest, destPos, length);
@@ -317,25 +321,6 @@
             destOffset = destOffset.add(wordSize());
             srcOffset = srcOffset.add(wordSize());
         }
-
-        if ((layoutHelper & layoutHelperElementTypePrimitiveInPlace()) != 0) {
-            genericPrimitiveCallCounter.inc();
-
-        } else {
-            probability(LIKELY_PROBABILITY);
-            genericObjectExactCallCounter.inc();
-
-            if (length > 0) {
-                int cardShift = cardTableShift();
-                long cardStart = cardTableStart();
-                Word destCardOffset = destStart.unsignedShiftRight(cardShift).add(Word.unsigned(cardStart));
-                Word destCardEnd = destEnd.subtract(1).unsignedShiftRight(cardShift).add(Word.unsigned(cardStart));
-                while (destCardOffset.belowOrEqual(destCardEnd)) {
-                    DirectStoreNode.store(destCardOffset.rawValue(), false, Kind.Boolean);
-                    destCardOffset = destCardOffset.add(1);
-                }
-            }
-        }
     }
 
     private static final SnippetCounter.Group checkCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("System.arraycopy checkInputs") : null;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,64 @@
+/*
+ * 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 java.lang.invoke.*;
+
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.*;
+
+@ServiceProvider(ReplacementsProvider.class)
+public class CallSiteSubstitutions implements ReplacementsProvider {
+
+    @Override
+    public void registerReplacements(Replacements replacements) {
+        if (GraalOptions.IntrinsifyCallSiteTarget) {
+            replacements.registerSubstitutions(ConstantCallSiteSubstitutions.class);
+            replacements.registerSubstitutions(MutableCallSiteSubstitutions.class);
+            replacements.registerSubstitutions(VolatileCallSiteSubstitutions.class);
+        }
+    }
+
+    @ClassSubstitution(ConstantCallSite.class)
+    private static class ConstantCallSiteSubstitutions {
+
+        @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class)
+        public static native MethodHandle getTarget(ConstantCallSite callSite);
+    }
+
+    @ClassSubstitution(MutableCallSite.class)
+    private static class MutableCallSiteSubstitutions {
+
+        @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class)
+        public static native MethodHandle getTarget(MutableCallSite callSite);
+    }
+
+    @ClassSubstitution(VolatileCallSite.class)
+    private static class VolatileCallSiteSubstitutions {
+
+        @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class)
+        public static native MethodHandle getTarget(VolatileCallSite callSite);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,78 @@
+/*
+ * 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 java.lang.invoke.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.replacements.nodes.*;
+
+public class CallSiteTargetNode extends MacroNode implements Canonicalizable, Lowerable {
+
+    public CallSiteTargetNode(Invoke invoke) {
+        super(invoke);
+    }
+
+    private ValueNode getCallSite() {
+        return arguments.get(0);
+    }
+
+    private ConstantNode getConstantCallTarget(MetaAccessProvider metaAccessProvider, Assumptions assumptions) {
+        if (getCallSite().isConstant() && !getCallSite().isNullConstant()) {
+            CallSite callSite = (CallSite) getCallSite().asConstant().asObject();
+            if (callSite instanceof ConstantCallSite) {
+                return ConstantNode.forObject(callSite.getTarget(), metaAccessProvider, graph());
+            } else if (callSite instanceof MutableCallSite || callSite instanceof VolatileCallSite && assumptions != null && assumptions.useOptimisticAssumptions()) {
+                MethodHandle target = callSite.getTarget();
+                assumptions.record(new Assumptions.CallSiteTargetValue(callSite, target));
+                return ConstantNode.forObject(target, metaAccessProvider, graph());
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        ConstantNode target = getConstantCallTarget(tool.runtime(), tool.assumptions());
+        if (target != null) {
+            return target;
+        }
+
+        return this;
+    }
+
+    @Override
+    public void lower(LoweringTool tool) {
+        StructuredGraph graph = (StructuredGraph) graph();
+        ConstantNode target = getConstantCallTarget(tool.getRuntime(), tool.assumptions());
+
+        if (target != null) {
+            graph.replaceFixedWithFloating(this, target);
+        } else {
+            graph.replaceFixedWithFixed(this, createInvoke());
+        }
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java	Mon Apr 15 08:49:14 2013 +0200
@@ -28,11 +28,9 @@
 import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*;
 import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
-import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.meta.*;
@@ -42,7 +40,11 @@
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
+import com.oracle.graal.replacements.Snippet.ConstantParameter;
+import com.oracle.graal.replacements.Snippet.VarargsParameter;
+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.*;
 
@@ -58,16 +60,11 @@
     @NodeIntrinsic(BreakpointNode.class)
     static native void bkpt(Object object, Word hub, Word objectHub);
 
-    // @formatter:off
-
     /**
      * Type test used when the type being tested against is a final type.
      */
     @Snippet
-    public static Object checkcastExact(
-                    @Parameter("object") Object object,
-                    @Parameter("exactHub") Word exactHub,
-                    @ConstantParameter("checkNull") boolean checkNull) {
+    public static Object checkcastExact(Object object, Word exactHub, @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -76,30 +73,25 @@
             if (objectHub.notEqual(exactHub)) {
                 probability(DEOPT_PATH_PROBABILITY);
                 exactMiss.inc();
-                //bkpt(object, exactHub, objectHub);
                 DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException);
             }
             exactHit.inc();
         }
-        /* make sure that the unsafeCast is done *after* the check above,
-         * cf. ReadAfterCheckCast */
+        /*
+         * make sure that the unsafeCast is done *after* the check above, cf. ReadAfterCheckCast
+         */
         BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic());
         return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode);
     }
 
     /**
      * Type test used when the type being tested against is a restricted primary type.
-     *
-     * This test ignores use of hints altogether as the display-based type check only
-     * involves one extra load where the second load should hit the same cache line as the
-     * first.
+     * 
+     * This test ignores use of hints altogether as the display-based type check only involves one
+     * extra load where the second load should hit the same cache line as the first.
      */
     @Snippet
-    public static Object checkcastPrimary(
-                    @Parameter("hub") Word hub,
-                    @Parameter("object") Object object,
-                    @ConstantParameter("checkNull") boolean checkNull,
-                    @ConstantParameter("superCheckOffset") int superCheckOffset) {
+    public static Object checkcastPrimary(Word hub, Object object, @ConstantParameter int superCheckOffset, @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -120,11 +112,7 @@
      * Type test used when the type being tested against is a restricted secondary type.
      */
     @Snippet
-    public static Object checkcastSecondary(
-                    @Parameter("hub") Word hub,
-                    @Parameter("object") Object object,
-                    @VarargsParameter("hints") Word[] hints,
-                    @ConstantParameter("checkNull") boolean checkNull) {
+    public static Object checkcastSecondary(Word hub, Object object, @VarargsParameter Word[] hints, @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -149,14 +137,11 @@
     }
 
     /**
-     * Type test used when the type being tested against is not known at compile time (e.g. the type test
-     * in an object array store check).
+     * Type test used when the type being tested against is not known at compile time (e.g. the type
+     * test in an object array store check).
      */
     @Snippet
-    public static Object checkcastDynamic(
-                    @Parameter("hub") Word hub,
-                    @Parameter("object") Object object,
-                    @ConstantParameter("checkNull") boolean checkNull) {
+    public static Object checkcastDynamic(Word hub, Object object, @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -170,21 +155,15 @@
         return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode);
     }
 
-    // @formatter:on
-
-    public static class Templates extends AbstractTemplates<CheckCastSnippets> {
+    public static class Templates extends AbstractTemplates {
 
-        private final ResolvedJavaMethod exact;
-        private final ResolvedJavaMethod primary;
-        private final ResolvedJavaMethod secondary;
-        private final ResolvedJavaMethod dynamic;
+        private final SnippetInfo exact = snippet(CheckCastSnippets.class, "checkcastExact");
+        private final SnippetInfo primary = snippet(CheckCastSnippets.class, "checkcastPrimary");
+        private final SnippetInfo secondary = snippet(CheckCastSnippets.class, "checkcastSecondary");
+        private final SnippetInfo dynamic = snippet(CheckCastSnippets.class, "checkcastDynamic");
 
         public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) {
-            super(runtime, replacements, target, CheckCastSnippets.class);
-            exact = snippet("checkcastExact", Object.class, Word.class, boolean.class);
-            primary = snippet("checkcastPrimary", Word.class, Object.class, boolean.class, int.class);
-            secondary = snippet("checkcastSecondary", Word.class, Object.class, Word[].class, boolean.class);
-            dynamic = snippet("checkcastDynamic", Word.class, Object.class, boolean.class);
+            super(runtime, replacements, target);
         }
 
         /**
@@ -193,31 +172,34 @@
         public void lower(CheckCastNode checkcast, LoweringTool tool) {
             StructuredGraph graph = (StructuredGraph) checkcast.graph();
             ValueNode object = checkcast.object();
-            final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) checkcast.type();
+            HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) checkcast.type();
             TypeCheckHints hintInfo = new TypeCheckHints(checkcast.type(), checkcast.profile(), tool.assumptions(), GraalOptions.CheckcastMinHintHitProbability, GraalOptions.CheckcastMaxHints);
             ValueNode hub = ConstantNode.forConstant(type.klass(), runtime, checkcast.graph());
-            boolean checkNull = !object.stamp().nonNull();
-            Arguments arguments;
-            Key key;
 
-            assert type != null;
+            Arguments args;
             if (hintInfo.exact) {
-                ConstantNode[] hints = createHints(hintInfo, runtime, graph);
+                ConstantNode[] hints = createHints(hintInfo, runtime, true, graph).hubs;
                 assert hints.length == 1;
-                key = new Key(exact).add("checkNull", checkNull);
-                arguments = arguments("object", object).add("exactHub", hints[0]);
+                args = new Arguments(exact);
+                args.add("object", object);
+                args.add("exactHub", hints[0]);
             } else if (type.isPrimaryType()) {
-                key = new Key(primary).add("checkNull", checkNull).add("superCheckOffset", type.superCheckOffset());
-                arguments = arguments("hub", hub).add("object", object);
+                args = new Arguments(primary);
+                args.add("hub", hub);
+                args.add("object", object);
+                args.addConst("superCheckOffset", type.superCheckOffset());
             } else {
-                ConstantNode[] hints = createHints(hintInfo, runtime, graph);
-                key = new Key(secondary).add("hints", Varargs.vargargs(new Word[hints.length], StampFactory.forKind(wordKind()))).add("checkNull", checkNull);
-                arguments = arguments("hub", hub).add("object", object).add("hints", hints);
+                ConstantNode[] hints = createHints(hintInfo, runtime, true, graph).hubs;
+                args = new Arguments(secondary);
+                args.add("hub", hub);
+                args.add("object", object);
+                args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind()), hints);
             }
+            args.addConst("checkNull", !object.stamp().nonNull());
 
-            SnippetTemplate template = cache.get(key);
-            Debug.log("Lowering checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, arguments);
-            template.instantiate(runtime, checkcast, DEFAULT_REPLACER, arguments);
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, args);
+            template.instantiate(runtime, checkcast, DEFAULT_REPLACER, args);
         }
 
         /**
@@ -225,16 +207,16 @@
          */
         public void lower(CheckCastDynamicNode checkcast) {
             StructuredGraph graph = (StructuredGraph) checkcast.graph();
-            ValueNode hub = checkcast.type();
             ValueNode object = checkcast.object();
-            boolean checkNull = !object.stamp().nonNull();
 
-            Key key = new Key(dynamic).add("checkNull", checkNull);
-            Arguments arguments = arguments("hub", hub).add("object", object);
+            Arguments args = new Arguments(dynamic);
+            args.add("hub", checkcast.type());
+            args.add("object", object);
+            args.addConst("checkNull", !object.stamp().nonNull());
 
-            SnippetTemplate template = cache.get(key);
-            Debug.log("Lowering dynamic checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, arguments);
-            template.instantiate(runtime, checkcast, DEFAULT_REPLACER, arguments);
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering dynamic checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, args);
+            template.instantiate(runtime, checkcast, DEFAULT_REPLACER, args);
         }
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotInstalledCodeSubstitutions.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotInstalledCodeSubstitutions.java	Mon Apr 15 08:49:14 2013 +0200
@@ -27,20 +27,18 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.replacements.Snippet.Fold;
-import com.oracle.graal.word.*;
 
 @ClassSubstitution(HotSpotInstalledCode.class)
 public class HotSpotInstalledCodeSubstitutions {
 
-    @MethodSubstitution
-    public static Object executeHelper(long nmethod, long metaspaceMethod, final Object arg1, final Object arg2, final Object arg3) {
-        final int verifiedEntryPointOffset = HotSpotSnippetUtils.verifiedEntryPointOffset();
-        final Word callTarget = Word.unsigned(nmethod).readWord(verifiedEntryPointOffset);
-        return HotSpotInstalledCodeExecuteNode.call(Kind.Object, callTarget, metaspaceMethod, getSignature(), arg1, arg2, arg3);
+    @MethodSubstitution(isStatic = false)
+    public static Object execute(HotSpotInstalledCode code, final Object arg1, final Object arg2, final Object arg3) {
+        return HotSpotInstalledCodeExecuteNode.call(Kind.Object, getSignature(), code, arg1, arg2, arg3);
     }
 
     @Fold
     private static Class[] getSignature() {
         return new Class[]{Object.class, Object.class, Object.class};
     }
+
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Mon Apr 15 08:49:14 2013 +0200
@@ -24,20 +24,22 @@
 
 import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*;
 import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*;
-import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.Hints;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
-import com.oracle.graal.replacements.SnippetTemplate.*;
+import com.oracle.graal.replacements.Snippet.ConstantParameter;
+import com.oracle.graal.replacements.Snippet.VarargsParameter;
+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.*;
 
@@ -51,18 +53,11 @@
  */
 public class InstanceOfSnippets implements Snippets {
 
-    // @formatter:off
-
     /**
      * A test against a final type.
      */
     @Snippet
-    public static Object instanceofExact(
-                    @Parameter("object") Object object,
-                    @Parameter("exactHub") Word exactHub,
-                    @Parameter("trueValue") Object trueValue,
-                    @Parameter("falseValue") Object falseValue,
-                    @ConstantParameter("checkNull") boolean checkNull) {
+    public static Object instanceofExact(Object object, Word exactHub, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -82,13 +77,7 @@
      * A test against a primary type.
      */
     @Snippet
-    public static Object instanceofPrimary(
-                    @Parameter("hub") Word hub,
-                    @Parameter("object") Object object,
-                    @Parameter("trueValue") Object trueValue,
-                    @Parameter("falseValue") Object falseValue,
-                    @ConstantParameter("checkNull") boolean checkNull,
-                    @ConstantParameter("superCheckOffset") int superCheckOffset) {
+    public static Object instanceofPrimary(Word hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -108,13 +97,8 @@
      * A test against a restricted secondary type type.
      */
     @Snippet
-    public static Object instanceofSecondary(
-                    @Parameter("hub") Word hub,
-                    @Parameter("object") Object object,
-                    @Parameter("trueValue") Object trueValue,
-                    @Parameter("falseValue") Object falseValue,
-                    @VarargsParameter("hints") Word[] hints,
-                    @ConstantParameter("checkNull") boolean checkNull) {
+    public static Object instanceofSecondary(Word hub, Object object, @VarargsParameter Word[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue,
+                    @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -125,10 +109,11 @@
         ExplodeLoopNode.explodeLoop();
         for (int i = 0; i < hints.length; i++) {
             Word hintHub = hints[i];
+            boolean positive = hintIsPositive[i];
             if (hintHub.equal(objectHub)) {
                 probability(NOT_FREQUENT_PROBABILITY);
                 hintsHit.inc();
-                return trueValue;
+                return positive ? trueValue : falseValue;
             }
         }
         if (!checkSecondarySubType(hub, objectHub)) {
@@ -141,12 +126,7 @@
      * Type test used when the type being tested against is not known at compile time.
      */
     @Snippet
-    public static Object instanceofDynamic(
-                    @Parameter("mirror") Class mirror,
-                    @Parameter("object") Object object,
-                    @Parameter("trueValue") Object trueValue,
-                    @Parameter("falseValue") Object falseValue,
-                    @ConstantParameter("checkNull") boolean checkNull) {
+    public static Object instanceofDynamic(Class mirror, Object object, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) {
         if (checkNull && object == null) {
             probability(NOT_FREQUENT_PROBABILITY);
             isNull.inc();
@@ -161,61 +141,63 @@
         return trueValue;
     }
 
-    // @formatter:on
-
-    public static class Templates extends InstanceOfSnippetsTemplates<InstanceOfSnippets> {
+    public static class Templates extends InstanceOfSnippetsTemplates {
 
-        private final ResolvedJavaMethod instanceofExact;
-        private final ResolvedJavaMethod instanceofPrimary;
-        private final ResolvedJavaMethod instanceofSecondary;
-        private final ResolvedJavaMethod instanceofDynamic;
+        private final SnippetInfo instanceofExact = snippet(InstanceOfSnippets.class, "instanceofExact");
+        private final SnippetInfo instanceofPrimary = snippet(InstanceOfSnippets.class, "instanceofPrimary");
+        private final SnippetInfo instanceofSecondary = snippet(InstanceOfSnippets.class, "instanceofSecondary");
+        private final SnippetInfo instanceofDynamic = snippet(InstanceOfSnippets.class, "instanceofDynamic");
 
         public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) {
-            super(runtime, replacements, target, InstanceOfSnippets.class);
-            instanceofExact = snippet("instanceofExact", Object.class, Word.class, Object.class, Object.class, boolean.class);
-            instanceofPrimary = snippet("instanceofPrimary", Word.class, Object.class, Object.class, Object.class, boolean.class, int.class);
-            instanceofSecondary = snippet("instanceofSecondary", Word.class, Object.class, Object.class, Object.class, Word[].class, boolean.class);
-            instanceofDynamic = snippet("instanceofDynamic", Class.class, Object.class, Object.class, Object.class, boolean.class);
+            super(runtime, replacements, target);
         }
 
         @Override
-        protected KeyAndArguments getKeyAndArguments(InstanceOfUsageReplacer replacer, LoweringTool tool) {
+        protected Arguments makeArguments(InstanceOfUsageReplacer replacer, LoweringTool tool) {
             if (replacer.instanceOf instanceof InstanceOfNode) {
                 InstanceOfNode instanceOf = (InstanceOfNode) replacer.instanceOf;
-                ValueNode trueValue = replacer.trueValue;
-                ValueNode falseValue = replacer.falseValue;
                 ValueNode object = instanceOf.object();
                 TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), instanceOf.profile(), tool.assumptions(), GraalOptions.InstanceOfMinHintHitProbability, GraalOptions.InstanceOfMaxHints);
                 final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) instanceOf.type();
                 ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, instanceOf.graph());
-                boolean checkNull = !object.stamp().nonNull();
-                Arguments arguments;
-                Key key;
+
+                Arguments args;
                 if (hintInfo.exact) {
-                    ConstantNode[] hints = createHints(hintInfo, runtime, hub.graph());
+                    ConstantNode[] hints = createHints(hintInfo, runtime, true, hub.graph()).hubs;
                     assert hints.length == 1;
-                    key = new Key(instanceofExact).add("checkNull", checkNull);
-                    arguments = arguments("object", object).add("exactHub", hints[0]).add("trueValue", trueValue).add("falseValue", falseValue);
+                    args = new Arguments(instanceofExact);
+                    args.add("object", object);
+                    args.add("exactHub", hints[0]);
                 } else if (type.isPrimaryType()) {
-                    key = new Key(instanceofPrimary).add("checkNull", checkNull).add("superCheckOffset", type.superCheckOffset());
-                    arguments = arguments("hub", hub).add("object", object).add("trueValue", trueValue).add("falseValue", falseValue);
+                    args = new Arguments(instanceofPrimary);
+                    args.add("hub", hub);
+                    args.add("object", object);
+                    args.addConst("superCheckOffset", type.superCheckOffset());
                 } else {
-                    ConstantNode[] hints = createHints(hintInfo, runtime, hub.graph());
-                    key = new Key(instanceofSecondary).add("hints", Varargs.vargargs(new Word[hints.length], StampFactory.forKind(wordKind()))).add("checkNull", checkNull);
-                    arguments = arguments("hub", hub).add("object", object).add("hints", hints).add("trueValue", trueValue).add("falseValue", falseValue);
+                    Hints hints = createHints(hintInfo, runtime, false, hub.graph());
+                    args = new Arguments(instanceofSecondary);
+                    args.add("hub", hub);
+                    args.add("object", object);
+                    args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind()), hints.hubs);
+                    args.addVarargs("hintIsPositive", boolean.class, StampFactory.forKind(Kind.Boolean), hints.isPositive);
                 }
-                return new KeyAndArguments(key, arguments);
+                args.add("trueValue", replacer.trueValue);
+                args.add("falseValue", replacer.falseValue);
+                args.addConst("checkNull", !object.stamp().nonNull());
+                return args;
+
             } else {
                 assert replacer.instanceOf instanceof InstanceOfDynamicNode;
                 InstanceOfDynamicNode instanceOf = (InstanceOfDynamicNode) replacer.instanceOf;
-                ValueNode trueValue = replacer.trueValue;
-                ValueNode falseValue = replacer.falseValue;
                 ValueNode object = instanceOf.object();
-                ValueNode mirror = instanceOf.mirror();
-                boolean checkNull = !object.stamp().nonNull();
-                Key key = new Key(instanceofDynamic).add("checkNull", checkNull);
-                Arguments arguments = arguments("mirror", mirror).add("object", object).add("trueValue", trueValue).add("falseValue", falseValue);
-                return new KeyAndArguments(key, arguments);
+
+                Arguments args = new Arguments(instanceofDynamic);
+                args.add("mirror", instanceOf.mirror());
+                args.add("object", object);
+                args.add("trueValue", replacer.trueValue);
+                args.add("falseValue", replacer.falseValue);
+                args.addConst("checkNull", !object.stamp().nonNull());
+                return args;
             }
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java	Mon Apr 15 08:49:14 2013 +0200
@@ -27,16 +27,13 @@
 import static com.oracle.graal.replacements.SnippetTemplate.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 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.Key;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
 import com.oracle.graal.word.*;
 
 /**
@@ -53,23 +50,17 @@
         return unsafeCast(exception, StampFactory.forNodeIntrinsic());
     }
 
-    public static class Templates extends AbstractTemplates<LoadExceptionObjectSnippets> {
+    public static class Templates extends AbstractTemplates {
 
-        private final ResolvedJavaMethod loadException;
+        private final SnippetInfo loadException = snippet(LoadExceptionObjectSnippets.class, "loadException");
 
         public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) {
-            super(runtime, replacements, target, LoadExceptionObjectSnippets.class);
-            loadException = snippet("loadException");
+            super(runtime, replacements, target);
         }
 
         public void lower(LoadExceptionObjectNode loadExceptionObject) {
-            StructuredGraph graph = (StructuredGraph) loadExceptionObject.graph();
-            Arguments arguments = new Arguments();
-
-            Key key = new Key(loadException);
-            SnippetTemplate template = cache.get(key);
-            Debug.log("Lowering exception object in %s: node=%s, template=%s, arguments=%s", graph, loadExceptionObject, template, arguments);
-            template.instantiate(runtime, loadExceptionObject, DEFAULT_REPLACER, arguments);
+            Arguments args = new Arguments(loadException);
+            template(args).instantiate(runtime, loadExceptionObject, DEFAULT_REPLACER, args);
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleInvokeBasicNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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 java.lang.invoke.*;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.nodes.*;
+
+/**
+ * Macro node for {@link MethodHandle}{@code .invokeBasic(Object...)}.
+ */
+public class MethodHandleInvokeBasicNode extends MacroNode {
+
+    public MethodHandleInvokeBasicNode(Invoke invoke) {
+        super(invoke);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToInterfaceNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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 java.lang.invoke.*;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.nodes.*;
+
+/**
+ * Macro node for {@link MethodHandle}{@code .linkToInterface(Object...)}.
+ */
+public class MethodHandleLinkToInterfaceNode extends MacroNode {
+
+    public MethodHandleLinkToInterfaceNode(Invoke invoke) {
+        super(invoke);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToSpecialNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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 java.lang.invoke.*;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.nodes.*;
+
+/**
+ * Macro node for {@link MethodHandle}{@code .linkToSpecial(Object...)}.
+ */
+public class MethodHandleLinkToSpecialNode extends MacroNode {
+
+    public MethodHandleLinkToSpecialNode(Invoke invoke) {
+        super(invoke);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToStaticNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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 java.lang.invoke.*;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.nodes.*;
+
+/**
+ * Macro node for {@link MethodHandle}{@code .linkToStatic(Object...)}.
+ */
+public class MethodHandleLinkToStaticNode extends MacroNode {
+
+    public MethodHandleLinkToStaticNode(Invoke invoke) {
+        super(invoke);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToVirtualNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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 java.lang.invoke.*;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.nodes.*;
+
+/**
+ * Macro node for {@link MethodHandle}{@code .linkToVirtual(Object...)}.
+ */
+public class MethodHandleLinkToVirtualNode extends MacroNode {
+
+    public MethodHandleLinkToVirtualNode(Invoke invoke) {
+        super(invoke);
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Mon Apr 15 08:49:14 2013 +0200
@@ -46,7 +46,10 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
+import com.oracle.graal.replacements.Snippet.ConstantParameter;
+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.word.*;
 
 /**
@@ -73,7 +76,7 @@
     public static final boolean CHECK_BALANCED_MONITORS = Boolean.getBoolean("graal.monitors.checkBalanced");
 
     @Snippet
-    public static void monitorenter(@Parameter("object") Object object, @ConstantParameter("checkNull") boolean checkNull, @ConstantParameter("trace") boolean trace) {
+    public static void monitorenter(Object object, @ConstantParameter boolean checkNull, @ConstantParameter boolean trace) {
         verifyOop(object);
 
         if (checkNull && object == null) {
@@ -262,7 +265,7 @@
      * Calls straight out to the monitorenter stub.
      */
     @Snippet
-    public static void monitorenterStub(@Parameter("object") Object object, @ConstantParameter("checkNull") boolean checkNull, @ConstantParameter("trace") boolean trace) {
+    public static void monitorenterStub(Object object, @ConstantParameter boolean checkNull, @ConstantParameter boolean trace) {
         verifyOop(object);
         incCounter();
         if (checkNull && object == null) {
@@ -276,7 +279,7 @@
     }
 
     @Snippet
-    public static void monitorexit(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) {
+    public static void monitorexit(Object object, @ConstantParameter boolean trace) {
         trace(trace, "           object: 0x%016lx\n", Word.fromObject(object));
         if (useBiasedLocking()) {
             // Check for biased locking unlock case, which is a no-op
@@ -328,7 +331,7 @@
      * Calls straight out to the monitorexit stub.
      */
     @Snippet
-    public static void monitorexitStub(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) {
+    public static void monitorexitStub(Object object, @ConstantParameter boolean trace) {
         verifyOop(object);
         traceObject(trace, "-lock{stub}", object);
         MonitorExitStubCall.call(object);
@@ -398,54 +401,45 @@
         }
     }
 
-    public static class Templates extends AbstractTemplates<MonitorSnippets> {
+    public static class Templates extends AbstractTemplates {
 
-        private final ResolvedJavaMethod monitorenter;
-        private final ResolvedJavaMethod monitorexit;
-        private final ResolvedJavaMethod monitorenterStub;
-        private final ResolvedJavaMethod monitorexitStub;
-        private final ResolvedJavaMethod monitorenterEliminated;
-        private final ResolvedJavaMethod monitorexitEliminated;
-        private final ResolvedJavaMethod initCounter;
-        private final ResolvedJavaMethod checkCounter;
+        private final SnippetInfo monitorenter = snippet(MonitorSnippets.class, "monitorenter");
+        private final SnippetInfo monitorexit = snippet(MonitorSnippets.class, "monitorexit");
+        private final SnippetInfo monitorenterStub = snippet(MonitorSnippets.class, "monitorenterStub");
+        private final SnippetInfo monitorexitStub = snippet(MonitorSnippets.class, "monitorexitStub");
+        private final SnippetInfo monitorenterEliminated = snippet(MonitorSnippets.class, "monitorenterEliminated");
+        private final SnippetInfo monitorexitEliminated = snippet(MonitorSnippets.class, "monitorexitEliminated");
+        private final SnippetInfo initCounter = snippet(MonitorSnippets.class, "initCounter");
+        private final SnippetInfo checkCounter = snippet(MonitorSnippets.class, "checkCounter");
+
         private final boolean useFastLocking;
 
         public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target, boolean useFastLocking) {
-            super(runtime, replacements, target, MonitorSnippets.class);
-            monitorenter = snippet("monitorenter", Object.class, boolean.class, boolean.class);
-            monitorexit = snippet("monitorexit", Object.class, boolean.class);
-            monitorenterStub = snippet("monitorenterStub", Object.class, boolean.class, boolean.class);
-            monitorexitStub = snippet("monitorexitStub", Object.class, boolean.class);
-            monitorenterEliminated = snippet("monitorenterEliminated");
-            monitorexitEliminated = snippet("monitorexitEliminated");
-            initCounter = snippet("initCounter");
-            checkCounter = snippet("checkCounter", String.class);
+            super(runtime, replacements, target);
             this.useFastLocking = useFastLocking;
         }
 
         public void lower(MonitorEnterNode monitorenterNode, @SuppressWarnings("unused") LoweringTool tool) {
             StructuredGraph graph = (StructuredGraph) monitorenterNode.graph();
-
             checkBalancedMonitors(graph);
-
             FrameState stateAfter = monitorenterNode.stateAfter();
-            boolean eliminated = monitorenterNode.eliminated();
-            ResolvedJavaMethod method = eliminated ? monitorenterEliminated : useFastLocking ? monitorenter : monitorenterStub;
-            boolean checkNull = !monitorenterNode.object().stamp().nonNull();
-            Key key = new Key(method);
-            if (method != monitorenterEliminated) {
-                key.add("checkNull", checkNull);
-            }
-            if (!eliminated) {
-                key.add("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method()));
+
+            Arguments args;
+            if (monitorenterNode.eliminated()) {
+                args = new Arguments(monitorenterEliminated);
+            } else {
+                if (useFastLocking) {
+                    args = new Arguments(monitorenter);
+                } else {
+                    args = new Arguments(monitorenterStub);
+                }
+                args.add("object", monitorenterNode.object());
+                args.addConst("checkNull", !monitorenterNode.object().stamp().nonNull());
+                args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method()));
             }
 
-            Arguments arguments = new Arguments();
-            if (!eliminated) {
-                arguments.add("object", monitorenterNode.object());
-            }
-            SnippetTemplate template = cache.get(key);
-            Map<Node, Node> nodes = template.instantiate(runtime, monitorenterNode, DEFAULT_REPLACER, arguments);
+            Map<Node, Node> nodes = template(args).instantiate(runtime, monitorenterNode, DEFAULT_REPLACER, args);
+
             for (Node n : nodes.values()) {
                 if (n instanceof BeginLockScopeNode) {
                     BeginLockScopeNode begin = (BeginLockScopeNode) n;
@@ -460,18 +454,22 @@
         public void lower(MonitorExitNode monitorexitNode, @SuppressWarnings("unused") LoweringTool tool) {
             StructuredGraph graph = (StructuredGraph) monitorexitNode.graph();
             FrameState stateAfter = monitorexitNode.stateAfter();
-            boolean eliminated = monitorexitNode.eliminated();
-            ResolvedJavaMethod method = eliminated ? monitorexitEliminated : useFastLocking ? monitorexit : monitorexitStub;
-            Key key = new Key(method);
-            if (!eliminated) {
-                key.add("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method()));
+
+            Arguments args;
+            if (monitorexitNode.eliminated()) {
+                args = new Arguments(monitorexitEliminated);
+            } else {
+                if (useFastLocking) {
+                    args = new Arguments(monitorexit);
+                } else {
+                    args = new Arguments(monitorexitStub);
+                }
+                args.add("object", monitorexitNode.object());
+                args.addConst("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method()));
             }
-            Arguments arguments = new Arguments();
-            if (!eliminated) {
-                arguments.add("object", monitorexitNode.object());
-            }
-            SnippetTemplate template = cache.get(key);
-            Map<Node, Node> nodes = template.instantiate(runtime, monitorexitNode, DEFAULT_REPLACER, arguments);
+
+            Map<Node, Node> nodes = template(args).instantiate(runtime, monitorexitNode, DEFAULT_REPLACER, args);
+
             for (Node n : nodes.values()) {
                 if (n instanceof EndLockScopeNode) {
                     EndLockScopeNode end = (EndLockScopeNode) n;
@@ -521,27 +519,27 @@
                 NodeIterable<MonitorCounterNode> nodes = graph.getNodes().filter(MonitorCounterNode.class);
                 if (nodes.isEmpty()) {
                     // Only insert the nodes if this is the first monitorenter being lowered.
-                    JavaType returnType = initCounter.getSignature().getReturnType(initCounter.getDeclaringClass());
-                    MethodCallTargetNode callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, initCounter, new ValueNode[0], returnType));
+                    JavaType returnType = initCounter.getMethod().getSignature().getReturnType(initCounter.getMethod().getDeclaringClass());
+                    MethodCallTargetNode callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, initCounter.getMethod(), new ValueNode[0], returnType));
                     InvokeNode invoke = graph.add(new InvokeNode(callTarget, 0));
                     invoke.setStateAfter(graph.start().stateAfter());
                     graph.addAfterFixed(graph.start(), invoke);
 
-                    StructuredGraph inlineeGraph = replacements.getSnippet(initCounter);
+                    StructuredGraph inlineeGraph = replacements.getSnippet(initCounter.getMethod());
                     InliningUtil.inline(invoke, inlineeGraph, false);
 
                     List<ReturnNode> rets = graph.getNodes().filter(ReturnNode.class).snapshot();
                     for (ReturnNode ret : rets) {
-                        returnType = checkCounter.getSignature().getReturnType(checkCounter.getDeclaringClass());
+                        returnType = checkCounter.getMethod().getSignature().getReturnType(checkCounter.getMethod().getDeclaringClass());
                         Object msg = ((HotSpotRuntime) runtime).registerGCRoot("unbalanced monitors in " + MetaUtil.format("%H.%n(%p)", graph.method()) + ", count = %d");
                         ConstantNode errMsg = ConstantNode.forObject(msg, runtime, graph);
-                        callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter, new ValueNode[]{errMsg}, returnType));
+                        callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter.getMethod(), new ValueNode[]{errMsg}, returnType));
                         invoke = graph.add(new InvokeNode(callTarget, 0));
                         List<ValueNode> stack = Collections.emptyList();
                         FrameState stateAfter = new FrameState(graph.method(), FrameState.AFTER_BCI, new ValueNode[0], stack, new ValueNode[0], false, false);
                         invoke.setStateAfter(graph.add(stateAfter));
                         graph.addBeforeFixed(ret, invoke);
-                        inlineeGraph = replacements.getSnippet(checkCounter);
+                        inlineeGraph = replacements.getSnippet(checkCounter.getMethod());
                         InliningUtil.inline(invoke, inlineeGraph, false);
                     }
                 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Mon Apr 15 08:49:14 2013 +0200
@@ -26,9 +26,7 @@
 import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*;
 import static com.oracle.graal.nodes.extended.UnsafeArrayCastNode.*;
 import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
-import static com.oracle.graal.replacements.Snippet.Varargs.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
-import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 import static com.oracle.graal.replacements.nodes.ExplodeLoopNode.*;
 
@@ -43,7 +41,11 @@
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
+import com.oracle.graal.replacements.Snippet.ConstantParameter;
+import com.oracle.graal.replacements.Snippet.VarargsParameter;
+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.*;
 
@@ -52,15 +54,16 @@
  */
 public class NewObjectSnippets implements Snippets {
 
-    // @formatter:off
-
     @Snippet
-    public static Word allocate(@Parameter("size") int size) {
+    public static Word allocate(int size) {
         Word thread = thread();
         Word top = readTlabTop(thread);
         Word end = readTlabEnd(thread);
         Word newTop = top.add(size);
-        // this check might lead to problems if the TLAB is within 16GB of the address space end (checked in c++ code)
+        /*
+         * this check might lead to problems if the TLAB is within 16GB of the address space end
+         * (checked in c++ code)
+         */
         if (newTop.belowOrEqual(end)) {
             probability(FAST_PATH_PROBABILITY);
             writeTlabTop(thread, newTop);
@@ -70,13 +73,7 @@
     }
 
     @Snippet
-    public static Object initializeObject(
-                    @Parameter("memory") Word memory,
-                    @Parameter("hub") Word hub,
-                    @Parameter("prototypeMarkWord") Word prototypeMarkWord,
-                    @ConstantParameter("size") int size,
-                    @ConstantParameter("fillContents") boolean fillContents,
-                    @ConstantParameter("locked") boolean locked) {
+    public static Object initializeObject(Word memory, Word hub, Word prototypeMarkWord, @ConstantParameter int size, @ConstantParameter boolean fillContents, @ConstantParameter boolean locked) {
 
         Object result;
         if (memory.equal(0)) {
@@ -91,19 +88,17 @@
             }
             result = memory.toObject();
         }
-        return unsafeCast(verifyOop(result), StampFactory.forNodeIntrinsic());
+        /*
+         * make sure that the unsafeCast is anchored after initialization, see ReadAfterCheckCast
+         * and CheckCastSnippets
+         */
+        BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic());
+        return unsafeCast(verifyOop(result), StampFactory.forNodeIntrinsic(), anchorNode);
     }
 
     @Snippet
-    public static Object initializeArray(
-                    @Parameter("memory") Word memory,
-                    @Parameter("hub") Word hub,
-                    @Parameter("length") int length,
-                    @Parameter("allocationSize") int allocationSize,
-                    @Parameter("prototypeMarkWord") Word prototypeMarkWord,
-                    @ConstantParameter("headerSize") int headerSize,
-                    @ConstantParameter("fillContents") boolean fillContents,
-                    @ConstantParameter("locked") boolean locked) {
+    public static Object initializeArray(Word memory, Word hub, int length, int allocationSize, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter boolean fillContents,
+                    @ConstantParameter boolean locked) {
         if (locked) {
             return initializeArray(memory, hub, length, allocationSize, thread().or(biasedLockPattern()), headerSize, fillContents);
         } else {
@@ -122,7 +117,8 @@
             formatArray(hub, allocationSize, length, headerSize, memory, prototypeMarkWord, fillContents);
             result = memory.toObject();
         }
-        return unsafeArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic());
+        BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic());
+        return unsafeArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic(), anchorNode);
     }
 
     /**
@@ -131,13 +127,8 @@
     public static final int MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH = 0x00FFFFFF;
 
     @Snippet
-    public static Object allocateArrayAndInitialize(
-                    @Parameter("length") int length,
-                    @ConstantParameter("alignment") int alignment,
-                    @ConstantParameter("headerSize") int headerSize,
-                    @ConstantParameter("log2ElementSize") int log2ElementSize,
-                    @ConstantParameter("fillContents") boolean fillContents,
-                    @ConstantParameter("type") ResolvedJavaType type) {
+    public static Object allocateArrayAndInitialize(int length, @ConstantParameter int alignment, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize,
+                    @ConstantParameter boolean fillContents, @ConstantParameter ResolvedJavaType type) {
         if (!belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) {
             probability(DEOPT_PATH_PROBABILITY);
             // This handles both negative array sizes and very large array sizes
@@ -149,9 +140,10 @@
     }
 
     /**
-     * Computes the size of the memory chunk allocated for an array. This size accounts for the array
-     * header size, boy size and any padding after the last element to satisfy object alignment requirements.
-     *
+     * Computes the size of the memory chunk allocated for an array. This size accounts for the
+     * array header size, boy size and any padding after the last element to satisfy object
+     * alignment requirements.
+     * 
      * @param length the number of elements in the array
      * @param alignment the object alignment requirement
      * @param headerSize the size of the array header
@@ -167,10 +159,7 @@
      * Calls the runtime stub for implementing MULTIANEWARRAY.
      */
     @Snippet
-    public static Object newmultiarray(
-                    @Parameter("hub") Word hub,
-                    @ConstantParameter("rank") int rank,
-                    @VarargsParameter("dimensions") int[] dimensions) {
+    public static Object newmultiarray(Word hub, @ConstantParameter int rank, @VarargsParameter int[] dimensions) {
         Word dims = DimensionsNode.allocaDimsArray(rank);
         ExplodeLoopNode.explodeLoop();
         for (int i = 0; i < rank; i++) {
@@ -180,9 +169,8 @@
     }
 
     /**
-     * Maximum size of an object whose body is initialized by a sequence of
-     * zero-stores to its fields. Larger objects have their bodies initialized
-     * in a loop.
+     * Maximum size of an object whose body is initialized by a sequence of zero-stores to its
+     * fields. Larger objects have their bodies initialized in a loop.
      */
     private static final int MAX_UNROLLED_OBJECT_ZEROING_SIZE = 10 * wordSize();
 
@@ -213,7 +201,10 @@
      */
     public static void formatArray(Word hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents) {
         memory.writeInt(arrayLengthOffset(), length, ANY_LOCATION);
-        // store hub last as the concurrent garbage collectors assume length is valid if hub field is not null
+        /*
+         * store hub last as the concurrent garbage collectors assume length is valid if hub field
+         * is not null
+         */
         initializeObjectHeader(memory, prototypeMarkWord, hub);
         if (fillContents) {
             for (int offset = headerSize; offset < allocationSize; offset += wordSize()) {
@@ -222,27 +213,19 @@
         }
     }
 
-    // @formatter:on
-
-    public static class Templates extends AbstractTemplates<NewObjectSnippets> {
+    public static class Templates extends AbstractTemplates {
 
-        private final ResolvedJavaMethod allocate;
-        private final ResolvedJavaMethod initializeObject;
-        private final ResolvedJavaMethod initializeArray;
-        private final ResolvedJavaMethod allocateArrayAndInitialize;
-        private final ResolvedJavaMethod newmultiarray;
-        private final TargetDescription target;
+        private final SnippetInfo allocate = snippet(NewObjectSnippets.class, "allocate");
+        private final SnippetInfo initializeObject = snippet(NewObjectSnippets.class, "initializeObject");
+        private final SnippetInfo initializeArray = snippet(NewObjectSnippets.class, "initializeArray");
+        private final SnippetInfo allocateArrayAndInitialize = snippet(NewObjectSnippets.class, "allocateArrayAndInitialize");
+        private final SnippetInfo newmultiarray = snippet(NewObjectSnippets.class, "newmultiarray");
+
         private final boolean useTLAB;
 
         public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target, boolean useTLAB) {
-            super(runtime, replacements, target, NewObjectSnippets.class);
-            this.target = target;
+            super(runtime, replacements, target);
             this.useTLAB = useTLAB;
-            allocate = snippet("allocate", int.class);
-            initializeObject = snippet("initializeObject", Word.class, Word.class, Word.class, int.class, boolean.class, boolean.class);
-            initializeArray = snippet("initializeArray", Word.class, Word.class, int.class, int.class, Word.class, int.class, boolean.class, boolean.class);
-            allocateArrayAndInitialize = snippet("allocateArrayAndInitialize", int.class, int.class, int.class, int.class, boolean.class, ResolvedJavaType.class);
-            newmultiarray = snippet("newmultiarray", Word.class, int.class, int[].class);
         }
 
         /**
@@ -285,9 +268,10 @@
             int log2ElementSize = CodeUtil.log2(target.sizeInBytes(elementKind));
             if (!useTLAB) {
                 ConstantNode zero = ConstantNode.defaultForKind(target.wordKind, graph);
-                // value for 'size' doesn't matter as it isn't used since a stub call will be made
-                // anyway
-                // for both allocation and initialization - it just needs to be non-null
+                /*
+                 * value for 'size' doesn't matter as it isn't used since a stub call will be made
+                 * anyway for both allocation and initialization - it just needs to be non-null
+                 */
                 ConstantNode size = ConstantNode.forInt(-1, graph);
                 InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(zero, lengthNode, size, arrayType, newArrayNode.fillContents(), newArrayNode.locked()));
                 graph.replaceFixedWithFixed(newArrayNode, initializeNode);
@@ -300,12 +284,17 @@
                 InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(tlabAllocateNode, lengthNode, sizeNode, arrayType, newArrayNode.fillContents(), newArrayNode.locked()));
                 graph.replaceFixedWithFixed(newArrayNode, initializeNode);
             } else {
-                Key key = new Key(allocateArrayAndInitialize).add("alignment", alignment).add("headerSize", headerSize).add("log2ElementSize", log2ElementSize).add("fillContents",
-                                newArrayNode.fillContents()).add("type", arrayType);
-                Arguments arguments = new Arguments().add("length", lengthNode);
-                SnippetTemplate template = cache.get(key);
-                Debug.log("Lowering allocateArrayAndInitialize in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, arguments);
-                template.instantiate(runtime, newArrayNode, DEFAULT_REPLACER, arguments);
+                Arguments args = new Arguments(allocateArrayAndInitialize);
+                args.add("length", lengthNode);
+                args.addConst("alignment", alignment);
+                args.addConst("headerSize", headerSize);
+                args.addConst("log2ElementSize", log2ElementSize);
+                args.addConst("fillContents", newArrayNode.fillContents());
+                args.addConst("type", arrayType);
+
+                SnippetTemplate template = template(args);
+                Debug.log("Lowering allocateArrayAndInitialize in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args);
+                template.instantiate(runtime, newArrayNode, DEFAULT_REPLACER, args);
             }
         }
 
@@ -313,11 +302,11 @@
         public void lower(TLABAllocateNode tlabAllocateNode, LoweringTool tool) {
             StructuredGraph graph = (StructuredGraph) tlabAllocateNode.graph();
             ValueNode size = tlabAllocateNode.size();
-            Key key = new Key(allocate);
-            Arguments arguments = arguments("size", size);
-            SnippetTemplate template = cache.get(key);
-            Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, arguments);
-            template.instantiate(runtime, tlabAllocateNode, DEFAULT_REPLACER, arguments);
+            Arguments args = new Arguments(allocate).add("size", size);
+
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, args);
+            template.instantiate(runtime, tlabAllocateNode, DEFAULT_REPLACER, args);
         }
 
         @SuppressWarnings("unused")
@@ -327,12 +316,18 @@
             assert !type.isArray();
             ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph);
             int size = instanceSize(type);
-            Key key = new Key(initializeObject).add("size", size).add("fillContents", initializeNode.fillContents()).add("locked", initializeNode.locked());
             ValueNode memory = initializeNode.memory();
-            Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeMarkWord", type.prototypeMarkWord());
-            SnippetTemplate template = cache.get(key);
-            Debug.log("Lowering initializeObject in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments);
-            template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, arguments);
+
+            Arguments args = new Arguments(initializeObject);
+            args.add("memory", memory);
+            args.add("hub", hub);
+            args.add("prototypeMarkWord", type.prototypeMarkWord());
+            args.addConst("size", size).addConst("fillContents", initializeNode.fillContents());
+            args.addConst("locked", initializeNode.locked());
+
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering initializeObject in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, args);
+            template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, args);
         }
 
         @SuppressWarnings("unused")
@@ -344,13 +339,21 @@
             ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph);
             Kind elementKind = elementType.getKind();
             final int headerSize = HotSpotRuntime.getArrayBaseOffset(elementKind);
-            Key key = new Key(initializeArray).add("headerSize", headerSize).add("fillContents", initializeNode.fillContents()).add("locked", initializeNode.locked());
             ValueNode memory = initializeNode.memory();
-            Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeMarkWord", type.prototypeMarkWord()).add("allocationSize", initializeNode.allocationSize()).add("length",
-                            initializeNode.length());
-            SnippetTemplate template = cache.get(key);
-            Debug.log("Lowering initializeArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments);
-            template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, arguments);
+
+            Arguments args = new Arguments(initializeArray);
+            args.add("memory", memory);
+            args.add("hub", hub);
+            args.add("length", initializeNode.length());
+            args.add("allocationSize", initializeNode.allocationSize());
+            args.add("prototypeMarkWord", type.prototypeMarkWord());
+            args.addConst("headerSize", headerSize);
+            args.addConst("fillContents", initializeNode.fillContents());
+            args.addConst("locked", initializeNode.locked());
+
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering initializeArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, args);
+            template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, args);
         }
 
         @SuppressWarnings("unused")
@@ -363,10 +366,12 @@
             }
             HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) newmultiarrayNode.type();
             ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph);
-            Key key = new Key(newmultiarray).add("dimensions", vargargs(new int[rank], StampFactory.forKind(Kind.Int))).add("rank", rank);
-            Arguments arguments = arguments("dimensions", dims).add("hub", hub);
-            SnippetTemplate template = cache.get(key);
-            template.instantiate(runtime, newmultiarrayNode, DEFAULT_REPLACER, arguments);
+
+            Arguments args = new Arguments(newmultiarray);
+            args.add("hub", hub);
+            args.addConst("rank", rank);
+            args.addVarargs("dimensions", int.class, StampFactory.forKind(Kind.Int), dims);
+            template(args).instantiate(runtime, newmultiarrayNode, DEFAULT_REPLACER, args);
         }
 
         private static int instanceSize(HotSpotResolvedObjectType type) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Mon Apr 15 08:49:14 2013 +0200
@@ -25,6 +25,8 @@
 import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
+import java.util.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
@@ -98,12 +100,45 @@
         return false;
     }
 
-    static ConstantNode[] createHints(TypeCheckHints hints, MetaAccessProvider runtime, Graph graph) {
-        ConstantNode[] hintHubs = new ConstantNode[hints.types.length];
-        for (int i = 0; i < hintHubs.length; i++) {
-            hintHubs[i] = ConstantNode.forConstant(((HotSpotResolvedObjectType) hints.types[i]).klass(), runtime, graph);
+    /**
+     * A set of type check hints ordered by decreasing probabilities.
+     */
+    public static class Hints {
+
+        /**
+         * The hubs of the hint types.
+         */
+        public final ConstantNode[] hubs;
+
+        /**
+         * A predicate over {@link #hubs} specifying whether the corresponding hint type is a
+         * sub-type of the checked type.
+         */
+        public final boolean[] isPositive;
+
+        Hints(ConstantNode[] hints, boolean[] hintIsPositive) {
+            this.hubs = hints;
+            this.isPositive = hintIsPositive;
         }
-        return hintHubs;
+    }
+
+    static Hints createHints(TypeCheckHints hints, MetaAccessProvider runtime, boolean positiveOnly, Graph graph) {
+        ConstantNode[] hubs = new ConstantNode[hints.hints.length];
+        boolean[] isPositive = new boolean[hints.hints.length];
+        int index = 0;
+        for (int i = 0; i < hubs.length; i++) {
+            if (!positiveOnly || hints.hints[i].positive) {
+                hubs[index] = ConstantNode.forConstant(((HotSpotResolvedObjectType) hints.hints[i].type).klass(), runtime, graph);
+                isPositive[index] = hints.hints[i].positive;
+                index++;
+            }
+        }
+        if (positiveOnly && index != hubs.length) {
+            assert index < hubs.length;
+            hubs = Arrays.copyOf(hubs, index);
+            isPositive = Arrays.copyOf(isPositive, index);
+        }
+        return new Hints(hubs, isPositive);
     }
 
     static Word loadSecondarySupersElement(Word metaspaceArray, int index) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java	Mon Apr 15 08:49:14 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -28,100 +28,27 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
-import com.oracle.graal.replacements.Snippet.Parameter;
 import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
 import com.oracle.graal.replacements.SnippetTemplate.Arguments;
-import com.oracle.graal.replacements.SnippetTemplate.Key;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
+import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
 
 public class WriteBarrierSnippets implements Snippets {
 
     @Snippet
-    public static void g1PreWriteBarrier(@Parameter("object") Object obj, @Parameter("expectedObject") Object expobj, @Parameter("location") Object location,
-                    @ConstantParameter("doLoad") boolean doLoad) {
-        Word thread = thread();
+    public static void serialArrayWriteBarrier(Object obj, Object location, @ConstantParameter boolean usePrecise) {
         Object object = FixedValueAnchorNode.getObject(obj);
-        Object expectedObject = FixedValueAnchorNode.getObject(expobj);
-        Word field = (Word) Word.fromArray(object, location);
-        Word previousOop = (Word) Word.fromObject(expectedObject);
-        byte markingValue = thread.readByte(HotSpotSnippetUtils.g1SATBQueueMarkingOffset());
-
-        Word bufferAddress = thread.readWord(HotSpotSnippetUtils.g1SATBQueueBufferOffset());
-        Word indexAddress = thread.add(HotSpotSnippetUtils.g1SATBQueueIndexOffset());
-        Word indexValue = indexAddress.readWord(0);
-
-        if (markingValue != (byte) 0) {
-            if (doLoad) {
-                previousOop = field.readWord(0);
-            }
-            if (previousOop.notEqual(Word.zero())) {
-                if (indexValue.notEqual(Word.zero())) {
-                    Word nextIndex = indexValue.subtract(HotSpotSnippetUtils.wordSize());
-                    Word logAddress = bufferAddress.add(nextIndex);
-                    logAddress.writeWord(0, previousOop);
-                    indexAddress.writeWord(0, nextIndex);
-                } else {
-                    WriteBarrierPreStubCall.call(previousOop);
-
-                }
-            }
-        }
-    }
-
-    @Snippet
-    public static void g1PostWriteBarrier(@Parameter("object") Object obj, @Parameter("value") Object value, @Parameter("location") Object location, @ConstantParameter("usePrecise") boolean usePrecise) {
-        Word thread = thread();
-        Object object = FixedValueAnchorNode.getObject(obj);
-        Object wrObject = FixedValueAnchorNode.getObject(value);
-        Word oop = (Word) Word.fromObject(object);
-        Word field;
+        Pointer oop;
         if (usePrecise) {
-            field = (Word) Word.fromArray(object, location);
+            oop = Word.fromArray(object, location);
         } else {
-            field = oop;
-        }
-        Word writtenValue = (Word) Word.fromObject(wrObject);
-        Word bufferAddress = thread.readWord(HotSpotSnippetUtils.g1CardQueueBufferOffset());
-        Word indexAddress = thread.add(HotSpotSnippetUtils.g1CardQueueIndexOffset());
-        Word indexValue = thread.readWord(HotSpotSnippetUtils.g1CardQueueIndexOffset());
-        Word xorResult = (field.xor(writtenValue)).unsignedShiftRight(HotSpotSnippetUtils.logOfHRGrainBytes());
-
-        // Card Table
-        Word cardBase = field.unsignedShiftRight(cardTableShift());
-        long startAddress = cardTableStart();
-        int displacement = 0;
-        if (((int) startAddress) == startAddress) {
-            displacement = (int) startAddress;
-        } else {
-            cardBase = cardBase.add(Word.unsigned(cardTableStart()));
+            oop = Word.fromObject(object);
         }
-        Word cardAddress = cardBase.add(displacement);
-
-        if (xorResult.notEqual(Word.zero())) {
-            if (writtenValue.notEqual(Word.zero())) {
-                byte cardByte = cardAddress.readByte(0);
-                if (cardByte != (byte) 0) {
-                    cardAddress.writeByte(0, (byte) 0); // smash zero into card
-                    if (indexValue.notEqual(Word.zero())) {
-                        Word nextIndex = indexValue.subtract(HotSpotSnippetUtils.wordSize());
-                        Word logAddress = bufferAddress.add(nextIndex);
-                        logAddress.writeWord(0, cardAddress);
-                        indexAddress.writeWord(0, nextIndex);
-                    } else {
-                        WriteBarrierPostStubCall.call(object, cardAddress);
-                    }
-                }
-            }
-        }
-    }
-
-    @Snippet
-    public static void serialFieldWriteBarrier(@Parameter("object") Object obj) {
-        Object object = FixedValueAnchorNode.getObject(obj);
-        Pointer oop = Word.fromObject(object);
         Word base = (Word) oop.unsignedShiftRight(cardTableShift());
         long startAddress = cardTableStart();
         int displacement = 0;
@@ -134,77 +61,44 @@
     }
 
     @Snippet
-    public static void serialArrayWriteBarrier(@Parameter("object") Object obj, @Parameter("location") Object location) {
-        Object object = FixedValueAnchorNode.getObject(obj);
-        Pointer oop = Word.fromArray(object, location);
-        Word base = (Word) oop.unsignedShiftRight(cardTableShift());
-        long startAddress = cardTableStart();
-        int displacement = 0;
-        if (((int) startAddress) == startAddress) {
-            displacement = (int) startAddress;
-        } else {
-            base = base.add(Word.unsigned(cardTableStart()));
+    public static void serialArrayRangeWriteBarrier(Object object, int startIndex, int length) {
+        Object dest = FixedValueAnchorNode.getObject(object);
+        int cardShift = cardTableShift();
+        long cardStart = cardTableStart();
+        final int scale = arrayIndexScale(Kind.Object);
+        int header = arrayBaseOffset(Kind.Object);
+        long dstAddr = GetObjectAddressNode.get(dest);
+        long start = (dstAddr + header + (long) startIndex * scale) >>> cardShift;
+        long end = (dstAddr + header + ((long) startIndex + length - 1) * scale) >>> cardShift;
+        long count = end - start + 1;
+        while (count-- > 0) {
+            DirectStoreNode.store((start + cardStart) + count, false, Kind.Boolean);
         }
-        base.writeByte(displacement, (byte) 0);
     }
 
-    public static class Templates extends AbstractTemplates<WriteBarrierSnippets> {
+    public static class Templates extends AbstractTemplates {
 
-        private final ResolvedJavaMethod serialFieldWriteBarrier;
-        private final ResolvedJavaMethod serialArrayWriteBarrier;
-        private final ResolvedJavaMethod g1PreWriteBarrier;
-        private final ResolvedJavaMethod g1PostWriteBarrier;
+        private final SnippetInfo serialArrayWriteBarrier = snippet(WriteBarrierSnippets.class, "serialArrayWriteBarrier");
+        private final SnippetInfo serialArrayRangeWriteBarrier = snippet(WriteBarrierSnippets.class, "serialArrayRangeWriteBarrier");
 
         public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) {
-            super(runtime, replacements, target, WriteBarrierSnippets.class);
-            serialFieldWriteBarrier = snippet("serialFieldWriteBarrier", Object.class);
-            serialArrayWriteBarrier = snippet("serialArrayWriteBarrier", Object.class, Object.class);
-            g1PreWriteBarrier = snippet("g1PreWriteBarrier", Object.class, Object.class, Object.class, boolean.class);
-            g1PostWriteBarrier = snippet("g1PostWriteBarrier", Object.class, Object.class, Object.class, boolean.class);
+            super(runtime, replacements, target);
         }
 
-        public void lower(ArrayWriteBarrier arrayWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) {
-            ResolvedJavaMethod method = serialArrayWriteBarrier;
-            Key key = new Key(method);
-            Arguments arguments = new Arguments();
-            arguments.add("object", arrayWriteBarrier.getObject());
-            arguments.add("location", arrayWriteBarrier.getLocation());
-            SnippetTemplate template = cache.get(key);
-            template.instantiate(runtime, arrayWriteBarrier, DEFAULT_REPLACER, arguments);
-        }
-
-        public void lower(FieldWriteBarrier fieldWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) {
-            ResolvedJavaMethod method = serialFieldWriteBarrier;
-            Key key = new Key(method);
-            Arguments arguments = new Arguments();
-            arguments.add("object", fieldWriteBarrier.getObject());
-            SnippetTemplate template = cache.get(key);
-            template.instantiate(runtime, fieldWriteBarrier, DEFAULT_REPLACER, arguments);
+        public void lower(SerialWriteBarrier arrayWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) {
+            Arguments args = new Arguments(serialArrayWriteBarrier);
+            args.add("obj", arrayWriteBarrier.getObject());
+            args.add("location", arrayWriteBarrier.getLocation());
+            args.addConst("usePrecise", arrayWriteBarrier.usePrecise());
+            template(args).instantiate(runtime, arrayWriteBarrier, DEFAULT_REPLACER, args);
         }
 
-        public void lower(WriteBarrierPre writeBarrierPre, @SuppressWarnings("unused") LoweringTool tool) {
-            ResolvedJavaMethod method = g1PreWriteBarrier;
-            Key key = new Key(method);
-            key.add("doLoad", writeBarrierPre.doLoad());
-            Arguments arguments = new Arguments();
-            arguments.add("object", writeBarrierPre.getObject());
-            arguments.add("expectedObject", writeBarrierPre.getExpectedObject());
-            arguments.add("location", writeBarrierPre.getLocation());
-            SnippetTemplate template = cache.get(key);
-            template.instantiate(runtime, writeBarrierPre, DEFAULT_REPLACER, arguments);
+        public void lower(SerialArrayRangeWriteBarrier arrayRangeWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) {
+            Arguments args = new Arguments(serialArrayRangeWriteBarrier);
+            args.add("object", arrayRangeWriteBarrier.getObject());
+            args.add("startIndex", arrayRangeWriteBarrier.getStartIndex());
+            args.add("length", arrayRangeWriteBarrier.getLength());
+            template(args).instantiate(runtime, arrayRangeWriteBarrier, DEFAULT_REPLACER, args);
         }
-
-        public void lower(WriteBarrierPost writeBarrierPost, @SuppressWarnings("unused") LoweringTool tool) {
-            ResolvedJavaMethod method = g1PostWriteBarrier;
-            Key key = new Key(method);
-            key.add("usePrecise", writeBarrierPost.usePrecise());
-            Arguments arguments = new Arguments();
-            arguments.add("object", writeBarrierPost.getObject());
-            arguments.add("location", writeBarrierPost.getLocation());
-            arguments.add("value", writeBarrierPost.getValue());
-            SnippetTemplate template = cache.get(key);
-            template.instantiate(runtime, writeBarrierPost, DEFAULT_REPLACER, arguments);
-        }
-
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Mon Apr 15 08:49:14 2013 +0200
@@ -27,15 +27,15 @@
 import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
-import com.oracle.graal.replacements.SnippetTemplate.*;
+import com.oracle.graal.replacements.Snippet.ConstantParameter;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
 import com.oracle.graal.word.*;
 
 /**
@@ -47,14 +47,19 @@
 public class NewArrayStub extends Stub {
 
     public NewArrayStub(final HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) {
-        super(runtime, replacements, target, linkage);
+        super(runtime, replacements, target, linkage, "newArray");
     }
 
     @Override
-    protected void populateKey(Key key) {
+    protected Arguments makeArguments(SnippetInfo stub) {
         HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) runtime.lookupJavaType(int[].class);
-        Constant intArrayHub = intArrayType.klass();
-        key.add("intArrayHub", intArrayHub).add("log", Boolean.getBoolean("graal.logNewArrayStub"));
+
+        Arguments args = new Arguments(stub);
+        args.add("hub", null);
+        args.add("length", null);
+        args.addConst("intArrayHub", intArrayType.klass());
+        args.addConst("log", Boolean.getBoolean("graal.logNewArrayStub"));
+        return args;
     }
 
     /**
@@ -67,7 +72,7 @@
      * @param log specifies if logging is enabled
      */
     @Snippet
-    private static Object newArray(@Parameter("hub") Word hub, @Parameter("length") int length, @ConstantParameter("intArrayHub") Word intArrayHub, @ConstantParameter("log") boolean log) {
+    private static Object newArray(Word hub, int length, @ConstantParameter Word intArrayHub, @ConstantParameter boolean log) {
         int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION);
         int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
         int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Mon Apr 15 08:49:14 2013 +0200
@@ -36,8 +36,8 @@
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
 import com.oracle.graal.replacements.Snippet.Fold;
-import com.oracle.graal.replacements.Snippet.Parameter;
-import com.oracle.graal.replacements.SnippetTemplate.Key;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
 import com.oracle.graal.word.*;
 
 /**
@@ -49,14 +49,18 @@
 public class NewInstanceStub extends Stub {
 
     public NewInstanceStub(final HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) {
-        super(runtime, replacements, target, linkage);
+        super(runtime, replacements, target, linkage, "newInstance");
     }
 
     @Override
-    protected void populateKey(Key key) {
+    protected Arguments makeArguments(SnippetInfo stub) {
         HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) runtime.lookupJavaType(int[].class);
-        Constant intArrayHub = intArrayType.klass();
-        key.add("intArrayHub", intArrayHub).add("log", Boolean.getBoolean("graal.logNewInstanceStub"));
+
+        Arguments args = new Arguments(stub);
+        args.add("hub", null);
+        args.addConst("intArrayHub", intArrayType.klass());
+        args.addConst("log", Boolean.getBoolean("graal.logNewInstanceStub"));
+        return args;
     }
 
     /**
@@ -67,7 +71,7 @@
      * @param intArrayHub the hub for {@code int[].class}
      */
     @Snippet
-    private static Object newInstance(@Parameter("hub") Word hub, @ConstantParameter("intArrayHub") Word intArrayHub, @ConstantParameter("log") boolean log) {
+    private static Object newInstance(Word hub, @ConstantParameter Word intArrayHub, @ConstantParameter boolean log) {
         int sizeInBytes = hub.readInt(klassInstanceSizeOffset(), FINAL_LOCATION);
         if (!forceSlowPath() && inlineContiguousAllocationSupported()) {
             if (hub.readInt(klassStateOffset(), CLASS_STATE_LOCATION) == klassStateFullyInitialized()) {
@@ -95,9 +99,6 @@
      *         operation was unsuccessful
      */
     static Word refillAllocate(Word intArrayHub, int sizeInBytes, boolean log) {
-        if (useG1GC()) {
-            return Word.zero();
-        }
         if (!useTLAB()) {
             return edenAllocate(Word.unsigned(sizeInBytes), log);
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Mon Apr 15 08:49:14 2013 +0200
@@ -22,9 +22,6 @@
  */
 package com.oracle.graal.hotspot.stubs;
 
-import static java.lang.reflect.Modifier.*;
-
-import java.lang.reflect.*;
 import java.util.concurrent.*;
 
 import com.oracle.graal.api.code.*;
@@ -42,7 +39,8 @@
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
 import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
-import com.oracle.graal.replacements.SnippetTemplate.Key;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
 
 /**
  * Base class for implementing some low level code providing the out-of-line slow path for a
@@ -56,7 +54,7 @@
     /**
      * The method implementing the stub.
      */
-    protected final HotSpotResolvedJavaMethod stubMethod;
+    protected final SnippetInfo stubInfo;
 
     /**
      * The linkage information for the stub.
@@ -69,15 +67,14 @@
     protected InstalledCode stubCode;
 
     /**
-     * Creates a new stub container. The new stub still needs to be {@linkplain #getAddress(Backend)
-     * installed}.
+     * Creates a new stub container. The new stub still needs to be
+     * {@linkplain #getAddress(Backend) installed}.
      * 
      * @param linkage linkage details for a call to the stub
      */
-    @SuppressWarnings("unchecked")
-    public Stub(HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) {
-        super(runtime, replacements, target, null);
-        stubMethod = findStubMethod(runtime, getClass());
+    public Stub(HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage, String methodName) {
+        super(runtime, replacements, target);
+        this.stubInfo = snippet(getClass(), methodName);
         this.linkage = linkage;
 
     }
@@ -85,7 +82,7 @@
     /**
      * Adds the {@linkplain ConstantParameter constant} arguments of this stub.
      */
-    protected abstract void populateKey(Key key);
+    protected abstract Arguments makeArguments(SnippetInfo stub);
 
     protected HotSpotRuntime runtime() {
         return (HotSpotRuntime) runtime;
@@ -95,7 +92,7 @@
      * Gets the method implementing this stub.
      */
     public ResolvedJavaMethod getMethod() {
-        return stubMethod;
+        return stubInfo.getMethod();
     }
 
     public HotSpotRuntimeCallTarget getLinkage() {
@@ -109,25 +106,22 @@
      */
     public synchronized long getAddress(Backend backend) {
         if (stubCode == null) {
-            StructuredGraph graph = replacements.getSnippet(stubMethod);
-
-            Key key = new Key(stubMethod);
-            populateKey(key);
-            SnippetTemplate template = cache.get(key);
-            graph = template.copySpecializedGraph();
+            Arguments args = makeArguments(stubInfo);
+            SnippetTemplate template = template(args);
+            StructuredGraph graph = template.copySpecializedGraph();
 
             PhasePlan phasePlan = new PhasePlan();
             GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
             phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
-            final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), stubMethod, graph, null, phasePlan,
-                            OptimisticOptimizations.ALL, new SpeculationLog());
+            final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), getMethod(), graph, null, phasePlan, OptimisticOptimizations.ALL,
+                            new SpeculationLog());
 
-            stubCode = Debug.scope("CodeInstall", new Object[]{runtime(), stubMethod}, new Callable<InstalledCode>() {
+            stubCode = Debug.scope("CodeInstall", new Object[]{runtime(), getMethod()}, new Callable<InstalledCode>() {
 
                 @Override
                 public InstalledCode call() {
-                    InstalledCode installedCode = runtime().addMethod(stubMethod, compResult);
-                    assert installedCode != null : "error installing stub " + stubMethod;
+                    InstalledCode installedCode = runtime().addMethod(getMethod(), compResult);
+                    assert installedCode != null : "error installing stub " + getMethod();
                     if (Debug.isDumpEnabled()) {
                         Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
                     }
@@ -135,24 +129,8 @@
                 }
             });
 
-            assert stubCode != null : "error installing stub " + stubMethod;
+            assert stubCode != null : "error installing stub " + getMethod();
         }
         return stubCode.getStart();
     }
-
-    /**
-     * Finds the static method annotated with {@link Snippet} in a given class of which there must
-     * be exactly one.
-     */
-    private static HotSpotResolvedJavaMethod findStubMethod(HotSpotRuntime runtime, Class<?> stubClass) {
-        HotSpotResolvedJavaMethod m = null;
-        for (Method candidate : stubClass.getDeclaredMethods()) {
-            if (isStatic(candidate.getModifiers()) && candidate.getAnnotation(Snippet.class) != null) {
-                assert m == null : "more than one method annotated with @" + Snippet.class.getSimpleName() + " in " + stubClass;
-                m = (HotSpotResolvedJavaMethod) runtime.lookupJavaMethod(candidate);
-            }
-        }
-        assert m != null : "no static method annotated with @" + Snippet.class.getSimpleName() + " in " + stubClass;
-        return m;
-    }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeDisassembler.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeDisassembler.java	Mon Apr 15 08:49:14 2013 +0200
@@ -102,6 +102,13 @@
                         buf.append(String.format("#%-10s // %s", cpi + ", " + stream.readUByte(bci + 3), calleeDesc));
                         break;
                     }
+                    case INVOKEDYNAMIC: {
+                        int cpi = stream.readCPI4();
+                        JavaMethod callee = cp.lookupMethod(cpi, opcode);
+                        String calleeDesc = callee.getDeclaringClass().getName().equals(method.getDeclaringClass().getName()) ? MetaUtil.format("%n:(%P)%R", callee) : MetaUtil.format("%H.%n:(%P)%R", callee);
+                        buf.append(String.format("#%-10d // %s", cpi, calleeDesc));
+                        break;
+                    }
                     case LDC            :
                     case LDC_W          :
                     case LDC2_W         : {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Mon Apr 15 08:49:14 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
@@ -23,6 +23,7 @@
 package com.oracle.graal.java;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
 
 public class GraphBuilderConfiguration {
 
@@ -30,6 +31,13 @@
     private final boolean omitAllExceptionEdges;
     private ResolvedJavaType[] skippedExceptionTypes;
 
+    /**
+     * When the graph builder is in eager infopoint mode, it inserts {@link InfopointNode}s in
+     * places where no safepoints would be inserted: inlining boundaries, and line number switches.
+     * This is relevant when code is to be generated for native, machine-code level debugging.
+     */
+    private boolean eagerInfopointMode;
+
     protected GraphBuilderConfiguration(boolean eagerResolving, boolean omitAllExceptionEdges) {
         this.eagerResolving = eagerResolving;
         this.omitAllExceptionEdges = omitAllExceptionEdges;
@@ -39,6 +47,10 @@
         this.skippedExceptionTypes = skippedExceptionTypes;
     }
 
+    public void setEagerInfopointMode(boolean eagerInfopointMode) {
+        this.eagerInfopointMode = eagerInfopointMode;
+    }
+
     public ResolvedJavaType[] getSkippedExceptionTypes() {
         return skippedExceptionTypes;
     }
@@ -51,6 +63,10 @@
         return omitAllExceptionEdges;
     }
 
+    public boolean eagerInfopointMode() {
+        return eagerInfopointMode;
+    }
+
     public static GraphBuilderConfiguration getDefault() {
         return new GraphBuilderConfiguration(false, false);
     }
@@ -64,9 +80,9 @@
     }
 
     /**
-     * Returns {@code true} if it is an error for a class/field/method resolution to fail.
-     * The default is the same result as returned by {@link #eagerResolving()}.
-     * However, it may be overridden to allow failure even when {@link #eagerResolving} is {@code true}.
+     * Returns {@code true} if it is an error for a class/field/method resolution to fail. The
+     * default is the same result as returned by {@link #eagerResolving()}. However, it may be
+     * overridden to allow failure even when {@link #eagerResolving} is {@code true}.
      */
     public boolean unresolvedIsError() {
         return eagerResolving;
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Apr 15 08:49:14 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -75,6 +75,10 @@
      */
     public static final int TRACELEVEL_STATE = 2;
 
+    private LineNumberTable lnt;
+    private int previousLineNumber;
+    private int currentLineNumber;
+
     protected StructuredGraph currentGraph;
 
     private final MetaAccessProvider runtime;
@@ -141,6 +145,10 @@
     @Override
     protected void run(StructuredGraph graph) {
         method = graph.method();
+        if (graphBuilderConfig.eagerInfopointMode()) {
+            lnt = method.getLineNumberTable();
+            previousLineNumber = -1;
+        }
         entryBCI = graph.getEntryBCI();
         profilingInfo = method.getProfilingInfo();
         assert method.getCode() != null : "method must contain bytecodes: " + method;
@@ -193,6 +201,13 @@
         }
         frameState.clearNonLiveLocals(blockMap.startBlock.localsLiveIn);
 
+        if (graphBuilderConfig.eagerInfopointMode()) {
+            ((StateSplit) lastInstr).setStateAfter(frameState.create(0));
+            InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.METHOD_START));
+            lastInstr.setNext(ipn);
+            lastInstr = ipn;
+        }
+
         // finish the start block
         ((StateSplit) lastInstr).setStateAfter(frameState.create(0));
 
@@ -1054,10 +1069,35 @@
         }
     }
 
+    private void genInvokeDynamic(JavaMethod target) {
+        if (target instanceof ResolvedJavaMethod) {
+            Object appendix = constantPool.lookupAppendix(stream.readCPI4(), Bytecodes.INVOKEDYNAMIC);
+            if (appendix != null) {
+                frameState.apush(ConstantNode.forObject(appendix, runtime, currentGraph));
+            }
+            ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(false), target.getSignature().getParameterCount(false));
+            appendInvoke(InvokeKind.Static, (ResolvedJavaMethod) target, args);
+        } else {
+            handleUnresolvedInvoke(target, InvokeKind.Static);
+        }
+    }
+
     private void genInvokeVirtual(JavaMethod target) {
         if (target instanceof ResolvedJavaMethod) {
-            ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true));
-            genInvokeIndirect(InvokeKind.Virtual, (ResolvedJavaMethod) target, args);
+            // Special handling for runtimes that rewrite an invocation of MethodHandle.invoke(...)
+            // or MethodHandle.invokeExact(...) to a static adapter. HotSpot does this - see
+            // https://wikis.oracle.com/display/HotSpotInternals/Method+handles+and+invokedynamic
+            boolean hasReceiver = !isStatic(((ResolvedJavaMethod) target).getModifiers());
+            Object appendix = constantPool.lookupAppendix(stream.readCPI(), Bytecodes.INVOKEVIRTUAL);
+            if (appendix != null) {
+                frameState.apush(ConstantNode.forObject(appendix, runtime, currentGraph));
+            }
+            ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(hasReceiver), target.getSignature().getParameterCount(hasReceiver));
+            if (hasReceiver) {
+                genInvokeIndirect(InvokeKind.Virtual, (ResolvedJavaMethod) target, args);
+            } else {
+                appendInvoke(InvokeKind.Static, (ResolvedJavaMethod) target, args);
+            }
         } else {
             handleUnresolvedInvoke(target, InvokeKind.Virtual);
         }
@@ -1493,7 +1533,7 @@
     }
 
     private void processBlock(Block block) {
-        // Ignore blocks that have no predecessors by the time it their bytecodes are parsed
+        // Ignore blocks that have no predecessors by the time their bytecodes are parsed
         if (block == null || block.firstInstruction == null) {
             Debug.log("Ignoring block %s", block);
             return;
@@ -1574,6 +1614,12 @@
         }
         ReturnNode returnNode = currentGraph.add(new ReturnNode(x));
 
+        if (graphBuilderConfig.eagerInfopointMode()) {
+            InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.METHOD_END));
+            ipn.setStateAfter(frameState.create(FrameState.AFTER_BCI));
+            append(ipn);
+        }
+
         append(returnNode);
     }
 
@@ -1684,6 +1730,16 @@
         BytecodesParsed.add(block.endBci - bci);
 
         while (bci < endBCI) {
+            if (graphBuilderConfig.eagerInfopointMode() && lnt != null) {
+                currentLineNumber = lnt.getLineNumber(bci);
+                if (currentLineNumber != previousLineNumber) {
+                    InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.LINE_NUMBER));
+                    ipn.setStateAfter(frameState.create(bci));
+                    append(ipn);
+                    previousLineNumber = currentLineNumber;
+                }
+            }
+
             // read the opcode
             int opcode = stream.currentBC();
             traceState();
@@ -1937,6 +1993,7 @@
             case INVOKESPECIAL  : cpi = stream.readCPI(); genInvokeSpecial(lookupMethod(cpi, opcode)); break;
             case INVOKESTATIC   : cpi = stream.readCPI(); genInvokeStatic(lookupMethod(cpi, opcode)); break;
             case INVOKEINTERFACE: cpi = stream.readCPI(); genInvokeInterface(lookupMethod(cpi, opcode)); break;
+            case INVOKEDYNAMIC  : cpi = stream.readCPI4(); genInvokeDynamic(lookupMethod(cpi, opcode)); break;
             case NEW            : genNewInstance(stream.readCPI()); break;
             case NEWARRAY       : genNewPrimitiveArray(stream.readLocalIndex()); break;
             case ANEWARRAY      : genNewObjectArray(stream.readCPI()); break;
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/System_setOut.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/System_setOut.java	Mon Apr 15 08:49:14 2013 +0200
@@ -46,6 +46,7 @@
         return sum;
     }
 
+    // CheckStyle: stop system..print check
     private static void doPrint(int n) {
         for (int i = 0; i < n; i++) {
             System.out.print('x');
@@ -56,6 +57,8 @@
         System.out.println(test(10000));
     }
 
+    // CheckStyle: resume system..print check
+
     @LongTest
     public void run0() throws Throwable {
         runTest("test", 10000);
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java	Mon Apr 15 08:49:14 2013 +0200
@@ -35,43 +35,14 @@
 
 public class AMD64Call {
 
-    @Opcode("CALL_DIRECT")
-    public static class DirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp {
+    public abstract static class CallOp extends AMD64LIRInstruction {
 
         @Def({REG, ILLEGAL}) protected Value result;
         @Use({REG, STACK}) protected Value[] parameters;
         @Temp protected Value[] temps;
         @State protected LIRFrameState state;
 
-        protected final ResolvedJavaMethod callTarget;
-
-        public DirectCallOp(ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
-            this.callTarget = callTarget;
-            this.result = result;
-            this.parameters = parameters;
-            this.state = state;
-            this.temps = temps;
-            assert temps != null;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            directCall(tasm, masm, callTarget, null, true, state);
-        }
-    }
-
-    @Opcode("CALL_NEAR_RUNTIME")
-    public static class DirectNearRuntimeCallOp extends AMD64LIRInstruction implements StandardOp.CallOp {
-
-        @Def({REG, ILLEGAL}) protected Value result;
-        @Use({REG, STACK}) protected Value[] parameters;
-        @Temp protected Value[] temps;
-        @State protected LIRFrameState state;
-
-        protected final RuntimeCallTarget callTarget;
-
-        public DirectNearRuntimeCallOp(RuntimeCallTarget callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
-            this.callTarget = callTarget;
+        public CallOp(Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
             this.result = result;
             this.parameters = parameters;
             this.state = state;
@@ -80,57 +51,43 @@
         }
 
         @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            directCall(tasm, masm, callTarget, null, false, state);
+        public boolean hasCall() {
+            return true;
         }
     }
 
-    @Opcode("CALL_FAR_RUNTIME")
-    public static class DirectFarRuntimeCallOp extends AMD64LIRInstruction implements StandardOp.CallOp {
+    public abstract static class MethodCallOp extends CallOp {
 
-        @Def({REG, ILLEGAL}) protected Value result;
-        @Use({REG, STACK}) protected Value[] parameters;
-        @Temp protected Value[] temps;
-        @State protected LIRFrameState state;
-        @Temp({REG}) protected AllocatableValue callTemp;
+        protected final ResolvedJavaMethod callTarget;
 
-        protected final RuntimeCallTarget callTarget;
-
-        public DirectFarRuntimeCallOp(LIRGeneratorTool gen, RuntimeCallTarget callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
+        public MethodCallOp(ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
+            super(result, parameters, temps, state);
             this.callTarget = callTarget;
-            this.result = result;
-            this.parameters = parameters;
-            this.state = state;
-            this.temps = temps;
-            assert temps != null;
-            callTemp = gen.newVariable(Kind.Long);
+        }
+
+    }
+
+    @Opcode("CALL_DIRECT")
+    public static class DirectCallOp extends MethodCallOp {
+
+        public DirectCallOp(ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
+            super(callTarget, result, parameters, temps, state);
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            directCall(tasm, masm, callTarget, ((RegisterValue) callTemp).getRegister(), false, state);
+            directCall(tasm, masm, callTarget, null, true, state);
         }
     }
 
     @Opcode("CALL_INDIRECT")
-    public static class IndirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp {
+    public static class IndirectCallOp extends MethodCallOp {
 
-        @Def({REG, ILLEGAL}) protected Value result;
-        @Use({REG, STACK}) protected Value[] parameters;
         @Use({REG}) protected Value targetAddress;
-        @Temp protected Value[] temps;
-        @State protected LIRFrameState state;
 
-        protected final InvokeTarget callTarget;
-
-        public IndirectCallOp(InvokeTarget callTarget, Value result, Value[] parameters, Value[] temps, Value targetAddress, LIRFrameState state) {
-            this.callTarget = callTarget;
-            this.result = result;
-            this.parameters = parameters;
+        public IndirectCallOp(ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, Value targetAddress, LIRFrameState state) {
+            super(callTarget, result, parameters, temps, state);
             this.targetAddress = targetAddress;
-            this.state = state;
-            this.temps = temps;
-            assert temps != null;
         }
 
         @Override
@@ -145,6 +102,50 @@
         }
     }
 
+    public abstract static class RuntimeCallOp extends CallOp {
+
+        protected final RuntimeCallTarget callTarget;
+
+        public RuntimeCallOp(RuntimeCallTarget callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
+            super(result, parameters, temps, state);
+            this.callTarget = callTarget;
+        }
+
+        @Override
+        public boolean hasCall() {
+            return !callTarget.preservesRegisters();
+        }
+    }
+
+    @Opcode("CALL_NEAR_RUNTIME")
+    public static class DirectNearRuntimeCallOp extends RuntimeCallOp {
+
+        public DirectNearRuntimeCallOp(RuntimeCallTarget callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
+            super(callTarget, result, parameters, temps, state);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            directCall(tasm, masm, callTarget, null, false, state);
+        }
+    }
+
+    @Opcode("CALL_FAR_RUNTIME")
+    public static class DirectFarRuntimeCallOp extends RuntimeCallOp {
+
+        @Temp({REG}) protected AllocatableValue callTemp;
+
+        public DirectFarRuntimeCallOp(LIRGeneratorTool gen, RuntimeCallTarget callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
+            super(callTarget, result, parameters, temps, state);
+            callTemp = gen.newVariable(Kind.Long);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            directCall(tasm, masm, callTarget, ((RegisterValue) callTemp).getRegister(), false, state);
+        }
+    }
+
     public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, InvokeTarget callTarget, Register scratch, boolean align, LIRFrameState info) {
         if (align) {
             emitAlignmentForDirectCall(tasm, masm);
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java	Mon Apr 15 08:49:14 2013 +0200
@@ -36,9 +36,9 @@
 public enum PTXArithmetic {
     IADD, ISUB, IMUL, IDIV, IDIVREM, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR,
     LADD, LSUB, LMUL, LDIV, LDIVREM, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR,
-    FADD, FSUB, FMUL, FDIV, FAND, FOR, FXOR,
-    DADD, DSUB, DMUL, DDIV, DAND, DOR, DXOR,
-    INEG, LNEG,
+    FADD, FSUB, FMUL, FDIV, FREM, FAND, FOR, FXOR,
+    DADD, DSUB, DMUL, DDIV, DREM, DAND, DOR, DXOR,
+    INEG, LNEG, FNEG, DNEG,
     I2L, L2I, I2B, I2C, I2S,
     F2D, D2F,
     I2F, I2D, F2I, D2I,
@@ -46,6 +46,47 @@
     MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L;
 
 
+    /**
+     * Unary operation with separate source and destination operand. 
+     */
+    public static class Unary2Op extends PTXLIRInstruction {
+        @Opcode private final PTXArithmetic opcode;
+        @Def({REG}) protected AllocatableValue result;
+        @Use({REG, STACK}) protected AllocatableValue x;
+
+        public Unary2Op(PTXArithmetic opcode, AllocatableValue result, AllocatableValue x) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            PTXMove.move(tasm, masm, result, x);
+            emit(tasm, masm, opcode, result, x, null);
+        }
+    }
+
+    /**
+     * Unary operation with single operand for source and destination. 
+     */
+    public static class Unary1Op extends PTXLIRInstruction {
+        @Opcode private final PTXArithmetic opcode;
+        @Def({REG, HINT}) protected AllocatableValue result;
+        @Use({REG, STACK}) protected AllocatableValue x;
+
+        public Unary1Op(PTXArithmetic opcode, AllocatableValue result, AllocatableValue x) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            emit(tasm, masm, opcode, result);
+        }
+    }
+
     public static class Op1Reg extends PTXLIRInstruction {
         @Opcode private final PTXArithmetic opcode;
         @Def({REG, HINT}) protected Value result;
@@ -213,23 +254,70 @@
         }
     }
 
-
-    @SuppressWarnings("unused")
-    protected static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value result) {
+    protected static void emit(@SuppressWarnings("unused") TargetMethodAssembler tasm,
+                               PTXAssembler masm, PTXArithmetic opcode, Value result) {
         switch (opcode) {
-            default:   throw GraalInternalError.shouldNotReachHere();
+        case L2I:  masm.and_b32(asIntReg(result), asIntReg(result), 0xFFFFFFFF); break;
+        case I2C:  masm.and_b16(asIntReg(result), asIntReg(result), (short) 0xFFFF); break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: "  + opcode);
         }
     }
 
     public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value dst, Value src, LIRFrameState info) {
         int exceptionOffset = -1;
         if (isRegister(src)) {
-            Register a = asIntReg(src);
-            Register d = asIntReg(dst);
             switch (opcode) {
-                case INEG: masm.neg_s32(d, a); break;
+                case INEG:
+                    masm.neg_s32(asIntReg(dst), asIntReg(src));
+                    break;
+                case I2L:
+                    masm.cvt_s64_s32(asLongReg(dst), asIntReg(src));
+                    break;
+                case I2C:
+                    masm.cvt_b16_s32(asIntReg(dst), asIntReg(src));
+                    break;
+                case I2B:
+                    masm.cvt_s8_s32(asIntReg(dst), asIntReg(src));
+                    break;
+                case I2F:
+                    masm.cvt_f32_s32(asFloatReg(dst), asIntReg(src));
+                    break;
+                case I2D:
+                    masm.cvt_f64_s32(asDoubleReg(dst), asIntReg(src));
+                    break;
+                case FNEG:
+                    masm.neg_f32(asFloatReg(dst), asFloatReg(src));
+                    break;
+                case DNEG:
+                    masm.neg_f64(asDoubleReg(dst), asDoubleReg(src));
+                    break;
+                case F2I:
+                    masm.cvt_s32_f32(asIntReg(dst), asFloatReg(src));
+                    break;
+                case F2L:
+                    masm.cvt_s64_f32(asLongReg(dst), asFloatReg(src));
+                    break;
+                case F2D:
+                    masm.cvt_f64_f32(asDoubleReg(dst), asFloatReg(src));
+                    break;
+                case D2I:
+                    masm.cvt_s32_f64(asIntReg(dst), asDoubleReg(src));
+                    break;
+                case D2L:
+                    masm.cvt_s64_f64(asLongReg(dst), asDoubleReg(src));
+                    break;
+                case D2F:
+                    masm.cvt_f32_f64(asFloatReg(dst), asDoubleReg(src));
+                    break;
+                case LSHL:
+                    masm.shl_s64(asLongReg(dst), asLongReg(dst), asIntReg(src));
+                    break;
+                case LSHR:
+                    masm.shr_s64(asLongReg(dst), asLongReg(dst), asIntReg(src));
+                    break;
                 default:
-                    throw GraalInternalError.shouldNotReachHere();
+                    throw GraalInternalError.shouldNotReachHere("missing: "  + opcode);
             }
         } else if (isConstant(src)) {
             switch (opcode) {
@@ -252,33 +340,74 @@
     public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value dst, Value src1, Value src2, LIRFrameState info) {
         int exceptionOffset = -1;
         if (isConstant(src1)) {
-            int      a = tasm.asIntConst(src1);
-            Register b = asIntReg(src2);
-            Register d = asIntReg(dst);
             switch (opcode) {
-            case ISUB:  masm.sub_s32(d, a, b); break;
-            case IAND:  masm.and_b32(d, b, a); break;
-            default:    throw GraalInternalError.shouldNotReachHere();
+            case ISUB:  masm.sub_s32(asIntReg(dst),    tasm.asIntConst(src1),    asIntReg(src2));         break;
+            case IAND:  masm.and_b32(asIntReg(dst),    asIntReg(src2),           tasm.asIntConst(src1));  break;
+            case IDIV:  masm.div_s32(asIntReg(dst),    tasm.asIntConst(src1),    asIntReg(src2));         break;
+            case FSUB:  masm.sub_f32(asFloatReg(dst),  tasm.asFloatConst(src1),  asFloatReg(src2));       break;
+            case FDIV:  masm.div_f32(asFloatReg(dst),  tasm.asFloatConst(src1),  asFloatReg(src2));       break;
+            case DSUB:  masm.sub_f64(asDoubleReg(dst), tasm.asDoubleConst(src1), asDoubleReg(src2));      break;
+            case DDIV:  masm.div_f64(asDoubleReg(dst), tasm.asDoubleConst(src1), asDoubleReg(src2));      break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
             }
         } else if (isConstant(src2)) {
-            Register a = asIntReg(src1);
-            int      b = tasm.asIntConst(src2);
-            Register d = asIntReg(dst);
             switch (opcode) {
-            case IADD:  masm.add_s32(d, a, b); break;
-            case IAND:  masm.and_b32(d, a, b); break;
-            case IUSHR: masm.shr_u32(d, a, b); break;
-            default:    throw GraalInternalError.shouldNotReachHere();
+            case IADD:  masm.add_s32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
+            case ISUB:  masm.sub_s32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
+            case IMUL:  masm.mul_s32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
+            case IAND:  masm.and_b32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
+            case ISHL:  masm.shl_s32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
+            case ISHR:  masm.shr_s32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
+            case IUSHR: masm.shr_u32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
+            case IXOR:  masm.xor_b32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
+            case LXOR:  masm.xor_b64(asLongReg(dst),   asLongReg(src1),   tasm.asLongConst(src2));   break;
+            case LUSHR: masm.shr_u64(asLongReg(dst),   asLongReg(src1),   tasm.asLongConst(src2));   break;
+            case FADD:  masm.add_f32(asFloatReg(dst),  asFloatReg(src1),  tasm.asFloatConst(src2));  break;
+            case FMUL:  masm.mul_f32(asFloatReg(dst),  asFloatReg(src1),  tasm.asFloatConst(src2));  break;
+            case FDIV:  masm.div_f32(asFloatReg(dst),  asFloatReg(src1),  tasm.asFloatConst(src2));  break;
+            case DADD:  masm.add_f64(asDoubleReg(dst), asDoubleReg(src1), tasm.asDoubleConst(src2)); break;
+            case DMUL:  masm.mul_f64(asDoubleReg(dst), asDoubleReg(src1), tasm.asDoubleConst(src2)); break;
+            case DDIV:  masm.div_f64(asDoubleReg(dst), asDoubleReg(src1), tasm.asDoubleConst(src2)); break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
             }
         } else {
-            Register a = asIntReg(src1);
-            Register b = asIntReg(src2);
-            Register d = asIntReg(dst);
             switch (opcode) {
-            case IADD:  masm.add_s32(d, a, b); break;
-            case ISUB:  masm.sub_s32(d, a, b); break;
-            case IMUL:  masm.mul_s32(d, a, b); break;
-            default:    throw GraalInternalError.shouldNotReachHere();
+            case IADD:  masm.add_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case ISUB:  masm.sub_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case IMUL:  masm.mul_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case IDIV:  masm.div_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case IAND:  masm.and_b32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case IOR:    masm.or_b32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case IXOR:  masm.xor_b32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case ISHL:  masm.shl_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case ISHR:  masm.shr_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case IUSHR: masm.shr_u32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case IREM:  masm.rem_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case LADD:  masm.add_s64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case LSUB:  masm.sub_s64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case LMUL:  masm.mul_s64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case LDIV:  masm.div_s64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case LAND:  masm.and_b64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case LOR:    masm.or_b64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case LXOR:  masm.xor_b64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case LSHL:  masm.shl_s64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case LSHR:  masm.shr_s64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case LUSHR: masm.shr_u64(asLongReg(dst),   asLongReg(src1),   asIntReg(src2));    break;
+            case LREM:  masm.rem_s64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case FADD:  masm.add_f32(asFloatReg(dst),  asFloatReg(src1),  asFloatReg(src2));  break;
+            case FSUB:  masm.sub_f32(asFloatReg(dst),  asFloatReg(src1),  asFloatReg(src2));  break;
+            case FMUL:  masm.mul_f32(asFloatReg(dst),  asFloatReg(src1),  asFloatReg(src2));  break;
+            case FDIV:  masm.div_f32(asFloatReg(dst),  asFloatReg(src1),  asFloatReg(src2));  break;
+            case FREM:  masm.div_f32(asFloatReg(dst),  asFloatReg(src1),  asFloatReg(src2));  break;
+            case DADD:  masm.add_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break;
+            case DSUB:  masm.sub_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break;
+            case DMUL:  masm.mul_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break;
+            case DDIV:  masm.div_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break;
+            case DREM:  masm.div_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("missing: "  + opcode);
             }
         }
 
@@ -289,9 +418,11 @@
     }
 
     private static void verifyKind(PTXArithmetic opcode, Value result, Value x, Value y) {
-        assert (opcode.name().startsWith("I") && result.getKind() == Kind.Int && x.getKind().getStackKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int)
+        if (((opcode.name().startsWith("I") && result.getKind() == Kind.Int && x.getKind().getStackKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int)
             || (opcode.name().startsWith("L") && result.getKind() == Kind.Long && x.getKind() == Kind.Long && y.getKind() == Kind.Long)
             || (opcode.name().startsWith("F") && result.getKind() == Kind.Float && x.getKind() == Kind.Float && y.getKind() == Kind.Float)
-            || (opcode.name().startsWith("D") && result.getKind() == Kind.Double && x.getKind() == Kind.Double && y.getKind() == Kind.Double);
+            || (opcode.name().startsWith("D") && result.getKind() == Kind.Double && x.getKind() == Kind.Double && y.getKind() == Kind.Double)) == false) {
+                throw GraalInternalError.shouldNotReachHere("opcode: "  + opcode.name() + " x: " + x.getKind() + " y: " + y.getKind());
+        }
     }
 }
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java	Mon Apr 15 08:49:14 2013 +0200
@@ -65,11 +65,15 @@
 
     public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXCompare opcode, Condition condition, Value x, Value y) {
         if (isConstant(x)) {
-            int a = tasm.asIntConst(x);
-            Register b = asIntReg(y);
             switch (opcode) {
                 case ICMP:
-                    emitCompareConstReg(masm, condition, a, b);
+                    emitCompareConstReg(masm, condition, tasm.asIntConst(x), asIntReg(y));
+                    break;
+                case FCMP:
+                    emitCompareConstReg(masm, condition, tasm.asFloatConst(x), asFloatReg(y));
+                    break;
+                case DCMP:
+                    emitCompareConstReg(masm, condition, tasm.asDoubleConst(x), asDoubleReg(y));
                     break;
                 default:
                     throw GraalInternalError.shouldNotReachHere();
@@ -101,18 +105,75 @@
                     throw GraalInternalError.shouldNotReachHere();
             }
         } else {
-            Register a = asIntReg(x);
-            Register b = asIntReg(y);
             switch (opcode) {
                 case ICMP:
-                    emitCompareRegReg(masm, condition, a, b);
+                    emitCompareRegReg(masm, condition, asIntReg(x), asIntReg(y));
+                    break;
+                case LCMP:
+                    emitCompareRegReg(masm, condition, asLongReg(x), asLongReg(y));
+                    break;
+                case FCMP:
+                    emitCompareRegReg(masm, condition, asFloatReg(x), asFloatReg(y));
+                    break;
+                case DCMP:
+                    emitCompareRegReg(masm, condition, asDoubleReg(x), asDoubleReg(y));
                     break;
                 default:
-                    throw GraalInternalError.shouldNotReachHere();
+                    throw GraalInternalError.shouldNotReachHere("missing: "  + opcode);
             }
         }
     }
 
+    private static void emitCompareConstReg(PTXAssembler masm, Condition condition, float a, Register b) {
+        switch (condition) {
+        case EQ:
+            masm.setp_eq_f32(a, b);
+            break;
+        case NE:
+            masm.setp_ne_f32(a, b);
+            break;
+        case LT:
+            masm.setp_lt_f32(a, b);
+            break;
+        case LE:
+            masm.setp_le_f32(a, b);
+            break;
+        case GT:
+            masm.setp_gt_f32(a, b);
+            break;
+        case GE:
+            masm.setp_ge_f32(a, b);
+            break;
+        default:
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private static void emitCompareConstReg(PTXAssembler masm, Condition condition, double a, Register b) {
+        switch (condition) {
+        case EQ:
+            masm.setp_eq_f64(a, b);
+            break;
+        case NE:
+            masm.setp_ne_f64(a, b);
+            break;
+        case LT:
+            masm.setp_lt_f64(a, b);
+            break;
+        case LE:
+            masm.setp_le_f64(a, b);
+            break;
+        case GT:
+            masm.setp_gt_f64(a, b);
+            break;
+        case GE:
+            masm.setp_ge_f64(a, b);
+            break;
+        default:
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
     private static void emitCompareConstReg(PTXAssembler masm, Condition condition, int a, Register b) {
         switch (condition) {
             case EQ:
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Mon Apr 15 08:49:14 2013 +0200
@@ -22,14 +22,28 @@
  */
 package com.oracle.graal.lir.ptx;
 
+import static com.oracle.graal.api.code.ValueUtil.asIntReg;
+import static com.oracle.graal.api.code.ValueUtil.asLongReg;
+import static com.oracle.graal.api.code.ValueUtil.asObjectReg;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.asm.*;
-import com.oracle.graal.asm.ptx.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.api.code.Register;
+import com.oracle.graal.api.code.CompilationResult.JumpTable;
+import com.oracle.graal.api.meta.Constant;
+import com.oracle.graal.api.meta.Kind;
+import com.oracle.graal.api.meta.Value;
+import com.oracle.graal.asm.Buffer;
+import com.oracle.graal.asm.Label;
+import com.oracle.graal.asm.NumUtil;
+import com.oracle.graal.asm.ptx.AbstractPTXAssembler;
+import com.oracle.graal.asm.ptx.PTXAssembler;
+import com.oracle.graal.graph.GraalInternalError;
+import com.oracle.graal.lir.LabelRef;
+import com.oracle.graal.lir.StandardOp;
+import com.oracle.graal.lir.StandardOp.FallThroughOp;
+import com.oracle.graal.lir.Variable;
+import com.oracle.graal.lir.asm.TargetMethodAssembler;
+import com.oracle.graal.nodes.calc.Condition;
 
 public class PTXControlFlow {
 
@@ -64,7 +78,7 @@
         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
             masm.at();
             Label l = destination.label();
-            l.addPatchAt(tasm.asm.codeBuffer.position());
+            // l.addPatchAt(tasm.asm.codeBuffer.position());
             String target = l.isBound() ? "L" + l.toString() : AbstractPTXAssembler.UNBOUND_TARGET;
             masm.bra(target);
         }
@@ -80,4 +94,176 @@
             condition = condition.negate();
         }
     }
+
+    @SuppressWarnings("unused")
+    public static class CondMoveOp extends PTXLIRInstruction {
+        @Def({REG, HINT}) protected Value result;
+        @Alive({REG}) protected Value trueValue;
+        @Use({REG, STACK, CONST}) protected Value falseValue;
+        private final Condition condition;
+
+        public CondMoveOp(Variable result, Condition condition, Variable trueValue, Value falseValue) {
+            this.result = result;
+            this.condition = condition;
+            this.trueValue = trueValue;
+            this.falseValue = falseValue;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            // cmove(tasm, masm, result, false, condition, false, trueValue, falseValue);
+            // see 8.3 Predicated Execution p. 61 of PTX ISA 3.1
+            throw new InternalError("NYI");
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static class FloatCondMoveOp extends PTXLIRInstruction {
+        @Def({REG}) protected Value result;
+        @Alive({REG}) protected Value trueValue;
+        @Alive({REG}) protected Value falseValue;
+        private final Condition condition;
+        private final boolean unorderedIsTrue;
+
+        public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) {
+            this.result = result;
+            this.condition = condition;
+            this.unorderedIsTrue = unorderedIsTrue;
+            this.trueValue = trueValue;
+            this.falseValue = falseValue;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            // cmove(tasm, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue);
+            // see 8.3 Predicated Execution p. 61 of PTX ISA 3.1
+            throw new InternalError("NYI");
+        }
+    }
+
+    public static class SequentialSwitchOp extends PTXLIRInstruction implements FallThroughOp {
+        @Use({CONST}) protected Constant[] keyConstants;
+        private final LabelRef[] keyTargets;
+        private LabelRef defaultTarget;
+        @Alive({REG}) protected Value key;
+        @Temp({REG, ILLEGAL}) protected Value scratch;
+
+        public SequentialSwitchOp(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget,
+                                  Value key, Value scratch) {
+            assert keyConstants.length == keyTargets.length;
+            this.keyConstants = keyConstants;
+            this.keyTargets = keyTargets;
+            this.defaultTarget = defaultTarget;
+            this.key = key;
+            this.scratch = scratch;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            if (key.getKind() == Kind.Int) {
+                Register intKey = asIntReg(key);
+                for (int i = 0; i < keyConstants.length; i++) {
+                    if (tasm.runtime.needsDataPatch(keyConstants[i])) {
+                        tasm.recordDataReferenceInCode(keyConstants[i], 0, true);
+                    }
+                    long lc = keyConstants[i].asLong();
+                    assert NumUtil.isInt(lc);
+                    masm.setp_eq_s32((int) lc, intKey);
+                    masm.at();
+                    Label l = keyTargets[i].label();
+                    l.addPatchAt(tasm.asm.codeBuffer.position());
+                    String target = l.isBound() ? "L" + l.toString() : AbstractPTXAssembler.UNBOUND_TARGET;
+                    masm.bra(target);
+                }
+            } else if (key.getKind() == Kind.Long) {
+                Register longKey = asLongReg(key);
+                for (int i = 0; i < keyConstants.length; i++) {
+                    masm.setp_eq_s64(tasm.asLongConst(keyConstants[i]), longKey);
+                    masm.at();
+                    Label l = keyTargets[i].label();
+                    l.addPatchAt(tasm.asm.codeBuffer.position());
+                    String target = l.isBound() ? "L" + l.toString() : AbstractPTXAssembler.UNBOUND_TARGET;
+                    masm.bra(target);
+                }
+            } else if (key.getKind() == Kind.Object) {
+                Register intKey = asObjectReg(key);
+                Register temp = asObjectReg(scratch);
+                for (int i = 0; i < keyConstants.length; i++) {
+                    PTXMove.move(tasm, masm, temp.asValue(Kind.Object), keyConstants[i]);
+                    masm.setp_eq_u32(intKey, temp);
+                    masm.at();
+                    masm.bra(keyTargets[i].label().toString());
+                }
+            } else {
+                throw new GraalInternalError("sequential switch only supported for int, long and object");
+            }
+            if (defaultTarget != null) {
+                masm.jmp(defaultTarget.label());
+            } else {
+                // masm.hlt();
+            }
+        }
+
+        @Override
+        public LabelRef fallThroughTarget() {
+            return defaultTarget;
+        }
+
+        @Override
+        public void setFallThroughTarget(LabelRef target) {
+            defaultTarget = target;
+        }
+    }
+
+    public static class TableSwitchOp extends PTXLIRInstruction {
+        private final int lowKey;
+        private final LabelRef defaultTarget;
+        private final LabelRef[] targets;
+        @Alive protected Value index;
+        @Temp protected Value scratch;
+
+        public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets,
+                             Variable index, Variable scratch) {
+            this.lowKey = lowKey;
+            this.defaultTarget = defaultTarget;
+            this.targets = targets;
+            this.index = index;
+            this.scratch = scratch;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            tableswitch(tasm, masm, lowKey, defaultTarget, targets, asIntReg(index), asLongReg(scratch));
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private static void tableswitch(TargetMethodAssembler tasm, PTXAssembler masm, int lowKey,
+                                    LabelRef defaultTarget, LabelRef[] targets,
+                                    Register value, Register scratch) {
+        Buffer buf = masm.codeBuffer;
+        // Compare index against jump table bounds
+        int highKey = lowKey + targets.length - 1;
+        if (lowKey != 0) {
+            // subtract the low value from the switch value
+            masm.sub_s32(value, value, lowKey);
+            masm.setp_gt_s32(value, highKey - lowKey);
+        } else {
+            masm.setp_gt_s32(value, highKey);
+        }
+
+        // Jump to default target if index is not within the jump table
+        if (defaultTarget != null) {
+            masm.at();
+            masm.bra(defaultTarget.label().toString());
+        }
+
+        // address of jump table
+        int tablePos = buf.position();
+
+        JumpTable jt = new JumpTable(tablePos, lowKey, highKey, 4);
+        tasm.compilationResult.addAnnotation(jt);
+
+        // PTX: unimp: tableswitch extract
+    }
 }
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java	Mon Apr 15 08:49:14 2013 +0200
@@ -133,9 +133,27 @@
         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
             PTXAddress addr = address.toAddress();
             switch (address.getKind()) {
+                case Byte:
+                    masm.ld_global_s8(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Short:
+                    masm.ld_global_s16(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Char:
+                    masm.ld_global_u16(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
                 case Int:
                     masm.ld_global_s32(asRegister(result), addr.getBase(), addr.getDisplacement());
                     break;
+                case Long:
+                    masm.ld_global_s64(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Float:
+                    masm.ld_global_f32(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Double:
+                    masm.ld_global_f64(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
                 case Object:
                     masm.ld_global_u32(asRegister(result), addr.getBase(), addr.getDisplacement());
                     break;
@@ -162,11 +180,29 @@
             assert isRegister(input);
             PTXAddress addr = address.toAddress();
             switch (address.getKind()) {
+                case Byte:
+                    masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Short:
+                    masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
                 case Int:
                     masm.st_global_s32(addr.getBase(), addr.getDisplacement(), asRegister(input));
                     break;
+                case Long:
+                    masm.st_global_s64(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Float:
+                    masm.st_global_f32(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Double:
+                    masm.st_global_f64(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Object:
+                    masm.st_global_s32(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
                 default:
-                    throw GraalInternalError.shouldNotReachHere();
+                    throw GraalInternalError.shouldNotReachHere("missing: " + address.getKind());
             }
         }
     }
@@ -250,11 +286,20 @@
             case Int:
                 masm.mov_s32(asRegister(result), asRegister(input));
                 break;
+            case Long:
+                masm.mov_s64(asRegister(result), asRegister(input));
+                break;
+            case Float:
+                masm.mov_f32(asRegister(result), asRegister(input));
+                break;
+            case Double:
+                masm.mov_f64(asRegister(result), asRegister(input));
+                break;
             case Object:
                 masm.mov_u64(asRegister(result), asRegister(input));
                 break;
             default:
-                throw GraalInternalError.shouldNotReachHere("kind=" + result.getKind());
+                throw GraalInternalError.shouldNotReachHere("missing: " + input.getKind());
         }
     }
 
@@ -266,8 +311,24 @@
                 }
                 masm.mov_s32(asRegister(result), input.asInt());
                 break;
+            case Long:
+                if (tasm.runtime.needsDataPatch(input)) {
+                    tasm.recordDataReferenceInCode(input, 0, true);
+                }
+                masm.mov_s64(asRegister(result), input.asLong());
+                break;
+            case Object:
+                if (input.isNull()) {
+                    masm.mov_u64(asRegister(result), 0x0L);
+                } else if (tasm.target.inlineObjects) {
+                    tasm.recordDataReferenceInCode(input, 0, true);
+                    masm.mov_u64(asRegister(result), 0xDEADDEADDEADDEADL);
+                } else {
+                    masm.mov_u64(asRegister(result), tasm.recordDataReferenceInCode(input, 0, false));
+                }
+                break;
             default:
-                throw GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere("missing: " + input.getKind());
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InfopointOp.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,49 @@
+/*
+ * 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.lir;
+
+import static com.oracle.graal.lir.LIRInstruction.Opcode;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Emits an infopoint (only mark the position).
+ */
+@Opcode("INFOPOINT")
+public class InfopointOp extends LIRInstruction {
+
+    @State protected LIRFrameState state;
+
+    private final InfopointReason reason;
+
+    public InfopointOp(LIRFrameState state, InfopointReason reason) {
+        this.state = state;
+        this.reason = reason;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm) {
+        tasm.recordInfopoint(tasm.asm.codeBuffer.position(), state, reason);
+    }
+}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Mon Apr 15 08:49:14 2013 +0200
@@ -260,8 +260,8 @@
      * Returns true when this instruction is a call instruction that destroys all caller-saved
      * registers.
      */
-    public final boolean hasCall() {
-        return this instanceof StandardOp.CallOp;
+    public boolean hasCall() {
+        return false;
     }
 
     public final void forEachInput(ValueProcedure proc) {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Mon Apr 15 08:49:14 2013 +0200
@@ -118,13 +118,6 @@
     }
 
     /**
-     * Marker interface for a LIR operation that calls a method, i.e., destroys all caller-saved
-     * registers.
-     */
-    public interface CallOp {
-    }
-
-    /**
      * Meta-operation that defines the incoming method parameters. In the LIR, every register and
      * variable must be defined before it is used. This operation is the definition point of method
      * parameters, but is otherwise a no-op. In particular, it is not the actual method prologue.
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Mon Apr 15 08:49:14 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, 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
@@ -101,7 +101,7 @@
 
         Debug.metric("TargetMethods").increment();
         Debug.metric("CodeBytesEmitted").add(compilationResult.getTargetCodeSize());
-        Debug.metric("SafepointsEmitted").add(compilationResult.getSafepoints().size());
+        Debug.metric("SafepointsEmitted").add(compilationResult.getInfopoints().size());
         Debug.metric("DataPatches").add(compilationResult.getDataReferences().size());
         Debug.metric("ExceptionHandlersEmitted").add(compilationResult.getExceptionHandlers().size());
         Debug.log("Finished target method %s, isStub %b", name, isStub);
@@ -122,7 +122,7 @@
     public void recordImplicitException(int pcOffset, LIRFrameState info) {
         // record an implicit exception point
         if (info != null) {
-            compilationResult.recordSafepoint(pcOffset, info.debugInfo());
+            compilationResult.recordInfopoint(pcOffset, info.debugInfo(), InfopointReason.IMPLICIT_EXCEPTION);
             assert info.exceptionEdge == null;
         }
     }
@@ -137,10 +137,10 @@
         compilationResult.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, false);
     }
 
-    public void recordSafepoint(int pos, LIRFrameState info) {
-        // safepoints always need debug info
+    public void recordInfopoint(int pos, LIRFrameState info, InfopointReason reason) {
+        // infopoints always need debug info
         DebugInfo debugInfo = info.debugInfo();
-        compilationResult.recordSafepoint(pos, debugInfo);
+        compilationResult.recordInfopoint(pos, debugInfo, reason);
     }
 
     public AbstractAddress recordDataReferenceInCode(Constant data, int alignment, boolean inlined) {
@@ -167,6 +167,36 @@
     }
 
     /**
+     * Returns the float value of any constant that can be represented by a 32-bit float value.
+     */
+    public float asFloatConst(Value value) {
+        assert (value.getKind().getStackKind() == Kind.Float && isConstant(value));
+        Constant constant = (Constant) value;
+        assert !runtime.needsDataPatch(constant) : constant + " should be in a DataPatch";
+        return constant.asFloat();
+    }
+
+    /**
+     * Returns the long value of any constant that can be represented by a 64-bit long value.
+     */
+    public long asLongConst(Value value) {
+        assert (value.getKind().getStackKind() == Kind.Long && isConstant(value));
+        Constant constant = (Constant) value;
+        assert !runtime.needsDataPatch(constant) : constant + " should be in a DataPatch";
+        return constant.asLong();
+    }
+
+    /**
+     * Returns the double value of any constant that can be represented by a 64-bit float value.
+     */
+    public double asDoubleConst(Value value) {
+        assert (value.getKind().getStackKind() == Kind.Double && isConstant(value));
+        Constant constant = (Constant) value;
+        assert !runtime.needsDataPatch(constant) : constant + " should be in a DataPatch";
+        return constant.asDouble();
+    }
+
+    /**
      * Returns the address of a float constant that is embedded as a data references into the code.
      */
     public AbstractAddress asFloatConstRef(Value value) {
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Mon Apr 15 08:49:14 2013 +0200
@@ -60,7 +60,7 @@
         while (!loopBegin.isDeleted()) {
             int mark = graph.getMark();
             peel(loop);
-            new CanonicalizerPhase(runtime, assumptions, mark, null).apply(graph);
+            new CanonicalizerPhase.Instance(runtime, assumptions, mark, null).apply(graph);
             if (iterations++ > UNROLL_LIMIT || graph.getNodeCount() > GraalOptions.MaximumDesiredSize * 3) {
                 throw new BailoutException("FullUnroll : Graph seems to grow out of proportion");
             }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java	Mon Apr 15 08:49:14 2013 +0200
@@ -22,31 +22,21 @@
  */
 package com.oracle.graal.loop.phases;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.tiers.*;
 
-public class LoopFullUnrollPhase extends Phase {
+public class LoopFullUnrollPhase extends BasePhase<HighTierContext> {
 
     private static final DebugMetric FULLY_UNROLLED_LOOPS = Debug.metric("FullUnrolls");
-    private final GraalCodeCacheProvider runtime;
-    private final Assumptions assumptions;
-    private int unrollCount;
 
-    public LoopFullUnrollPhase(GraalCodeCacheProvider runtime, Assumptions assumptions) {
-        this.runtime = runtime;
-        this.assumptions = assumptions;
-    }
-
-    public int getUnrollCount() {
-        return unrollCount;
+    public LoopFullUnrollPhase() {
     }
 
     @Override
-    protected void run(StructuredGraph graph) {
+    protected void run(StructuredGraph graph, HighTierContext context) {
         if (graph.hasLoops()) {
             boolean peeled;
             do {
@@ -56,11 +46,10 @@
                 for (LoopEx loop : dataCounted.countedLoops()) {
                     if (LoopPolicies.shouldFullUnroll(loop)) {
                         Debug.log("FullUnroll %s", loop);
-                        LoopTransformations.fullUnroll(loop, runtime, assumptions);
+                        LoopTransformations.fullUnroll(loop, context.getRuntime(), context.getAssumptions());
                         FULLY_UNROLLED_LOOPS.increment();
                         Debug.dump(graph, "After fullUnroll %s", loop);
                         peeled = true;
-                        unrollCount++;
                         break;
                     }
                 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -186,5 +186,5 @@
     }
 
     @NodeIntrinsic
-    public static native <T> T anchor(@ConstantNodeParameter Stamp stamp);
+    public static native BeginNode anchor(@ConstantNodeParameter Stamp stamp);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -29,7 +29,7 @@
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}")
-public class DeoptimizeNode extends ControlSinkNode implements Node.IterableNodeType, LIRLowerable, DeoptimizingNode {
+public class DeoptimizeNode extends ControlSinkNode implements Node.IterableNodeType, Lowerable, LIRLowerable, DeoptimizingNode {
 
     @Input private FrameState deoptState;
 
@@ -51,6 +51,11 @@
     }
 
     @Override
+    public void lower(LoweringTool tool) {
+        tool.getRuntime().lower(this, tool);
+    }
+
+    @Override
     public void generate(LIRGeneratorTool gen) {
         gen.emitDeoptimize(action, this);
     }
@@ -70,6 +75,7 @@
 
     @Override
     public void setDeoptimizationState(FrameState f) {
+        updateUsages(deoptState, f);
         deoptState = f;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -49,6 +49,7 @@
 
     @Override
     public void setDeoptimizationState(FrameState f) {
+        updateUsages(deoptState, f);
         deoptState = f;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Mon Apr 15 08:49:14 2013 +0200
@@ -239,7 +239,7 @@
                 copy.remove(copy.size() - 1);
             }
             ValueNode lastSlot = copy.get(copy.size() - 1);
-            assert lastSlot.kind().getStackKind() == popKind.getStackKind() || (lastSlot instanceof BoxedVirtualObjectNode && popKind == Kind.Object);
+            assert lastSlot.kind().getStackKind() == popKind.getStackKind();
             copy.remove(copy.size() - 1);
         }
         Collections.addAll(copy, pushedValues);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GenericArrayRangeWriteBarrier.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,56 @@
+/*
+ * 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);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,62 @@
+/*
+ * 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.api.code.*;
+import com.oracle.graal.graph.Node.IterableNodeType;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Nodes of this type are inserted into the graph to denote points of interest to debugging.
+ */
+public class InfopointNode extends AbstractStateSplit implements LIRLowerable, IterableNodeType {
+
+    public final InfopointReason reason;
+
+    public InfopointNode(InfopointReason reason) {
+        super(StampFactory.forVoid());
+        this.reason = reason;
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool generator) {
+        generator.visitInfopointNode(this);
+    }
+
+    @Override
+    public boolean hasSideEffect() {
+        return false;
+    }
+
+    @Override
+    public void setStateAfter(FrameState state) {
+        // shield this node from frame state removal
+        // TODO turn InfopointNode into a FixedWithNextNode subclass with a self-maintained
+        // FrameState that is correctly dealt with by scheduling and partial escape analysis
+        if (state != null) {
+            super.setStateAfter(state);
+        }
+    }
+
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Mon Apr 15 08:49:14 2013 +0200
@@ -41,7 +41,7 @@
 
     int bci();
 
-    FixedNode node();
+    FixedNode asNode();
 
     FrameState stateDuring();
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -38,6 +38,7 @@
 public final class InvokeNode extends AbstractStateSplit implements StateSplit, Node.IterableNodeType, Invoke, LIRLowerable, MemoryCheckpoint {
 
     @Input private final CallTargetNode callTarget;
+    @Input private FrameState deoptState;
     private final int bci;
     private boolean polymorphic;
     private boolean useForInlining;
@@ -139,13 +140,16 @@
     }
 
     @Override
-    public FixedNode node() {
+    public FixedNode asNode() {
         return this;
     }
 
     @Override
     public FrameState stateDuring() {
         FrameState stateAfter = stateAfter();
+        if (stateAfter == null) {
+            return null;
+        }
         FrameState stateDuring = stateAfter.duplicateModified(bci(), stateAfter.rethrowException(), kind());
         stateDuring.setDuringCall(true);
         return stateDuring;
@@ -188,7 +192,12 @@
 
     @Override
     public FrameState getDeoptimizationState() {
-        return stateDuring();
+        if (deoptState == null) {
+            FrameState stateDuring = stateDuring();
+            updateUsages(deoptState, stateDuring);
+            deoptState = stateDuring;
+        }
+        return deoptState;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -37,6 +37,7 @@
     @Successor private BeginNode next;
     @Successor private DispatchBeginNode exceptionEdge;
     @Input private final CallTargetNode callTarget;
+    @Input private FrameState deoptState;
     @Input private FrameState stateAfter;
     private final int bci;
     private boolean polymorphic;
@@ -125,7 +126,7 @@
     }
 
     @Override
-    public FixedNode node() {
+    public FixedNode asNode() {
         return this;
     }
 
@@ -234,7 +235,12 @@
 
     @Override
     public FrameState getDeoptimizationState() {
-        return stateDuring();
+        if (deoptState == null) {
+            FrameState stateDuring = stateDuring();
+            updateUsages(deoptState, stateDuring);
+            deoptState = stateDuring;
+        }
+        return deoptState;
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialArrayRangeWriteBarrier.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,58 @@
+/*
+ * 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.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+public final class SerialArrayRangeWriteBarrier extends FixedWithNextNode implements Lowerable {
+
+    @Input private ValueNode object;
+    @Input private ValueNode startIndex;
+    @Input private ValueNode length;
+
+    public ValueNode getObject() {
+        return object;
+    }
+
+    public ValueNode getStartIndex() {
+        return startIndex;
+    }
+
+    public ValueNode getLength() {
+        return length;
+    }
+
+    public SerialArrayRangeWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) {
+        super(StampFactory.forVoid());
+        this.object = object;
+        this.startIndex = startIndex;
+        this.length = length;
+
+    }
+
+    public void lower(LoweringTool generator) {
+        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/SerialWriteBarrier.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,58 @@
+/*
+ * 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.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+public final class SerialWriteBarrier extends FixedWithNextNode implements Lowerable {
+
+    @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 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) {
+        generator.getRuntime().lower(this, generator);
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -172,5 +172,15 @@
     }
 
     @NodeIntrinsic
-    public static native <S, T> S convert(@ConstantNodeParameter Op op, T value);
+    public static native float convert(@ConstantNodeParameter Op op, int value);
+
+    @NodeIntrinsic
+    public static native int convert(@ConstantNodeParameter Op op, float value);
+
+    @NodeIntrinsic
+    public static native double convert(@ConstantNodeParameter Op op, long value);
+
+    @NodeIntrinsic
+    public static native long convert(@ConstantNodeParameter Op op, double value);
+
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -81,8 +81,35 @@
             // one of them is virtual: they can never be the same objects
             tool.replaceWithValue(LogicConstantNode.contradiction(graph()));
         } else if (xVirtual && yVirtual) {
-            // both are virtual: check if they refer to the same object
-            tool.replaceWithValue(LogicConstantNode.forBoolean(stateX == stateY, graph()));
+            boolean xIdentity = stateX.getVirtualObject().hasIdentity();
+            boolean yIdentity = stateY.getVirtualObject().hasIdentity();
+            if (xIdentity ^ yIdentity) {
+                /*
+                 * One of the two objects has identity, the other doesn't. In code, this looks like
+                 * "Integer.valueOf(a) == new Integer(b)", which is always false.
+                 * 
+                 * In other words: an object created via valueOf can never be equal to one created
+                 * by new in the same compilation unit.
+                 */
+                tool.replaceWithValue(LogicConstantNode.contradiction(graph()));
+            } else if (!xIdentity && !yIdentity) {
+                // both are virtual without identity: check contents
+                assert stateX.getVirtualObject().entryCount() == 1 && stateY.getVirtualObject().entryCount() == 1;
+                assert stateX.getVirtualObject().type() == stateY.getVirtualObject().type();
+                assert stateX.getVirtualObject().entryKind(0) == Kind.Int || stateX.getVirtualObject().entryKind(0) == Kind.Long;
+                final IntegerEqualsNode equals = new IntegerEqualsNode(stateX.getEntry(0), stateY.getEntry(0));
+                tool.customAction(new Runnable() {
+
+                    @Override
+                    public void run() {
+                        graph().add(equals);
+                    }
+                });
+                tool.replaceWithValue(equals);
+            } else {
+                // both are virtual with identity: check if they refer to the same object
+                tool.replaceWithValue(LogicConstantNode.forBoolean(stateX == stateY, graph()));
+            }
         }
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -121,6 +121,9 @@
 
     @Override
     public void lower(LoweringTool tool) {
+        if (!enabled) {
+            throw new GraalInternalError("counter nodes shouldn't exist when not enabled");
+        }
         StructuredGraph graph = (StructuredGraph) graph();
         if (excludedClassPrefix == null || !graph.method().getDeclaringClass().getName().startsWith(excludedClassPrefix)) {
             int index = addContext ? getIndex(name + " @ " + MetaUtil.format("%h.%n", ((StructuredGraph) graph()).method())) : getIndex(name);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java	Mon Apr 15 08:49:14 2013 +0200
@@ -33,5 +33,5 @@
 
     void setNullCheck(boolean check);
 
-    Node node();
+    Node asNode();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -79,7 +79,7 @@
     }
 
     @Override
-    public Node node() {
+    public Node asNode() {
         return this;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -23,80 +23,84 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
-
-public final class BoxNode extends AbstractStateSplit implements StateSplit, Node.IterableNodeType, Canonicalizable {
+import com.oracle.graal.nodes.virtual.*;
 
-    @Input private ValueNode source;
-    private final int bci;
-    private final Kind sourceKind;
+/**
+ * This node represents the boxing of a primitive value. This corresponds to a call to the valueOf
+ * methods in Integer, Long, etc.
+ */
+public class BoxNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Canonicalizable {
 
-    public BoxNode(ValueNode value, ResolvedJavaType type, Kind sourceKind, int bci) {
-        super(StampFactory.exactNonNull(type));
-        this.source = value;
-        this.bci = bci;
-        this.sourceKind = sourceKind;
-        assert value.kind() != Kind.Object : "can only box from primitive type";
+    @Input private ValueNode value;
+    private final Kind boxingKind;
+
+    public BoxNode(ValueNode value, ResolvedJavaType resultType, Kind boxingKind) {
+        super(StampFactory.exactNonNull(resultType));
+        this.value = value;
+        this.boxingKind = boxingKind;
     }
 
-    public ValueNode source() {
-        return source;
-    }
-
-    public Kind getSourceKind() {
-        return sourceKind;
+    public Kind getBoxingKind() {
+        return boxingKind;
     }
 
-    public void expand(BoxingMethodPool pool) {
-        ResolvedJavaMethod boxingMethod = pool.getBoxingMethod(sourceKind);
-        MethodCallTargetNode callTarget = graph().add(
-                        new MethodCallTargetNode(InvokeKind.Static, boxingMethod, new ValueNode[]{source}, boxingMethod.getSignature().getReturnType(boxingMethod.getDeclaringClass())));
-        InvokeNode invokeNode = graph().add(new InvokeNode(callTarget, bci));
-        invokeNode.setProbability(this.probability());
-        invokeNode.setStateAfter(stateAfter());
-        ((StructuredGraph) graph()).replaceFixedWithFixed(this, invokeNode);
+    public ValueNode getValue() {
+        return value;
+    }
+
+    @Override
+    public void lower(LoweringTool tool) {
+        tool.getRuntime().lower(this, tool);
     }
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
+        /*
+         * Constant values are not canonicalized into their constant boxing objects because this
+         * would mean that the information that they came from a valueOf is lost.
+         */
+        if (usages().isEmpty()) {
+            return null;
+        }
+        return this;
+    }
 
-        if (source.isConstant()) {
-            Constant sourceConstant = source.asConstant();
-            switch (sourceKind) {
-                case Boolean:
-                    return ConstantNode.forObject(Boolean.valueOf(sourceConstant.asBoolean()), tool.runtime(), graph());
-                case Byte:
-                    return ConstantNode.forObject(Byte.valueOf((byte) sourceConstant.asInt()), tool.runtime(), graph());
-                case Char:
-                    return ConstantNode.forObject(Character.valueOf((char) sourceConstant.asInt()), tool.runtime(), graph());
-                case Short:
-                    return ConstantNode.forObject(Short.valueOf((short) sourceConstant.asInt()), tool.runtime(), graph());
-                case Int:
-                    return ConstantNode.forObject(Integer.valueOf(sourceConstant.asInt()), tool.runtime(), graph());
-                case Long:
-                    return ConstantNode.forObject(Long.valueOf(sourceConstant.asLong()), tool.runtime(), graph());
-                case Float:
-                    return ConstantNode.forObject(Float.valueOf(sourceConstant.asFloat()), tool.runtime(), graph());
-                case Double:
-                    return ConstantNode.forObject(Double.valueOf(sourceConstant.asDouble()), tool.runtime(), graph());
-                default:
-                    assert false : "Unexpected source kind for boxing";
-                    break;
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        ValueNode v = tool.getReplacedValue(getValue());
+        ResolvedJavaType type = objectStamp().type();
+
+        VirtualBoxingNode newVirtual = new VirtualBoxingNode(type, boxingKind);
+        assert newVirtual.getFields().length == 1;
+
+        tool.createVirtualObject(newVirtual, new ValueNode[]{v}, 0);
+        tool.replaceWithVirtual(newVirtual);
+    }
+
+    @NodeIntrinsic
+    public static native Boolean box(boolean value, @ConstantNodeParameter Class<?> clazz, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native Byte box(byte value, @ConstantNodeParameter Class<?> clazz, @ConstantNodeParameter Kind kind);
 
-            }
-        }
+    @NodeIntrinsic
+    public static native Character box(char value, @ConstantNodeParameter Class<?> clazz, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native Double box(double value, @ConstantNodeParameter Class<?> clazz, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native Float box(float value, @ConstantNodeParameter Class<?> clazz, @ConstantNodeParameter Kind kind);
 
-        for (Node usage : usages()) {
-            if (usage != stateAfter()) {
-                return this;
-            }
-        }
-        replaceAtUsages(null);
-        return null;
-    }
+    @NodeIntrinsic
+    public static native Integer box(int value, @ConstantNodeParameter Class<?> clazz, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native Long box(long value, @ConstantNodeParameter Class<?> clazz, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native Short box(short value, @ConstantNodeParameter Class<?> clazz, @ConstantNodeParameter Kind kind);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxingMethodPool.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +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.graal.nodes.extended;
-
-import java.util.*;
-
-import com.oracle.graal.api.meta.*;
-
-public class BoxingMethodPool {
-
-    private final Set<JavaMethod> specialMethods = new HashSet<>();
-    private final MetaAccessProvider runtime;
-    private final ResolvedJavaMethod[] boxingMethods = new ResolvedJavaMethod[Kind.values().length];
-    private final ResolvedJavaMethod[] unboxingMethods = new ResolvedJavaMethod[Kind.values().length];
-    private final ResolvedJavaField[] boxFields = new ResolvedJavaField[Kind.values().length];
-
-    public BoxingMethodPool(MetaAccessProvider runtime) {
-        this.runtime = runtime;
-
-        try {
-            initialize(Kind.Boolean, Boolean.class, "booleanValue");
-            initialize(Kind.Byte, Byte.class, "byteValue");
-            initialize(Kind.Char, Character.class, "charValue");
-            initialize(Kind.Short, Short.class, "shortValue");
-            initialize(Kind.Int, Integer.class, "intValue");
-            initialize(Kind.Long, Long.class, "longValue");
-            initialize(Kind.Float, Float.class, "floatValue");
-            initialize(Kind.Double, Double.class, "doubleValue");
-        } catch (SecurityException | NoSuchMethodException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    private void initialize(Kind kind, Class<?> type, String unboxMethod) throws SecurityException, NoSuchMethodException {
-        // Get boxing method from runtime.
-        ResolvedJavaMethod boxingMethod = runtime.lookupJavaMethod(type.getDeclaredMethod("valueOf", kind.toJavaClass()));
-        specialMethods.add(boxingMethod);
-        boxingMethods[kind.ordinal()] = boxingMethod;
-
-        // Get unboxing method from runtime.
-        ResolvedJavaMethod unboxingMethod = runtime.lookupJavaMethod(type.getDeclaredMethod(unboxMethod));
-        unboxingMethods[kind.ordinal()] = unboxingMethod;
-        specialMethods.add(unboxingMethod);
-
-        // Get the field that contains the boxed value.
-        ResolvedJavaField[] fields = runtime.lookupJavaType(type).getInstanceFields(false);
-        ResolvedJavaField boxField = fields[0];
-        assert fields.length == 1 && boxField.getKind() == kind;
-        boxFields[kind.ordinal()] = boxField;
-    }
-
-    public boolean isSpecialMethod(ResolvedJavaMethod method) {
-        return specialMethods.contains(method);
-    }
-
-    public boolean isBoxingMethod(ResolvedJavaMethod method) {
-        return isSpecialMethod(method) && method.getSignature().getReturnKind() == Kind.Object;
-    }
-
-    public boolean isUnboxingMethod(ResolvedJavaMethod method) {
-        return isSpecialMethod(method) && method.getSignature().getReturnKind() != Kind.Object;
-    }
-
-    public ResolvedJavaMethod getBoxingMethod(Kind kind) {
-        return boxingMethods[kind.ordinal()];
-    }
-
-    public ResolvedJavaMethod getUnboxingMethod(Kind kind) {
-        return unboxingMethods[kind.ordinal()];
-    }
-
-    public ResolvedJavaField getBoxField(Kind kind) {
-        return boxFields[kind.ordinal()];
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -76,7 +76,7 @@
     }
 
     @Override
-    public Node node() {
+    public Node asNode() {
         return this;
     }
 
@@ -97,6 +97,7 @@
 
     @Override
     public void setDeoptimizationState(FrameState f) {
+        updateUsages(deoptState, f);
         deoptState = f;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -105,7 +105,7 @@
             ResolvedJavaType fieldType = ((ResolvedJavaField) locId).getDeclaringClass();
             ResolvedJavaType beforePiType = parent.object().objectStamp().type();
 
-            if (fieldType.isAssignableFrom(beforePiType)) {
+            if (beforePiType != null && fieldType.isAssignableFrom(beforePiType)) {
                 replaceFirstInput(parent, parent.object());
                 return true;
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -81,7 +81,8 @@
             if ((stateDuring.stackSize() > 0 && stateDuring.stackAt(stateDuring.stackSize() - 1) == this) || (stateDuring.stackSize() > 1 && stateDuring.stackAt(stateDuring.stackSize() - 2) == this)) {
                 stateDuring = stateDuring.duplicateModified(stateDuring.bci, stateDuring.rethrowException(), this.kind());
             }
-            return stateDuring;
+            updateUsages(deoptState, stateDuring);
+            return deoptState = stateDuring;
         }
         return null;
     }
@@ -91,6 +92,7 @@
         if (deoptState != null) {
             throw new IllegalStateException();
         }
+        updateUsages(deoptState, f);
         deoptState = f;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -23,47 +23,49 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public final class UnboxNode extends FixedWithNextNode implements Node.IterableNodeType, Canonicalizable {
+public class UnboxNode extends FixedWithNextNode implements Virtualizable, Lowerable, Canonicalizable {
 
-    @Input private ValueNode source;
-    private Kind destinationKind;
+    @Input private ValueNode value;
+    private final Kind boxingKind;
 
-    public UnboxNode(Kind kind, ValueNode source) {
-        super(StampFactory.forKind(kind));
-        this.source = source;
-        this.destinationKind = kind;
-        assert kind != Kind.Object : "can only unbox to primitive";
-        assert source.kind() == Kind.Object : "can only unbox objects";
+    public UnboxNode(ValueNode value, Kind boxingKind) {
+        super(StampFactory.forKind(boxingKind.getStackKind()));
+        this.value = value;
+        this.boxingKind = boxingKind;
+    }
+
+    public Kind getBoxingKind() {
+        return boxingKind;
     }
 
-    public ValueNode source() {
-        return source;
+    public ValueNode getValue() {
+        return value;
     }
 
-    public Kind destinationKind() {
-        return destinationKind;
+    @Override
+    public void lower(LoweringTool tool) {
+        tool.getRuntime().lower(this, tool);
     }
 
-    public void expand(BoxingMethodPool pool) {
-        ResolvedJavaField field = pool.getBoxField(kind());
-        LoadFieldNode loadField = graph().add(new LoadFieldNode(source, field));
-        loadField.setProbability(probability());
-        ((StructuredGraph) graph()).replaceFixedWithFixed(this, loadField);
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        State state = tool.getObjectState(value);
+        if (state != null && state.getState() == EscapeState.Virtual) {
+            tool.replaceWithValue(state.getEntry(0));
+        }
     }
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        if (source.isConstant()) {
-            Constant constant = source.asConstant();
+        if (value.isConstant()) {
+            Constant constant = value.asConstant();
             Object o = constant.asObject();
             if (o != null) {
-                switch (destinationKind) {
+                switch (boxingKind) {
                     case Boolean:
                         return ConstantNode.forBoolean((Boolean) o, graph());
                     case Byte:
@@ -84,7 +86,36 @@
                         ValueNodeUtil.shouldNotReachHere();
                 }
             }
+        } else if (value instanceof BoxNode) {
+            return ((BoxNode) value).getValue();
+        }
+        if (usages().isEmpty()) {
+            return null;
         }
         return this;
     }
+
+    @NodeIntrinsic
+    public static native boolean unbox(Boolean value, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native byte unbox(Byte value, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native char unbox(Character value, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native double unbox(Double value, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native float unbox(Float value, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native int unbox(Integer value, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native long unbox(Long value, @ConstantNodeParameter Kind kind);
+
+    @NodeIntrinsic
+    public static native short unbox(Short value, @ConstantNodeParameter Kind kind);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -37,8 +37,8 @@
         return length;
     }
 
-    public UnsafeArrayCastNode(ValueNode object, ValueNode length, Stamp stamp) {
-        super(object, stamp);
+    public UnsafeArrayCastNode(ValueNode object, ValueNode length, Stamp stamp, ValueNode anchor) {
+        super(object, stamp, anchor);
         this.length = length;
     }
 
@@ -51,5 +51,5 @@
     }
 
     @NodeIntrinsic
-    public static native <T> T unsafeArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp);
+    public static native <T> T unsafeArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp, Object anchor);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -25,14 +25,34 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.graph.*;
 
 /**
  * Writes a given {@linkplain #value() value} a {@linkplain AccessNode memory location}.
  */
-public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint {
+public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint, Node.IterableNodeType {
 
     @Input private ValueNode value;
     @Input(notDataflow = true) private FrameState stateAfter;
+    private final WriteBarrierType barrierType;
+
+    /*
+     * The types of write barriers attached to stores.
+     */
+    public enum WriteBarrierType {
+        /*
+         * Primitive stores which do not necessitate write barriers.
+         */
+        NONE,
+        /*
+         * Array object stores which necessitate precise write barriers.
+         */
+        PRECISE,
+        /*
+         * Field object stores which necessitate imprecise write barriers.
+         */
+        IMPRECISE
+    }
 
     public FrameState stateAfter() {
         return stateAfter;
@@ -52,9 +72,14 @@
         return value;
     }
 
-    public WriteNode(ValueNode object, ValueNode value, ValueNode location) {
+    public WriteBarrierType getWriteBarrierType() {
+        return barrierType;
+    }
+
+    public WriteNode(ValueNode object, ValueNode value, ValueNode location, WriteBarrierType barrierType) {
         super(object, location, StampFactory.forVoid());
         this.value = value;
+        this.barrierType = barrierType;
     }
 
     @Override
@@ -63,7 +88,7 @@
     }
 
     @NodeIntrinsic
-    public static native void writeMemory(Object object, Object value, Object location);
+    public static native void writeMemory(Object object, Object value, Object location, @ConstantNodeParameter boolean usePreciseWriteBarriers);
 
     @Override
     public Object[] getLocationIdentities() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -28,6 +28,7 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.virtual.*;
 
 /**
  * The {@code AccessMonitorNode} is the base class of both monitor acquisition and release.
@@ -72,7 +73,7 @@
     @Override
     public void virtualize(VirtualizerTool tool) {
         State state = tool.getObjectState(object);
-        if (state != null && state.getState() == EscapeState.Virtual) {
+        if (state != null && state.getState() == EscapeState.Virtual && state.getVirtualObject().getClass() == VirtualInstanceNode.class) {
             Debug.log("monitor operation %s on %s\n", this, state);
             int newLockCount = state.getLockCount() + (this instanceof MonitorEnterNode ? 1 : -1);
             state.setLockCount(newLockCount);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -102,7 +102,9 @@
     public void virtualize(VirtualizerTool tool) {
         State state = tool.getObjectState(object);
         if (state != null && state.getState() == EscapeState.Virtual) {
-            tool.replaceWithVirtual(state.getVirtualObject());
+            if (type.isAssignableFrom(state.getVirtualObject().type())) {
+                tool.replaceWithVirtual(state.getVirtualObject());
+            }
         }
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -25,8 +25,10 @@
 import static com.oracle.graal.graph.UnsafeAccess.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.extended.WriteNode.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -34,13 +36,14 @@
  * Represents an atomic compare-and-swap operation The result is a boolean that contains whether the
  * value matched the expected value.
  */
-public class CompareAndSwapNode extends AbstractStateSplit implements StateSplit, LIRLowerable, Lowerable, MemoryCheckpoint {
+public class CompareAndSwapNode extends AbstractStateSplit implements StateSplit, LIRLowerable, Lowerable, MemoryCheckpoint, Node.IterableNodeType {
 
     @Input private ValueNode object;
     @Input private ValueNode offset;
     @Input private ValueNode expected;
     @Input private ValueNode newValue;
     private final int displacement;
+    private WriteBarrierType barrierType;
 
     public ValueNode object() {
         return object;
@@ -62,6 +65,14 @@
         return displacement;
     }
 
+    public WriteBarrierType getWriteBarrierType() {
+        return barrierType;
+    }
+
+    public void setWriteBarrierType(WriteBarrierType type) {
+        this.barrierType = type;
+    }
+
     public CompareAndSwapNode(ValueNode object, int displacement, ValueNode offset, ValueNode expected, ValueNode newValue) {
         super(StampFactory.forKind(Kind.Boolean.getStackKind()));
         assert expected.kind() == newValue.kind();
@@ -70,6 +81,7 @@
         this.expected = expected;
         this.newValue = newValue;
         this.displacement = displacement;
+        this.barrierType = WriteBarrierType.NONE;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -48,8 +48,15 @@
         //
     }
 
+    private boolean isLowered() {
+        return (stamp() == StampFactory.forVoid());
+    }
+
     @Override
     public void lower(LoweringTool tool) {
+        if (isLowered()) {
+            return;
+        }
         StructuredGraph graph = (StructuredGraph) graph();
         LoadExceptionObjectNode loadException = graph.add(new LoadExceptionObjectNode(stamp()));
         loadException.setStateAfter(stateAfter());
@@ -62,6 +69,9 @@
 
     @Override
     public boolean verify() {
+        if (isLowered()) {
+            return true;
+        }
         assertTrue(stateAfter() != null || stamp() == StampFactory.forVoid(), "an exception handler needs a frame state");
         return super.verify();
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -65,7 +65,8 @@
         } else if (stamp.type() != null && !stamp.type().hasFinalizableSubclass()) {
             // if either the declared type of receiver or the holder
             // can be assumed to have no finalizers
-            if (tool.assumptions().useOptimisticAssumptions() && tool.assumptions().recordNoFinalizableSubclassAssumption(stamp.type())) {
+            if (tool.assumptions().useOptimisticAssumptions()) {
+                tool.assumptions().recordNoFinalizableSubclassAssumption(stamp.type());
                 needsCheck = false;
             }
         }
@@ -97,6 +98,7 @@
 
     @Override
     public void setDeoptimizationState(FrameState f) {
+        updateUsages(deoptState, f);
         deoptState = f;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java	Mon Apr 15 08:49:14 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.spi;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 
 /**
@@ -30,5 +31,17 @@
  */
 public interface GraalCodeCacheProvider extends CodeCacheProvider {
 
+    /**
+     * Adds the given compilation result as an implementation of the given method without making it
+     * the default implementation. The graph might be inlined later on.
+     * 
+     * @param method a method to which the executable code is begin added
+     * @param compResult the compilation result to be added
+     * @param graph the graph that represents the method
+     * @return a reference to the compiled and ready-to-run code or null if the code installation
+     *         failed
+     */
+    InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, Graph graph);
+
     void lower(Node n, LoweringTool tool);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Mon Apr 15 08:49:14 2013 +0200
@@ -137,4 +137,6 @@
      */
     public void beforeRegisterAllocation() {
     }
+
+    public abstract void visitInfopointNode(InfopointNode i);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MacroSubstitution.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MacroSubstitution.java	Mon Apr 15 08:49:14 2013 +0200
@@ -61,9 +61,25 @@
     String signature() default "";
 
     /**
+     * Determines if the substitution is for a method that may not be part of the runtime. For
+     * example, a method introduced in a later JDK version. Substitutions for such methods are
+     * omitted if the original method cannot be found.
+     */
+    boolean optional() default false;
+
+    /**
      * The node class with which the method invocation should be replaced. It needs to be a subclass
      * of {@link FixedWithNextNode}, and it is expected to provide a public constructor that takes
      * an {@link InvokeNode} as a parameter.
      */
     Class<? extends FixedWithNextNode> macro();
+
+    /**
+     * Determines if this method should be substituted in all cases, even if inlining thinks it is
+     * not important.
+     * 
+     * Not that this is still depending on whether inlining sees the correct call target, so it's
+     * only a hard guarantee for static and special invocations.
+     */
+    boolean forced() default false;
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java	Mon Apr 15 08:49:14 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes.spi;
 
+import java.util.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
@@ -61,13 +63,19 @@
     Assumptions getAssumptions();
 
     /**
-     * Registers all the snippet methods defined by a given class.
-     */
-    void registerSnippets(Class<?> snippets);
-
-    /**
      * Registers all the {@linkplain MethodSubstitution method} and {@linkplain MacroSubstitution
      * macro} substitutions defined by a given class.
      */
     void registerSubstitutions(Class<?> substitutions);
+
+    /**
+     * Returns all methods that are currently registered as method/macro substitution or as a
+     * snippet.
+     */
+    Collection<ResolvedJavaMethod> getAllReplacements();
+
+    /**
+     * Determines whether the replacement of this method is flagged as being inlined always.
+     */
+    boolean isForcedSubstitution(ResolvedJavaMethod methodAt);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Mon Apr 15 08:49:14 2013 +0200
@@ -23,12 +23,15 @@
 package com.oracle.graal.nodes.type;
 
 import com.oracle.graal.api.code.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.type.GenericStamp.GenericStampType;
 
 public class StampFactory {
 
+    // JaCoCo Exclude
+
     private static final Stamp[] stampCache = new Stamp[Kind.values().length];
     private static final Stamp objectStamp = new ObjectStamp(null, false, false, false);
     private static final Stamp objectNonNullStamp = new ObjectStamp(null, false, true, false);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Mon Apr 15 08:49:14 2013 +0200
@@ -202,7 +202,7 @@
         while (n != null) {
             if (n instanceof MethodCallTargetNode) {
                 elements.add(((MethodCallTargetNode) n).targetMethod().asStackTraceElement(-1));
-                n = ((MethodCallTargetNode) n).invoke().node();
+                n = ((MethodCallTargetNode) n).invoke().asNode();
             }
 
             if (n instanceof StateSplit) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2011, 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.graal.nodes.virtual;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-
-public class BoxedVirtualObjectNode extends VirtualObjectNode implements LIRLowerable, Node.ValueNumberable {
-
-    @Input ValueNode unboxedValue;
-    private final ResolvedJavaType type;
-    private final Kind kind;
-
-    public BoxedVirtualObjectNode(ResolvedJavaType type, Kind kind, ValueNode unboxedValue) {
-        this.type = type;
-        this.kind = kind;
-        this.unboxedValue = unboxedValue;
-    }
-
-    public ValueNode getUnboxedValue() {
-        return unboxedValue;
-    }
-
-    @Override
-    public ResolvedJavaType type() {
-        return type;
-    }
-
-    @Override
-    public int entryCount() {
-        return 1;
-    }
-
-    @Override
-    public String fieldName(int index) {
-        assert index == 0;
-        return "value";
-    }
-
-    @Override
-    public int entryIndexForOffset(long constantOffset) {
-        // (lstadler) unsafe access to a newly created boxing object should only ever touch the
-        // value field
-        return 0;
-    }
-
-    @Override
-    public Kind entryKind(int index) {
-        return kind;
-    }
-
-    @Override
-    public BoxedVirtualObjectNode duplicate() {
-        return new BoxedVirtualObjectNode(type, kind, unboxedValue);
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -22,10 +22,14 @@
  */
 package com.oracle.graal.nodes.virtual;
 
+import java.util.*;
+
 import sun.misc.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(nameTemplate = "VirtualArray {p#componentType/s}[{p#length}]")
@@ -137,4 +141,19 @@
     public VirtualArrayNode duplicate() {
         return new VirtualArrayNode(componentType, length);
     }
+
+    @Override
+    public void materializeAt(FixedWithNextNode materializeNode, List<ValueNode> values, boolean defaultValuesOnly, int lockCount) {
+        StructuredGraph graph = (StructuredGraph) graph();
+        ResolvedJavaType element = componentType();
+        NewArrayNode newArray = graph.add(new NewArrayNode(element, ConstantNode.forInt(entryCount(), graph), defaultValuesOnly, lockCount > 0));
+        materializeNode.replaceAtUsages(newArray);
+        graph.addBeforeFixed(materializeNode, newArray);
+        if (!defaultValuesOnly) {
+            for (int i = 0; i < entryCount(); i++) {
+                graph.addBeforeFixed(materializeNode, graph.add(new StoreIndexedNode(newArray, ConstantNode.forInt(i, graph), element.getKind(), values.get(i))));
+            }
+        }
+        graph.removeFixed(materializeNode);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualBoxingNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,58 @@
+/*
+ * 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.virtual;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+
+public class VirtualBoxingNode extends VirtualInstanceNode {
+
+    private final Kind boxingKind;
+
+    public VirtualBoxingNode(ResolvedJavaType type, Kind boxingKind) {
+        super(type);
+        this.boxingKind = boxingKind;
+    }
+
+    @Override
+    public VirtualBoxingNode duplicate() {
+        return new VirtualBoxingNode(type(), boxingKind);
+    }
+
+    @Override
+    public boolean hasIdentity() {
+        return false;
+    }
+
+    @Override
+    public void materializeAt(FixedWithNextNode materializeNode, List<ValueNode> values, boolean defaultValuesOnly, int lockCount) {
+        assert values.size() == 1;
+        assert lockCount == 0;
+        StructuredGraph graph = (StructuredGraph) graph();
+        BoxNode valueOf = graph.add(new BoxNode(values.get(0), type(), boxingKind));
+        graph.replaceFixedWithFixed(materializeNode, valueOf);
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -22,8 +22,12 @@
  */
 package com.oracle.graal.nodes.virtual;
 
+import java.util.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
 
 @NodeInfo(nameTemplate = "VirtualInstance {p#type}")
 public class VirtualInstanceNode extends VirtualObjectNode {
@@ -93,4 +97,18 @@
     public VirtualInstanceNode duplicate() {
         return new VirtualInstanceNode(type);
     }
+
+    @Override
+    public void materializeAt(FixedWithNextNode materializeNode, List<ValueNode> values, boolean defaultValuesOnly, int lockCount) {
+        StructuredGraph graph = (StructuredGraph) graph();
+        NewInstanceNode newInstance = graph.add(new NewInstanceNode(type(), defaultValuesOnly, lockCount > 0));
+        materializeNode.replaceAtUsages(newInstance);
+        graph.addBeforeFixed(materializeNode, newInstance);
+        if (!defaultValuesOnly) {
+            for (int i = 0; i < entryCount(); i++) {
+                graph.addBeforeFixed(materializeNode, graph.add(new StoreFieldNode(newInstance, field(i), values.get(i))));
+            }
+        }
+        graph.removeFixed(materializeNode);
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes.virtual;
 
+import java.util.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -46,13 +48,15 @@
 
     public abstract String fieldName(int i);
 
-    public void materializeAt(@SuppressWarnings("unused") FixedNode fixed) {
-        // nothing to do in here - this method allows subclasses to respond to materialization
-    }
+    public abstract void materializeAt(FixedWithNextNode materializeNode, List<ValueNode> values, boolean defaultValuesOnly, int lockCount);
 
     public abstract int entryIndexForOffset(long constantOffset);
 
     public abstract Kind entryKind(int index);
 
     public abstract VirtualObjectNode duplicate();
+
+    public boolean hasIdentity() {
+        return true;
+    }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/BoxingEliminationPhase.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +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.graal.phases.common;
-
-import static com.oracle.graal.graph.iterators.NodePredicates.*;
-
-import java.util.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.iterators.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.virtual.*;
-import com.oracle.graal.phases.*;
-
-public class BoxingEliminationPhase extends Phase {
-
-    private final MetaAccessProvider metaAccess;
-
-    public BoxingEliminationPhase(MetaAccessProvider metaAccess) {
-        this.metaAccess = metaAccess;
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        if (graph.getNodes(UnboxNode.class).isNotEmpty()) {
-
-            Map<PhiNode, PhiNode> phiReplacements = new HashMap<>();
-            for (UnboxNode unboxNode : graph.getNodes(UnboxNode.class)) {
-                tryEliminate(graph, unboxNode, phiReplacements);
-            }
-
-            new DeadCodeEliminationPhase().apply(graph);
-
-            for (BoxNode boxNode : graph.getNodes(BoxNode.class)) {
-                tryEliminate(boxNode);
-            }
-        }
-    }
-
-    private void tryEliminate(StructuredGraph graph, UnboxNode unboxNode, Map<PhiNode, PhiNode> phiReplacements) {
-        ValueNode unboxedValue = unboxedValue(unboxNode.source(), unboxNode.destinationKind(), phiReplacements);
-        if (unboxedValue != null) {
-            assert unboxedValue.kind() == unboxNode.kind();
-            unboxNode.replaceAtUsages(unboxedValue);
-            graph.removeFixed(unboxNode);
-        }
-    }
-
-    private PhiNode getReplacementPhi(PhiNode phiNode, Kind kind, Map<PhiNode, PhiNode> phiReplacements) {
-        if (!phiReplacements.containsKey(phiNode)) {
-            PhiNode result = null;
-            ObjectStamp stamp = phiNode.objectStamp();
-            if (stamp.nonNull() && stamp.isExactType()) {
-                ResolvedJavaType type = stamp.type();
-                if (type != null && type.equals(metaAccess.lookupJavaType(kind.toBoxedJavaClass()))) {
-                    StructuredGraph graph = (StructuredGraph) phiNode.graph();
-                    result = graph.add(new PhiNode(kind, phiNode.merge()));
-                    phiReplacements.put(phiNode, result);
-                    virtualizeUsages(phiNode, result, type, kind);
-                    int i = 0;
-                    for (ValueNode n : phiNode.values()) {
-                        ValueNode unboxedValue = unboxedValue(n, kind, phiReplacements);
-                        if (unboxedValue != null) {
-                            assert unboxedValue.kind() == kind;
-                            result.addInput(unboxedValue);
-                        } else {
-                            UnboxNode unboxNode = graph.add(new UnboxNode(kind, n));
-                            FixedNode pred = phiNode.merge().phiPredecessorAt(i);
-                            graph.addBeforeFixed(pred, unboxNode);
-                            result.addInput(unboxNode);
-                        }
-                        ++i;
-                    }
-                }
-            }
-        }
-        return phiReplacements.get(phiNode);
-    }
-
-    private ValueNode unboxedValue(ValueNode n, Kind kind, Map<PhiNode, PhiNode> phiReplacements) {
-        if (n instanceof BoxNode) {
-            BoxNode boxNode = (BoxNode) n;
-            return boxNode.source();
-        } else if (n instanceof PhiNode) {
-            PhiNode phiNode = (PhiNode) n;
-            return getReplacementPhi(phiNode, kind, phiReplacements);
-        } else {
-            return null;
-        }
-    }
-
-    private static void tryEliminate(BoxNode boxNode) {
-
-        assert boxNode.objectStamp().isExactType();
-        virtualizeUsages(boxNode, boxNode.source(), boxNode.objectStamp().type(), boxNode.getSourceKind());
-
-        if (boxNode.usages().filter(isNotA(VirtualState.class)).isNotEmpty()) {
-            // Elimination failed, because boxing object escapes.
-            return;
-        }
-
-        FrameState stateAfter = boxNode.stateAfter();
-        boxNode.setStateAfter(null);
-        stateAfter.safeDelete();
-
-        ((StructuredGraph) boxNode.graph()).removeFixed(boxNode);
-    }
-
-    private static void virtualizeUsages(ValueNode boxNode, ValueNode replacement, ResolvedJavaType exactType, Kind sourceKind) {
-        ValueNode virtualValueNode = null;
-        VirtualObjectNode virtualObjectNode = null;
-        for (Node n : boxNode.usages().filter(NodePredicates.isA(VirtualState.class)).snapshot()) {
-            if (virtualValueNode == null) {
-                virtualObjectNode = n.graph().unique(new BoxedVirtualObjectNode(exactType, sourceKind, replacement));
-            }
-            n.replaceFirstInput(boxNode, virtualObjectNode);
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Mon Apr 15 08:49:14 2013 +0200
@@ -36,8 +36,9 @@
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.tiers.*;
 
-public class CanonicalizerPhase extends Phase {
+public class CanonicalizerPhase extends BasePhase<PhaseContext> {
 
     private static final int MAX_ITERATION_PER_NODE = 10;
     private static final DebugMetric METRIC_CANONICALIZED_NODES = Debug.metric("CanonicalizedNodes");
@@ -47,155 +48,161 @@
     private static final DebugMetric METRIC_SIMPLIFICATION_CONSIDERED_NODES = Debug.metric("SimplificationConsideredNodes");
     public static final DebugMetric METRIC_GLOBAL_VALUE_NUMBERING_HITS = Debug.metric("GlobalValueNumberingHits");
 
-    private final int newNodesMark;
-    private final Assumptions assumptions;
-    private final MetaAccessProvider runtime;
-    private final CustomCanonicalizer customCanonicalizer;
-    private final Iterable<Node> initWorkingSet;
-
-    private NodeWorkList workList;
-    private Tool tool;
-    private List<Node> snapshotTemp;
-
     public interface CustomCanonicalizer {
 
-        ValueNode canonicalize(Node node);
-    }
-
-    public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions) {
-        this(runtime, assumptions, null, 0, null);
-    }
-
-    /**
-     * @param runtime
-     * @param assumptions
-     * @param workingSet the initial working set of nodes on which the canonicalizer works, should
-     *            be an auto-grow node bitmap
-     * @param customCanonicalizer
-     */
-    public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, CustomCanonicalizer customCanonicalizer) {
-        this(runtime, assumptions, workingSet, 0, customCanonicalizer);
-    }
-
-    /**
-     * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by this
-     *            mark are processed otherwise all nodes in the graph are processed
-     */
-    public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
-        this(runtime, assumptions, null, newNodesMark, customCanonicalizer);
-    }
-
-    public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
-        this.newNodesMark = newNodesMark;
-        this.assumptions = assumptions;
-        this.runtime = runtime;
-        this.customCanonicalizer = customCanonicalizer;
-        this.initWorkingSet = workingSet;
-        this.snapshotTemp = new ArrayList<>();
+        ValueNode canonicalize(ValueNode node);
     }
 
     @Override
-    protected void run(StructuredGraph graph) {
-        if (initWorkingSet == null) {
-            workList = graph.createNodeWorkList(newNodesMark == 0, MAX_ITERATION_PER_NODE);
-        } else {
-            workList = graph.createNodeWorkList(false, MAX_ITERATION_PER_NODE);
-            workList.addAll(initWorkingSet);
-        }
-        if (newNodesMark > 0) {
-            workList.addAll(graph.getNewNodes(newNodesMark));
-        }
-        tool = new Tool(workList, runtime, assumptions);
-        processWorkSet(graph);
+    protected void run(StructuredGraph graph, PhaseContext context) {
+        new Instance(context.getRuntime(), context.getAssumptions()).run(graph);
     }
 
-    private void processWorkSet(StructuredGraph graph) {
-        graph.trackInputChange(new InputChangedListener() {
+    public static class Instance extends Phase {
+
+        private final int newNodesMark;
+        private final Assumptions assumptions;
+        private final MetaAccessProvider runtime;
+        private final CustomCanonicalizer customCanonicalizer;
+        private final Iterable<Node> initWorkingSet;
+
+        private NodeWorkList workList;
+        private Tool tool;
+        private List<Node> snapshotTemp;
+
+        public Instance(MetaAccessProvider runtime, Assumptions assumptions) {
+            this(runtime, assumptions, null, 0, null);
+        }
 
-            @Override
-            public void inputChanged(Node node) {
-                workList.addAgain(node);
-            }
-        });
+        /**
+         * @param runtime
+         * @param assumptions
+         * @param workingSet the initial working set of nodes on which the canonicalizer works,
+         *            should be an auto-grow node bitmap
+         * @param customCanonicalizer
+         */
+        public Instance(MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, CustomCanonicalizer customCanonicalizer) {
+            this(runtime, assumptions, workingSet, 0, customCanonicalizer);
+        }
 
-        for (Node n : workList) {
-            processNode(n, graph);
+        /**
+         * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by
+         *            this mark are processed otherwise all nodes in the graph are processed
+         */
+        public Instance(MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
+            this(runtime, assumptions, null, newNodesMark, customCanonicalizer);
+        }
+
+        public Instance(MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
+            super("Canonicalizer");
+            this.newNodesMark = newNodesMark;
+            this.assumptions = assumptions;
+            this.runtime = runtime;
+            this.customCanonicalizer = customCanonicalizer;
+            this.initWorkingSet = workingSet;
+            this.snapshotTemp = new ArrayList<>();
         }
 
-        graph.stopTrackingInputChange();
-    }
-
-    private void processNode(Node node, StructuredGraph graph) {
-        if (node.isAlive()) {
-            METRIC_PROCESSED_NODES.increment();
-
-            if (tryGlobalValueNumbering(node, graph)) {
-                return;
+        @Override
+        protected void run(StructuredGraph graph) {
+            if (initWorkingSet == null) {
+                workList = graph.createNodeWorkList(newNodesMark == 0, MAX_ITERATION_PER_NODE);
+            } else {
+                workList = graph.createNodeWorkList(false, MAX_ITERATION_PER_NODE);
+                workList.addAll(initWorkingSet);
+            }
+            if (newNodesMark > 0) {
+                workList.addAll(graph.getNewNodes(newNodesMark));
             }
-            int mark = graph.getMark();
-            if (!tryKillUnused(node)) {
-                node.inputs().filter(GraphUtil.isFloatingNode()).snapshotTo(snapshotTemp);
-                if (!tryCanonicalize(node, graph)) {
-                    tryInferStamp(node, graph);
-                } else {
-                    for (Node in : snapshotTemp) {
-                        if (in.isAlive() && in.usages().isEmpty()) {
-                            GraphUtil.killWithUnusedFloatingInputs(in);
+            tool = new Tool(workList, runtime, assumptions);
+            processWorkSet(graph);
+        }
+
+        private void processWorkSet(StructuredGraph graph) {
+            graph.trackInputChange(new InputChangedListener() {
+
+                @Override
+                public void inputChanged(Node node) {
+                    workList.addAgain(node);
+                }
+            });
+
+            for (Node n : workList) {
+                processNode(n, graph);
+            }
+
+            graph.stopTrackingInputChange();
+        }
+
+        private void processNode(Node node, StructuredGraph graph) {
+            if (node.isAlive()) {
+                METRIC_PROCESSED_NODES.increment();
+
+                if (tryGlobalValueNumbering(node, graph)) {
+                    return;
+                }
+                int mark = graph.getMark();
+                if (!tryKillUnused(node)) {
+                    node.inputs().filter(GraphUtil.isFloatingNode()).snapshotTo(snapshotTemp);
+                    if (!tryCanonicalize(node, graph)) {
+                        tryInferStamp(node, graph);
+                    } else {
+                        for (Node in : snapshotTemp) {
+                            if (in.isAlive() && in.usages().isEmpty()) {
+                                GraphUtil.killWithUnusedFloatingInputs(in);
+                            }
                         }
                     }
+                    snapshotTemp.clear();
                 }
-                snapshotTemp.clear();
-            }
 
-            for (Node newNode : graph.getNewNodes(mark)) {
-                workList.add(newNode);
+                for (Node newNode : graph.getNewNodes(mark)) {
+                    workList.add(newNode);
+                }
             }
         }
-    }
 
-    private static boolean tryKillUnused(Node node) {
-        if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.usages().isEmpty()) {
-            GraphUtil.killWithUnusedFloatingInputs(node);
-            return true;
-        }
-        return false;
-    }
-
-    public static boolean tryGlobalValueNumbering(Node node, StructuredGraph graph) {
-        if (node.getNodeClass().valueNumberable()) {
-            Node newNode = graph.findDuplicate(node);
-            if (newNode != null) {
-                assert !(node instanceof FixedNode || newNode instanceof FixedNode);
-                node.replaceAtUsages(newNode);
-                node.safeDelete();
-                METRIC_GLOBAL_VALUE_NUMBERING_HITS.increment();
-                Debug.log("GVN applied and new node is %1s", newNode);
+        private static boolean tryKillUnused(Node node) {
+            if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.usages().isEmpty()) {
+                GraphUtil.killWithUnusedFloatingInputs(node);
                 return true;
             }
+            return false;
         }
-        return false;
-    }
 
-    public boolean tryCanonicalize(final Node node, final StructuredGraph graph) {
-        boolean result = baseTryCanonicalize(node, graph);
-        if (!result && customCanonicalizer != null) {
-            ValueNode canonical = customCanonicalizer.canonicalize(node);
-            if (canonical == node && customCanonicalizer != null) {
-                canonical = customCanonicalizer.canonicalize(node);
+        public static boolean tryGlobalValueNumbering(Node node, StructuredGraph graph) {
+            if (node.getNodeClass().valueNumberable()) {
+                Node newNode = graph.findDuplicate(node);
+                if (newNode != null) {
+                    assert !(node instanceof FixedNode || newNode instanceof FixedNode);
+                    node.replaceAtUsages(newNode);
+                    node.safeDelete();
+                    METRIC_GLOBAL_VALUE_NUMBERING_HITS.increment();
+                    Debug.log("GVN applied and new node is %1s", newNode);
+                    return true;
+                }
             }
-            result = performReplacement(node, graph, canonical);
+            return false;
         }
-        return result;
-    }
 
-    public boolean baseTryCanonicalize(final Node node, final StructuredGraph graph) {
-        if (node instanceof Canonicalizable) {
-            assert !(node instanceof Simplifiable);
-            METRIC_CANONICALIZATION_CONSIDERED_NODES.increment();
-            return Debug.scope("CanonicalizeNode", node, new Callable<Boolean>() {
+        public boolean tryCanonicalize(final Node node, final StructuredGraph graph) {
+            boolean result = baseTryCanonicalize(node, graph);
+            if (!result && customCanonicalizer != null && node instanceof ValueNode) {
+                ValueNode valueNode = (ValueNode) node;
+                ValueNode canonical = customCanonicalizer.canonicalize(valueNode);
+                result = performReplacement(node, graph, canonical);
+            }
+            return result;
+        }
 
-                public Boolean call() {
-                    ValueNode canonical = ((Canonicalizable) node).canonical(tool);
+        public boolean baseTryCanonicalize(final Node node, final StructuredGraph graph) {
+            if (node instanceof Canonicalizable) {
+                assert !(node instanceof Simplifiable);
+                METRIC_CANONICALIZATION_CONSIDERED_NODES.increment();
+                return Debug.scope("CanonicalizeNode", node, new Callable<Boolean>() {
+
+                    public Boolean call() {
+                        ValueNode canonical = ((Canonicalizable) node).canonical(tool);
 // @formatter:off
 //     cases:                                           original node:
 //                                         |Floating|Fixed-unconnected|Fixed-connected|
@@ -211,137 +218,139 @@
 //       X: must not happen (checked with assertions)
 // @formatter:on
 
-                    return performReplacement(node, graph, canonical);
-                }
-            });
-        } else if (node instanceof Simplifiable) {
-            Debug.log("Canonicalizer: simplifying %s", node);
-            METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment();
-            Debug.scope("SimplifyNode", node, new Runnable() {
+                        return performReplacement(node, graph, canonical);
+                    }
+                });
+            } else if (node instanceof Simplifiable) {
+                Debug.log("Canonicalizer: simplifying %s", node);
+                METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment();
+                Debug.scope("SimplifyNode", node, new Runnable() {
 
-                public void run() {
-                    ((Simplifiable) node).simplify(tool);
-                }
-            });
+                    public void run() {
+                        ((Simplifiable) node).simplify(tool);
+                    }
+                });
+            }
+            return node.isDeleted();
         }
-        return node.isDeleted();
-    }
 
-    private boolean performReplacement(final Node node, final StructuredGraph graph, ValueNode canonical) {
-        if (canonical == node) {
-            Debug.log("Canonicalizer: work on %s", node);
-            return false;
-        } else {
-            Debug.log("Canonicalizer: replacing %s with %s", node, canonical);
-            METRIC_CANONICALIZED_NODES.increment();
-            if (node instanceof FloatingNode) {
-                if (canonical == null) {
-                    // case 1
-                    graph.removeFloating((FloatingNode) node);
+        private boolean performReplacement(final Node node, final StructuredGraph graph, ValueNode canonical) {
+            if (canonical == node) {
+                Debug.log("Canonicalizer: work on %s", node);
+                return false;
+            } else {
+                Debug.log("Canonicalizer: replacing %s with %s", node, canonical);
+                METRIC_CANONICALIZED_NODES.increment();
+                if (node instanceof FloatingNode) {
+                    if (canonical == null) {
+                        // case 1
+                        graph.removeFloating((FloatingNode) node);
+                    } else {
+                        // case 2
+                        assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode || canonical instanceof MergeNode) : node + " -> " + canonical +
+                                        " : replacement should be floating or fixed and connected";
+                        graph.replaceFloating((FloatingNode) node, canonical);
+                    }
                 } else {
-                    // case 2
-                    assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode || canonical instanceof MergeNode) : node + " -> " + canonical +
-                                    " : replacement should be floating or fixed and connected";
-                    graph.replaceFloating((FloatingNode) node, canonical);
-                }
-            } else {
-                assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")";
-                FixedWithNextNode fixedWithNext = (FixedWithNextNode) node;
+                    assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")";
+                    FixedWithNextNode fixedWithNext = (FixedWithNextNode) node;
 
-                // When removing a fixed node, new canonicalization opportunities for its successor
-                // may arise
-                assert fixedWithNext.next() != null;
-                tool.addToWorkList(fixedWithNext.next());
+                    // When removing a fixed node, new canonicalization opportunities for its
+// successor
+                    // may arise
+                    assert fixedWithNext.next() != null;
+                    tool.addToWorkList(fixedWithNext.next());
 
-                if (canonical == null) {
-                    // case 3
-                    graph.removeFixed(fixedWithNext);
-                } else if (canonical instanceof FloatingNode) {
-                    // case 4
-                    graph.replaceFixedWithFloating(fixedWithNext, (FloatingNode) canonical);
-                } else {
-                    assert canonical instanceof FixedNode;
-                    if (canonical.predecessor() == null) {
-                        assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors";
-                        // case 5
-                        graph.replaceFixedWithFixed(fixedWithNext, (FixedWithNextNode) canonical);
+                    if (canonical == null) {
+                        // case 3
+                        graph.removeFixed(fixedWithNext);
+                    } else if (canonical instanceof FloatingNode) {
+                        // case 4
+                        graph.replaceFixedWithFloating(fixedWithNext, (FloatingNode) canonical);
                     } else {
-                        assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors";
-                        // case 6
-                        node.replaceAtUsages(canonical);
-                        graph.removeFixed(fixedWithNext);
+                        assert canonical instanceof FixedNode;
+                        if (canonical.predecessor() == null) {
+                            assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors";
+                            // case 5
+                            graph.replaceFixedWithFixed(fixedWithNext, (FixedWithNextNode) canonical);
+                        } else {
+                            assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors";
+                            // case 6
+                            node.replaceAtUsages(canonical);
+                            graph.removeFixed(fixedWithNext);
+                        }
                     }
                 }
+                return true;
             }
-            return true;
         }
-    }
 
-    /**
-     * Calls {@link ValueNode#inferStamp()} on the node and, if it returns true (which means that
-     * the stamp has changed), re-queues the node's usages . If the stamp has changed then this
-     * method also checks if the stamp now describes a constant integer value, in which case the
-     * node is replaced with a constant.
-     */
-    private void tryInferStamp(Node node, StructuredGraph graph) {
-        if (node.isAlive() && node instanceof ValueNode) {
-            ValueNode valueNode = (ValueNode) node;
-            METRIC_INFER_STAMP_CALLED.increment();
-            if (valueNode.inferStamp()) {
-                METRIC_STAMP_CHANGED.increment();
-                if (valueNode.stamp() instanceof IntegerStamp && valueNode.integerStamp().lowerBound() == valueNode.integerStamp().upperBound()) {
-                    ValueNode replacement = ConstantNode.forIntegerKind(valueNode.kind(), valueNode.integerStamp().lowerBound(), graph);
-                    Debug.log("Canonicalizer: replacing %s with %s (inferStamp)", valueNode, replacement);
-                    valueNode.replaceAtUsages(replacement);
-                } else {
-                    for (Node usage : valueNode.usages()) {
-                        workList.addAgain(usage);
+        /**
+         * Calls {@link ValueNode#inferStamp()} on the node and, if it returns true (which means
+         * that the stamp has changed), re-queues the node's usages . If the stamp has changed then
+         * this method also checks if the stamp now describes a constant integer value, in which
+         * case the node is replaced with a constant.
+         */
+        private void tryInferStamp(Node node, StructuredGraph graph) {
+            if (node.isAlive() && node instanceof ValueNode) {
+                ValueNode valueNode = (ValueNode) node;
+                METRIC_INFER_STAMP_CALLED.increment();
+                if (valueNode.inferStamp()) {
+                    METRIC_STAMP_CHANGED.increment();
+                    if (valueNode.stamp() instanceof IntegerStamp && valueNode.integerStamp().lowerBound() == valueNode.integerStamp().upperBound()) {
+                        ValueNode replacement = ConstantNode.forIntegerKind(valueNode.kind(), valueNode.integerStamp().lowerBound(), graph);
+                        Debug.log("Canonicalizer: replacing %s with %s (inferStamp)", valueNode, replacement);
+                        valueNode.replaceAtUsages(replacement);
+                    } else {
+                        for (Node usage : valueNode.usages()) {
+                            workList.addAgain(usage);
+                        }
                     }
                 }
             }
         }
-    }
 
-    private static final class Tool implements SimplifierTool {
+        private static final class Tool implements SimplifierTool {
 
-        private final NodeWorkList nodeWorkSet;
-        private final MetaAccessProvider runtime;
-        private final Assumptions assumptions;
+            private final NodeWorkList nodeWorkSet;
+            private final MetaAccessProvider runtime;
+            private final Assumptions assumptions;
 
-        public Tool(NodeWorkList nodeWorkSet, MetaAccessProvider runtime, Assumptions assumptions) {
-            this.nodeWorkSet = nodeWorkSet;
-            this.runtime = runtime;
-            this.assumptions = assumptions;
-        }
+            public Tool(NodeWorkList nodeWorkSet, MetaAccessProvider runtime, Assumptions assumptions) {
+                this.nodeWorkSet = nodeWorkSet;
+                this.runtime = runtime;
+                this.assumptions = assumptions;
+            }
 
-        @Override
-        public void deleteBranch(FixedNode branch) {
-            branch.predecessor().replaceFirstSuccessor(branch, null);
-            GraphUtil.killCFG(branch);
-        }
+            @Override
+            public void deleteBranch(FixedNode branch) {
+                branch.predecessor().replaceFirstSuccessor(branch, null);
+                GraphUtil.killCFG(branch);
+            }
 
-        /**
-         * @return an object that can be used for recording assumptions or {@code null} if
-         *         assumptions are not allowed in the current context.
-         */
-        @Override
-        public Assumptions assumptions() {
-            return assumptions;
-        }
+            /**
+             * @return an object that can be used for recording assumptions or {@code null} if
+             *         assumptions are not allowed in the current context.
+             */
+            @Override
+            public Assumptions assumptions() {
+                return assumptions;
+            }
 
-        @Override
-        public MetaAccessProvider runtime() {
-            return runtime;
-        }
+            @Override
+            public MetaAccessProvider runtime() {
+                return runtime;
+            }
 
-        @Override
-        public void addToWorkList(Node node) {
-            nodeWorkSet.addAgain(node);
-        }
+            @Override
+            public void addToWorkList(Node node) {
+                nodeWorkSet.addAgain(node);
+            }
 
-        @Override
-        public void removeIfUnused(Node node) {
-            tryKillUnused(node);
+            @Override
+            public void removeIfUnused(Node node) {
+                tryKillUnused(node);
+            }
         }
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java	Mon Apr 15 08:49:14 2013 +0200
@@ -346,7 +346,7 @@
         private static Scope createScope(Loop loop, HashMap<Loop, Scope> processedLoops) {
             Scope parent = processedLoops.get(loop.parent);
             if (parent == null) {
-                parent = createScope(loop, processedLoops);
+                parent = createScope(loop.parent, processedLoops);
             }
             Scope result = new Scope(loop.loopBegin(), parent);
             processedLoops.put(loop, result);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandBoxingNodesPhase.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +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.graal.phases.common;
-
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.phases.*;
-
-public class ExpandBoxingNodesPhase extends Phase {
-
-    private final BoxingMethodPool pool;
-
-    public ExpandBoxingNodesPhase(BoxingMethodPool pool) {
-        this.pool = pool;
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        for (BoxNode boxNode : graph.getNodes(BoxNode.class)) {
-            boxNode.expand(pool);
-        }
-
-        for (UnboxNode unboxNode : graph.getNodes(UnboxNode.class)) {
-            unboxNode.expand(pool);
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2013, 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.phases.common;
+
+import java.util.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.graph.*;
+import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure;
+
+public class FrameStateAssignmentPhase extends Phase {
+
+    private static class FrameStateAssignmentState {
+
+        private FrameState framestate;
+
+        public FrameStateAssignmentState(FrameState framestate) {
+            this.framestate = framestate;
+        }
+
+        public FrameState getFramestate() {
+            return framestate;
+        }
+
+        public void setFramestate(FrameState framestate) {
+            assert framestate != null;
+            this.framestate = framestate;
+        }
+
+        @Override
+        public String toString() {
+            return "FrameStateAssignementState: " + framestate;
+        }
+    }
+
+    private static class FrameStateAssignementClosure extends BlockIteratorClosure<FrameStateAssignmentState> {
+
+        @Override
+        protected void processBlock(Block block, FrameStateAssignmentState currentState) {
+            FixedNode node = block.getBeginNode();
+            while (node != null) {
+                if (node instanceof DeoptimizingNode) {
+                    DeoptimizingNode deopt = (DeoptimizingNode) node;
+                    if (deopt.canDeoptimize() && deopt.getDeoptimizationState() == null) {
+                        deopt.setDeoptimizationState(currentState.getFramestate());
+                    }
+                }
+
+                if (node instanceof StateSplit) {
+                    StateSplit stateSplit = (StateSplit) node;
+                    if (stateSplit.stateAfter() != null) {
+                        currentState.setFramestate(stateSplit.stateAfter());
+                        stateSplit.setStateAfter(null);
+                    }
+                }
+
+                if (node instanceof FixedWithNextNode) {
+                    node = ((FixedWithNextNode) node).next();
+                } else {
+                    node = null;
+                }
+            }
+        }
+
+        @Override
+        protected FrameStateAssignmentState merge(Block mergeBlock, List<FrameStateAssignmentState> states) {
+            MergeNode merge = (MergeNode) mergeBlock.getBeginNode();
+            if (merge.stateAfter() != null) {
+                return new FrameStateAssignmentState(merge.stateAfter());
+            }
+            return new FrameStateAssignmentState(singleFrameState(states));
+        }
+
+        @Override
+        protected FrameStateAssignmentState cloneState(FrameStateAssignmentState oldState) {
+            return new FrameStateAssignmentState(oldState.getFramestate());
+        }
+
+        @Override
+        protected List<FrameStateAssignmentState> processLoop(Loop loop, FrameStateAssignmentState initialState) {
+            return ReentrantBlockIterator.processLoop(this, loop, initialState).exitStates;
+        }
+
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        assert checkFixedDeopts(graph);
+        ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, false, false);
+        ReentrantBlockIterator.apply(new FrameStateAssignementClosure(), cfg.getStartBlock(), new FrameStateAssignmentState(null), null);
+    }
+
+    private static boolean checkFixedDeopts(StructuredGraph graph) {
+        NodePredicate isFloatingNode = GraphUtil.isFloatingNode();
+        for (Node n : graph.getNodes().filterInterface(DeoptimizingNode.class)) {
+            if (((DeoptimizingNode) n).canDeoptimize() && isFloatingNode.apply(n)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static FrameState singleFrameState(List<FrameStateAssignmentState> states) {
+        Iterator<FrameStateAssignmentState> it = states.iterator();
+        assert it.hasNext();
+        FrameState first = it.next().getFramestate();
+        while (it.hasNext()) {
+            if (first != it.next().getFramestate()) {
+                return null;
+            }
+        }
+        return first;
+    }
+}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Mon Apr 15 08:49:14 2013 +0200
@@ -114,12 +114,12 @@
                 Access fixedAccess = access;
                 if (access instanceof FloatingAccessNode) {
                     fixedAccess = ((FloatingAccessNode) access).asFixedNode();
-                    replaceCurrent((FixedWithNextNode) fixedAccess.node());
+                    replaceCurrent((FixedWithNextNode) fixedAccess.asNode());
                 }
                 assert fixedAccess instanceof FixedNode;
                 fixedAccess.setNullCheck(true);
                 LogicNode condition = guard.condition();
-                guard.replaceAndDelete(fixedAccess.node());
+                guard.replaceAndDelete(fixedAccess.asNode());
                 if (condition.usages().isEmpty()) {
                     GraphUtil.killWithUnusedFloatingInputs(condition);
                 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IdentifyBoxingPhase.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +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.graal.phases.common;
-
-import java.lang.reflect.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.phases.*;
-
-public class IdentifyBoxingPhase extends Phase {
-
-    private final BoxingMethodPool pool;
-
-    public IdentifyBoxingPhase(BoxingMethodPool pool) {
-        this.pool = pool;
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        for (Invoke invoke : graph.getInvokes()) {
-            tryIntrinsify(invoke);
-        }
-    }
-
-    public void tryIntrinsify(Invoke invoke) {
-        if (!(invoke.callTarget() instanceof MethodCallTargetNode)) {
-            return;
-        }
-        MethodCallTargetNode callTarget = invoke.methodCallTarget();
-        ResolvedJavaMethod targetMethod = callTarget.targetMethod();
-        if (pool.isSpecialMethod(targetMethod)) {
-            assert callTarget.arguments().size() == 1 : "boxing/unboxing method must have exactly one argument";
-            Kind returnKind = callTarget.returnKind();
-            ValueNode sourceValue = callTarget.arguments().get(0);
-
-            // Check whether this is a boxing or an unboxing.
-            Node newNode = null;
-            if (returnKind == Kind.Object) {
-                // We have a boxing method here.
-                assert Modifier.isStatic(targetMethod.getModifiers()) : "boxing method must be static";
-                Kind sourceKind = targetMethod.getSignature().getParameterKind(0);
-                newNode = invoke.graph().add(new BoxNode(sourceValue, targetMethod.getDeclaringClass(), sourceKind, invoke.bci()));
-            } else {
-                // We have an unboxing method here.
-                assert !Modifier.isStatic(targetMethod.getModifiers()) : "unboxing method must be an instance method";
-                newNode = invoke.graph().add(new UnboxNode(returnKind, sourceValue));
-            }
-
-            // Intrinsify the invoke to the special node.
-            invoke.intrinsify(newNode);
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Mon Apr 15 08:49:14 2013 +0200
@@ -68,7 +68,8 @@
     private static final DebugMetric metricInliningStoppedByMaxDesiredSize = Debug.metric("InliningStoppedByMaxDesiredSize");
     private static final DebugMetric metricInliningRuns = Debug.metric("Runs");
 
-    public InliningPhase(MetaAccessProvider runtime, Map<Invoke, Double> hints, Replacements replacements, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
+    public InliningPhase(MetaAccessProvider runtime, Map<Invoke, Double> hints, Replacements replacements, Assumptions assumptions, GraphCache cache, PhasePlan plan,
+                    OptimisticOptimizations optimisticOpts) {
         this(runtime, replacements, assumptions, cache, plan, createInliningPolicy(runtime, replacements, assumptions, optimisticOpts, hints), optimisticOpts);
     }
 
@@ -110,13 +111,13 @@
                 if (isWorthInlining) {
                     int mark = graph.getMark();
                     try {
-                        List<Node> invokeUsages = candidate.invoke().node().usages().snapshot();
+                        List<Node> invokeUsages = candidate.invoke().asNode().usages().snapshot();
                         candidate.inline(graph, runtime, replacements, this, assumptions);
                         Debug.dump(graph, "after %s", candidate);
                         Iterable<Node> newNodes = graph.getNewNodes(mark);
                         inliningPolicy.scanInvokes(newNodes);
                         if (GraalOptions.OptCanonicalizer) {
-                            new CanonicalizerPhase(runtime, assumptions, invokeUsages, mark, customCanonicalizer).apply(graph);
+                            new CanonicalizerPhase.Instance(runtime, assumptions, invokeUsages, mark, customCanonicalizer).apply(graph);
                         }
                         inliningCount++;
                         metricInliningPerformed.increment();
@@ -160,7 +161,7 @@
                     new ComputeProbabilityPhase().apply(newGraph);
                 }
                 if (GraalOptions.OptCanonicalizer) {
-                    new CanonicalizerPhase(runtime, assumptions).apply(newGraph);
+                    new CanonicalizerPhase.Instance(runtime, assumptions).apply(newGraph);
                 }
                 if (GraalOptions.CullFrameStates) {
                     new CullFrameStatesPhase().apply(newGraph);
@@ -200,8 +201,14 @@
              * also getting queued in the compilation queue concurrently)
              */
 
-            if (GraalOptions.AlwaysInlineIntrinsics && onlyIntrinsics(replacements, info)) {
-                return InliningUtil.logInlinedMethod(info, "intrinsic");
+            if (GraalOptions.AlwaysInlineIntrinsics) {
+                if (onlyIntrinsics(replacements, info)) {
+                    return InliningUtil.logInlinedMethod(info, "intrinsic");
+                }
+            } else {
+                if (onlyForcedIntrinsics(replacements, info)) {
+                    return InliningUtil.logInlinedMethod(info, "intrinsic");
+                }
             }
 
             double bonus = 1;
@@ -271,7 +278,7 @@
         private static int countInvokeUsages(InlineInfo info) {
             // inlining calls with lots of usages simplifies the caller
             int usages = 0;
-            for (Node n : info.invoke().node().usages()) {
+            for (Node n : info.invoke().asNode().usages()) {
                 if (!(n instanceof FrameState)) {
                     usages++;
                 }
@@ -347,6 +354,18 @@
             }
             return true;
         }
+
+        private static boolean onlyForcedIntrinsics(Replacements replacements, InlineInfo info) {
+            for (int i = 0; i < info.numberOfMethods(); i++) {
+                if (!InliningUtil.canIntrinsify(replacements, info.methodAt(i))) {
+                    return false;
+                }
+                if (!replacements.isForcedSubstitution(info.methodAt(i))) {
+                    return false;
+                }
+            }
+            return true;
+        }
     }
 
     private static class CFInliningPolicy implements InliningPolicy {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Mon Apr 15 08:49:14 2013 +0200
@@ -73,13 +73,47 @@
         boolean isWorthInlining(InlineInfo info);
     }
 
+    /**
+     * Print a HotSpot-style inlining message to the console.
+     */
+    private static void printInlining(final InlineInfo info, final boolean success, final String msg, final Object... args) {
+        printInlining(info.methodAt(0), info.invoke(), success, msg, args);
+    }
+
+    /**
+     * Print a HotSpot-style inlining message to the console.
+     */
+    private static void printInlining(final ResolvedJavaMethod method, final Invoke invoke, final boolean success, final String msg, final Object... args) {
+        if (GraalOptions.HotSpotPrintInlining) {
+            final int mod = method.getModifiers();
+            // 1234567
+            TTY.print("        ");     // print timestamp
+            // 1234
+            TTY.print("     ");        // print compilation number
+            // % s ! b n
+            TTY.print("%c%c%c%c%c ", ' ', Modifier.isSynchronized(mod) ? 's' : ' ', ' ', ' ', Modifier.isNative(mod) ? 'n' : ' ');
+            TTY.print("     ");        // more indent
+            TTY.print("    ");         // initial inlining indent
+            final int level = computeInliningLevel(invoke);
+            for (int i = 0; i < level; i++) {
+                TTY.print("  ");
+            }
+            TTY.println(String.format("@ %d  %s   %s%s", invoke.bci(), methodName(method, null), success ? "" : "not inlining ", String.format(msg, args)));
+        }
+    }
+
+    public static boolean logInlinedMethod(InlineInfo info, String msg, Object... args) {
+        logInliningDecision(info, true, msg, args);
+        return true;
+    }
+
     public static boolean logNotInlinedMethod(InlineInfo info, String msg, Object... args) {
-
         logInliningDecision(info, false, msg, args);
         return false;
     }
 
     public static void logInliningDecision(InlineInfo info, boolean success, String msg, final Object... args) {
+        printInlining(info, success, msg, args);
         if (shouldLogInliningDecision()) {
             logInliningDecision(methodName(info), success, msg, args);
         }
@@ -94,11 +128,6 @@
         });
     }
 
-    public static boolean logInlinedMethod(InlineInfo info, String string, Object... args) {
-        logInliningDecision(info, true, string, args);
-        return true;
-    }
-
     private static boolean logNotInlinedMethodAndReturnFalse(Invoke invoke, String msg) {
         if (shouldLogInliningDecision()) {
             String methodString = invoke.toString() + (invoke.callTarget() == null ? " callTarget=null" : invoke.callTarget().targetName());
@@ -112,6 +141,7 @@
     }
 
     private static InlineInfo logNotInlinedMethodAndReturnNull(Invoke invoke, ResolvedJavaMethod method, String msg, Object... args) {
+        printInlining(method, invoke, false, msg, args);
         if (shouldLogInliningDecision()) {
             String methodString = methodName(method, invoke);
             logInliningDecision(methodString, false, msg, args);
@@ -120,6 +150,7 @@
     }
 
     private static boolean logNotInlinedMethodAndReturnFalse(Invoke invoke, ResolvedJavaMethod method, String msg) {
+        printInlining(method, invoke, false, msg, new Object[0]);
         if (shouldLogInliningDecision()) {
             String methodString = methodName(method, invoke);
             logInliningDecision(methodString, false, msg, new Object[0]);
@@ -227,9 +258,9 @@
                 try {
                     macroNode = macroNodeClass.getConstructor(Invoke.class).newInstance(invoke);
                 } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) {
-                    throw new GraalInternalError(e).addContext(invoke.node()).addContext("macroSubstitution", macroNodeClass);
+                    throw new GraalInternalError(e).addContext(invoke.asNode()).addContext("macroSubstitution", macroNodeClass);
                 }
-                macroNode.setProbability(invoke.node().probability());
+                macroNode.setProbability(invoke.asNode().probability());
                 CallTargetNode callTarget = invoke.callTarget();
                 if (invoke instanceof InvokeNode) {
                     graph.replaceFixedWithFixed((InvokeNode) invoke, graph.add(macroNode));
@@ -268,7 +299,7 @@
         protected void replaceInvokeCallTarget(StructuredGraph graph, InvokeKind invokeKind, ResolvedJavaMethod targetMethod) {
             MethodCallTargetNode oldCallTarget = invoke.methodCallTarget();
             MethodCallTargetNode newCallTarget = graph.add(new MethodCallTargetNode(invokeKind, targetMethod, oldCallTarget.arguments().toArray(new ValueNode[0]), oldCallTarget.returnType()));
-            invoke.node().replaceFirstInput(oldCallTarget, newCallTarget);
+            invoke.asNode().replaceFirstInput(oldCallTarget, newCallTarget);
         }
     }
 
@@ -364,9 +395,9 @@
             ValueNode anchoredReceiver = createAnchoredReceiver(graph, anchor, type, receiver, true);
             invoke.callTarget().replaceFirstInput(receiver, anchoredReceiver);
 
-            graph.addBeforeFixed(invoke.node(), receiverHub);
-            graph.addBeforeFixed(invoke.node(), guard);
-            graph.addBeforeFixed(invoke.node(), anchor);
+            graph.addBeforeFixed(invoke.asNode(), receiverHub);
+            graph.addBeforeFixed(invoke.asNode(), guard);
+            graph.addBeforeFixed(invoke.asNode(), anchor);
         }
 
         @Override
@@ -439,8 +470,8 @@
             returnMerge.setStateAfter(invoke.stateAfter().duplicate(invoke.stateAfter().bci));
 
             PhiNode returnValuePhi = null;
-            if (invoke.node().kind() != Kind.Void) {
-                returnValuePhi = graph.unique(new PhiNode(invoke.node().kind(), returnMerge));
+            if (invoke.asNode().kind() != Kind.Void) {
+                returnValuePhi = graph.unique(new PhiNode(invoke.asNode().kind(), returnMerge));
             }
 
             MergeNode exceptionMerge = null;
@@ -489,7 +520,7 @@
                 GraphUtil.killCFG(invokeWithExceptionNode.exceptionEdge());
             }
 
-            assert invoke.node().isAlive();
+            assert invoke.asNode().isAlive();
 
             // replace the invoke with a switch on the type of the actual receiver
             createDispatchOnTypeBeforeInvoke(graph, successors, false);
@@ -497,8 +528,8 @@
             assert invoke.next() == continuation;
             invoke.setNext(null);
             returnMerge.setNext(continuation);
-            invoke.node().replaceAtUsages(returnValuePhi);
-            invoke.node().replaceAndDelete(null);
+            invoke.asNode().replaceAtUsages(returnValuePhi);
+            invoke.asNode().replaceAndDelete(null);
 
             ArrayList<PiNode> replacementNodes = new ArrayList<>();
 
@@ -586,7 +617,7 @@
             BeginNode[] successors = new BeginNode[]{calleeEntryNode, unknownTypeSux};
             createDispatchOnTypeBeforeInvoke(graph, successors, false);
 
-            calleeEntryNode.setNext(invoke.node());
+            calleeEntryNode.setNext(invoke.asNode());
 
             ResolvedJavaMethod concrete = concretes.get(0);
             inline(invoke, concrete, callback, replacements, assumptions, false);
@@ -597,7 +628,7 @@
 
             Kind hubKind = invoke.methodCallTarget().targetMethod().getDeclaringClass().getEncoding(Representation.ObjectHub).getKind();
             LoadHubNode hub = graph.add(new LoadHubNode(invoke.methodCallTarget().receiver(), hubKind));
-            graph.addBeforeFixed(invoke.node(), hub);
+            graph.addBeforeFixed(invoke.asNode(), hub);
 
             ResolvedJavaType[] keys = new ResolvedJavaType[ptypes.size()];
             double[] keyProbabilities = new double[ptypes.size() + 1];
@@ -612,7 +643,7 @@
             keySuccessors[keySuccessors.length - 1] = successors.length - 1;
 
             TypeSwitchNode typeSwitch = graph.add(new TypeSwitchNode(hub, successors, keys, keyProbabilities, keySuccessors));
-            FixedWithNextNode pred = (FixedWithNextNode) invoke.node().predecessor();
+            FixedWithNextNode pred = (FixedWithNextNode) invoke.asNode().predecessor();
             pred.setNext(typeSwitch);
         }
 
@@ -620,7 +651,7 @@
                         double probability, boolean useForInlining) {
             Invoke duplicatedInvoke = duplicateInvokeForInlining(graph, invoke, exceptionMerge, exceptionObjectPhi, useForInlining, probability);
             BeginNode calleeEntryNode = graph.add(new BeginNode());
-            calleeEntryNode.setNext(duplicatedInvoke.node());
+            calleeEntryNode.setNext(duplicatedInvoke.asNode());
             calleeEntryNode.setProbability(probability);
 
             EndNode endNode = graph.add(new EndNode());
@@ -630,24 +661,24 @@
             returnMerge.addForwardEnd(endNode);
 
             if (returnValuePhi != null) {
-                returnValuePhi.addInput(duplicatedInvoke.node());
+                returnValuePhi.addInput(duplicatedInvoke.asNode());
             }
             return calleeEntryNode;
         }
 
         private static Invoke duplicateInvokeForInlining(StructuredGraph graph, Invoke invoke, MergeNode exceptionMerge, PhiNode exceptionObjectPhi, boolean useForInlining, double probability) {
-            Invoke result = (Invoke) invoke.node().copyWithInputs();
+            Invoke result = (Invoke) invoke.asNode().copyWithInputs();
             Node callTarget = result.callTarget().copyWithInputs();
-            result.node().replaceFirstInput(result.callTarget(), callTarget);
+            result.asNode().replaceFirstInput(result.callTarget(), callTarget);
             result.setUseForInlining(useForInlining);
             result.setProbability(probability);
             result.setInliningRelevance(invoke.inliningRelevance() * probability);
 
-            Kind kind = invoke.node().kind();
+            Kind kind = invoke.asNode().kind();
             if (kind != Kind.Void) {
                 FrameState stateAfter = invoke.stateAfter();
                 stateAfter = stateAfter.duplicate(stateAfter.bci);
-                stateAfter.replaceFirstInput(invoke.node(), result.node());
+                stateAfter.replaceFirstInput(invoke.asNode(), result.asNode());
                 result.setStateAfter(stateAfter);
             }
 
@@ -712,7 +743,7 @@
             BeginNode[] successors = new BeginNode[]{invocationEntry, unknownTypeSux};
             createDispatchOnTypeBeforeInvoke(graph, successors, true);
 
-            invocationEntry.setNext(invoke.node());
+            invocationEntry.setNext(invoke.asNode());
             ValueNode receiver = invoke.methodCallTarget().receiver();
             PiNode anchoredReceiver = createAnchoredReceiver(graph, invocationEntry, target.getDeclaringClass(), receiver, false);
             invoke.callTarget().replaceFirstInput(receiver, anchoredReceiver);
@@ -935,7 +966,7 @@
     }
 
     private static boolean checkInvokeConditions(Invoke invoke) {
-        if (invoke.predecessor() == null || !invoke.node().isAlive()) {
+        if (invoke.predecessor() == null || !invoke.asNode().isAlive()) {
             return logNotInlinedMethodAndReturnFalse(invoke, "the invoke is dead code");
         } else if (!(invoke.callTarget() instanceof MethodCallTargetNode)) {
             return logNotInlinedMethodAndReturnFalse(invoke, "the invoke has already been lowered, or has been created as a low-level node");
@@ -1017,7 +1048,7 @@
      */
     public static Map<Node, Node> inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck) {
         NodeInputList<ValueNode> parameters = invoke.callTarget().arguments();
-        StructuredGraph graph = (StructuredGraph) invoke.node().graph();
+        StructuredGraph graph = (StructuredGraph) invoke.asNode().graph();
 
         FrameState stateAfter = invoke.stateAfter();
         assert stateAfter.isAlive();
@@ -1045,17 +1076,17 @@
             }
         }
         // ensure proper anchoring of things that were anchored to the StartNode
-        replacements.put(entryPointNode, BeginNode.prevBegin(invoke.node()));
+        replacements.put(entryPointNode, BeginNode.prevBegin(invoke.asNode()));
 
-        assert invoke.node().successors().first() != null : invoke;
-        assert invoke.node().predecessor() != null;
+        assert invoke.asNode().successors().first() != null : invoke;
+        assert invoke.asNode().predecessor() != null;
 
         Map<Node, Node> duplicates = graph.addDuplicates(nodes, replacements);
         FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode);
         if (receiverNullCheck) {
             receiverNullCheck(invoke);
         }
-        invoke.node().replaceAtPredecessor(firstCFGNodeDuplicate);
+        invoke.asNode().replaceAtPredecessor(firstCFGNodeDuplicate);
 
         FrameState stateAtExceptionEdge = null;
         if (invoke instanceof InvokeWithExceptionNode) {
@@ -1094,7 +1125,7 @@
         }
 
         FrameState outerFrameState = null;
-        double invokeProbability = invoke.node().probability();
+        double invokeProbability = invoke.asNode().probability();
         int callerLockDepth = stateAfter.nestedLockDepth();
         for (Node node : duplicates.values()) {
             if (GraalOptions.ProbabilityAnalysis) {
@@ -1117,7 +1148,7 @@
             }
             if (node instanceof FrameState) {
                 FrameState frameState = (FrameState) node;
-                assert frameState.bci != FrameState.BEFORE_BCI;
+                assert frameState.bci != FrameState.BEFORE_BCI : frameState;
                 if (frameState.bci == FrameState.AFTER_BCI) {
                     frameState.replaceAndDelete(stateAfter);
                 } else if (frameState.bci == FrameState.AFTER_EXCEPTION_BCI) {
@@ -1132,7 +1163,7 @@
                     if (frameState.outerFrameState() == null) {
                         assert frameState.bci == FrameState.INVALID_FRAMESTATE_BCI || frameState.method() == inlineGraph.method();
                         if (outerFrameState == null) {
-                            outerFrameState = stateAfter.duplicateModified(invoke.bci(), stateAfter.rethrowException(), invoke.node().kind());
+                            outerFrameState = stateAfter.duplicateModified(invoke.bci(), stateAfter.rethrowException(), invoke.asNode().kind());
                             outerFrameState.setDuringCall(true);
                         }
                         frameState.setOuterFrameState(outerFrameState);
@@ -1152,7 +1183,7 @@
             } else {
                 returnValue = duplicates.get(returnNode.result());
             }
-            invoke.node().replaceAtUsages(returnValue);
+            invoke.asNode().replaceAtUsages(returnValue);
             Node returnDuplicate = duplicates.get(returnNode);
             returnDuplicate.clearInputs();
             Node n = invoke.next();
@@ -1160,8 +1191,8 @@
             returnDuplicate.replaceAndDelete(n);
         }
 
-        invoke.node().replaceAtUsages(null);
-        GraphUtil.killCFG(invoke.node());
+        invoke.asNode().replaceAtUsages(null);
+        GraphUtil.killCFG(invoke.asNode());
 
         return duplicates;
     }
@@ -1172,7 +1203,7 @@
         NodeInputList<ValueNode> parameters = callTarget.arguments();
         ValueNode firstParam = parameters.size() <= 0 ? null : parameters.get(0);
         if (!callTarget.isStatic() && firstParam.kind() == Kind.Object && !firstParam.objectStamp().nonNull()) {
-            graph.addBeforeFixed(invoke.node(),
+            graph.addBeforeFixed(invoke.asNode(),
                             graph.add(new FixedGuardNode(graph.unique(new IsNullNode(firstParam)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true)));
         }
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Mon Apr 15 08:49:14 2013 +0200
@@ -53,7 +53,7 @@
             if (canonicalizationRoots.isEmpty()) {
                 break;
             }
-            new CanonicalizerPhase(runtime, assumptions, canonicalizationRoots, null).apply(graph);
+            new CanonicalizerPhase.Instance(runtime, assumptions, canonicalizationRoots, null).apply(graph);
             canonicalizationRoots.clear();
         }
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Mon Apr 15 08:49:14 2013 +0200
@@ -151,7 +151,7 @@
             deferred = false;
             processBlock(schedule.getCFG().getStartBlock(), graph.createNodeBitMap(), null, schedule, processed);
             Debug.dump(graph, "Lowering iteration %d", i++);
-            new CanonicalizerPhase(runtime, assumptions, mark, null).apply(graph);
+            new CanonicalizerPhase.Instance(runtime, assumptions, mark, null).apply(graph);
 
             if (!deferred && !containsLowerable(graph.getNewNodes(mark))) {
                 // No new lowerable nodes - done!
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/PushNodesThroughPi.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +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.phases.common;
-
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.phases.*;
-
-public class PushNodesThroughPi extends Phase {
-
-    public static final DebugMetric PUSHED_NODES = Debug.metric("NodesPushedThroughPi");
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        for (PiNode pi : graph.getNodes(PiNode.class)) {
-            for (Node n : pi.usages().snapshot()) {
-                if (n instanceof PiPushable) {
-                    PiPushable pip = (PiPushable) n;
-                    if (pip.push(pi)) {
-                        PUSHED_NODES.add(1);
-                    }
-                }
-            }
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/PushThroughPiPhase.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,48 @@
+/*
+ * 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.phases.common;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.*;
+
+public class PushThroughPiPhase extends Phase {
+
+    public static final DebugMetric PUSHED_NODES = Debug.metric("NodesPushedThroughPi");
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (PiNode pi : graph.getNodes(PiNode.class)) {
+            for (Node n : pi.usages().snapshot()) {
+                if (n instanceof PiPushable) {
+                    PiPushable pip = (PiPushable) n;
+                    if (pip.push(pi)) {
+                        PUSHED_NODES.add(1);
+                    }
+                }
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Mon Apr 15 08:49:14 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -46,7 +46,6 @@
     /*
      * Various metrics on the circumstances in which tail duplication was/wasn't performed.
      */
-    private static final DebugMetric metricDuplicationMonitors = Debug.metric("DuplicationMonitors");
     private static final DebugMetric metricDuplicationEnd = Debug.metric("DuplicationEnd");
     private static final DebugMetric metricDuplicationEndPerformed = Debug.metric("DuplicationEndPerformed");
     private static final DebugMetric metricDuplicationOther = Debug.metric("DuplicationOther");
@@ -128,21 +127,13 @@
         }
     };
 
-    private int tailDuplicationCount;
-
-    public int getTailDuplicationCount() {
-        return tailDuplicationCount;
-    }
-
     @Override
     protected void run(StructuredGraph graph) {
         // A snapshot is taken here, so that new MergeNode instances aren't considered for tail
         // duplication.
         for (MergeNode merge : graph.getNodes(MergeNode.class).snapshot()) {
             if (!(merge instanceof LoopBeginNode) && merge.probability() >= GraalOptions.TailDuplicationProbability) {
-                if (tailDuplicate(merge, DEFAULT_DECISION, null)) {
-                    tailDuplicationCount++;
-                }
+                tailDuplicate(merge, DEFAULT_DECISION, null);
             }
         }
     }
@@ -168,20 +159,11 @@
         assert replacements == null || replacements.size() == merge.forwardEndCount();
         FixedNode fixed = merge;
         int fixedCount = 0;
-        boolean containsMonitor = false;
         while (fixed instanceof FixedWithNextNode) {
-            if (fixed instanceof MonitorEnterNode || fixed instanceof MonitorExitNode) {
-                containsMonitor = true;
-            }
             fixed = ((FixedWithNextNode) fixed).next();
             fixedCount++;
         }
-        if (containsMonitor) {
-            // cannot currently be handled
-            // TODO (ls) re-evaluate this limitation after changes to the lock representation and
-            // the LIR generator
-            metricDuplicationMonitors.increment();
-        } else if (fixedCount > 1) {
+        if (fixedCount > 1) {
             if (fixed instanceof EndNode && !(((EndNode) fixed).merge() instanceof LoopBeginNode)) {
                 metricDuplicationEnd.increment();
                 if (decision.doTransform(merge, fixedCount)) {
@@ -261,7 +243,6 @@
             final HashSet<Node> duplicatedNodes = buildDuplicatedNodeSet(fixedNodes, stateAfter);
             mergeAfter.clearEnds();
             expandDuplicated(duplicatedNodes, mergeAfter);
-            retargetDependencies(duplicatedNodes, anchor);
 
             List<EndNode> endSnapshot = merge.forwardEnds().snapshot();
             List<PhiNode> phiSnapshot = merge.phis().snapshot();
@@ -536,29 +517,6 @@
         }
 
         /**
-         * Moves all depdendencies that point outside the duplicated area to the supplied value
-         * anchor node.
-         * 
-         * @param duplicatedNodes The set of duplicated nodes.
-         * @param anchor The node that will be the new target for all dependencies that point
-         *            outside the duplicated set of nodes.
-         */
-        private static void retargetDependencies(HashSet<Node> duplicatedNodes, ValueAnchorNode anchor) {
-            for (Node node : duplicatedNodes) {
-                if (node instanceof ValueNode) {
-                    NodeInputList<ValueNode> dependencies = ((ValueNode) node).dependencies();
-                    for (int i = 0; i < dependencies.size(); i++) {
-                        Node dependency = dependencies.get(i);
-                        if (dependency != null && !duplicatedNodes.contains(dependency)) {
-                            Debug.log("retargeting dependency %s to %s on %s", dependency, anchor, node);
-                            dependencies.set(i, anchor);
-                        }
-                    }
-                }
-            }
-        }
-
-        /**
          * Checks if the given node has usages that are not within the given set of nodes.
          * 
          * @param node The node whose usages are checked.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,77 @@
+/*
+ * 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
+ * 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.phases;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * Base class for all compiler phases. Subclasses should be stateless. There will be one global
+ * instance for each compiler phase that is shared for all compilations. VM-, target- and
+ * compilation-specific data can be passed with a context object.
+ */
+public abstract class BasePhase<C> {
+
+    private String name;
+    private static final DebugMetric metricPhaseRuns = Debug.metric("Runs");
+    protected static final DebugMetric METRIC_PROCESSED_NODES = Debug.metric("ProcessedNodes");
+
+    protected BasePhase() {
+        this.name = this.getClass().getSimpleName();
+        if (name.endsWith("Phase")) {
+            name = name.substring(0, name.length() - "Phase".length());
+        }
+    }
+
+    protected BasePhase(String name) {
+        this.name = name;
+    }
+
+    protected String getDetailedName() {
+        return getName();
+    }
+
+    public final void apply(final StructuredGraph graph, final C context) {
+        apply(graph, context, true);
+    }
+
+    public final void apply(final StructuredGraph graph, final C context, final boolean dumpGraph) {
+        Debug.scope(name, this, new Runnable() {
+
+            public void run() {
+                BasePhase.this.run(graph, context);
+                metricPhaseRuns.increment();
+                if (dumpGraph) {
+                    Debug.dump(graph, "After phase %s", name);
+                }
+                assert graph.verify();
+            }
+        });
+    }
+
+    public final String getName() {
+        return name;
+    }
+
+    protected abstract void run(StructuredGraph graph, C context);
+}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Mon Apr 15 08:49:14 2013 +0200
@@ -88,6 +88,9 @@
     public static int     SlowQueueCutoff                    = 100000;
     public static boolean SlowCompileThreads                 = ____;
     public static boolean DynamicCompilePriority             = ____;
+    public static String  CompileTheWorld                    = null;
+    public static int     CompileTheWorldStartAt             = 1;
+    public static int     CompileTheWorldStopAt              = Integer.MAX_VALUE;
 
     // graph caching
     public static boolean CacheGraphs                        = true;
@@ -116,6 +119,7 @@
     // Debug settings:
     public static boolean Debug                              = true;
     public static boolean DebugReplacements                  = ____;
+    public static boolean BootstrapReplacements              = ____;
     public static boolean PerThreadDebugValues               = ____;
     public static boolean SummarizeDebugValues               = ____;
     public static boolean SummarizePerPhase                  = ____;
@@ -127,7 +131,7 @@
     public static String  MethodFilter                       = null;
     public static boolean DumpOnError                        = ____;
     public static boolean GenericDynamicCounters             = ____;
-    public static boolean BenchmarkDynamicCounters           = ____;
+    public static String  BenchmarkDynamicCounters           = null;
 
     // Ideal graph visualizer output settings
     public static boolean PrintBinaryGraphs                  = true;
@@ -151,6 +155,10 @@
     public static boolean ExitVMOnBailout                    = ____;
     public static boolean ExitVMOnException                  = true;
 
+    // HotSpot command line options
+    public static boolean HotSpotPrintCompilation            = ____;
+    public static boolean HotSpotPrintInlining               = ____;
+
     // Register allocator debugging
     public static String  RegisterPressure                   = null;
 
@@ -217,6 +225,7 @@
     public static boolean IntrinsifyMathMethods              = true;
     public static boolean IntrinsifyAESMethods               = true;
     public static boolean IntrinsifyInstalledCodeMethods     = true;
+    public static boolean IntrinsifyCallSiteTarget           = true;
     /**
      * Counts the various paths taken through snippets.
      */
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/Phase.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/Phase.java	Mon Apr 15 08:49:14 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
@@ -22,28 +22,18 @@
  */
 package com.oracle.graal.phases;
 
-import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 
-public abstract class Phase {
-
-    private String name;
-    private static final DebugMetric metricPhaseRuns = Debug.metric("Runs");
-    protected static final DebugMetric METRIC_PROCESSED_NODES = Debug.metric("ProcessedNodes");
+/**
+ * Base class for compiler phases that don't need a context object.
+ */
+public abstract class Phase extends BasePhase<Object> {
 
     protected Phase() {
-        this.name = this.getClass().getSimpleName();
-        if (name.endsWith("Phase")) {
-            name = name.substring(0, name.length() - "Phase".length());
-        }
     }
 
     protected Phase(String name) {
-        this.name = name;
-    }
-
-    protected String getDetailedName() {
-        return getName();
+        super(name);
     }
 
     public final void apply(final StructuredGraph graph) {
@@ -51,22 +41,13 @@
     }
 
     public final void apply(final StructuredGraph graph, final boolean dumpGraph) {
-        Debug.scope(name, this, new Runnable() {
-
-            public void run() {
-                Phase.this.run(graph);
-                metricPhaseRuns.increment();
-                if (dumpGraph) {
-                    Debug.dump(graph, "After phase %s", name);
-                }
-                assert graph.verify();
-            }
-        });
-    }
-
-    public final String getName() {
-        return name;
+        apply(graph, null, dumpGraph);
     }
 
     protected abstract void run(StructuredGraph graph);
+
+    @Override
+    protected final void run(StructuredGraph graph, Object context) {
+        run(graph);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhaseSuite.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,44 @@
+/*
+ * 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.phases;
+
+import java.util.*;
+
+import com.oracle.graal.nodes.*;
+
+public class PhaseSuite<C> extends BasePhase<C> {
+
+    private final List<BasePhase<? super C>> phases;
+
+    public PhaseSuite(String name, List<BasePhase<? super C>> phases) {
+        super(name);
+        this.phases = phases;
+    }
+
+    @Override
+    protected void run(StructuredGraph graph, C context) {
+        for (BasePhase<? super C> phase : phases) {
+            phase.apply(graph, context);
+        }
+    }
+}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java	Mon Apr 15 08:49:14 2013 +0200
@@ -217,7 +217,7 @@
     }
 
     protected void invoke(Invoke invoke) {
-        node(invoke.node());
+        node(invoke.asNode());
     }
 
     protected void finished() {
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java	Mon Apr 15 08:49:14 2013 +0200
@@ -39,7 +39,7 @@
 
         protected abstract void processBlock(Block block, StateT currentState);
 
-        protected abstract StateT merge(MergeNode merge, List<StateT> states);
+        protected abstract StateT merge(Block merge, List<StateT> states);
 
         protected abstract StateT cloneState(StateT oldState);
 
@@ -161,12 +161,11 @@
                     assert current.getPredecessors().size() > 1;
                     MergeNode merge = (MergeNode) current.getBeginNode();
                     ArrayList<StateT> mergedStates = new ArrayList<>(merge.forwardEndCount());
-                    for (int i = 0; i < merge.forwardEndCount(); i++) {
-                        StateT other = states.get(merge.forwardEndAt(i));
-                        assert other != null;
-                        mergedStates.add(other);
+                    for (Block predecessor : current.getPredecessors()) {
+                        EndNode end = (EndNode) predecessor.getEndNode();
+                        mergedStates.add(states.get(end));
                     }
-                    state = closure.merge(merge, mergedStates);
+                    state = closure.merge(current, mergedStates);
                 }
                 assert state != null;
             }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Mon Apr 15 08:49:14 2013 +0200
@@ -39,6 +39,30 @@
 
 public final class SchedulePhase extends Phase {
 
+    /**
+     * Error thrown when a graph cannot be scheduled.
+     */
+    public static class SchedulingError extends Error {
+
+        private static final long serialVersionUID = 1621001069476473145L;
+
+        public SchedulingError() {
+            super();
+        }
+
+        /**
+         * This constructor creates a {@link SchedulingError} with a message assembled via
+         * {@link String#format(String, Object...)}.
+         * 
+         * @param format a {@linkplain Formatter format} string
+         * @param args parameters to {@link String#format(String, Object...)}
+         */
+        public SchedulingError(String format, Object... args) {
+            super(String.format(format, args));
+        }
+
+    }
+
     public static enum SchedulingStrategy {
         EARLIEST, LATEST, LATEST_OUT_OF_LOOPS
     }
@@ -91,7 +115,7 @@
         }
 
         @Override
-        protected HashSet<FloatingReadNode> merge(MergeNode merge, List<HashSet<FloatingReadNode>> states) {
+        protected HashSet<FloatingReadNode> merge(Block merge, List<HashSet<FloatingReadNode>> states) {
             HashSet<FloatingReadNode> state = new HashSet<>(states.get(0));
             for (int i = 1; i < states.size(); i++) {
                 state.retainAll(states.get(i));
@@ -169,8 +193,8 @@
 
     /**
      * Sets {@link ScheduledNode#scheduledNext} on all scheduled nodes in all blocks using the
-     * scheduling built by @link {@link #run(StructuredGraph)}. This method should thus only be
-     * called when run has been successfully executed.
+     * scheduling built by {@link #run(StructuredGraph)}. This method should thus only be called
+     * when run has been successfully executed.
      */
     public void scheduleGraph() {
         assert blockToNodesMap != null : "cannot set scheduledNext before run has been executed";
@@ -207,7 +231,9 @@
     private void assignBlockToNodes(StructuredGraph graph, SchedulingStrategy strategy) {
         for (Block block : cfg.getBlocks()) {
             List<ScheduledNode> nodes = new ArrayList<>();
-            assert blockToNodesMap.get(block) == null;
+            if (blockToNodesMap.get(block) != null) {
+                throw new SchedulingError();
+            }
             blockToNodesMap.put(block, nodes);
             for (FixedNode node : block.getNodes()) {
                 nodes.add(node);
@@ -234,8 +260,9 @@
         }
         // PhiNodes and FixedNodes should already have been placed in blocks by
         // ControlFlowGraph.identifyBlocks
-        assert !(node instanceof PhiNode) : node;
-        assert !(node instanceof FixedNode) : node;
+        if (node instanceof PhiNode || node instanceof FixedNode) {
+            throw new SchedulingError("%s should already have been placed in a block", node);
+        }
 
         Block block;
         switch (strategy) {
@@ -251,8 +278,10 @@
                     // schedule at the latest position possible in the outermost loop possible
                     Block earliestBlock = earliestBlock(node);
                     block = scheduleOutOfLoops(node, block, earliestBlock);
-                    assert earliestBlock.dominates(block) : "Graph cannot be scheduled : inconsistent for " + node + ", " + node.usages().count() + " usages, (" + earliestBlock +
-                                    " needs to dominate " + block + ")";
+                    if (!earliestBlock.dominates(block)) {
+                        throw new SchedulingError("%s: Graph cannot be scheduled : inconsistent for %s, %d usages, (%s needs to dominate %s)", node.graph(), node, node.usages().count(),
+                                        earliestBlock, block);
+                    }
                 }
                 break;
             default:
@@ -271,7 +300,9 @@
     private Block latestBlock(ScheduledNode node, SchedulingStrategy strategy) {
         CommonDominatorBlockClosure cdbc = new CommonDominatorBlockClosure(null);
         for (Node succ : node.successors().nonNull()) {
-            assert cfg.getNodeToBlock().get(succ) != null;
+            if (cfg.getNodeToBlock().get(succ) == null) {
+                throw new SchedulingError();
+            }
             cdbc.apply(cfg.getNodeToBlock().get(succ));
         }
         ensureScheduledUsages(node, strategy);
@@ -281,7 +312,9 @@
         List<FixedNode> usages = phantomUsages.get(node);
         if (usages != null) {
             for (FixedNode usage : usages) {
-                assert cfg.getNodeToBlock().get(usage) != null;
+                if (cfg.getNodeToBlock().get(usage) == null) {
+                    throw new SchedulingError();
+                }
                 cdbc.apply(cfg.getNodeToBlock().get(usage));
             }
         }
@@ -331,7 +364,9 @@
          */
         BitSet dominators = new BitSet(cfg.getBlocks().length);
 
-        assert node.predecessor() == null;
+        if (node.predecessor() != null) {
+            throw new SchedulingError();
+        }
         for (Node input : node.inputs().nonNull()) {
             assert input instanceof ValueNode;
             Block inputEarliest;
@@ -356,7 +391,9 @@
     }
 
     private static Block scheduleOutOfLoops(Node n, Block latestBlock, Block earliest) {
-        assert latestBlock != null : "no latest : " + n;
+        if (latestBlock == null) {
+            throw new SchedulingError("no latest : %s", n);
+        }
         Block cur = latestBlock;
         Block result = latestBlock;
         while (cur.getLoop() != null && cur != earliest && cur.getDominator() != null) {
@@ -378,7 +415,9 @@
      * @param closure the closure that will be called for each block
      */
     private void blocksForUsage(ScheduledNode node, Node usage, BlockClosure closure, SchedulingStrategy strategy) {
-        assert !(node instanceof PhiNode);
+        if (node instanceof PhiNode) {
+            throw new SchedulingError(node.toString());
+        }
 
         if (usage instanceof PhiNode) {
             // An input to a PhiNode is used at the end of the predecessor block that corresponds to
@@ -388,7 +427,9 @@
             PhiNode phi = (PhiNode) usage;
             MergeNode merge = phi.merge();
             Block mergeBlock = cfg.getNodeToBlock().get(merge);
-            assert mergeBlock != null : "no block for merge " + merge.toString(Verbosity.Id);
+            if (mergeBlock == null) {
+                throw new SchedulingError("no block for merge %s", merge.toString(Verbosity.Id));
+            }
             for (int i = 0; i < phi.valueCount(); ++i) {
                 if (phi.valueAt(i) == node) {
                     if (mergeBlock.getPredecessorCount() <= i) {
@@ -412,7 +453,9 @@
                     blocksForUsage(node, unscheduledUsage, closure, strategy);
                 } else if (unscheduledUsage instanceof MergeNode) {
                     // Only FrameStates can be connected to MergeNodes.
-                    assert usage instanceof FrameState;
+                    if (!(usage instanceof FrameState)) {
+                        throw new SchedulingError(usage.toString());
+                    }
                     // If a FrameState belongs to a MergeNode then it's inputs will be placed at the
                     // common dominator of all EndNodes.
                     for (Node pred : unscheduledUsage.cfgPredecessors()) {
@@ -420,8 +463,12 @@
                     }
                 } else {
                     // For the time being, only FrameStates can be connected to StateSplits.
-                    assert usage instanceof FrameState;
-                    assert unscheduledUsage instanceof StateSplit;
+                    if (!(usage instanceof FrameState)) {
+                        throw new SchedulingError(usage.toString());
+                    }
+                    if (!(unscheduledUsage instanceof StateSplit || unscheduledUsage instanceof DeoptimizingNode)) {
+                        throw new SchedulingError(unscheduledUsage.toString());
+                    }
                     // Otherwise: Put the input into the same block as the usage.
                     assignBlockToNode((ScheduledNode) unscheduledUsage, strategy);
                     closure.apply(cfg.getNodeToBlock().get(unscheduledUsage));
@@ -459,8 +506,12 @@
     }
 
     private void sortNodesWithinBlock(Block b, NodeBitMap visited, SchedulingStrategy strategy) {
-        assert !visited.isMarked(b.getBeginNode()) && cfg.blockFor(b.getBeginNode()) == b;
-        assert !visited.isMarked(b.getEndNode()) && cfg.blockFor(b.getEndNode()) == b;
+        if (visited.isMarked(b.getBeginNode()) || cfg.blockFor(b.getBeginNode()) != b) {
+            throw new SchedulingError();
+        }
+        if (visited.isMarked(b.getEndNode()) || cfg.blockFor(b.getEndNode()) != b) {
+            throw new SchedulingError();
+        }
 
         List<ScheduledNode> sortedInstructions;
         switch (strategy) {
@@ -520,7 +571,9 @@
     private void addUnscheduledToLatestSorting(Block b, VirtualState state, List<ScheduledNode> sortedInstructions, NodeBitMap visited) {
         if (state != null) {
             // UnscheduledNodes should never be marked as visited.
-            assert !visited.isMarked(state);
+            if (visited.isMarked(state)) {
+                throw new SchedulingError();
+            }
 
             for (Node input : state.inputs()) {
                 if (input instanceof VirtualState) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,33 @@
+/*
+ * 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.phases.tiers;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+
+public class HighTierContext extends PhaseContext {
+
+    public HighTierContext(MetaAccessProvider runtime, Assumptions assumptions) {
+        super(runtime, assumptions);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/PhaseContext.java	Mon Apr 15 08:49:14 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.phases.tiers;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+
+public class PhaseContext {
+
+    private final MetaAccessProvider runtime;
+    private final Assumptions assumptions;
+
+    public PhaseContext(MetaAccessProvider runtime, Assumptions assumptions) {
+        this.runtime = runtime;
+        this.assumptions = assumptions;
+    }
+
+    public MetaAccessProvider getRuntime() {
+        return runtime;
+    }
+
+    public Assumptions getAssumptions() {
+        return assumptions;
+    }
+}
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java	Mon Apr 15 08:49:14 2013 +0200
@@ -288,7 +288,9 @@
         }
 
         void warning(int offset, String message) {
+            // CheckStyle: stop system..print check
             System.err.println("Warning: " + errorMessage(offset, message));
+            // CheckStyle: resume system..print check
         }
 
         String errorMessage(int offset, String message) {
@@ -316,8 +318,10 @@
             int lineStart = input.lastIndexOf(HexCodeFile.NEW_LINE, index) + 1;
 
             String l = input.substring(lineStart, lineStart + 10);
+            // CheckStyle: stop system..print check
             System.out.println("YYY" + input.substring(index, index + 10) + "...");
             System.out.println("XXX" + l + "...");
+            // CheckStyle: resume system..print check
 
             int pos = input.indexOf(HexCodeFile.NEW_LINE, 0);
             int line = 1;
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java	Mon Apr 15 08:49:14 2013 +0200
@@ -23,18 +23,20 @@
 package com.oracle.graal.replacements.amd64;
 
 import static com.oracle.graal.replacements.SnippetTemplate.*;
-import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
+import java.util.*;
+
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.calc.ConvertNode.Op;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
+import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
 
 /**
  * Snippets used for conversion operations on AMD64 where the AMD64 instruction used does not match
@@ -54,7 +56,7 @@
      * @param result the result produced by the CVTTSS2SI instruction
      */
     @Snippet
-    public static int f2i(@Parameter("input") float input, @Parameter("result") int result) {
+    public static int f2i(float input, int result) {
         if (result == Integer.MIN_VALUE) {
             probability(NOT_FREQUENT_PROBABILITY);
             if (Float.isNaN(input)) {
@@ -80,7 +82,7 @@
      * @param result the result produced by the CVTTSS2SI instruction
      */
     @Snippet
-    public static long f2l(@Parameter("input") float input, @Parameter("result") long result) {
+    public static long f2l(float input, long result) {
         if (result == Long.MIN_VALUE) {
             probability(NOT_FREQUENT_PROBABILITY);
             if (Float.isNaN(input)) {
@@ -106,7 +108,7 @@
      * @param result the result produced by the CVTTSS2SI instruction
      */
     @Snippet
-    public static int d2i(@Parameter("input") double input, @Parameter("result") int result) {
+    public static int d2i(double input, int result) {
         if (result == Integer.MIN_VALUE) {
             probability(NOT_FREQUENT_PROBABILITY);
             if (Double.isNaN(input)) {
@@ -132,7 +134,7 @@
      * @param result the result produced by the CVTTSS2SI instruction
      */
     @Snippet
-    public static long d2l(@Parameter("input") double input, @Parameter("result") long result) {
+    public static long d2l(double input, long result) {
         if (result == Long.MIN_VALUE) {
             probability(NOT_FREQUENT_PROBABILITY);
             if (Double.isNaN(input)) {
@@ -146,34 +148,26 @@
         return result;
     }
 
-    public static class Templates extends AbstractTemplates<AMD64ConvertSnippets> {
+    public static class Templates extends AbstractTemplates {
 
-        private final ResolvedJavaMethod f2i;
-        private final ResolvedJavaMethod f2l;
-        private final ResolvedJavaMethod d2i;
-        private final ResolvedJavaMethod d2l;
+        private final EnumMap<Op, SnippetInfo> snippets;
 
         public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) {
-            super(runtime, replacements, target, AMD64ConvertSnippets.class);
-            f2i = snippet("f2i", float.class, int.class);
-            f2l = snippet("f2l", float.class, long.class);
-            d2i = snippet("d2i", double.class, int.class);
-            d2l = snippet("d2l", double.class, long.class);
+            super(runtime, replacements, target);
+
+            snippets = new EnumMap<>(Op.class);
+            snippets.put(Op.F2I, snippet(AMD64ConvertSnippets.class, "f2i"));
+            snippets.put(Op.F2L, snippet(AMD64ConvertSnippets.class, "f2l"));
+            snippets.put(Op.D2I, snippet(AMD64ConvertSnippets.class, "d2i"));
+            snippets.put(Op.D2L, snippet(AMD64ConvertSnippets.class, "d2l"));
         }
 
         public void lower(ConvertNode convert, LoweringTool tool) {
-            if (convert.opcode == Op.F2I) {
-                lower0(convert, tool, f2i);
-            } else if (convert.opcode == Op.F2L) {
-                lower0(convert, tool, f2l);
-            } else if (convert.opcode == Op.D2I) {
-                lower0(convert, tool, d2i);
-            } else if (convert.opcode == Op.D2L) {
-                lower0(convert, tool, d2l);
+            SnippetInfo key = snippets.get(convert.opcode);
+            if (key == null) {
+                return;
             }
-        }
 
-        private void lower0(ConvertNode convert, LoweringTool tool, ResolvedJavaMethod snippet) {
             StructuredGraph graph = (StructuredGraph) convert.graph();
 
             // Insert a unique placeholder node in place of the Convert node so that the
@@ -183,11 +177,13 @@
 
             LocalNode replacee = graph.add(new LocalNode(Integer.MAX_VALUE, convert.stamp()));
             convert.replaceAtUsages(replacee);
-            Key key = new Key(snippet);
-            Arguments arguments = arguments("input", convert.value()).add("result", convert);
-            SnippetTemplate template = cache.get(key);
-            Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.opcode, graph, convert, template, arguments);
-            template.instantiate(runtime, replacee, DEFAULT_REPLACER, tool, arguments);
+            Arguments args = new Arguments(key);
+            args.add("input", convert.value());
+            args.add("result", convert);
+
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.opcode, graph, convert, template, args);
+            template.instantiate(runtime, replacee, DEFAULT_REPLACER, tool, args);
         }
     }
 }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/CheckCastTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,214 +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.graal.replacements;
-
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.test.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
-
-/**
- * Tests the implementation of checkcast, allowing profiling information to be manually specified.
- */
-public class CheckCastTest extends TypeCheckTest {
-
-    @Override
-    protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) {
-        CheckCastNode ccn = graph.getNodes(CheckCastNode.class).first();
-        if (ccn != null) {
-            CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.type(), ccn.object(), profile));
-            graph.replaceFixedWithFixed(ccn, ccnNew);
-        }
-    }
-
-    @LongTest
-    public void test1() {
-        test("asNumber", profile(), 111);
-        test("asNumber", profile(Integer.class), 111);
-        test("asNumber", profile(Long.class, Short.class), 111);
-        test("asNumberExt", profile(), 111);
-        test("asNumberExt", profile(Integer.class), 111);
-        test("asNumberExt", profile(Long.class, Short.class), 111);
-    }
-
-    @LongTest
-    public void test2() {
-        test("asString", profile(), "111");
-        test("asString", profile(String.class), "111");
-        test("asString", profile(String.class), "111");
-
-        final String nullString = null;
-        test("asString", profile(), nullString);
-        test("asString", profile(String.class), nullString);
-        test("asString", profile(String.class), nullString);
-
-        test("asStringExt", profile(), "111");
-        test("asStringExt", profile(String.class), "111");
-        test("asStringExt", profile(String.class), "111");
-    }
-
-    @LongTest
-    public void test3() {
-        test("asNumber", profile(), "111");
-    }
-
-    @LongTest
-    public void test4() {
-        test("asString", profile(String.class), 111);
-    }
-
-    @LongTest
-    public void test5() {
-        test("asNumberExt", profile(), "111");
-    }
-
-    @LongTest
-    public void test6() {
-        test("asStringExt", profile(String.class), 111);
-    }
-
-    @LongTest
-    public void test7() {
-        Throwable throwable = new Exception();
-        test("asThrowable", profile(), throwable);
-        test("asThrowable", profile(Throwable.class), throwable);
-        test("asThrowable", profile(Exception.class, Error.class), throwable);
-    }
-
-    @LongTest
-    public void test8() {
-        test("arrayStore", new Object[100], "111");
-    }
-
-    @LongTest
-    public void test8_1() {
-        test("arrayFill", new Object[100], "111");
-    }
-
-    public static Number asNumber(Object o) {
-        return (Number) o;
-    }
-
-    public static String asString(Object o) {
-        return (String) o;
-    }
-
-    public static Throwable asThrowable(Object o) {
-        return (Throwable) o;
-    }
-
-    public static ValueNode asValueNode(Object o) {
-        return (ValueNode) o;
-    }
-
-    public static Number asNumberExt(Object o) {
-        Number n = (Number) o;
-        return n.intValue() + 10;
-    }
-
-    public static String asStringExt(Object o) {
-        String s = (String) o;
-        return "#" + s;
-    }
-
-    public static Object[] arrayStore(Object[] arr, Object value) {
-        arr[15] = value;
-        return arr;
-    }
-
-    public static Object[] arrayFill(Object[] arr, Object value) {
-        for (int i = 0; i < arr.length; i++) {
-            arr[i] = value;
-        }
-        return arr;
-    }
-
-    static class Depth1 implements Cloneable {
-    }
-
-    static class Depth2 extends Depth1 {
-    }
-
-    static class Depth3 extends Depth2 {
-    }
-
-    static class Depth4 extends Depth3 {
-    }
-
-    static class Depth5 extends Depth4 {
-    }
-
-    static class Depth6 extends Depth5 {
-    }
-
-    static class Depth7 extends Depth6 {
-    }
-
-    static class Depth8 extends Depth7 {
-    }
-
-    static class Depth9 extends Depth8 {
-    }
-
-    static class Depth10 extends Depth9 {
-    }
-
-    static class Depth11 extends Depth10 {
-    }
-
-    static class Depth12 extends Depth11 {
-    }
-
-    static class Depth13 extends Depth12 {
-    }
-
-    static class Depth14 extends Depth12 {
-    }
-
-    public static Depth12 asDepth12(Object o) {
-        return (Depth12) o;
-    }
-
-    public static Depth12[][] asDepth12Arr(Object o) {
-        return (Depth12[][]) o;
-    }
-
-    public static Cloneable asCloneable(Object o) {
-        return (Cloneable) o;
-    }
-
-    @LongTest
-    public void test9() {
-        Object o = new Depth13();
-        test("asDepth12", profile(), o);
-        test("asDepth12", profile(Depth13.class), o);
-        test("asDepth12", profile(Depth13.class, Depth14.class), o);
-    }
-
-    @LongTest
-    public void test10() {
-        Object o = new Depth13[3][];
-        test("asDepth12Arr", o);
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/CompiledExceptionHandlerTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +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.graal.replacements;
-
-import java.lang.reflect.*;
-
-import org.junit.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.common.*;
-
-/**
- * Tests compilation of a hot exception handler.
- */
-public class CompiledExceptionHandlerTest extends GraalCompilerTest {
-
-    @Override
-    protected void editPhasePlan(ResolvedJavaMethod method, StructuredGraph graph, PhasePlan phasePlan) {
-        phasePlan.disablePhase(InliningPhase.class);
-    }
-
-    @Override
-    protected StructuredGraph parse(Method m) {
-        StructuredGraph graph = super.parse(m);
-        int handlers = graph.getNodes().filter(ExceptionObjectNode.class).count();
-        Assert.assertEquals(1, handlers);
-        return graph;
-    }
-
-    private static void raiseException(String s) {
-        throw new RuntimeException(s);
-    }
-
-    @Test
-    public void test1() {
-        // Ensure the profile shows a hot exception
-        for (int i = 0; i < 10000; i++) {
-            test1Snippet("");
-            test1Snippet(null);
-        }
-
-        test("test1Snippet", "a string");
-    }
-
-    public static String test1Snippet(String message) {
-        if (message != null) {
-            try {
-                raiseException(message);
-            } catch (Exception e) {
-                return message;
-            }
-        }
-        return null;
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/InstanceOfDynamicTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +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.graal.replacements;
-
-import com.oracle.graal.test.*;
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.nodes.java.*;
-
-/**
- * Tests for {@link InstanceOfDynamicNode}.
- */
-public class InstanceOfDynamicTest extends GraalCompilerTest {
-
-    public static int id(int value) {
-        return value;
-    }
-
-    @LongTest
-    public void test100() {
-        final Object nul = null;
-        test("isStringDynamic", nul);
-        test("isStringDynamic", "object");
-        test("isStringDynamic", Object.class);
-    }
-
-    @LongTest
-    public void test101() {
-        final Object nul = null;
-        test("isStringIntDynamic", nul);
-        test("isStringIntDynamic", "object");
-        test("isStringIntDynamic", Object.class);
-    }
-
-    @LongTest
-    public void test103() {
-        test("isInstanceDynamic", String.class, null);
-        test("isInstanceDynamic", String.class, "object");
-        test("isInstanceDynamic", String.class, Object.class);
-        test("isInstanceDynamic", int.class, null);
-        test("isInstanceDynamic", int.class, "Object");
-        test("isInstanceDynamic", int.class, Object.class);
-    }
-
-    @LongTest
-    public void test104() {
-        test("isInstanceIntDynamic", String.class, null);
-        test("isInstanceIntDynamic", String.class, "object");
-        test("isInstanceIntDynamic", String.class, Object.class);
-        test("isInstanceIntDynamic", int.class, null);
-        test("isInstanceIntDynamic", int.class, "Object");
-        test("isInstanceIntDynamic", int.class, Object.class);
-    }
-
-    public static boolean isStringDynamic(Object o) {
-        return String.class.isInstance(o);
-    }
-
-    public static int isStringIntDynamic(Object o) {
-        if (String.class.isInstance(o)) {
-            return o.toString().length();
-        }
-        return o.getClass().getName().length();
-    }
-
-    public static boolean isInstanceDynamic(Class c, Object o) {
-        return c.isInstance(o);
-    }
-
-    public static int isInstanceIntDynamic(Class c, Object o) {
-        if (c.isInstance(o)) {
-            return o.toString().length();
-        }
-        return o.getClass().getName().length();
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/InstanceOfTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,398 +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.graal.replacements;
-
-import java.util.*;
-
-
-import com.oracle.graal.api.code.CompilationResult.Call;
-import com.oracle.graal.api.code.CompilationResult.Mark;
-import com.oracle.graal.api.code.CompilationResult.Site;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.test.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.common.*;
-import com.oracle.graal.replacements.CheckCastTest.*;
-
-/**
- * Tests the implementation of instanceof, allowing profiling information to be manually specified.
- */
-public class InstanceOfTest extends TypeCheckTest {
-
-    @Override
-    protected void editPhasePlan(ResolvedJavaMethod method, StructuredGraph graph, PhasePlan phasePlan) {
-        phasePlan.disablePhase(InliningPhase.class);
-    }
-
-    @Override
-    protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) {
-        InstanceOfNode ion = graph.getNodes().filter(InstanceOfNode.class).first();
-        if (ion != null) {
-            InstanceOfNode ionNew = graph.add(new InstanceOfNode(ion.type(), ion.object(), profile));
-            graph.replaceFloating(ion, ionNew);
-        }
-    }
-
-    @LongTest
-    public void test1() {
-        test("isString", profile(), "object");
-        test("isString", profile(String.class), "object");
-
-        test("isString", profile(), Object.class);
-        test("isString", profile(String.class), Object.class);
-    }
-
-    @LongTest
-    public void test2() {
-        test("isStringInt", profile(), "object");
-        test("isStringInt", profile(String.class), "object");
-
-        test("isStringInt", profile(), Object.class);
-        test("isStringInt", profile(String.class), Object.class);
-    }
-
-    @LongTest
-    public void test2_1() {
-        test("isStringIntComplex", profile(), "object");
-        test("isStringIntComplex", profile(String.class), "object");
-
-        test("isStringIntComplex", profile(), Object.class);
-        test("isStringIntComplex", profile(String.class), Object.class);
-    }
-
-    @LongTest
-    public void test3() {
-        Throwable throwable = new Exception();
-        test("isThrowable", profile(), throwable);
-        test("isThrowable", profile(Throwable.class), throwable);
-        test("isThrowable", profile(Exception.class, Error.class), throwable);
-
-        test("isThrowable", profile(), Object.class);
-        test("isThrowable", profile(Throwable.class), Object.class);
-        test("isThrowable", profile(Exception.class, Error.class), Object.class);
-    }
-
-    @LongTest
-    public void test3_1() {
-        onlyFirstIsException(new Exception(), new Error());
-        test("onlyFirstIsException", profile(), new Exception(), new Error());
-        test("onlyFirstIsException", profile(), new Error(), new Exception());
-        test("onlyFirstIsException", profile(), new Exception(), new Exception());
-        test("onlyFirstIsException", profile(), new Error(), new Error());
-    }
-
-    @LongTest
-    public void test4() {
-        Throwable throwable = new Exception();
-        test("isThrowableInt", profile(), throwable);
-        test("isThrowableInt", profile(Throwable.class), throwable);
-        test("isThrowableInt", profile(Exception.class, Error.class), throwable);
-
-        test("isThrowableInt", profile(), Object.class);
-        test("isThrowableInt", profile(Throwable.class), Object.class);
-        test("isThrowableInt", profile(Exception.class, Error.class), Object.class);
-    }
-
-    @LongTest
-    public void test5() {
-        Map map = new HashMap<>();
-        test("isMap", profile(), map);
-        test("isMap", profile(HashMap.class), map);
-        test("isMap", profile(TreeMap.class, HashMap.class), map);
-
-        test("isMap", profile(), Object.class);
-        test("isMap", profile(HashMap.class), Object.class);
-        test("isMap", profile(TreeMap.class, HashMap.class), Object.class);
-    }
-
-    @LongTest
-    public void test6() {
-        Map map = new HashMap<>();
-        test("isMapInt", profile(), map);
-        test("isMapInt", profile(HashMap.class), map);
-        test("isMapInt", profile(TreeMap.class, HashMap.class), map);
-
-        test("isMapInt", profile(), Object.class);
-        test("isMapInt", profile(HashMap.class), Object.class);
-        test("isMapInt", profile(TreeMap.class, HashMap.class), Object.class);
-    }
-
-    @LongTest
-    public void test7() {
-        Object o = new Depth13();
-        test("isDepth12", profile(), o);
-        test("isDepth12", profile(Depth13.class), o);
-        test("isDepth12", profile(Depth13.class, Depth14.class), o);
-
-        o = "not a depth";
-        test("isDepth12", profile(), o);
-        test("isDepth12", profile(Depth13.class), o);
-        test("isDepth12", profile(Depth13.class, Depth14.class), o);
-    }
-
-    @LongTest
-    public void test8() {
-        Object o = new Depth13();
-        test("isDepth12Int", profile(), o);
-        test("isDepth12Int", profile(Depth13.class), o);
-        test("isDepth12Int", profile(Depth13.class, Depth14.class), o);
-
-        o = "not a depth";
-        test("isDepth12Int", profile(), o);
-        test("isDepth12Int", profile(Depth13.class), o);
-        test("isDepth12Int", profile(Depth13.class, Depth14.class), o);
-    }
-
-    public static boolean isString(Object o) {
-        return o instanceof String;
-    }
-
-    public static int isStringInt(Object o) {
-        if (o instanceof String) {
-            return id(1);
-        }
-        return id(0);
-    }
-
-    public static int isStringIntComplex(Object o) {
-        if (o instanceof String || o instanceof Integer) {
-            return id(o instanceof String ? 1 : 0);
-        }
-        return id(0);
-    }
-
-    public static int id(int value) {
-        return value;
-    }
-
-    public static boolean isThrowable(Object o) {
-        return ((Throwable) o) instanceof Exception;
-    }
-
-    public static int onlyFirstIsException(Throwable t1, Throwable t2) {
-        if (t1 instanceof Exception ^ t2 instanceof Exception) {
-            return t1 instanceof Exception ? 1 : -1;
-        }
-        return -1;
-    }
-
-    public static int isThrowableInt(Object o) {
-        int result = o instanceof Throwable ? 4 : 5;
-        if (o instanceof Throwable) {
-            return id(4);
-        }
-        return result;
-    }
-
-    public static boolean isMap(Object o) {
-        return o instanceof Map;
-    }
-
-    public static int isMapInt(Object o) {
-        if (o instanceof Map) {
-            return id(1);
-        }
-        return id(0);
-    }
-
-    public static boolean isDepth12(Object o) {
-        return o instanceof Depth12;
-    }
-
-    public static int isDepth12Int(Object o) {
-        if (o instanceof Depth12) {
-            return id(0);
-        }
-        return id(0);
-    }
-
-    abstract static class MySite {
-
-        final int offset;
-
-        MySite(int offset) {
-            this.offset = offset;
-        }
-    }
-
-    static class MyMark extends MySite {
-
-        MyMark(int offset) {
-            super(offset);
-        }
-    }
-
-    abstract static class MySafepoint extends MySite {
-
-        MySafepoint(int offset) {
-            super(offset);
-        }
-    }
-
-    static class MyCall extends MySafepoint {
-
-        MyCall(int offset) {
-            super(offset);
-        }
-    }
-
-    @LongTest
-    public void test9() {
-        MyCall callAt63 = new MyCall(63);
-        MyMark markAt63 = new MyMark(63);
-        test("compareMySites", callAt63, callAt63);
-        test("compareMySites", callAt63, markAt63);
-        test("compareMySites", markAt63, callAt63);
-        test("compareMySites", markAt63, markAt63);
-    }
-
-    public static int compareMySites(MySite s1, MySite s2) {
-        if (s1.offset == s2.offset && (s1 instanceof MyMark ^ s2 instanceof MyMark)) {
-            return s1 instanceof MyMark ? -1 : 1;
-        }
-        return s1.offset - s2.offset;
-    }
-
-    @LongTest
-    public void test10() {
-        Mark[] noMarks = {};
-        Call callAt63 = new Call(null, 63, 5, true, null);
-        Mark markAt63 = new Mark(63, "1", noMarks);
-        test("compareSites", callAt63, callAt63);
-        test("compareSites", callAt63, markAt63);
-        test("compareSites", markAt63, callAt63);
-        test("compareSites", markAt63, markAt63);
-    }
-
-    public static int compareSites(Site s1, Site s2) {
-        if (s1.pcOffset == s2.pcOffset && (s1 instanceof Mark ^ s2 instanceof Mark)) {
-            return s1 instanceof Mark ? -1 : 1;
-        }
-        return s1.pcOffset - s2.pcOffset;
-    }
-
-    /**
-     * This test exists to show the kind of pattern that is be optimizable by
-     * {@code removeIntermediateMaterialization()} in {@link IfNode}.
-     * <p>
-     * The test exists in this source file as the transformation was originally motivated by the
-     * need to remove use of special JumpNodes in the {@code InstanceOfSnippets}.
-     */
-    @LongTest
-    public void test_removeIntermediateMaterialization() {
-        List<String> list = Arrays.asList("1", "2", "3", "4");
-        test("removeIntermediateMaterialization", profile(), list, "2", "yes", "no");
-        test("removeIntermediateMaterialization", profile(), list, null, "yes", "no");
-        test("removeIntermediateMaterialization", profile(), null, "2", "yes", "no");
-    }
-
-    public static String removeIntermediateMaterialization(List<Object> list, Object e, String a, String b) {
-        boolean test;
-        if (list == null || e == null) {
-            test = false;
-        } else {
-            test = false;
-            for (Object i : list) {
-                if (i.equals(e)) {
-                    test = true;
-                    break;
-                }
-            }
-        }
-        if (test) {
-            return a;
-        }
-        return b;
-    }
-
-    abstract static class A {
-    }
-
-    static class B extends A {
-    }
-
-    static class C extends B {
-    }
-
-    abstract static class D extends C {
-    }
-
-    public static boolean isArrayOfA(Object o) {
-        return o instanceof A[];
-    }
-
-    public static boolean isArrayOfB(Object o) {
-        return o instanceof B[];
-    }
-
-    public static boolean isArrayOfC(Object o) {
-        return o instanceof C[];
-    }
-
-    public static boolean isArrayOfD(Object o) {
-        return o instanceof D[];
-    }
-
-    @LongTest
-    public void testArray() {
-        Object aArray = new A[10];
-        test("isArrayOfA", aArray);
-
-        Object bArray = new B[10];
-        test("isArrayOfA", aArray);
-        test("isArrayOfA", bArray);
-        test("isArrayOfB", aArray);
-        test("isArrayOfB", bArray);
-
-        Object cArray = new C[10];
-        test("isArrayOfA", aArray);
-        test("isArrayOfA", bArray);
-        test("isArrayOfA", cArray);
-        test("isArrayOfB", aArray);
-        test("isArrayOfB", bArray);
-        test("isArrayOfB", cArray);
-        test("isArrayOfC", aArray);
-        test("isArrayOfC", bArray);
-        test("isArrayOfC", cArray);
-
-        Object dArray = new D[10];
-        test("isArrayOfA", aArray);
-        test("isArrayOfA", bArray);
-        test("isArrayOfA", cArray);
-        test("isArrayOfA", dArray);
-        test("isArrayOfB", aArray);
-        test("isArrayOfB", bArray);
-        test("isArrayOfB", cArray);
-        test("isArrayOfB", dArray);
-        test("isArrayOfC", aArray);
-        test("isArrayOfC", bArray);
-        test("isArrayOfC", cArray);
-        test("isArrayOfC", dArray);
-        test("isArrayOfD", aArray);
-        test("isArrayOfD", bArray);
-        test("isArrayOfD", cArray);
-        test("isArrayOfD", dArray);
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/InvokeTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +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.graal.replacements;
-
-import org.junit.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.common.*;
-
-/**
- * Tests the implementation of the snippets for lowering the INVOKE* instructions.
- */
-public class InvokeTest extends GraalCompilerTest {
-
-    @Override
-    protected void editPhasePlan(ResolvedJavaMethod method, StructuredGraph graph, PhasePlan phasePlan) {
-        phasePlan.disablePhase(InliningPhase.class);
-    }
-
-    public interface I {
-
-        String virtualMethod(String s);
-    }
-
-    public static class A implements I {
-
-        final String name = "A";
-
-        public String virtualMethod(String s) {
-            return name + s;
-        }
-    }
-
-    @SuppressWarnings("static-method")
-    private String privateMethod(String s) {
-        return s;
-    }
-
-    @Test
-    public void test1() {
-        test("invokestatic", "a string");
-        test("invokespecialConstructor", "a string");
-        test("invokespecial", this, "a string");
-        test("invokevirtual", new A(), "a string");
-        test("invokevirtual2", new A(), "a string");
-        test("invokeinterface", new A(), "a string");
-        Object[] args = {null};
-        test("invokestatic", args);
-        test("invokespecialConstructor", args);
-        test("invokespecial", null, null);
-        test("invokevirtual", null, null);
-        test("invokevirtual2", null, null);
-        test("invokeinterface", null, null);
-    }
-
-    public static String invokestatic(String s) {
-        return staticMethod(s);
-    }
-
-    public static String staticMethod(String s) {
-        return s;
-    }
-
-    public static String invokespecialConstructor(String s) {
-        return new A().virtualMethod(s);
-    }
-
-    public static String invokespecial(InvokeTest a, String s) {
-        return a.privateMethod(s);
-    }
-
-    public static String invokevirtual(A a, String s) {
-        return a.virtualMethod(s);
-    }
-
-    public static String invokevirtual2(A a, String s) {
-        a.virtualMethod(s);
-        return a.virtualMethod(s);
-    }
-
-    public static String invokeinterface(I i, String s) {
-        return i.virtualMethod(s);
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/MethodSubstitutionTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * 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.graal.replacements;
-
-import static org.junit.Assert.*;
-
-import java.util.concurrent.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.common.*;
-
-/**
- * Tests if {@link MethodSubstitution}s are inlined correctly. Most test cases only assert that
- * there are no remaining invocations in the graph. This is sufficient if the method that is being
- * substituted is a native method. For Java methods, additional checks are necessary.
- */
-public abstract class MethodSubstitutionTest extends GraalCompilerTest {
-
-    protected StructuredGraph test(final String snippet) {
-        return Debug.scope("MethodSubstitutionTest", runtime.lookupJavaMethod(getMethod(snippet)), new Callable<StructuredGraph>() {
-
-            @Override
-            public StructuredGraph call() {
-                StructuredGraph graph = parse(snippet);
-                PhasePlan phasePlan = getDefaultPhasePlan();
-                Assumptions assumptions = new Assumptions(true);
-                new ComputeProbabilityPhase().apply(graph);
-                Debug.dump(graph, "Graph");
-                new InliningPhase(runtime(), null, replacements, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
-                Debug.dump(graph, "Graph");
-                new CanonicalizerPhase(runtime(), assumptions).apply(graph);
-                new DeadCodeEliminationPhase().apply(graph);
-
-                assertNotInGraph(graph, Invoke.class);
-                return graph;
-            }
-        });
-    }
-
-    protected static StructuredGraph assertNotInGraph(StructuredGraph graph, Class<?> clazz) {
-        for (Node node : graph.getNodes()) {
-            if (clazz.isInstance(node)) {
-                fail(node.toString());
-            }
-        }
-        return graph;
-    }
-
-    protected static StructuredGraph assertInGraph(StructuredGraph graph, Class<?> clazz) {
-        for (Node node : graph.getNodes()) {
-            if (clazz.isInstance(node)) {
-                return graph;
-            }
-        }
-        fail("Graph does not contain a node of class " + clazz.getName());
-        return graph;
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/MonitorTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,209 +0,0 @@
-/*
- * 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.graal.replacements;
-
-import org.junit.*;
-
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.virtual.phases.ea.*;
-
-public class MonitorTest extends GraalCompilerTest {
-
-    @Test
-    public void test0() {
-        test("lockObjectSimple", new Object(), new Object());
-        test("lockObjectSimple", new Object(), null);
-    }
-
-    @Test
-    public void test0_1() {
-        test("lockThisSimple", "test1", new Object());
-        test("lockThisSimple", "test1", null);
-    }
-
-    @Test
-    public void test0_2() {
-        test("lockObjectSimple", null, "test1");
-    }
-
-    @Test
-    public void test1_1() {
-        test("lockObject", new Object(), "test1", new String[1]);
-    }
-
-    @Test
-    public void test1_2() {
-        test("lockObject", null, "test1_1", new String[1]);
-    }
-
-    @Test
-    public void test2() {
-        test("lockThis", "test2", new String[1]);
-    }
-
-    /**
-     * Tests monitor operations on {@link PartialEscapeAnalysisPhase virtual objects}.
-     */
-    @Test
-    public void test3() {
-        test("lockLocalObject", "test3", new String[1]);
-    }
-
-    /**
-     * Tests recursive locking of objects which should be biasable.
-     */
-    @Test
-    public void test4() {
-        Chars src = new Chars("1234567890".toCharArray());
-        Chars dst = new Chars(src.data.length);
-        test("copyObj", src, dst, 100);
-    }
-
-    /**
-     * Tests recursive locking of objects which do not appear to be biasable.
-     */
-    @Test
-    public void test5() {
-        char[] src = "1234567890".toCharArray();
-        char[] dst = new char[src.length];
-        test("copyArr", src, dst, 100);
-    }
-
-    /**
-     * Extends {@link #test4()} with contention.
-     */
-    @Test
-    public void test6() {
-        Chars src = new Chars("1234567890".toCharArray());
-        Chars dst = new Chars(src.data.length);
-        int n = Runtime.getRuntime().availableProcessors();
-        testN(n, "copyObj", src, dst, 100);
-    }
-
-    /**
-     * Extends {@link #test5()} with contention.
-     */
-    @Test
-    public void test7() {
-        char[] src = "1234567890".toCharArray();
-        char[] dst = new char[src.length];
-        int n = Runtime.getRuntime().availableProcessors();
-        testN(n, "copyArr", src, dst, 100);
-    }
-
-    private static String setAndGet(String[] box, String value) {
-        synchronized (box) {
-            box[0] = null;
-        }
-
-        // Do a GC while a object is locked (by the caller)
-        System.gc();
-
-        synchronized (box) {
-            box[0] = value;
-        }
-        return box[0];
-    }
-
-    public static Object lockObjectSimple(Object o, Object value) {
-        synchronized (o) {
-            value.hashCode();
-            return value;
-        }
-    }
-
-    public String lockThisSimple(String value, Object o) {
-        synchronized (this) {
-            synchronized (value) {
-                o.hashCode();
-                return value;
-            }
-        }
-    }
-
-    public static String lockObject(Object o, String value, String[] box) {
-        synchronized (o) {
-            return setAndGet(box, value);
-        }
-    }
-
-    public String lockThis(String value, String[] box) {
-        synchronized (this) {
-            return setAndGet(box, value);
-        }
-    }
-
-    public static String lockLocalObject(String value, String[] box) {
-        Object o = new Object();
-        synchronized (o) {
-            return setAndGet(box, value);
-        }
-    }
-
-    static class Chars {
-
-        final char[] data;
-
-        public Chars(int size) {
-            this.data = new char[size];
-        }
-
-        public Chars(char[] data) {
-            this.data = data;
-        }
-    }
-
-    public static String copyObj(Chars src, Chars dst, int n) {
-        for (int j = 0; j < n; j++) {
-            for (int i = 0; i < src.data.length; i++) {
-                synchronized (src) {
-                    synchronized (dst) {
-                        synchronized (src) {
-                            synchronized (dst) {
-                                dst.data[i] = src.data[i];
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return new String(dst.data);
-    }
-
-    public static String copyArr(char[] src, char[] dst, int n) {
-        for (int j = 0; j < n; j++) {
-            for (int i = 0; i < src.length; i++) {
-                synchronized (src) {
-                    synchronized (dst) {
-                        synchronized (src) {
-                            synchronized (dst) {
-                                dst[i] = src[i];
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return new String(dst);
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/NewArrayTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +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.graal.replacements;
-
-import org.junit.*;
-
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.test.*;
-
-/**
- * Tests the implementation of {@code [A]NEWARRAY}.
- */
-public class NewArrayTest extends GraalCompilerTest {
-
-    @Override
-    protected void assertEquals(Object expected, Object actual) {
-        Assert.assertTrue(expected != null);
-        Assert.assertTrue(actual != null);
-        super.assertEquals(expected.getClass(), actual.getClass());
-        if (expected instanceof int[]) {
-            Assert.assertArrayEquals((int[]) expected, (int[]) actual);
-        } else if (expected instanceof byte[]) {
-            Assert.assertArrayEquals((byte[]) expected, (byte[]) actual);
-        } else if (expected instanceof char[]) {
-            Assert.assertArrayEquals((char[]) expected, (char[]) actual);
-        } else if (expected instanceof short[]) {
-            Assert.assertArrayEquals((short[]) expected, (short[]) actual);
-        } else if (expected instanceof float[]) {
-            Assert.assertArrayEquals((float[]) expected, (float[]) actual, 0.0f);
-        } else if (expected instanceof long[]) {
-            Assert.assertArrayEquals((long[]) expected, (long[]) actual);
-        } else if (expected instanceof double[]) {
-            Assert.assertArrayEquals((double[]) expected, (double[]) actual, 0.0d);
-        } else if (expected instanceof Object[]) {
-            Assert.assertArrayEquals((Object[]) expected, (Object[]) actual);
-        } else {
-            Assert.fail("non-array value encountered: " + expected);
-        }
-    }
-
-    @LongTest
-    public void test1() {
-        for (String type : new String[]{"Byte", "Char", "Short", "Int", "Float", "Long", "Double", "String"}) {
-            test("new" + type + "Array7");
-            test("new" + type + "ArrayMinus7");
-            test("new" + type + "Array", 7);
-            test("new" + type + "Array", -7);
-            test("new" + type + "Array", Integer.MAX_VALUE);
-            test("new" + type + "Array", Integer.MIN_VALUE);
-        }
-    }
-
-    public static Object newCharArray7() {
-        return new char[7];
-    }
-
-    public static Object newCharArrayMinus7() {
-        return new char[-7];
-    }
-
-    public static Object newCharArray(int length) {
-        return new char[length];
-    }
-
-    public static Object newShortArray7() {
-        return new short[7];
-    }
-
-    public static Object newShortArrayMinus7() {
-        return new short[-7];
-    }
-
-    public static Object newShortArray(int length) {
-        return new short[length];
-    }
-
-    public static Object newFloatArray7() {
-        return new float[7];
-    }
-
-    public static Object newFloatArrayMinus7() {
-        return new float[-7];
-    }
-
-    public static Object newFloatArray(int length) {
-        return new float[length];
-    }
-
-    public static Object newLongArray7() {
-        return new long[7];
-    }
-
-    public static Object newLongArrayMinus7() {
-        return new long[-7];
-    }
-
-    public static Object newLongArray(int length) {
-        return new long[length];
-    }
-
-    public static Object newDoubleArray7() {
-        return new double[7];
-    }
-
-    public static Object newDoubleArrayMinus7() {
-        return new double[-7];
-    }
-
-    public static Object newDoubleArray(int length) {
-        return new double[length];
-    }
-
-    public static Object newIntArray7() {
-        return new int[7];
-    }
-
-    public static Object newIntArrayMinus7() {
-        return new int[-7];
-    }
-
-    public static Object newIntArray(int length) {
-        return new int[length];
-    }
-
-    public static Object newByteArray7() {
-        return new byte[7];
-    }
-
-    public static Object newByteArrayMinus7() {
-        return new byte[-7];
-    }
-
-    public static Object newByteArray(int length) {
-        return new byte[length];
-    }
-
-    public static Object newStringArray7() {
-        return new String[7];
-    }
-
-    public static Object newStringArrayMinus7() {
-        return new String[-7];
-    }
-
-    public static Object newStringArray(int length) {
-        return new String[length];
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/NewInstanceTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,249 +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.graal.replacements;
-
-import java.util.*;
-
-import org.junit.*;
-
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.test.*;
-
-/**
- * Tests the implementation of {@code NEW}.
- */
-public class NewInstanceTest extends GraalCompilerTest {
-
-    @Override
-    protected void assertEquals(Object expected, Object actual) {
-        Assert.assertTrue(expected != null);
-        Assert.assertTrue(actual != null);
-        super.assertEquals(expected.getClass(), actual.getClass());
-
-        if (expected instanceof Object[]) {
-            Assert.assertTrue(actual instanceof Object[]);
-            Object[] eArr = (Object[]) expected;
-            Object[] aArr = (Object[]) actual;
-            Assert.assertTrue(eArr.length == aArr.length);
-            for (int i = 0; i < eArr.length; i++) {
-                assertEquals(eArr[i], aArr[i]);
-            }
-        } else if (expected.getClass() != Object.class) {
-            try {
-                expected.getClass().getDeclaredMethod("equals", Object.class);
-                super.assertEquals(expected, actual);
-            } catch (Exception e) {
-            }
-        }
-    }
-
-    @LongTest
-    public void test1() {
-        test("newObject");
-    }
-
-    @LongTest
-    public void test2() {
-        test("newObjectTwice");
-    }
-
-    public static Object newObject() {
-        return new Object();
-    }
-
-    @LongTest
-    public void test3() {
-        test("newObjectLoop", 100);
-    }
-
-    @LongTest
-    public void test4() {
-        test("newBigObject");
-    }
-
-    @LongTest
-    public void test5() {
-        test("newSomeObject");
-    }
-
-    @LongTest
-    public void test6() {
-        test("newEmptyString");
-    }
-
-    @LongTest
-    public void test7() {
-        test("newString", "value");
-    }
-
-    @LongTest
-    public void test8() {
-        test("newHashMap", 31);
-    }
-
-    @LongTest
-    public void test9() {
-        test("newRegression", true);
-    }
-
-    public static Object[] newObjectTwice() {
-        Object[] res = {new Object(), new Object()};
-        return res;
-    }
-
-    public static Object[] newObjectLoop(int n) {
-        Object[] res = new Object[n];
-        for (int i = 0; i < n; i++) {
-            res[i] = new Object();
-        }
-        return res;
-    }
-
-    public static BigObject newBigObject() {
-        return new BigObject();
-    }
-
-    public static SomeObject newSomeObject() {
-        return new SomeObject();
-    }
-
-    public static String newEmptyString() {
-        return new String();
-    }
-
-    public static String newString(String value) {
-        return new String(value);
-    }
-
-    public static HashMap newHashMap(int initialCapacity) {
-        return new HashMap(initialCapacity);
-    }
-
-    static class SomeObject {
-
-        String name = "o1";
-        HashMap<String, Object> map = new HashMap<>();
-
-        public SomeObject() {
-            map.put(name, this.getClass());
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof SomeObject) {
-                SomeObject so = (SomeObject) obj;
-                return so.name.equals(name) && so.map.equals(map);
-            }
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            return name.hashCode();
-        }
-    }
-
-    static class BigObject {
-
-        Object f01;
-        Object f02;
-        Object f03;
-        Object f04;
-        Object f05;
-        Object f06;
-        Object f07;
-        Object f08;
-        Object f09;
-        Object f10;
-        Object f12;
-        Object f13;
-        Object f14;
-        Object f15;
-        Object f16;
-        Object f17;
-        Object f18;
-        Object f19;
-        Object f20;
-        Object f21;
-        Object f22;
-        Object f23;
-        Object f24;
-        Object f25;
-        Object f26;
-        Object f27;
-        Object f28;
-        Object f29;
-        Object f30;
-        Object f31;
-        Object f32;
-        Object f33;
-        Object f34;
-        Object f35;
-        Object f36;
-        Object f37;
-        Object f38;
-        Object f39;
-        Object f40;
-        Object f41;
-        Object f42;
-        Object f43;
-        Object f44;
-        Object f45;
-    }
-
-    /**
-     * Tests that an earlier bug does not occur. The issue was that the loading of the TLAB 'top'
-     * and 'end' values was being GVN'ed from each branch of the 'if' statement. This meant that the
-     * allocated B object in the true branch overwrote the allocated array. The cause is that
-     * RegisterNode was a floating node and the reads from it were UnsafeLoads which are also
-     * floating. The fix was to make RegisterNode a fixed node (which it should have been in the
-     * first place).
-     */
-    public static Object newRegression(boolean condition) {
-        Object result;
-        if (condition) {
-            Object[] arr = {0, 1, 2, 3, 4, 5};
-            result = new B();
-            for (int i = 0; i < arr.length; ++i) {
-                // If the bug exists, the values of arr will now be deadbeef values
-                // and the virtual dispatch will cause a segfault. This can result in
-                // either a VM crash or a spurious NullPointerException.
-                if (arr[i].equals(Integer.valueOf(i))) {
-                    return false;
-                }
-            }
-        } else {
-            result = new B();
-        }
-        return result;
-    }
-
-    static class B {
-
-        long f1 = 0xdeadbeefdeadbe01L;
-        long f2 = 0xdeadbeefdeadbe02L;
-        long f3 = 0xdeadbeefdeadbe03L;
-        long f4 = 0xdeadbeefdeadbe04L;
-        long f5 = 0xdeadbeefdeadbe05L;
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/NewMultiArrayTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-/*
- * 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.graal.replacements;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.test.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
-
-/**
- * Tests the lowering of the MULTIANEWARRAY instruction.
- */
-public class NewMultiArrayTest extends GraalCompilerTest {
-
-    private static int rank(ResolvedJavaType type) {
-        String name = type.getName();
-        int dims = 0;
-        while (dims < name.length() && name.charAt(dims) == '[') {
-            dims++;
-        }
-        return dims;
-    }
-
-    @Override
-    protected InstalledCode getCode(final ResolvedJavaMethod method, final StructuredGraph graph) {
-        boolean forceCompile = false;
-        if (bottomType != null) {
-            List<NewMultiArrayNode> snapshot = graph.getNodes().filter(NewMultiArrayNode.class).snapshot();
-            assert snapshot != null;
-            assert snapshot.size() == 1;
-
-            NewMultiArrayNode node = snapshot.get(0);
-            assert rank(arrayType) == dimensions.length;
-            int rank = dimensions.length;
-            ValueNode[] dimensionNodes = new ValueNode[rank];
-            for (int i = 0; i < rank; i++) {
-                dimensionNodes[i] = graph.unique(ConstantNode.forInt(dimensions[i], graph));
-            }
-
-            NewMultiArrayNode repl = graph.add(new NewMultiArrayNode(arrayType, dimensionNodes));
-            graph.replaceFixedWithFixed(node, repl);
-            forceCompile = true;
-        }
-        return super.getCode(method, graph, forceCompile);
-    }
-
-    @Override
-    protected Object referenceInvoke(Method method, Object receiver, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
-        if (bottomType != null) {
-            try {
-                return Array.newInstance(bottomClass, dimensions);
-            } catch (Exception e) {
-                throw new InvocationTargetException(e);
-            }
-        }
-        return super.referenceInvoke(method, receiver, args);
-    }
-
-    ResolvedJavaType arrayType;
-    ResolvedJavaType bottomType;
-    Class bottomClass;
-    int[] dimensions;
-
-    @LongTest
-    public void test1() {
-        for (Class clazz : new Class[]{byte.class, char.class, short.class, int.class, float.class, long.class, double.class, String.class}) {
-            bottomClass = clazz;
-            bottomType = runtime.lookupJavaType(clazz);
-            arrayType = bottomType;
-            for (int rank : new int[]{1, 2, 10, 50, 100, 200, 254, 255}) {
-                while (rank(arrayType) != rank) {
-                    arrayType = arrayType.getArrayClass();
-                }
-
-                dimensions = new int[rank];
-                for (int i = 0; i < rank; i++) {
-                    dimensions[i] = 1;
-                }
-
-                test("newMultiArray");
-            }
-        }
-        bottomType = null;
-        arrayType = null;
-    }
-
-    public static Object newMultiArray() {
-        // This is merely a template - the NewMultiArrayNode is replaced in getCode() above.
-        // This also means we need a separate test for correct handling of negative dimensions
-        // as deoptimization won't do what we want for a graph modified to be different from the
-        // source bytecode.
-        return new Object[10][9][8];
-    }
-
-    @LongTest
-    public void test2() {
-        test("newMultiArrayException");
-    }
-
-    public static Object newMultiArrayException() {
-        return new Object[10][9][-8];
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/PointerTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,399 +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.replacements;
-
-import java.lang.reflect.*;
-
-import org.junit.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.replacements.Snippet.*;
-import com.oracle.graal.word.*;
-
-/**
- * Tests for the {@link Pointer} read and write operations.
- */
-public class PointerTest extends GraalCompilerTest implements Snippets {
-
-    private static final Object ID = new Object();
-    private static final Kind[] KINDS = new Kind[]{Kind.Byte, Kind.Char, Kind.Short, Kind.Int, Kind.Long, Kind.Float, Kind.Double, Kind.Object};
-    private final TargetDescription target;
-    private final ReplacementsImpl installer;
-
-    public PointerTest() {
-        target = Graal.getRequiredCapability(CodeCacheProvider.class).getTarget();
-        installer = new ReplacementsImpl(runtime, new Assumptions(false), target);
-    }
-
-    private static final ThreadLocal<SnippetInliningPolicy> inliningPolicy = new ThreadLocal<>();
-
-    @Override
-    protected StructuredGraph parse(Method m) {
-        ResolvedJavaMethod resolvedMethod = runtime.lookupJavaMethod(m);
-        return installer.makeGraph(resolvedMethod, null, inliningPolicy.get());
-    }
-
-    @Test
-    public void test_read1() {
-        for (Kind kind : KINDS) {
-            assertRead(parse("read" + kind.name() + "1"), kind, false, ID);
-        }
-    }
-
-    @Test
-    public void test_read2() {
-        for (Kind kind : KINDS) {
-            assertRead(parse("read" + kind.name() + "2"), kind, true, ID);
-        }
-    }
-
-    @Test
-    public void test_read3() {
-        for (Kind kind : KINDS) {
-            assertRead(parse("read" + kind.name() + "3"), kind, false, LocationNode.ANY_LOCATION);
-        }
-    }
-
-    @Test
-    public void test_write1() {
-        for (Kind kind : KINDS) {
-            assertWrite(parse("write" + kind.name() + "1"), kind, false, ID);
-        }
-    }
-
-    @Test
-    public void test_write2() {
-        for (Kind kind : KINDS) {
-            assertWrite(parse("write" + kind.name() + "2"), kind, true, ID);
-        }
-    }
-
-    @Test
-    public void test_write3() {
-        for (Kind kind : KINDS) {
-            assertWrite(parse("write" + kind.name() + "3"), kind, false, LocationNode.ANY_LOCATION);
-        }
-    }
-
-    private void assertRead(StructuredGraph graph, Kind kind, boolean indexConvert, Object locationIdentity) {
-        ReadNode read = (ReadNode) graph.start().next();
-        Assert.assertEquals(kind.getStackKind(), read.kind());
-
-        UnsafeCastNode cast = (UnsafeCastNode) read.object();
-        Assert.assertEquals(graph.getLocal(0), cast.object());
-        Assert.assertEquals(target.wordKind, cast.kind());
-
-        IndexedLocationNode location = (IndexedLocationNode) read.location();
-        Assert.assertEquals(kind, location.getValueKind());
-        Assert.assertEquals(locationIdentity, location.locationIdentity());
-        Assert.assertEquals(1, location.indexScaling());
-
-        if (indexConvert) {
-            ConvertNode convert = (ConvertNode) location.index();
-            Assert.assertEquals(ConvertNode.Op.I2L, convert.opcode);
-            Assert.assertEquals(graph.getLocal(1), convert.value());
-        } else {
-            Assert.assertEquals(graph.getLocal(1), location.index());
-        }
-
-        ReturnNode ret = (ReturnNode) read.next();
-        Assert.assertEquals(read, ret.result());
-    }
-
-    private void assertWrite(StructuredGraph graph, Kind kind, boolean indexConvert, Object locationIdentity) {
-        WriteNode write = (WriteNode) graph.start().next();
-        Assert.assertEquals(graph.getLocal(2), write.value());
-        Assert.assertEquals(Kind.Void, write.kind());
-        Assert.assertEquals(FrameState.INVALID_FRAMESTATE_BCI, write.stateAfter().bci);
-
-        UnsafeCastNode cast = (UnsafeCastNode) write.object();
-        Assert.assertEquals(graph.getLocal(0), cast.object());
-        Assert.assertEquals(target.wordKind, cast.kind());
-
-        IndexedLocationNode location = (IndexedLocationNode) write.location();
-        Assert.assertEquals(kind, location.getValueKind());
-        Assert.assertEquals(locationIdentity, location.locationIdentity());
-        Assert.assertEquals(1, location.indexScaling());
-
-        if (indexConvert) {
-            ConvertNode convert = (ConvertNode) location.index();
-            Assert.assertEquals(ConvertNode.Op.I2L, convert.opcode);
-            Assert.assertEquals(graph.getLocal(1), convert.value());
-        } else {
-            Assert.assertEquals(graph.getLocal(1), location.index());
-        }
-
-        AbstractStateSplit stateSplit = (AbstractStateSplit) write.next();
-        Assert.assertEquals(FrameState.AFTER_BCI, stateSplit.stateAfter().bci);
-
-        ReturnNode ret = (ReturnNode) stateSplit.next();
-        Assert.assertEquals(null, ret.result());
-    }
-
-    @Snippet
-    public static byte readByte1(Object o, int offset) {
-        return Word.fromObject(o).readByte(offset, ID);
-    }
-
-    @Snippet
-    public static byte readByte2(Object o, int offset) {
-        return Word.fromObject(o).readByte(Word.signed(offset), ID);
-    }
-
-    @Snippet
-    public static byte readByte3(Object o, int offset) {
-        return Word.fromObject(o).readByte(offset);
-    }
-
-    @Snippet
-    public static void writeByte1(Object o, int offset, byte value) {
-        Word.fromObject(o).writeByte(offset, value, ID);
-    }
-
-    @Snippet
-    public static void writeByte2(Object o, int offset, byte value) {
-        Word.fromObject(o).writeByte(Word.signed(offset), value, ID);
-    }
-
-    @Snippet
-    public static void writeByte3(Object o, int offset, byte value) {
-        Word.fromObject(o).writeByte(offset, value);
-    }
-
-    @Snippet
-    public static char readChar1(Object o, int offset) {
-        return Word.fromObject(o).readChar(offset, ID);
-    }
-
-    @Snippet
-    public static char readChar2(Object o, int offset) {
-        return Word.fromObject(o).readChar(Word.signed(offset), ID);
-    }
-
-    @Snippet
-    public static char readChar3(Object o, int offset) {
-        return Word.fromObject(o).readChar(offset);
-    }
-
-    @Snippet
-    public static void writeChar1(Object o, int offset, char value) {
-        Word.fromObject(o).writeChar(offset, value, ID);
-    }
-
-    @Snippet
-    public static void writeChar2(Object o, int offset, char value) {
-        Word.fromObject(o).writeChar(Word.signed(offset), value, ID);
-    }
-
-    @Snippet
-    public static void writeChar3(Object o, int offset, char value) {
-        Word.fromObject(o).writeChar(offset, value);
-    }
-
-    @Snippet
-    public static short readShort1(Object o, int offset) {
-        return Word.fromObject(o).readShort(offset, ID);
-    }
-
-    @Snippet
-    public static short readShort2(Object o, int offset) {
-        return Word.fromObject(o).readShort(Word.signed(offset), ID);
-    }
-
-    @Snippet
-    public static short readShort3(Object o, int offset) {
-        return Word.fromObject(o).readShort(offset);
-    }
-
-    @Snippet
-    public static void writeShort1(Object o, int offset, short value) {
-        Word.fromObject(o).writeShort(offset, value, ID);
-    }
-
-    @Snippet
-    public static void writeShort2(Object o, int offset, short value) {
-        Word.fromObject(o).writeShort(Word.signed(offset), value, ID);
-    }
-
-    @Snippet
-    public static void writeShort3(Object o, int offset, short value) {
-        Word.fromObject(o).writeShort(offset, value);
-    }
-
-    @Snippet
-    public static int readInt1(Object o, int offset) {
-        return Word.fromObject(o).readInt(offset, ID);
-    }
-
-    @Snippet
-    public static int readInt2(Object o, int offset) {
-        return Word.fromObject(o).readInt(Word.signed(offset), ID);
-    }
-
-    @Snippet
-    public static int readInt3(Object o, int offset) {
-        return Word.fromObject(o).readInt(offset);
-    }
-
-    @Snippet
-    public static void writeInt1(Object o, int offset, int value) {
-        Word.fromObject(o).writeInt(offset, value, ID);
-    }
-
-    @Snippet
-    public static void writeInt2(Object o, int offset, int value) {
-        Word.fromObject(o).writeInt(Word.signed(offset), value, ID);
-    }
-
-    @Snippet
-    public static void writeInt3(Object o, int offset, int value) {
-        Word.fromObject(o).writeInt(offset, value);
-    }
-
-    @Snippet
-    public static long readLong1(Object o, int offset) {
-        return Word.fromObject(o).readLong(offset, ID);
-    }
-
-    @Snippet
-    public static long readLong2(Object o, int offset) {
-        return Word.fromObject(o).readLong(Word.signed(offset), ID);
-    }
-
-    @Snippet
-    public static long readLong3(Object o, int offset) {
-        return Word.fromObject(o).readLong(offset);
-    }
-
-    @Snippet
-    public static void writeLong1(Object o, int offset, long value) {
-        Word.fromObject(o).writeLong(offset, value, ID);
-    }
-
-    @Snippet
-    public static void writeLong2(Object o, int offset, long value) {
-        Word.fromObject(o).writeLong(Word.signed(offset), value, ID);
-    }
-
-    @Snippet
-    public static void writeLong3(Object o, int offset, long value) {
-        Word.fromObject(o).writeLong(offset, value);
-    }
-
-    @Snippet
-    public static float readFloat1(Object o, int offset) {
-        return Word.fromObject(o).readFloat(offset, ID);
-    }
-
-    @Snippet
-    public static float readFloat2(Object o, int offset) {
-        return Word.fromObject(o).readFloat(Word.signed(offset), ID);
-    }
-
-    @Snippet
-    public static float readFloat3(Object o, int offset) {
-        return Word.fromObject(o).readFloat(offset);
-    }
-
-    @Snippet
-    public static void writeFloat1(Object o, int offset, float value) {
-        Word.fromObject(o).writeFloat(offset, value, ID);
-    }
-
-    @Snippet
-    public static void writeFloat2(Object o, int offset, float value) {
-        Word.fromObject(o).writeFloat(Word.signed(offset), value, ID);
-    }
-
-    @Snippet
-    public static void writeFloat3(Object o, int offset, float value) {
-        Word.fromObject(o).writeFloat(offset, value);
-    }
-
-    @Snippet
-    public static double readDouble1(Object o, int offset) {
-        return Word.fromObject(o).readDouble(offset, ID);
-    }
-
-    @Snippet
-    public static double readDouble2(Object o, int offset) {
-        return Word.fromObject(o).readDouble(Word.signed(offset), ID);
-    }
-
-    @Snippet
-    public static double readDouble3(Object o, int offset) {
-        return Word.fromObject(o).readDouble(offset);
-    }
-
-    @Snippet
-    public static void writeDouble1(Object o, int offset, double value) {
-        Word.fromObject(o).writeDouble(offset, value, ID);
-    }
-
-    @Snippet
-    public static void writeDouble2(Object o, int offset, double value) {
-        Word.fromObject(o).writeDouble(Word.signed(offset), value, ID);
-    }
-
-    @Snippet
-    public static void writeDouble3(Object o, int offset, double value) {
-        Word.fromObject(o).writeDouble(offset, value);
-    }
-
-    @Snippet
-    public static Object readObject1(Object o, int offset) {
-        return Word.fromObject(o).readObject(offset, ID);
-    }
-
-    @Snippet
-    public static Object readObject2(Object o, int offset) {
-        return Word.fromObject(o).readObject(Word.signed(offset), ID);
-    }
-
-    @Snippet
-    public static Object readObject3(Object o, int offset) {
-        return Word.fromObject(o).readObject(offset);
-    }
-
-    @Snippet
-    public static void writeObject1(Object o, int offset, Object value) {
-        Word.fromObject(o).writeObject(offset, value, ID);
-    }
-
-    @Snippet
-    public static void writeObject2(Object o, int offset, Object value) {
-        Word.fromObject(o).writeObject(Word.signed(offset), value, ID);
-    }
-
-    @Snippet
-    public static void writeObject3(Object o, int offset, Object value) {
-        Word.fromObject(o).writeObject(offset, value);
-    }
-
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/StandardMethodSubstitutionsTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,453 +0,0 @@
-/*
- * 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.graal.replacements;
-
-import static com.oracle.graal.graph.UnsafeAccess.*;
-import static com.oracle.graal.replacements.UnsafeSubstitutions.*;
-
-import java.lang.reflect.*;
-import java.util.concurrent.atomic.*;
-
-import org.junit.*;
-
-import sun.misc.*;
-
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.replacements.nodes.*;
-
-/**
- * Tests the VM independent {@link MethodSubstitution}s.
- */
-public class StandardMethodSubstitutionsTest extends MethodSubstitutionTest {
-
-    static long off(Object o, String name) {
-        try {
-            return unsafe.objectFieldOffset(o.getClass().getDeclaredField(name));
-        } catch (Exception e) {
-            Assert.fail(e.toString());
-            return 0L;
-        }
-    }
-
-    static class Foo {
-
-        boolean z;
-        byte b;
-        short s;
-        char c;
-        int i;
-        long l;
-        float f;
-        double d;
-        Object o;
-
-        void testGet(Field field, long offset, String getName, Object value) throws Exception {
-            field.set(this, value);
-            Method m1 = Unsafe.class.getDeclaredMethod(getName, Object.class, long.class);
-            Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, Object.class, long.class);
-            Object expected = m1.invoke(unsafe, this, offset);
-            Object actual = m2.invoke(null, unsafe, this, offset);
-            Assert.assertEquals(expected, actual);
-        }
-
-        void testDirect(Field field, long offset, String type, Object value) throws Exception {
-            if (type.equals("Boolean") || type.equals("Object")) {
-                // No direct memory access for these types
-                return;
-            }
-
-            long address = unsafe.allocateMemory(offset + 16);
-
-            String getName = "get" + type;
-            String putName = "put" + type;
-            Method m1 = Unsafe.class.getDeclaredMethod(putName, long.class, field.getType());
-            Method m2 = Unsafe.class.getDeclaredMethod(getName, long.class);
-
-            Method m3 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, long.class, field.getType());
-            Method m4 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, long.class);
-
-            m1.invoke(unsafe, address + offset, value);
-            Object expected = m2.invoke(unsafe, address + offset);
-
-            m3.invoke(null, unsafe, address + offset, value);
-            Object actual = m4.invoke(null, unsafe, address + offset);
-
-            unsafe.freeMemory(address);
-            Assert.assertEquals(expected, actual);
-        }
-
-        void testPut(Field field, long offset, String putName, Object value) throws Exception {
-            Object initialValue = field.get(new Foo());
-            field.set(this, initialValue);
-
-            try {
-                Method m1 = Unsafe.class.getDeclaredMethod(putName, Object.class, long.class, field.getType());
-                Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, Object.class, long.class, field.getType());
-                m1.invoke(unsafe, this, offset, value);
-                Object expected = field.get(this);
-                m2.invoke(null, unsafe, this, offset, value);
-                Object actual = field.get(this);
-                Assert.assertEquals(expected, actual);
-            } catch (NoSuchMethodException e) {
-                if (!putName.startsWith("putOrdered")) {
-                    throw e;
-                }
-            }
-        }
-
-        void test(String fieldName, String typeSuffix, Object value) {
-            try {
-                Field field = Foo.class.getDeclaredField(fieldName);
-                long offset = unsafe.objectFieldOffset(field);
-                testGet(field, offset, "get" + typeSuffix, value);
-                testGet(field, offset, "get" + typeSuffix + "Volatile", value);
-                testPut(field, offset, "put" + typeSuffix, value);
-                testPut(field, offset, "put" + typeSuffix + "Volatile", value);
-                testPut(field, offset, "putOrdered" + typeSuffix, value);
-                testDirect(field, offset, typeSuffix, value);
-            } catch (Exception e) {
-                throw new AssertionError(e);
-            }
-        }
-    }
-
-    @Test
-    public void testUnsafeSubstitutions() throws Exception {
-        test("unsafeCompareAndSwapInt");
-        test("unsafeCompareAndSwapLong");
-        test("unsafeCompareAndSwapObject");
-
-        test("unsafeGetBoolean");
-        test("unsafeGetByte");
-        test("unsafeGetShort");
-        test("unsafeGetChar");
-        test("unsafeGetInt");
-        test("unsafeGetLong");
-        test("unsafeGetFloat");
-        test("unsafeGetDouble");
-        test("unsafeGetObject");
-
-        test("unsafePutBoolean");
-        test("unsafePutByte");
-        test("unsafePutShort");
-        test("unsafePutChar");
-        test("unsafePutInt");
-        test("unsafePutFloat");
-        test("unsafePutDouble");
-        test("unsafePutObject");
-
-        test("unsafeDirectMemoryRead");
-        test("unsafeDirectMemoryWrite");
-
-        AtomicInteger a1 = new AtomicInteger(42);
-        AtomicInteger a2 = new AtomicInteger(42);
-        assertEquals(unsafe.compareAndSwapInt(a1, off(a1, "value"), 42, 53), compareAndSwapInt(unsafe, a2, off(a2, "value"), 42, 53));
-        assertEquals(a1.get(), a2.get());
-
-        AtomicLong l1 = new AtomicLong(42);
-        AtomicLong l2 = new AtomicLong(42);
-        assertEquals(unsafe.compareAndSwapLong(l1, off(l1, "value"), 42, 53), compareAndSwapLong(unsafe, l2, off(l2, "value"), 42, 53));
-        assertEquals(l1.get(), l2.get());
-
-        AtomicReference o1 = new AtomicReference<>("42");
-        AtomicReference o2 = new AtomicReference<>("42");
-        assertEquals(unsafe.compareAndSwapObject(o1, off(o1, "value"), "42", "53"), compareAndSwapObject(unsafe, o2, off(o2, "value"), "42", "53"));
-        assertEquals(o1.get(), o2.get());
-
-        Foo f1 = new Foo();
-        f1.test("z", "Boolean", Boolean.TRUE);
-        f1.test("b", "Byte", Byte.MIN_VALUE);
-        f1.test("s", "Short", Short.MAX_VALUE);
-        f1.test("c", "Char", '!');
-        f1.test("i", "Int", 1010010);
-        f1.test("f", "Float", -34.5F);
-        f1.test("l", "Long", 99999L);
-        f1.test("d", "Double", 1234.5678D);
-        f1.test("o", "Object", "object");
-    }
-
-    @SuppressWarnings("all")
-    public static boolean unsafeCompareAndSwapInt(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.compareAndSwapInt(obj, offset, 0, 1);
-    }
-
-    @SuppressWarnings("all")
-    public static boolean unsafeCompareAndSwapLong(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.compareAndSwapLong(obj, offset, 0, 1);
-    }
-
-    @SuppressWarnings("all")
-    public static boolean unsafeCompareAndSwapObject(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.compareAndSwapObject(obj, offset, null, new Object());
-    }
-
-    @SuppressWarnings("all")
-    public static boolean unsafeGetBoolean(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getBoolean(obj, offset) && unsafe.getBooleanVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static int unsafeGetByte(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getByte(obj, offset) + unsafe.getByteVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static int unsafeGetShort(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getShort(obj, offset) + unsafe.getShortVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static int unsafeGetChar(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getChar(obj, offset) + unsafe.getCharVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static int unsafeGetInt(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getInt(obj, offset) + unsafe.getIntVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static long unsafeGetLong(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getLong(obj, offset) + unsafe.getLongVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static float unsafeGetFloat(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getFloat(obj, offset) + unsafe.getFloatVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static double unsafeGetDouble(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getDouble(obj, offset) + unsafe.getDoubleVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static boolean unsafeGetObject(Unsafe unsafe, Object obj, long offset) {
-        return unsafe.getObject(obj, offset) == unsafe.getObjectVolatile(obj, offset);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutBoolean(Unsafe unsafe, Object obj, long offset, boolean value) {
-        unsafe.putBoolean(obj, offset, value);
-        unsafe.putBooleanVolatile(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutByte(Unsafe unsafe, Object obj, long offset, byte value) {
-        unsafe.putByte(obj, offset, value);
-        unsafe.putByteVolatile(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutShort(Unsafe unsafe, Object obj, long offset, short value) {
-        unsafe.putShort(obj, offset, value);
-        unsafe.putShortVolatile(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutChar(Unsafe unsafe, Object obj, long offset, char value) {
-        unsafe.putChar(obj, offset, value);
-        unsafe.putCharVolatile(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutInt(Unsafe unsafe, Object obj, long offset, int value) {
-        unsafe.putInt(obj, offset, value);
-        unsafe.putIntVolatile(obj, offset, value);
-        unsafe.putOrderedInt(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutLong(Unsafe unsafe, Object obj, long offset, long value) {
-        unsafe.putLong(obj, offset, value);
-        unsafe.putLongVolatile(obj, offset, value);
-        unsafe.putOrderedLong(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutFloat(Unsafe unsafe, Object obj, long offset, float value) {
-        unsafe.putFloat(obj, offset, value);
-        unsafe.putFloatVolatile(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutDouble(Unsafe unsafe, Object obj, long offset, double value) {
-        unsafe.putDouble(obj, offset, value);
-        unsafe.putDoubleVolatile(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafePutObject(Unsafe unsafe, Object obj, long offset, Object value) {
-        unsafe.putObject(obj, offset, value);
-        unsafe.putObjectVolatile(obj, offset, value);
-        unsafe.putOrderedObject(obj, offset, value);
-    }
-
-    @SuppressWarnings("all")
-    public static double unsafeDirectMemoryRead(Unsafe unsafe, long address) {
-        // Unsafe.getBoolean(long) and Unsafe.getObject(long) do not exist
-        return unsafe.getByte(address) + unsafe.getShort(address) + unsafe.getChar(address) + unsafe.getInt(address) + unsafe.getLong(address) + unsafe.getFloat(address) + unsafe.getDouble(address);
-    }
-
-    @SuppressWarnings("all")
-    public static void unsafeDirectMemoryWrite(Unsafe unsafe, long address, byte value) {
-        // Unsafe.putBoolean(long) and Unsafe.putObject(long) do not exist
-        unsafe.putByte(address, value);
-        unsafe.putShort(address, value);
-        unsafe.putChar(address, (char) value);
-        unsafe.putInt(address, value);
-        unsafe.putLong(address, value);
-        unsafe.putFloat(address, value);
-        unsafe.putDouble(address, value);
-    }
-
-    @Test
-    public void testMathSubstitutions() {
-        assertInGraph(assertNotInGraph(test("mathAbs"), IfNode.class), MathIntrinsicNode.class);     // Java
-        test("math");
-
-        double value = 34567.891D;
-        assertEquals(Math.sqrt(value), MathSubstitutionsX86.sqrt(value));
-        assertEquals(Math.log(value), MathSubstitutionsX86.log(value));
-        assertEquals(Math.log10(value), MathSubstitutionsX86.log10(value));
-        assertEquals(Math.sin(value), MathSubstitutionsX86.sin(value));
-        assertEquals(Math.cos(value), MathSubstitutionsX86.cos(value));
-        assertEquals(Math.tan(value), MathSubstitutionsX86.tan(value));
-    }
-
-    @SuppressWarnings("all")
-    public static double mathAbs(double value) {
-        return Math.abs(value);
-    }
-
-    @SuppressWarnings("all")
-    public static double math(double value) {
-        return Math.sqrt(value) + Math.log(value) + Math.log10(value) + Math.sin(value) + Math.cos(value) + Math.tan(value);
-        // Math.exp(value) +
-        // Math.pow(value, 13);
-    }
-
-    @Test
-    public void testIntegerSubstitutions() {
-        assertInGraph(test("integerReverseBytes"), ReverseBytesNode.class);              // Java
-        assertInGraph(test("integerNumberOfLeadingZeros"), BitScanReverseNode.class);    // Java
-        assertInGraph(test("integerNumberOfTrailingZeros"), BitScanForwardNode.class);   // Java
-        assertInGraph(test("integerBitCount"), BitCountNode.class);                      // Java
-
-        for (int i : new int[]{Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE}) {
-            assertEquals(Integer.reverseBytes(i), IntegerSubstitutions.reverseBytes(i));
-            assertEquals(Integer.numberOfLeadingZeros(i), IntegerSubstitutions.numberOfLeadingZeros(i));
-            assertEquals(Integer.numberOfTrailingZeros(i), IntegerSubstitutions.numberOfTrailingZeros(i));
-            assertEquals(Integer.bitCount(i), IntegerSubstitutions.bitCount(i));
-        }
-    }
-
-    @SuppressWarnings("all")
-    public static int integerReverseBytes(int value) {
-        return Integer.reverseBytes(value);
-    }
-
-    @SuppressWarnings("all")
-    public static int integerNumberOfLeadingZeros(int value) {
-        return Integer.numberOfLeadingZeros(value);
-    }
-
-    @SuppressWarnings("all")
-    public static int integerNumberOfTrailingZeros(int value) {
-        return Integer.numberOfTrailingZeros(value);
-    }
-
-    @SuppressWarnings("all")
-    public static int integerBitCount(int value) {
-        return Integer.bitCount(value);
-    }
-
-    @Test
-    public void testLongSubstitutions() {
-        assertInGraph(test("longReverseBytes"), ReverseBytesNode.class);              // Java
-        assertInGraph(test("longNumberOfLeadingZeros"), BitScanReverseNode.class);    // Java
-        assertInGraph(test("longNumberOfTrailingZeros"), BitScanForwardNode.class);   // Java
-        assertInGraph(test("longBitCount"), BitCountNode.class);                      // Java
-
-        for (long l : new long[]{Long.MIN_VALUE, -1L, 0L, 1L, Long.MAX_VALUE}) {
-            assertEquals(Long.reverseBytes(l), LongSubstitutions.reverseBytes(l));
-            assertEquals(Long.numberOfLeadingZeros(l), LongSubstitutions.numberOfLeadingZeros(l));
-            assertEquals(Long.numberOfTrailingZeros(l), LongSubstitutions.numberOfTrailingZeros(l));
-            assertEquals(Long.bitCount(l), LongSubstitutions.bitCount(l));
-        }
-    }
-
-    @SuppressWarnings("all")
-    public static long longReverseBytes(long value) {
-        return Long.reverseBytes(value);
-    }
-
-    @SuppressWarnings("all")
-    public static long longNumberOfLeadingZeros(long value) {
-        return Long.numberOfLeadingZeros(value);
-    }
-
-    @SuppressWarnings("all")
-    public static long longNumberOfTrailingZeros(long value) {
-        return Long.numberOfTrailingZeros(value);
-    }
-
-    @SuppressWarnings("all")
-    public static int longBitCount(long value) {
-        return Long.bitCount(value);
-    }
-
-    @Test
-    public void testFloatSubstitutions() {
-        assertInGraph(test("floatToIntBits"), ConvertNode.class); // Java
-        test("intBitsToFloat");
-    }
-
-    @SuppressWarnings("all")
-    public static int floatToIntBits(float value) {
-        return Float.floatToIntBits(value);
-    }
-
-    @SuppressWarnings("all")
-    public static float intBitsToFloat(int value) {
-        return Float.intBitsToFloat(value);
-    }
-
-    @Test
-    public void testDoubleSubstitutions() {
-        assertInGraph(test("doubleToLongBits"), ConvertNode.class); // Java
-        test("longBitsToDouble");
-    }
-
-    @SuppressWarnings("all")
-    public static long doubleToLongBits(double value) {
-        return Double.doubleToLongBits(value);
-    }
-
-    @SuppressWarnings("all")
-    public static double longBitsToDouble(long value) {
-        return Double.longBitsToDouble(value);
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/TypeCheckTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +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.graal.replacements;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.nodes.*;
-
-/**
- * Base class for checkcast and instanceof test classes.
- */
-public abstract class TypeCheckTest extends GraalCompilerTest {
-
-    protected abstract void replaceProfile(StructuredGraph graph, JavaTypeProfile profile);
-
-    protected JavaTypeProfile currentProfile;
-
-    @Override
-    protected InstalledCode getCode(final ResolvedJavaMethod method, final StructuredGraph graph) {
-        boolean forceCompile = false;
-        if (currentProfile != null) {
-            replaceProfile(graph, currentProfile);
-            forceCompile = true;
-        }
-        return super.getCode(method, graph, forceCompile);
-    }
-
-    protected JavaTypeProfile profile(Class... types) {
-        return profile(TriState.UNKNOWN, types);
-    }
-
-    protected JavaTypeProfile profile(TriState nullSeen, Class... types) {
-        if (types.length == 0) {
-            return null;
-        }
-        ProfiledType[] ptypes = new ProfiledType[types.length];
-        for (int i = 0; i < types.length; i++) {
-            ptypes[i] = new ProfiledType(runtime.lookupJavaType(types[i]), 1.0D / types.length);
-        }
-        return new JavaTypeProfile(nullSeen, 0.0D, ptypes);
-    }
-
-    protected void test(String name, JavaTypeProfile profile, Object... args) {
-        assert currentProfile == null;
-        currentProfile = profile;
-        try {
-            super.test(name, args);
-        } finally {
-            currentProfile = null;
-        }
-    }
-}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/WordTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,227 +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.graal.replacements;
-
-import java.lang.reflect.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.test.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.replacements.Snippet.*;
-import com.oracle.graal.word.*;
-
-/**
- * Tests for the {@link Word} type.
- */
-public class WordTest extends GraalCompilerTest implements Snippets {
-
-    private final ReplacementsImpl installer;
-
-    public WordTest() {
-        TargetDescription target = Graal.getRequiredCapability(CodeCacheProvider.class).getTarget();
-        installer = new ReplacementsImpl(runtime, new Assumptions(false), target);
-    }
-
-    private static final ThreadLocal<SnippetInliningPolicy> inliningPolicy = new ThreadLocal<>();
-
-    @Override
-    protected StructuredGraph parse(Method m) {
-        ResolvedJavaMethod resolvedMethod = runtime.lookupJavaMethod(m);
-        return installer.makeGraph(resolvedMethod, null, inliningPolicy.get());
-    }
-
-    @LongTest
-    public void construction() {
-        long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE, Integer.MAX_VALUE - 1L, Integer.MAX_VALUE, Integer.MAX_VALUE + 1L,
-                        Integer.MIN_VALUE - 1L, Integer.MIN_VALUE, Integer.MIN_VALUE + 1L};
-        for (long word : words) {
-            test("unsigned_long", word);
-            test("unsigned_int", (int) word);
-            test("signed_long", word);
-            test("signed_int", (int) word);
-        }
-    }
-
-    @LongTest
-    public void test_arithmetic() {
-        long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE, Integer.MAX_VALUE - 1L, Integer.MAX_VALUE, Integer.MAX_VALUE + 1L,
-                        Integer.MIN_VALUE - 1L, Integer.MIN_VALUE, Integer.MIN_VALUE + 1L};
-        for (long word : words) {
-            test("unsigned_not", word);
-            test("signed_not", word);
-            for (long addend : words) {
-                test("unsigned_plus_int", word, (int) addend);
-                test("unsigned_minus_int", word, (int) addend);
-                test("unsigned_plus_int", word, -((int) addend));
-                test("unsigned_minus_int", word, -((int) addend));
-                test("unsigned_plus_long", word, addend);
-                test("unsigned_minus_long", word, addend);
-                test("unsigned_plus_long", word, -addend);
-                test("unsigned_minus_long", word, -addend);
-                test("signed_plus_int", word, (int) addend);
-                test("signed_minus_int", word, (int) addend);
-                test("signed_plus_int", word, -((int) addend));
-                test("signed_minus_int", word, -((int) addend));
-                test("signed_plus_long", word, addend);
-                test("signed_minus_long", word, addend);
-                test("signed_plus_long", word, -addend);
-                test("signed_minus_long", word, -addend);
-
-                test("and_int", word, (int) addend);
-                test("or_int", word, (int) addend);
-                test("and_int", word, -((int) addend));
-                test("or_int", word, -((int) addend));
-                test("and_long", word, addend);
-                test("or_long", word, addend);
-                test("and_long", word, -addend);
-                test("or_long", word, -addend);
-            }
-        }
-    }
-
-    @LongTest
-    public void test_compare() {
-        long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE};
-        for (long word1 : words) {
-            for (long word2 : words) {
-                for (String method : new String[]{"aboveOrEqual", "above", "belowOrEqual", "below"}) {
-                    test(method, word1, word2);
-                    test(method, word2, word1);
-                }
-            }
-        }
-    }
-
-    @Snippet
-    public static long unsigned_long(long word) {
-        return Word.unsigned(word).rawValue();
-    }
-
-    @Snippet
-    public static long unsigned_int(int word) {
-        return Word.unsigned(word).rawValue();
-    }
-
-    @Snippet
-    public static long signed_long(long word) {
-        return Word.signed(word).rawValue();
-    }
-
-    @Snippet
-    public static long signed_int(int word) {
-        return Word.signed(word).rawValue();
-    }
-
-    @Snippet
-    public static long unsigned_plus_int(long word, int addend) {
-        return Word.unsigned(word).add(addend).rawValue();
-    }
-
-    @Snippet
-    public static long unsigned_minus_int(long word, int addend) {
-        return Word.unsigned(word).subtract(addend).rawValue();
-    }
-
-    @Snippet
-    public static long unsigned_plus_long(long word, long addend) {
-        return Word.unsigned(word).add(Word.unsigned(addend)).rawValue();
-    }
-
-    @Snippet
-    public static long unsigned_minus_long(long word, long addend) {
-        return Word.unsigned(word).subtract(Word.unsigned(addend)).rawValue();
-    }
-
-    @Snippet
-    public static long signed_plus_int(long word, int addend) {
-        return Word.signed(word).add(addend).rawValue();
-    }
-
-    @Snippet
-    public static long signed_minus_int(long word, int addend) {
-        return Word.signed(word).subtract(addend).rawValue();
-    }
-
-    @Snippet
-    public static long signed_plus_long(long word, long addend) {
-        return Word.signed(word).add(Word.signed(addend)).rawValue();
-    }
-
-    @Snippet
-    public static long signed_minus_long(long word, long addend) {
-        return Word.signed(word).subtract(Word.signed(addend)).rawValue();
-    }
-
-    @Snippet
-    public static long signed_not(long word) {
-        return Word.signed(word).not().rawValue();
-    }
-
-    @Snippet
-    public static long unsigned_not(long word) {
-        return Word.unsigned(word).not().rawValue();
-    }
-
-    @Snippet
-    public static boolean aboveOrEqual(long word1, long word2) {
-        return Word.unsigned(word1).aboveOrEqual(Word.unsigned(word2));
-    }
-
-    @Snippet
-    public static boolean above(long word1, long word2) {
-        return Word.unsigned(word1).aboveThan(Word.unsigned(word2));
-    }
-
-    @Snippet
-    public static boolean belowOrEqual(long word1, long word2) {
-        return Word.unsigned(word1).belowOrEqual(Word.unsigned(word2));
-    }
-
-    @Snippet
-    public static boolean below(long word1, long word2) {
-        return Word.unsigned(word1).belowThan(Word.unsigned(word2));
-    }
-
-    @Snippet
-    public static long and_int(long word, int addend) {
-        return Word.unsigned(word).and(addend).rawValue();
-    }
-
-    @Snippet
-    public static long or_int(long word, int addend) {
-        return Word.unsigned(word).or(addend).rawValue();
-    }
-
-    @Snippet
-    public static long and_long(long word, long addend) {
-        return Word.unsigned(word).and(Word.unsigned(addend)).rawValue();
-    }
-
-    @Snippet
-    public static long or_long(long word, long addend) {
-        return Word.unsigned(word).or(Word.unsigned(addend)).rawValue();
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,214 @@
+/*
+ * 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.graal.replacements.test;
+
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.test.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+
+/**
+ * Tests the implementation of checkcast, allowing profiling information to be manually specified.
+ */
+public class CheckCastTest extends TypeCheckTest {
+
+    @Override
+    protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) {
+        CheckCastNode ccn = graph.getNodes(CheckCastNode.class).first();
+        if (ccn != null) {
+            CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.type(), ccn.object(), profile));
+            graph.replaceFixedWithFixed(ccn, ccnNew);
+        }
+    }
+
+    @LongTest
+    public void test1() {
+        test("asNumber", profile(), 111);
+        test("asNumber", profile(Integer.class), 111);
+        test("asNumber", profile(Long.class, Short.class), 111);
+        test("asNumberExt", profile(), 111);
+        test("asNumberExt", profile(Integer.class), 111);
+        test("asNumberExt", profile(Long.class, Short.class), 111);
+    }
+
+    @LongTest
+    public void test2() {
+        test("asString", profile(), "111");
+        test("asString", profile(String.class), "111");
+        test("asString", profile(String.class), "111");
+
+        final String nullString = null;
+        test("asString", profile(), nullString);
+        test("asString", profile(String.class), nullString);
+        test("asString", profile(String.class), nullString);
+
+        test("asStringExt", profile(), "111");
+        test("asStringExt", profile(String.class), "111");
+        test("asStringExt", profile(String.class), "111");
+    }
+
+    @LongTest
+    public void test3() {
+        test("asNumber", profile(), "111");
+    }
+
+    @LongTest
+    public void test4() {
+        test("asString", profile(String.class), 111);
+    }
+
+    @LongTest
+    public void test5() {
+        test("asNumberExt", profile(), "111");
+    }
+
+    @LongTest
+    public void test6() {
+        test("asStringExt", profile(String.class), 111);
+    }
+
+    @LongTest
+    public void test7() {
+        Throwable throwable = new Exception();
+        test("asThrowable", profile(), throwable);
+        test("asThrowable", profile(Throwable.class), throwable);
+        test("asThrowable", profile(Exception.class, Error.class), throwable);
+    }
+
+    @LongTest
+    public void test8() {
+        test("arrayStore", new Object[100], "111");
+    }
+
+    @LongTest
+    public void test8_1() {
+        test("arrayFill", new Object[100], "111");
+    }
+
+    public static Number asNumber(Object o) {
+        return (Number) o;
+    }
+
+    public static String asString(Object o) {
+        return (String) o;
+    }
+
+    public static Throwable asThrowable(Object o) {
+        return (Throwable) o;
+    }
+
+    public static ValueNode asValueNode(Object o) {
+        return (ValueNode) o;
+    }
+
+    public static Number asNumberExt(Object o) {
+        Number n = (Number) o;
+        return n.intValue() + 10;
+    }
+
+    public static String asStringExt(Object o) {
+        String s = (String) o;
+        return "#" + s;
+    }
+
+    public static Object[] arrayStore(Object[] arr, Object value) {
+        arr[15] = value;
+        return arr;
+    }
+
+    public static Object[] arrayFill(Object[] arr, Object value) {
+        for (int i = 0; i < arr.length; i++) {
+            arr[i] = value;
+        }
+        return arr;
+    }
+
+    static class Depth1 implements Cloneable {
+    }
+
+    static class Depth2 extends Depth1 {
+    }
+
+    static class Depth3 extends Depth2 {
+    }
+
+    static class Depth4 extends Depth3 {
+    }
+
+    static class Depth5 extends Depth4 {
+    }
+
+    static class Depth6 extends Depth5 {
+    }
+
+    static class Depth7 extends Depth6 {
+    }
+
+    static class Depth8 extends Depth7 {
+    }
+
+    static class Depth9 extends Depth8 {
+    }
+
+    static class Depth10 extends Depth9 {
+    }
+
+    static class Depth11 extends Depth10 {
+    }
+
+    static class Depth12 extends Depth11 {
+    }
+
+    static class Depth13 extends Depth12 {
+    }
+
+    static class Depth14 extends Depth12 {
+    }
+
+    public static Depth12 asDepth12(Object o) {
+        return (Depth12) o;
+    }
+
+    public static Depth12[][] asDepth12Arr(Object o) {
+        return (Depth12[][]) o;
+    }
+
+    public static Cloneable asCloneable(Object o) {
+        return (Cloneable) o;
+    }
+
+    @LongTest
+    public void test9() {
+        Object o = new Depth13();
+        test("asDepth12", profile(), o);
+        test("asDepth12", profile(Depth13.class), o);
+        test("asDepth12", profile(Depth13.class, Depth14.class), o);
+    }
+
+    @LongTest
+    public void test10() {
+        Object o = new Depth13[3][];
+        test("asDepth12Arr", o);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,79 @@
+/*
+ * 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.graal.replacements.test;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+
+/**
+ * Tests compilation of a hot exception handler.
+ */
+public class CompiledExceptionHandlerTest extends GraalCompilerTest {
+
+    @Override
+    protected void editPhasePlan(ResolvedJavaMethod method, StructuredGraph graph, PhasePlan phasePlan) {
+        phasePlan.disablePhase(InliningPhase.class);
+    }
+
+    @Override
+    protected StructuredGraph parse(Method m) {
+        StructuredGraph graph = super.parse(m);
+        int handlers = graph.getNodes().filter(ExceptionObjectNode.class).count();
+        Assert.assertEquals(1, handlers);
+        return graph;
+    }
+
+    private static void raiseException(String s) {
+        throw new RuntimeException(s);
+    }
+
+    @Test
+    public void test1() {
+        // Ensure the profile shows a hot exception
+        for (int i = 0; i < 10000; i++) {
+            test1Snippet("");
+            test1Snippet(null);
+        }
+
+        test("test1Snippet", "a string");
+    }
+
+    public static String test1Snippet(String message) {
+        if (message != null) {
+            try {
+                raiseException(message);
+            } catch (Exception e) {
+                return message;
+            }
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfDynamicTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,95 @@
+/*
+ * 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.graal.replacements.test;
+
+import com.oracle.graal.test.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.nodes.java.*;
+
+/**
+ * Tests for {@link InstanceOfDynamicNode}.
+ */
+public class InstanceOfDynamicTest extends GraalCompilerTest {
+
+    public static int id(int value) {
+        return value;
+    }
+
+    @LongTest
+    public void test100() {
+        final Object nul = null;
+        test("isStringDynamic", nul);
+        test("isStringDynamic", "object");
+        test("isStringDynamic", Object.class);
+    }
+
+    @LongTest
+    public void test101() {
+        final Object nul = null;
+        test("isStringIntDynamic", nul);
+        test("isStringIntDynamic", "object");
+        test("isStringIntDynamic", Object.class);
+    }
+
+    @LongTest
+    public void test103() {
+        test("isInstanceDynamic", String.class, null);
+        test("isInstanceDynamic", String.class, "object");
+        test("isInstanceDynamic", String.class, Object.class);
+        test("isInstanceDynamic", int.class, null);
+        test("isInstanceDynamic", int.class, "Object");
+        test("isInstanceDynamic", int.class, Object.class);
+    }
+
+    @LongTest
+    public void test104() {
+        test("isInstanceIntDynamic", String.class, null);
+        test("isInstanceIntDynamic", String.class, "object");
+        test("isInstanceIntDynamic", String.class, Object.class);
+        test("isInstanceIntDynamic", int.class, null);
+        test("isInstanceIntDynamic", int.class, "Object");
+        test("isInstanceIntDynamic", int.class, Object.class);
+    }
+
+    public static boolean isStringDynamic(Object o) {
+        return String.class.isInstance(o);
+    }
+
+    public static int isStringIntDynamic(Object o) {
+        if (String.class.isInstance(o)) {
+            return o.toString().length();
+        }
+        return o.getClass().getName().length();
+    }
+
+    public static boolean isInstanceDynamic(Class c, Object o) {
+        return c.isInstance(o);
+    }
+
+    public static int isInstanceIntDynamic(Class c, Object o) {
+        if (c.isInstance(o)) {
+            return o.toString().length();
+        }
+        return o.getClass().getName().length();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,401 @@
+/*
+ * 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.graal.replacements.test;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.CompilationResult.Call;
+import com.oracle.graal.api.code.CompilationResult.Mark;
+import com.oracle.graal.api.code.CompilationResult.Site;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.replacements.test.CheckCastTest.Depth12;
+import com.oracle.graal.replacements.test.CheckCastTest.Depth13;
+import com.oracle.graal.replacements.test.CheckCastTest.Depth14;
+import com.oracle.graal.test.*;
+
+/**
+ * Tests the implementation of instanceof, allowing profiling information to be manually specified.
+ */
+public class InstanceOfTest extends TypeCheckTest {
+
+    @Override
+    protected void editPhasePlan(ResolvedJavaMethod method, StructuredGraph graph, PhasePlan phasePlan) {
+        phasePlan.disablePhase(InliningPhase.class);
+    }
+
+    @Override
+    protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) {
+        InstanceOfNode ion = graph.getNodes().filter(InstanceOfNode.class).first();
+        if (ion != null) {
+            InstanceOfNode ionNew = graph.add(new InstanceOfNode(ion.type(), ion.object(), profile));
+            graph.replaceFloating(ion, ionNew);
+        }
+    }
+
+    @LongTest
+    public void test1() {
+        test("isString", profile(), "object");
+        test("isString", profile(String.class), "object");
+
+        test("isString", profile(), Object.class);
+        test("isString", profile(String.class), Object.class);
+    }
+
+    @LongTest
+    public void test2() {
+        test("isStringInt", profile(), "object");
+        test("isStringInt", profile(String.class), "object");
+
+        test("isStringInt", profile(), Object.class);
+        test("isStringInt", profile(String.class), Object.class);
+    }
+
+    @LongTest
+    public void test2_1() {
+        test("isStringIntComplex", profile(), "object");
+        test("isStringIntComplex", profile(String.class), "object");
+
+        test("isStringIntComplex", profile(), Object.class);
+        test("isStringIntComplex", profile(String.class), Object.class);
+    }
+
+    @LongTest
+    public void test3() {
+        Throwable throwable = new Exception();
+        test("isThrowable", profile(), throwable);
+        test("isThrowable", profile(Throwable.class), throwable);
+        test("isThrowable", profile(Exception.class, Error.class), throwable);
+
+        test("isThrowable", profile(), Object.class);
+        test("isThrowable", profile(Throwable.class), Object.class);
+        test("isThrowable", profile(Exception.class, Error.class), Object.class);
+    }
+
+    @LongTest
+    public void test3_1() {
+        onlyFirstIsException(new Exception(), new Error());
+        test("onlyFirstIsException", profile(), new Exception(), new Error());
+        test("onlyFirstIsException", profile(), new Error(), new Exception());
+        test("onlyFirstIsException", profile(), new Exception(), new Exception());
+        test("onlyFirstIsException", profile(), new Error(), new Error());
+    }
+
+    @LongTest
+    public void test4() {
+        Throwable throwable = new Exception();
+        test("isThrowableInt", profile(), throwable);
+        test("isThrowableInt", profile(Throwable.class), throwable);
+        test("isThrowableInt", profile(Exception.class, Error.class), throwable);
+
+        test("isThrowableInt", profile(), Object.class);
+        test("isThrowableInt", profile(Throwable.class), Object.class);
+        test("isThrowableInt", profile(Exception.class, Error.class), Object.class);
+    }
+
+    @LongTest
+    public void test5() {
+        Map map = new HashMap<>();
+        test("isMap", profile(), map);
+        test("isMap", profile(HashMap.class), map);
+        test("isMap", profile(TreeMap.class, HashMap.class), map);
+
+        test("isMap", profile(), Object.class);
+        test("isMap", profile(HashMap.class), Object.class);
+        test("isMap", profile(TreeMap.class, HashMap.class), Object.class);
+        test("isMap", profile(String.class, HashMap.class), Object.class);
+    }
+
+    @LongTest
+    public void test6() {
+        Map map = new HashMap<>();
+        test("isMapInt", profile(), map);
+        test("isMapInt", profile(HashMap.class), map);
+        test("isMapInt", profile(TreeMap.class, HashMap.class), map);
+
+        test("isMapInt", profile(), Object.class);
+        test("isMapInt", profile(HashMap.class), Object.class);
+        test("isMapInt", profile(TreeMap.class, HashMap.class), Object.class);
+    }
+
+    @LongTest
+    public void test7() {
+        Object o = new Depth13();
+        test("isDepth12", profile(), o);
+        test("isDepth12", profile(Depth13.class), o);
+        test("isDepth12", profile(Depth13.class, Depth14.class), o);
+
+        o = "not a depth";
+        test("isDepth12", profile(), o);
+        test("isDepth12", profile(Depth13.class), o);
+        test("isDepth12", profile(Depth13.class, Depth14.class), o);
+        test("isDepth12", profile(String.class, HashMap.class), o);
+    }
+
+    @LongTest
+    public void test8() {
+        Object o = new Depth13();
+        test("isDepth12Int", profile(), o);
+        test("isDepth12Int", profile(Depth13.class), o);
+        test("isDepth12Int", profile(Depth13.class, Depth14.class), o);
+
+        o = "not a depth";
+        test("isDepth12Int", profile(), o);
+        test("isDepth12Int", profile(Depth13.class), o);
+        test("isDepth12Int", profile(Depth13.class, Depth14.class), o);
+    }
+
+    public static boolean isString(Object o) {
+        return o instanceof String;
+    }
+
+    public static int isStringInt(Object o) {
+        if (o instanceof String) {
+            return id(1);
+        }
+        return id(0);
+    }
+
+    public static int isStringIntComplex(Object o) {
+        if (o instanceof String || o instanceof Integer) {
+            return id(o instanceof String ? 1 : 0);
+        }
+        return id(0);
+    }
+
+    public static int id(int value) {
+        return value;
+    }
+
+    public static boolean isThrowable(Object o) {
+        return ((Throwable) o) instanceof Exception;
+    }
+
+    public static int onlyFirstIsException(Throwable t1, Throwable t2) {
+        if (t1 instanceof Exception ^ t2 instanceof Exception) {
+            return t1 instanceof Exception ? 1 : -1;
+        }
+        return -1;
+    }
+
+    public static int isThrowableInt(Object o) {
+        int result = o instanceof Throwable ? 4 : 5;
+        if (o instanceof Throwable) {
+            return id(4);
+        }
+        return result;
+    }
+
+    public static boolean isMap(Object o) {
+        return o instanceof Map;
+    }
+
+    public static int isMapInt(Object o) {
+        if (o instanceof Map) {
+            return id(1);
+        }
+        return id(0);
+    }
+
+    public static boolean isDepth12(Object o) {
+        return o instanceof Depth12;
+    }
+
+    public static int isDepth12Int(Object o) {
+        if (o instanceof Depth12) {
+            return id(0);
+        }
+        return id(0);
+    }
+
+    abstract static class MySite {
+
+        final int offset;
+
+        MySite(int offset) {
+            this.offset = offset;
+        }
+    }
+
+    static class MyMark extends MySite {
+
+        MyMark(int offset) {
+            super(offset);
+        }
+    }
+
+    abstract static class MySafepoint extends MySite {
+
+        MySafepoint(int offset) {
+            super(offset);
+        }
+    }
+
+    static class MyCall extends MySafepoint {
+
+        MyCall(int offset) {
+            super(offset);
+        }
+    }
+
+    @LongTest
+    public void test9() {
+        MyCall callAt63 = new MyCall(63);
+        MyMark markAt63 = new MyMark(63);
+        test("compareMySites", callAt63, callAt63);
+        test("compareMySites", callAt63, markAt63);
+        test("compareMySites", markAt63, callAt63);
+        test("compareMySites", markAt63, markAt63);
+    }
+
+    public static int compareMySites(MySite s1, MySite s2) {
+        if (s1.offset == s2.offset && (s1 instanceof MyMark ^ s2 instanceof MyMark)) {
+            return s1 instanceof MyMark ? -1 : 1;
+        }
+        return s1.offset - s2.offset;
+    }
+
+    @LongTest
+    public void test10() {
+        Mark[] noMarks = {};
+        Call callAt63 = new Call(null, 63, 5, true, null);
+        Mark markAt63 = new Mark(63, "1", noMarks);
+        test("compareSites", callAt63, callAt63);
+        test("compareSites", callAt63, markAt63);
+        test("compareSites", markAt63, callAt63);
+        test("compareSites", markAt63, markAt63);
+    }
+
+    public static int compareSites(Site s1, Site s2) {
+        if (s1.pcOffset == s2.pcOffset && (s1 instanceof Mark ^ s2 instanceof Mark)) {
+            return s1 instanceof Mark ? -1 : 1;
+        }
+        return s1.pcOffset - s2.pcOffset;
+    }
+
+    /**
+     * This test exists to show the kind of pattern that is be optimizable by
+     * {@code removeIntermediateMaterialization()} in {@link IfNode}.
+     * <p>
+     * The test exists in this source file as the transformation was originally motivated by the
+     * need to remove use of special JumpNodes in the {@code InstanceOfSnippets}.
+     */
+    @LongTest
+    public void test_removeIntermediateMaterialization() {
+        List<String> list = Arrays.asList("1", "2", "3", "4");
+        test("removeIntermediateMaterialization", profile(), list, "2", "yes", "no");
+        test("removeIntermediateMaterialization", profile(), list, null, "yes", "no");
+        test("removeIntermediateMaterialization", profile(), null, "2", "yes", "no");
+    }
+
+    public static String removeIntermediateMaterialization(List<Object> list, Object e, String a, String b) {
+        boolean test;
+        if (list == null || e == null) {
+            test = false;
+        } else {
+            test = false;
+            for (Object i : list) {
+                if (i.equals(e)) {
+                    test = true;
+                    break;
+                }
+            }
+        }
+        if (test) {
+            return a;
+        }
+        return b;
+    }
+
+    abstract static class A {
+    }
+
+    static class B extends A {
+    }
+
+    static class C extends B {
+    }
+
+    abstract static class D extends C {
+    }
+
+    public static boolean isArrayOfA(Object o) {
+        return o instanceof A[];
+    }
+
+    public static boolean isArrayOfB(Object o) {
+        return o instanceof B[];
+    }
+
+    public static boolean isArrayOfC(Object o) {
+        return o instanceof C[];
+    }
+
+    public static boolean isArrayOfD(Object o) {
+        return o instanceof D[];
+    }
+
+    @LongTest
+    public void testArray() {
+        Object aArray = new A[10];
+        test("isArrayOfA", aArray);
+
+        Object bArray = new B[10];
+        test("isArrayOfA", aArray);
+        test("isArrayOfA", bArray);
+        test("isArrayOfB", aArray);
+        test("isArrayOfB", bArray);
+
+        Object cArray = new C[10];
+        test("isArrayOfA", aArray);
+        test("isArrayOfA", bArray);
+        test("isArrayOfA", cArray);
+        test("isArrayOfB", aArray);
+        test("isArrayOfB", bArray);
+        test("isArrayOfB", cArray);
+        test("isArrayOfC", aArray);
+        test("isArrayOfC", bArray);
+        test("isArrayOfC", cArray);
+
+        Object dArray = new D[10];
+        test("isArrayOfA", aArray);
+        test("isArrayOfA", bArray);
+        test("isArrayOfA", cArray);
+        test("isArrayOfA", dArray);
+        test("isArrayOfB", aArray);
+        test("isArrayOfB", bArray);
+        test("isArrayOfB", cArray);
+        test("isArrayOfB", dArray);
+        test("isArrayOfC", aArray);
+        test("isArrayOfC", bArray);
+        test("isArrayOfC", cArray);
+        test("isArrayOfC", dArray);
+        test("isArrayOfD", aArray);
+        test("isArrayOfD", bArray);
+        test("isArrayOfD", cArray);
+        test("isArrayOfD", dArray);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InvokeTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,107 @@
+/*
+ * 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.graal.replacements.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+
+/**
+ * Tests the implementation of the snippets for lowering the INVOKE* instructions.
+ */
+public class InvokeTest extends GraalCompilerTest {
+
+    @Override
+    protected void editPhasePlan(ResolvedJavaMethod method, StructuredGraph graph, PhasePlan phasePlan) {
+        phasePlan.disablePhase(InliningPhase.class);
+    }
+
+    public interface I {
+
+        String virtualMethod(String s);
+    }
+
+    public static class A implements I {
+
+        final String name = "A";
+
+        public String virtualMethod(String s) {
+            return name + s;
+        }
+    }
+
+    @SuppressWarnings("static-method")
+    private String privateMethod(String s) {
+        return s;
+    }
+
+    @Test
+    public void test1() {
+        test("invokestatic", "a string");
+        test("invokespecialConstructor", "a string");
+        test("invokespecial", this, "a string");
+        test("invokevirtual", new A(), "a string");
+        test("invokevirtual2", new A(), "a string");
+        test("invokeinterface", new A(), "a string");
+        Object[] args = {null};
+        test("invokestatic", args);
+        test("invokespecialConstructor", args);
+        test("invokespecial", null, null);
+        test("invokevirtual", null, null);
+        test("invokevirtual2", null, null);
+        test("invokeinterface", null, null);
+    }
+
+    public static String invokestatic(String s) {
+        return staticMethod(s);
+    }
+
+    public static String staticMethod(String s) {
+        return s;
+    }
+
+    public static String invokespecialConstructor(String s) {
+        return new A().virtualMethod(s);
+    }
+
+    public static String invokespecial(InvokeTest a, String s) {
+        return a.privateMethod(s);
+    }
+
+    public static String invokevirtual(A a, String s) {
+        return a.virtualMethod(s);
+    }
+
+    public static String invokevirtual2(A a, String s) {
+        a.virtualMethod(s);
+        return a.virtualMethod(s);
+    }
+
+    public static String invokeinterface(I i, String s) {
+        return i.virtualMethod(s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,84 @@
+/*
+ * 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.graal.replacements.test;
+
+import static org.junit.Assert.*;
+
+import java.util.concurrent.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+
+/**
+ * Tests if {@link MethodSubstitution}s are inlined correctly. Most test cases only assert that
+ * there are no remaining invocations in the graph. This is sufficient if the method that is being
+ * substituted is a native method. For Java methods, additional checks are necessary.
+ */
+public abstract class MethodSubstitutionTest extends GraalCompilerTest {
+
+    protected StructuredGraph test(final String snippet) {
+        return Debug.scope("MethodSubstitutionTest", runtime.lookupJavaMethod(getMethod(snippet)), new Callable<StructuredGraph>() {
+
+            @Override
+            public StructuredGraph call() {
+                StructuredGraph graph = parse(snippet);
+                PhasePlan phasePlan = getDefaultPhasePlan();
+                Assumptions assumptions = new Assumptions(true);
+                new ComputeProbabilityPhase().apply(graph);
+                Debug.dump(graph, "Graph");
+                new InliningPhase(runtime(), null, replacements, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
+                Debug.dump(graph, "Graph");
+                new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+                new DeadCodeEliminationPhase().apply(graph);
+
+                assertNotInGraph(graph, Invoke.class);
+                return graph;
+            }
+        });
+    }
+
+    protected static StructuredGraph assertNotInGraph(StructuredGraph graph, Class<?> clazz) {
+        for (Node node : graph.getNodes()) {
+            if (clazz.isInstance(node)) {
+                fail(node.toString());
+            }
+        }
+        return graph;
+    }
+
+    protected static StructuredGraph assertInGraph(StructuredGraph graph, Class<?> clazz) {
+        for (Node node : graph.getNodes()) {
+            if (clazz.isInstance(node)) {
+                return graph;
+            }
+        }
+        fail("Graph does not contain a node of class " + clazz.getName());
+        return graph;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,209 @@
+/*
+ * 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.graal.replacements.test;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.virtual.phases.ea.*;
+
+public class MonitorTest extends GraalCompilerTest {
+
+    @Test
+    public void test0() {
+        test("lockObjectSimple", new Object(), new Object());
+        test("lockObjectSimple", new Object(), null);
+    }
+
+    @Test
+    public void test0_1() {
+        test("lockThisSimple", "test1", new Object());
+        test("lockThisSimple", "test1", null);
+    }
+
+    @Test
+    public void test0_2() {
+        test("lockObjectSimple", null, "test1");
+    }
+
+    @Test
+    public void test1_1() {
+        test("lockObject", new Object(), "test1", new String[1]);
+    }
+
+    @Test
+    public void test1_2() {
+        test("lockObject", null, "test1_1", new String[1]);
+    }
+
+    @Test
+    public void test2() {
+        test("lockThis", "test2", new String[1]);
+    }
+
+    /**
+     * Tests monitor operations on {@link PartialEscapeAnalysisPhase virtual objects}.
+     */
+    @Test
+    public void test3() {
+        test("lockLocalObject", "test3", new String[1]);
+    }
+
+    /**
+     * Tests recursive locking of objects which should be biasable.
+     */
+    @Test
+    public void test4() {
+        Chars src = new Chars("1234567890".toCharArray());
+        Chars dst = new Chars(src.data.length);
+        test("copyObj", src, dst, 100);
+    }
+
+    /**
+     * Tests recursive locking of objects which do not appear to be biasable.
+     */
+    @Test
+    public void test5() {
+        char[] src = "1234567890".toCharArray();
+        char[] dst = new char[src.length];
+        test("copyArr", src, dst, 100);
+    }
+
+    /**
+     * Extends {@link #test4()} with contention.
+     */
+    @Test
+    public void test6() {
+        Chars src = new Chars("1234567890".toCharArray());
+        Chars dst = new Chars(src.data.length);
+        int n = Runtime.getRuntime().availableProcessors();
+        testN(n, "copyObj", src, dst, 100);
+    }
+
+    /**
+     * Extends {@link #test5()} with contention.
+     */
+    @Test
+    public void test7() {
+        char[] src = "1234567890".toCharArray();
+        char[] dst = new char[src.length];
+        int n = Runtime.getRuntime().availableProcessors();
+        testN(n, "copyArr", src, dst, 100);
+    }
+
+    private static String setAndGet(String[] box, String value) {
+        synchronized (box) {
+            box[0] = null;
+        }
+
+        // Do a GC while a object is locked (by the caller)
+        System.gc();
+
+        synchronized (box) {
+            box[0] = value;
+        }
+        return box[0];
+    }
+
+    public static Object lockObjectSimple(Object o, Object value) {
+        synchronized (o) {
+            value.hashCode();
+            return value;
+        }
+    }
+
+    public String lockThisSimple(String value, Object o) {
+        synchronized (this) {
+            synchronized (value) {
+                o.hashCode();
+                return value;
+            }
+        }
+    }
+
+    public static String lockObject(Object o, String value, String[] box) {
+        synchronized (o) {
+            return setAndGet(box, value);
+        }
+    }
+
+    public String lockThis(String value, String[] box) {
+        synchronized (this) {
+            return setAndGet(box, value);
+        }
+    }
+
+    public static String lockLocalObject(String value, String[] box) {
+        Object o = new Object();
+        synchronized (o) {
+            return setAndGet(box, value);
+        }
+    }
+
+    static class Chars {
+
+        final char[] data;
+
+        public Chars(int size) {
+            this.data = new char[size];
+        }
+
+        public Chars(char[] data) {
+            this.data = data;
+        }
+    }
+
+    public static String copyObj(Chars src, Chars dst, int n) {
+        for (int j = 0; j < n; j++) {
+            for (int i = 0; i < src.data.length; i++) {
+                synchronized (src) {
+                    synchronized (dst) {
+                        synchronized (src) {
+                            synchronized (dst) {
+                                dst.data[i] = src.data[i];
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return new String(dst.data);
+    }
+
+    public static String copyArr(char[] src, char[] dst, int n) {
+        for (int j = 0; j < n; j++) {
+            for (int i = 0; i < src.length; i++) {
+                synchronized (src) {
+                    synchronized (dst) {
+                        synchronized (src) {
+                            synchronized (dst) {
+                                dst[i] = src[i];
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return new String(dst);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewArrayTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,168 @@
+/*
+ * 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.graal.replacements.test;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.test.*;
+
+/**
+ * Tests the implementation of {@code [A]NEWARRAY}.
+ */
+public class NewArrayTest extends GraalCompilerTest {
+
+    @Override
+    protected void assertEquals(Object expected, Object actual) {
+        Assert.assertTrue(expected != null);
+        Assert.assertTrue(actual != null);
+        super.assertEquals(expected.getClass(), actual.getClass());
+        if (expected instanceof int[]) {
+            Assert.assertArrayEquals((int[]) expected, (int[]) actual);
+        } else if (expected instanceof byte[]) {
+            Assert.assertArrayEquals((byte[]) expected, (byte[]) actual);
+        } else if (expected instanceof char[]) {
+            Assert.assertArrayEquals((char[]) expected, (char[]) actual);
+        } else if (expected instanceof short[]) {
+            Assert.assertArrayEquals((short[]) expected, (short[]) actual);
+        } else if (expected instanceof float[]) {
+            Assert.assertArrayEquals((float[]) expected, (float[]) actual, 0.0f);
+        } else if (expected instanceof long[]) {
+            Assert.assertArrayEquals((long[]) expected, (long[]) actual);
+        } else if (expected instanceof double[]) {
+            Assert.assertArrayEquals((double[]) expected, (double[]) actual, 0.0d);
+        } else if (expected instanceof Object[]) {
+            Assert.assertArrayEquals((Object[]) expected, (Object[]) actual);
+        } else {
+            Assert.fail("non-array value encountered: " + expected);
+        }
+    }
+
+    @LongTest
+    public void test1() {
+        for (String type : new String[]{"Byte", "Char", "Short", "Int", "Float", "Long", "Double", "String"}) {
+            test("new" + type + "Array7");
+            test("new" + type + "ArrayMinus7");
+            test("new" + type + "Array", 7);
+            test("new" + type + "Array", -7);
+            test("new" + type + "Array", Integer.MAX_VALUE);
+            test("new" + type + "Array", Integer.MIN_VALUE);
+        }
+    }
+
+    public static Object newCharArray7() {
+        return new char[7];
+    }
+
+    public static Object newCharArrayMinus7() {
+        return new char[-7];
+    }
+
+    public static Object newCharArray(int length) {
+        return new char[length];
+    }
+
+    public static Object newShortArray7() {
+        return new short[7];
+    }
+
+    public static Object newShortArrayMinus7() {
+        return new short[-7];
+    }
+
+    public static Object newShortArray(int length) {
+        return new short[length];
+    }
+
+    public static Object newFloatArray7() {
+        return new float[7];
+    }
+
+    public static Object newFloatArrayMinus7() {
+        return new float[-7];
+    }
+
+    public static Object newFloatArray(int length) {
+        return new float[length];
+    }
+
+    public static Object newLongArray7() {
+        return new long[7];
+    }
+
+    public static Object newLongArrayMinus7() {
+        return new long[-7];
+    }
+
+    public static Object newLongArray(int length) {
+        return new long[length];
+    }
+
+    public static Object newDoubleArray7() {
+        return new double[7];
+    }
+
+    public static Object newDoubleArrayMinus7() {
+        return new double[-7];
+    }
+
+    public static Object newDoubleArray(int length) {
+        return new double[length];
+    }
+
+    public static Object newIntArray7() {
+        return new int[7];
+    }
+
+    public static Object newIntArrayMinus7() {
+        return new int[-7];
+    }
+
+    public static Object newIntArray(int length) {
+        return new int[length];
+    }
+
+    public static Object newByteArray7() {
+        return new byte[7];
+    }
+
+    public static Object newByteArrayMinus7() {
+        return new byte[-7];
+    }
+
+    public static Object newByteArray(int length) {
+        return new byte[length];
+    }
+
+    public static Object newStringArray7() {
+        return new String[7];
+    }
+
+    public static Object newStringArrayMinus7() {
+        return new String[-7];
+    }
+
+    public static Object newStringArray(int length) {
+        return new String[length];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewInstanceTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,249 @@
+/*
+ * 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.graal.replacements.test;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.test.*;
+
+/**
+ * Tests the implementation of {@code NEW}.
+ */
+public class NewInstanceTest extends GraalCompilerTest {
+
+    @Override
+    protected void assertEquals(Object expected, Object actual) {
+        Assert.assertTrue(expected != null);
+        Assert.assertTrue(actual != null);
+        super.assertEquals(expected.getClass(), actual.getClass());
+
+        if (expected instanceof Object[]) {
+            Assert.assertTrue(actual instanceof Object[]);
+            Object[] eArr = (Object[]) expected;
+            Object[] aArr = (Object[]) actual;
+            Assert.assertTrue(eArr.length == aArr.length);
+            for (int i = 0; i < eArr.length; i++) {
+                assertEquals(eArr[i], aArr[i]);
+            }
+        } else if (expected.getClass() != Object.class) {
+            try {
+                expected.getClass().getDeclaredMethod("equals", Object.class);
+                super.assertEquals(expected, actual);
+            } catch (Exception e) {
+            }
+        }
+    }
+
+    @LongTest
+    public void test1() {
+        test("newObject");
+    }
+
+    @LongTest
+    public void test2() {
+        test("newObjectTwice");
+    }
+
+    public static Object newObject() {
+        return new Object();
+    }
+
+    @LongTest
+    public void test3() {
+        test("newObjectLoop", 100);
+    }
+
+    @LongTest
+    public void test4() {
+        test("newBigObject");
+    }
+
+    @LongTest
+    public void test5() {
+        test("newSomeObject");
+    }
+
+    @LongTest
+    public void test6() {
+        test("newEmptyString");
+    }
+
+    @LongTest
+    public void test7() {
+        test("newString", "value");
+    }
+
+    @LongTest
+    public void test8() {
+        test("newHashMap", 31);
+    }
+
+    @LongTest
+    public void test9() {
+        test("newRegression", true);
+    }
+
+    public static Object[] newObjectTwice() {
+        Object[] res = {new Object(), new Object()};
+        return res;
+    }
+
+    public static Object[] newObjectLoop(int n) {
+        Object[] res = new Object[n];
+        for (int i = 0; i < n; i++) {
+            res[i] = new Object();
+        }
+        return res;
+    }
+
+    public static BigObject newBigObject() {
+        return new BigObject();
+    }
+
+    public static SomeObject newSomeObject() {
+        return new SomeObject();
+    }
+
+    public static String newEmptyString() {
+        return new String();
+    }
+
+    public static String newString(String value) {
+        return new String(value);
+    }
+
+    public static HashMap newHashMap(int initialCapacity) {
+        return new HashMap(initialCapacity);
+    }
+
+    static class SomeObject {
+
+        String name = "o1";
+        HashMap<String, Object> map = new HashMap<>();
+
+        public SomeObject() {
+            map.put(name, this.getClass());
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof SomeObject) {
+                SomeObject so = (SomeObject) obj;
+                return so.name.equals(name) && so.map.equals(map);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return name.hashCode();
+        }
+    }
+
+    static class BigObject {
+
+        Object f01;
+        Object f02;
+        Object f03;
+        Object f04;
+        Object f05;
+        Object f06;
+        Object f07;
+        Object f08;
+        Object f09;
+        Object f10;
+        Object f12;
+        Object f13;
+        Object f14;
+        Object f15;
+        Object f16;
+        Object f17;
+        Object f18;
+        Object f19;
+        Object f20;
+        Object f21;
+        Object f22;
+        Object f23;
+        Object f24;
+        Object f25;
+        Object f26;
+        Object f27;
+        Object f28;
+        Object f29;
+        Object f30;
+        Object f31;
+        Object f32;
+        Object f33;
+        Object f34;
+        Object f35;
+        Object f36;
+        Object f37;
+        Object f38;
+        Object f39;
+        Object f40;
+        Object f41;
+        Object f42;
+        Object f43;
+        Object f44;
+        Object f45;
+    }
+
+    /**
+     * Tests that an earlier bug does not occur. The issue was that the loading of the TLAB 'top'
+     * and 'end' values was being GVN'ed from each branch of the 'if' statement. This meant that the
+     * allocated B object in the true branch overwrote the allocated array. The cause is that
+     * RegisterNode was a floating node and the reads from it were UnsafeLoads which are also
+     * floating. The fix was to make RegisterNode a fixed node (which it should have been in the
+     * first place).
+     */
+    public static Object newRegression(boolean condition) {
+        Object result;
+        if (condition) {
+            Object[] arr = {0, 1, 2, 3, 4, 5};
+            result = new B();
+            for (int i = 0; i < arr.length; ++i) {
+                // If the bug exists, the values of arr will now be deadbeef values
+                // and the virtual dispatch will cause a segfault. This can result in
+                // either a VM crash or a spurious NullPointerException.
+                if (arr[i].equals(Integer.valueOf(i))) {
+                    return false;
+                }
+            }
+        } else {
+            result = new B();
+        }
+        return result;
+    }
+
+    static class B {
+
+        long f1 = 0xdeadbeefdeadbe01L;
+        long f2 = 0xdeadbeefdeadbe02L;
+        long f3 = 0xdeadbeefdeadbe03L;
+        long f4 = 0xdeadbeefdeadbe04L;
+        long f5 = 0xdeadbeefdeadbe05L;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewMultiArrayTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,128 @@
+/*
+ * 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.graal.replacements.test;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.test.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+
+/**
+ * Tests the lowering of the MULTIANEWARRAY instruction.
+ */
+public class NewMultiArrayTest extends GraalCompilerTest {
+
+    private static int rank(ResolvedJavaType type) {
+        String name = type.getName();
+        int dims = 0;
+        while (dims < name.length() && name.charAt(dims) == '[') {
+            dims++;
+        }
+        return dims;
+    }
+
+    @Override
+    protected InstalledCode getCode(final ResolvedJavaMethod method, final StructuredGraph graph) {
+        boolean forceCompile = false;
+        if (bottomType != null) {
+            List<NewMultiArrayNode> snapshot = graph.getNodes().filter(NewMultiArrayNode.class).snapshot();
+            assert snapshot != null;
+            assert snapshot.size() == 1;
+
+            NewMultiArrayNode node = snapshot.get(0);
+            assert rank(arrayType) == dimensions.length;
+            int rank = dimensions.length;
+            ValueNode[] dimensionNodes = new ValueNode[rank];
+            for (int i = 0; i < rank; i++) {
+                dimensionNodes[i] = graph.unique(ConstantNode.forInt(dimensions[i], graph));
+            }
+
+            NewMultiArrayNode repl = graph.add(new NewMultiArrayNode(arrayType, dimensionNodes));
+            graph.replaceFixedWithFixed(node, repl);
+            forceCompile = true;
+        }
+        return super.getCode(method, graph, forceCompile);
+    }
+
+    @Override
+    protected Object referenceInvoke(Method method, Object receiver, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+        if (bottomType != null) {
+            try {
+                return Array.newInstance(bottomClass, dimensions);
+            } catch (Exception e) {
+                throw new InvocationTargetException(e);
+            }
+        }
+        return super.referenceInvoke(method, receiver, args);
+    }
+
+    ResolvedJavaType arrayType;
+    ResolvedJavaType bottomType;
+    Class bottomClass;
+    int[] dimensions;
+
+    @LongTest
+    public void test1() {
+        for (Class clazz : new Class[]{byte.class, char.class, short.class, int.class, float.class, long.class, double.class, String.class}) {
+            bottomClass = clazz;
+            bottomType = runtime.lookupJavaType(clazz);
+            arrayType = bottomType;
+            for (int rank : new int[]{1, 2, 10, 50, 100, 200, 254, 255}) {
+                while (rank(arrayType) != rank) {
+                    arrayType = arrayType.getArrayClass();
+                }
+
+                dimensions = new int[rank];
+                for (int i = 0; i < rank; i++) {
+                    dimensions[i] = 1;
+                }
+
+                test("newMultiArray");
+            }
+        }
+        bottomType = null;
+        arrayType = null;
+    }
+
+    public static Object newMultiArray() {
+        // This is merely a template - the NewMultiArrayNode is replaced in getCode() above.
+        // This also means we need a separate test for correct handling of negative dimensions
+        // as deoptimization won't do what we want for a graph modified to be different from the
+        // source bytecode.
+        return new Object[10][9][8];
+    }
+
+    @LongTest
+    public void test2() {
+        test("newMultiArrayException");
+    }
+
+    public static Object newMultiArrayException() {
+        return new Object[10][9][-8];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,400 @@
+/*
+ * 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.replacements.test;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.replacements.*;
+import com.oracle.graal.replacements.Snippet.*;
+import com.oracle.graal.word.*;
+
+/**
+ * Tests for the {@link Pointer} read and write operations.
+ */
+public class PointerTest extends GraalCompilerTest implements Snippets {
+
+    private static final Object ID = new Object();
+    private static final Kind[] KINDS = new Kind[]{Kind.Byte, Kind.Char, Kind.Short, Kind.Int, Kind.Long, Kind.Float, Kind.Double, Kind.Object};
+    private final TargetDescription target;
+    private final ReplacementsImpl installer;
+
+    public PointerTest() {
+        target = Graal.getRequiredCapability(CodeCacheProvider.class).getTarget();
+        installer = new ReplacementsImpl(runtime, new Assumptions(false), target);
+    }
+
+    private static final ThreadLocal<SnippetInliningPolicy> inliningPolicy = new ThreadLocal<>();
+
+    @Override
+    protected StructuredGraph parse(Method m) {
+        ResolvedJavaMethod resolvedMethod = runtime.lookupJavaMethod(m);
+        return installer.makeGraph(resolvedMethod, null, inliningPolicy.get());
+    }
+
+    @Test
+    public void test_read1() {
+        for (Kind kind : KINDS) {
+            assertRead(parse("read" + kind.name() + "1"), kind, false, ID);
+        }
+    }
+
+    @Test
+    public void test_read2() {
+        for (Kind kind : KINDS) {
+            assertRead(parse("read" + kind.name() + "2"), kind, true, ID);
+        }
+    }
+
+    @Test
+    public void test_read3() {
+        for (Kind kind : KINDS) {
+            assertRead(parse("read" + kind.name() + "3"), kind, false, LocationNode.ANY_LOCATION);
+        }
+    }
+
+    @Test
+    public void test_write1() {
+        for (Kind kind : KINDS) {
+            assertWrite(parse("write" + kind.name() + "1"), kind, false, ID);
+        }
+    }
+
+    @Test
+    public void test_write2() {
+        for (Kind kind : KINDS) {
+            assertWrite(parse("write" + kind.name() + "2"), kind, true, ID);
+        }
+    }
+
+    @Test
+    public void test_write3() {
+        for (Kind kind : KINDS) {
+            assertWrite(parse("write" + kind.name() + "3"), kind, false, LocationNode.ANY_LOCATION);
+        }
+    }
+
+    private void assertRead(StructuredGraph graph, Kind kind, boolean indexConvert, Object locationIdentity) {
+        ReadNode read = (ReadNode) graph.start().next();
+        Assert.assertEquals(kind.getStackKind(), read.kind());
+
+        UnsafeCastNode cast = (UnsafeCastNode) read.object();
+        Assert.assertEquals(graph.getLocal(0), cast.object());
+        Assert.assertEquals(target.wordKind, cast.kind());
+
+        IndexedLocationNode location = (IndexedLocationNode) read.location();
+        Assert.assertEquals(kind, location.getValueKind());
+        Assert.assertEquals(locationIdentity, location.locationIdentity());
+        Assert.assertEquals(1, location.indexScaling());
+
+        if (indexConvert) {
+            ConvertNode convert = (ConvertNode) location.index();
+            Assert.assertEquals(ConvertNode.Op.I2L, convert.opcode);
+            Assert.assertEquals(graph.getLocal(1), convert.value());
+        } else {
+            Assert.assertEquals(graph.getLocal(1), location.index());
+        }
+
+        ReturnNode ret = (ReturnNode) read.next();
+        Assert.assertEquals(read, ret.result());
+    }
+
+    private void assertWrite(StructuredGraph graph, Kind kind, boolean indexConvert, Object locationIdentity) {
+        WriteNode write = (WriteNode) graph.start().next();
+        Assert.assertEquals(graph.getLocal(2), write.value());
+        Assert.assertEquals(Kind.Void, write.kind());
+        Assert.assertEquals(FrameState.INVALID_FRAMESTATE_BCI, write.stateAfter().bci);
+
+        UnsafeCastNode cast = (UnsafeCastNode) write.object();
+        Assert.assertEquals(graph.getLocal(0), cast.object());
+        Assert.assertEquals(target.wordKind, cast.kind());
+
+        IndexedLocationNode location = (IndexedLocationNode) write.location();
+        Assert.assertEquals(kind, location.getValueKind());
+        Assert.assertEquals(locationIdentity, location.locationIdentity());
+        Assert.assertEquals(1, location.indexScaling());
+
+        if (indexConvert) {
+            ConvertNode convert = (ConvertNode) location.index();
+            Assert.assertEquals(ConvertNode.Op.I2L, convert.opcode);
+            Assert.assertEquals(graph.getLocal(1), convert.value());
+        } else {
+            Assert.assertEquals(graph.getLocal(1), location.index());
+        }
+
+        AbstractStateSplit stateSplit = (AbstractStateSplit) write.next();
+        Assert.assertEquals(FrameState.AFTER_BCI, stateSplit.stateAfter().bci);
+
+        ReturnNode ret = (ReturnNode) stateSplit.next();
+        Assert.assertEquals(null, ret.result());
+    }
+
+    @Snippet
+    public static byte readByte1(Object o, int offset) {
+        return Word.fromObject(o).readByte(offset, ID);
+    }
+
+    @Snippet
+    public static byte readByte2(Object o, int offset) {
+        return Word.fromObject(o).readByte(Word.signed(offset), ID);
+    }
+
+    @Snippet
+    public static byte readByte3(Object o, int offset) {
+        return Word.fromObject(o).readByte(offset);
+    }
+
+    @Snippet
+    public static void writeByte1(Object o, int offset, byte value) {
+        Word.fromObject(o).writeByte(offset, value, ID);
+    }
+
+    @Snippet
+    public static void writeByte2(Object o, int offset, byte value) {
+        Word.fromObject(o).writeByte(Word.signed(offset), value, ID);
+    }
+
+    @Snippet
+    public static void writeByte3(Object o, int offset, byte value) {
+        Word.fromObject(o).writeByte(offset, value);
+    }
+
+    @Snippet
+    public static char readChar1(Object o, int offset) {
+        return Word.fromObject(o).readChar(offset, ID);
+    }
+
+    @Snippet
+    public static char readChar2(Object o, int offset) {
+        return Word.fromObject(o).readChar(Word.signed(offset), ID);
+    }
+
+    @Snippet
+    public static char readChar3(Object o, int offset) {
+        return Word.fromObject(o).readChar(offset);
+    }
+
+    @Snippet
+    public static void writeChar1(Object o, int offset, char value) {
+        Word.fromObject(o).writeChar(offset, value, ID);
+    }
+
+    @Snippet
+    public static void writeChar2(Object o, int offset, char value) {
+        Word.fromObject(o).writeChar(Word.signed(offset), value, ID);
+    }
+
+    @Snippet
+    public static void writeChar3(Object o, int offset, char value) {
+        Word.fromObject(o).writeChar(offset, value);
+    }
+
+    @Snippet
+    public static short readShort1(Object o, int offset) {
+        return Word.fromObject(o).readShort(offset, ID);
+    }
+
+    @Snippet
+    public static short readShort2(Object o, int offset) {
+        return Word.fromObject(o).readShort(Word.signed(offset), ID);
+    }
+
+    @Snippet
+    public static short readShort3(Object o, int offset) {
+        return Word.fromObject(o).readShort(offset);
+    }
+
+    @Snippet
+    public static void writeShort1(Object o, int offset, short value) {
+        Word.fromObject(o).writeShort(offset, value, ID);
+    }
+
+    @Snippet
+    public static void writeShort2(Object o, int offset, short value) {
+        Word.fromObject(o).writeShort(Word.signed(offset), value, ID);
+    }
+
+    @Snippet
+    public static void writeShort3(Object o, int offset, short value) {
+        Word.fromObject(o).writeShort(offset, value);
+    }
+
+    @Snippet
+    public static int readInt1(Object o, int offset) {
+        return Word.fromObject(o).readInt(offset, ID);
+    }
+
+    @Snippet
+    public static int readInt2(Object o, int offset) {
+        return Word.fromObject(o).readInt(Word.signed(offset), ID);
+    }
+
+    @Snippet
+    public static int readInt3(Object o, int offset) {
+        return Word.fromObject(o).readInt(offset);
+    }
+
+    @Snippet
+    public static void writeInt1(Object o, int offset, int value) {
+        Word.fromObject(o).writeInt(offset, value, ID);
+    }
+
+    @Snippet
+    public static void writeInt2(Object o, int offset, int value) {
+        Word.fromObject(o).writeInt(Word.signed(offset), value, ID);
+    }
+
+    @Snippet
+    public static void writeInt3(Object o, int offset, int value) {
+        Word.fromObject(o).writeInt(offset, value);
+    }
+
+    @Snippet
+    public static long readLong1(Object o, int offset) {
+        return Word.fromObject(o).readLong(offset, ID);
+    }
+
+    @Snippet
+    public static long readLong2(Object o, int offset) {
+        return Word.fromObject(o).readLong(Word.signed(offset), ID);
+    }
+
+    @Snippet
+    public static long readLong3(Object o, int offset) {
+        return Word.fromObject(o).readLong(offset);
+    }
+
+    @Snippet
+    public static void writeLong1(Object o, int offset, long value) {
+        Word.fromObject(o).writeLong(offset, value, ID);
+    }
+
+    @Snippet
+    public static void writeLong2(Object o, int offset, long value) {
+        Word.fromObject(o).writeLong(Word.signed(offset), value, ID);
+    }
+
+    @Snippet
+    public static void writeLong3(Object o, int offset, long value) {
+        Word.fromObject(o).writeLong(offset, value);
+    }
+
+    @Snippet
+    public static float readFloat1(Object o, int offset) {
+        return Word.fromObject(o).readFloat(offset, ID);
+    }
+
+    @Snippet
+    public static float readFloat2(Object o, int offset) {
+        return Word.fromObject(o).readFloat(Word.signed(offset), ID);
+    }
+
+    @Snippet
+    public static float readFloat3(Object o, int offset) {
+        return Word.fromObject(o).readFloat(offset);
+    }
+
+    @Snippet
+    public static void writeFloat1(Object o, int offset, float value) {
+        Word.fromObject(o).writeFloat(offset, value, ID);
+    }
+
+    @Snippet
+    public static void writeFloat2(Object o, int offset, float value) {
+        Word.fromObject(o).writeFloat(Word.signed(offset), value, ID);
+    }
+
+    @Snippet
+    public static void writeFloat3(Object o, int offset, float value) {
+        Word.fromObject(o).writeFloat(offset, value);
+    }
+
+    @Snippet
+    public static double readDouble1(Object o, int offset) {
+        return Word.fromObject(o).readDouble(offset, ID);
+    }
+
+    @Snippet
+    public static double readDouble2(Object o, int offset) {
+        return Word.fromObject(o).readDouble(Word.signed(offset), ID);
+    }
+
+    @Snippet
+    public static double readDouble3(Object o, int offset) {
+        return Word.fromObject(o).readDouble(offset);
+    }
+
+    @Snippet
+    public static void writeDouble1(Object o, int offset, double value) {
+        Word.fromObject(o).writeDouble(offset, value, ID);
+    }
+
+    @Snippet
+    public static void writeDouble2(Object o, int offset, double value) {
+        Word.fromObject(o).writeDouble(Word.signed(offset), value, ID);
+    }
+
+    @Snippet
+    public static void writeDouble3(Object o, int offset, double value) {
+        Word.fromObject(o).writeDouble(offset, value);
+    }
+
+    @Snippet
+    public static Object readObject1(Object o, int offset) {
+        return Word.fromObject(o).readObject(offset, ID);
+    }
+
+    @Snippet
+    public static Object readObject2(Object o, int offset) {
+        return Word.fromObject(o).readObject(Word.signed(offset), ID);
+    }
+
+    @Snippet
+    public static Object readObject3(Object o, int offset) {
+        return Word.fromObject(o).readObject(offset);
+    }
+
+    @Snippet
+    public static void writeObject1(Object o, int offset, Object value) {
+        Word.fromObject(o).writeObject(offset, value, ID);
+    }
+
+    @Snippet
+    public static void writeObject2(Object o, int offset, Object value) {
+        Word.fromObject(o).writeObject(Word.signed(offset), value, ID);
+    }
+
+    @Snippet
+    public static void writeObject3(Object o, int offset, Object value) {
+        Word.fromObject(o).writeObject(offset, value);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,454 @@
+/*
+ * 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.graal.replacements.test;
+
+import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.replacements.UnsafeSubstitutions.*;
+
+import java.lang.reflect.*;
+import java.util.concurrent.atomic.*;
+
+import org.junit.*;
+
+import sun.misc.*;
+
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.replacements.*;
+import com.oracle.graal.replacements.nodes.*;
+
+/**
+ * Tests the VM independent {@link MethodSubstitution}s.
+ */
+public class StandardMethodSubstitutionsTest extends MethodSubstitutionTest {
+
+    static long off(Object o, String name) {
+        try {
+            return unsafe.objectFieldOffset(o.getClass().getDeclaredField(name));
+        } catch (Exception e) {
+            Assert.fail(e.toString());
+            return 0L;
+        }
+    }
+
+    static class Foo {
+
+        boolean z;
+        byte b;
+        short s;
+        char c;
+        int i;
+        long l;
+        float f;
+        double d;
+        Object o;
+
+        void testGet(Field field, long offset, String getName, Object value) throws Exception {
+            field.set(this, value);
+            Method m1 = Unsafe.class.getDeclaredMethod(getName, Object.class, long.class);
+            Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, Object.class, long.class);
+            Object expected = m1.invoke(unsafe, this, offset);
+            Object actual = m2.invoke(null, unsafe, this, offset);
+            Assert.assertEquals(expected, actual);
+        }
+
+        void testDirect(Field field, long offset, String type, Object value) throws Exception {
+            if (type.equals("Boolean") || type.equals("Object")) {
+                // No direct memory access for these types
+                return;
+            }
+
+            long address = unsafe.allocateMemory(offset + 16);
+
+            String getName = "get" + type;
+            String putName = "put" + type;
+            Method m1 = Unsafe.class.getDeclaredMethod(putName, long.class, field.getType());
+            Method m2 = Unsafe.class.getDeclaredMethod(getName, long.class);
+
+            Method m3 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, long.class, field.getType());
+            Method m4 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, long.class);
+
+            m1.invoke(unsafe, address + offset, value);
+            Object expected = m2.invoke(unsafe, address + offset);
+
+            m3.invoke(null, unsafe, address + offset, value);
+            Object actual = m4.invoke(null, unsafe, address + offset);
+
+            unsafe.freeMemory(address);
+            Assert.assertEquals(expected, actual);
+        }
+
+        void testPut(Field field, long offset, String putName, Object value) throws Exception {
+            Object initialValue = field.get(new Foo());
+            field.set(this, initialValue);
+
+            try {
+                Method m1 = Unsafe.class.getDeclaredMethod(putName, Object.class, long.class, field.getType());
+                Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, Object.class, long.class, field.getType());
+                m1.invoke(unsafe, this, offset, value);
+                Object expected = field.get(this);
+                m2.invoke(null, unsafe, this, offset, value);
+                Object actual = field.get(this);
+                Assert.assertEquals(expected, actual);
+            } catch (NoSuchMethodException e) {
+                if (!putName.startsWith("putOrdered")) {
+                    throw e;
+                }
+            }
+        }
+
+        void test(String fieldName, String typeSuffix, Object value) {
+            try {
+                Field field = Foo.class.getDeclaredField(fieldName);
+                long offset = unsafe.objectFieldOffset(field);
+                testGet(field, offset, "get" + typeSuffix, value);
+                testGet(field, offset, "get" + typeSuffix + "Volatile", value);
+                testPut(field, offset, "put" + typeSuffix, value);
+                testPut(field, offset, "put" + typeSuffix + "Volatile", value);
+                testPut(field, offset, "putOrdered" + typeSuffix, value);
+                testDirect(field, offset, typeSuffix, value);
+            } catch (Exception e) {
+                throw new AssertionError(e);
+            }
+        }
+    }
+
+    @Test
+    public void testUnsafeSubstitutions() throws Exception {
+        test("unsafeCompareAndSwapInt");
+        test("unsafeCompareAndSwapLong");
+        test("unsafeCompareAndSwapObject");
+
+        test("unsafeGetBoolean");
+        test("unsafeGetByte");
+        test("unsafeGetShort");
+        test("unsafeGetChar");
+        test("unsafeGetInt");
+        test("unsafeGetLong");
+        test("unsafeGetFloat");
+        test("unsafeGetDouble");
+        test("unsafeGetObject");
+
+        test("unsafePutBoolean");
+        test("unsafePutByte");
+        test("unsafePutShort");
+        test("unsafePutChar");
+        test("unsafePutInt");
+        test("unsafePutFloat");
+        test("unsafePutDouble");
+        test("unsafePutObject");
+
+        test("unsafeDirectMemoryRead");
+        test("unsafeDirectMemoryWrite");
+
+        AtomicInteger a1 = new AtomicInteger(42);
+        AtomicInteger a2 = new AtomicInteger(42);
+        assertEquals(unsafe.compareAndSwapInt(a1, off(a1, "value"), 42, 53), compareAndSwapInt(unsafe, a2, off(a2, "value"), 42, 53));
+        assertEquals(a1.get(), a2.get());
+
+        AtomicLong l1 = new AtomicLong(42);
+        AtomicLong l2 = new AtomicLong(42);
+        assertEquals(unsafe.compareAndSwapLong(l1, off(l1, "value"), 42, 53), compareAndSwapLong(unsafe, l2, off(l2, "value"), 42, 53));
+        assertEquals(l1.get(), l2.get());
+
+        AtomicReference o1 = new AtomicReference<>("42");
+        AtomicReference o2 = new AtomicReference<>("42");
+        assertEquals(unsafe.compareAndSwapObject(o1, off(o1, "value"), "42", "53"), compareAndSwapObject(unsafe, o2, off(o2, "value"), "42", "53"));
+        assertEquals(o1.get(), o2.get());
+
+        Foo f1 = new Foo();
+        f1.test("z", "Boolean", Boolean.TRUE);
+        f1.test("b", "Byte", Byte.MIN_VALUE);
+        f1.test("s", "Short", Short.MAX_VALUE);
+        f1.test("c", "Char", '!');
+        f1.test("i", "Int", 1010010);
+        f1.test("f", "Float", -34.5F);
+        f1.test("l", "Long", 99999L);
+        f1.test("d", "Double", 1234.5678D);
+        f1.test("o", "Object", "object");
+    }
+
+    @SuppressWarnings("all")
+    public static boolean unsafeCompareAndSwapInt(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.compareAndSwapInt(obj, offset, 0, 1);
+    }
+
+    @SuppressWarnings("all")
+    public static boolean unsafeCompareAndSwapLong(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.compareAndSwapLong(obj, offset, 0, 1);
+    }
+
+    @SuppressWarnings("all")
+    public static boolean unsafeCompareAndSwapObject(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.compareAndSwapObject(obj, offset, null, new Object());
+    }
+
+    @SuppressWarnings("all")
+    public static boolean unsafeGetBoolean(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getBoolean(obj, offset) && unsafe.getBooleanVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static int unsafeGetByte(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getByte(obj, offset) + unsafe.getByteVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static int unsafeGetShort(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getShort(obj, offset) + unsafe.getShortVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static int unsafeGetChar(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getChar(obj, offset) + unsafe.getCharVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static int unsafeGetInt(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getInt(obj, offset) + unsafe.getIntVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static long unsafeGetLong(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getLong(obj, offset) + unsafe.getLongVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static float unsafeGetFloat(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getFloat(obj, offset) + unsafe.getFloatVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static double unsafeGetDouble(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getDouble(obj, offset) + unsafe.getDoubleVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static boolean unsafeGetObject(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getObject(obj, offset) == unsafe.getObjectVolatile(obj, offset);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutBoolean(Unsafe unsafe, Object obj, long offset, boolean value) {
+        unsafe.putBoolean(obj, offset, value);
+        unsafe.putBooleanVolatile(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutByte(Unsafe unsafe, Object obj, long offset, byte value) {
+        unsafe.putByte(obj, offset, value);
+        unsafe.putByteVolatile(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutShort(Unsafe unsafe, Object obj, long offset, short value) {
+        unsafe.putShort(obj, offset, value);
+        unsafe.putShortVolatile(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutChar(Unsafe unsafe, Object obj, long offset, char value) {
+        unsafe.putChar(obj, offset, value);
+        unsafe.putCharVolatile(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutInt(Unsafe unsafe, Object obj, long offset, int value) {
+        unsafe.putInt(obj, offset, value);
+        unsafe.putIntVolatile(obj, offset, value);
+        unsafe.putOrderedInt(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutLong(Unsafe unsafe, Object obj, long offset, long value) {
+        unsafe.putLong(obj, offset, value);
+        unsafe.putLongVolatile(obj, offset, value);
+        unsafe.putOrderedLong(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutFloat(Unsafe unsafe, Object obj, long offset, float value) {
+        unsafe.putFloat(obj, offset, value);
+        unsafe.putFloatVolatile(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutDouble(Unsafe unsafe, Object obj, long offset, double value) {
+        unsafe.putDouble(obj, offset, value);
+        unsafe.putDoubleVolatile(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafePutObject(Unsafe unsafe, Object obj, long offset, Object value) {
+        unsafe.putObject(obj, offset, value);
+        unsafe.putObjectVolatile(obj, offset, value);
+        unsafe.putOrderedObject(obj, offset, value);
+    }
+
+    @SuppressWarnings("all")
+    public static double unsafeDirectMemoryRead(Unsafe unsafe, long address) {
+        // Unsafe.getBoolean(long) and Unsafe.getObject(long) do not exist
+        return unsafe.getByte(address) + unsafe.getShort(address) + unsafe.getChar(address) + unsafe.getInt(address) + unsafe.getLong(address) + unsafe.getFloat(address) + unsafe.getDouble(address);
+    }
+
+    @SuppressWarnings("all")
+    public static void unsafeDirectMemoryWrite(Unsafe unsafe, long address, byte value) {
+        // Unsafe.putBoolean(long) and Unsafe.putObject(long) do not exist
+        unsafe.putByte(address, value);
+        unsafe.putShort(address, value);
+        unsafe.putChar(address, (char) value);
+        unsafe.putInt(address, value);
+        unsafe.putLong(address, value);
+        unsafe.putFloat(address, value);
+        unsafe.putDouble(address, value);
+    }
+
+    @Test
+    public void testMathSubstitutions() {
+        assertInGraph(assertNotInGraph(test("mathAbs"), IfNode.class), MathIntrinsicNode.class);     // Java
+        test("math");
+
+        double value = 34567.891D;
+        assertEquals(Math.sqrt(value), MathSubstitutionsX86.sqrt(value));
+        assertEquals(Math.log(value), MathSubstitutionsX86.log(value));
+        assertEquals(Math.log10(value), MathSubstitutionsX86.log10(value));
+        assertEquals(Math.sin(value), MathSubstitutionsX86.sin(value));
+        assertEquals(Math.cos(value), MathSubstitutionsX86.cos(value));
+        assertEquals(Math.tan(value), MathSubstitutionsX86.tan(value));
+    }
+
+    @SuppressWarnings("all")
+    public static double mathAbs(double value) {
+        return Math.abs(value);
+    }
+
+    @SuppressWarnings("all")
+    public static double math(double value) {
+        return Math.sqrt(value) + Math.log(value) + Math.log10(value) + Math.sin(value) + Math.cos(value) + Math.tan(value);
+        // Math.exp(value) +
+        // Math.pow(value, 13);
+    }
+
+    @Test
+    public void testIntegerSubstitutions() {
+        assertInGraph(test("integerReverseBytes"), ReverseBytesNode.class);              // Java
+        assertInGraph(test("integerNumberOfLeadingZeros"), BitScanReverseNode.class);    // Java
+        assertInGraph(test("integerNumberOfTrailingZeros"), BitScanForwardNode.class);   // Java
+        assertInGraph(test("integerBitCount"), BitCountNode.class);                      // Java
+
+        for (int i : new int[]{Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE}) {
+            assertEquals(Integer.reverseBytes(i), IntegerSubstitutions.reverseBytes(i));
+            assertEquals(Integer.numberOfLeadingZeros(i), IntegerSubstitutions.numberOfLeadingZeros(i));
+            assertEquals(Integer.numberOfTrailingZeros(i), IntegerSubstitutions.numberOfTrailingZeros(i));
+            assertEquals(Integer.bitCount(i), IntegerSubstitutions.bitCount(i));
+        }
+    }
+
+    @SuppressWarnings("all")
+    public static int integerReverseBytes(int value) {
+        return Integer.reverseBytes(value);
+    }
+
+    @SuppressWarnings("all")
+    public static int integerNumberOfLeadingZeros(int value) {
+        return Integer.numberOfLeadingZeros(value);
+    }
+
+    @SuppressWarnings("all")
+    public static int integerNumberOfTrailingZeros(int value) {
+        return Integer.numberOfTrailingZeros(value);
+    }
+
+    @SuppressWarnings("all")
+    public static int integerBitCount(int value) {
+        return Integer.bitCount(value);
+    }
+
+    @Test
+    public void testLongSubstitutions() {
+        assertInGraph(test("longReverseBytes"), ReverseBytesNode.class);              // Java
+        assertInGraph(test("longNumberOfLeadingZeros"), BitScanReverseNode.class);    // Java
+        assertInGraph(test("longNumberOfTrailingZeros"), BitScanForwardNode.class);   // Java
+        assertInGraph(test("longBitCount"), BitCountNode.class);                      // Java
+
+        for (long l : new long[]{Long.MIN_VALUE, -1L, 0L, 1L, Long.MAX_VALUE}) {
+            assertEquals(Long.reverseBytes(l), LongSubstitutions.reverseBytes(l));
+            assertEquals(Long.numberOfLeadingZeros(l), LongSubstitutions.numberOfLeadingZeros(l));
+            assertEquals(Long.numberOfTrailingZeros(l), LongSubstitutions.numberOfTrailingZeros(l));
+            assertEquals(Long.bitCount(l), LongSubstitutions.bitCount(l));
+        }
+    }
+
+    @SuppressWarnings("all")
+    public static long longReverseBytes(long value) {
+        return Long.reverseBytes(value);
+    }
+
+    @SuppressWarnings("all")
+    public static long longNumberOfLeadingZeros(long value) {
+        return Long.numberOfLeadingZeros(value);
+    }
+
+    @SuppressWarnings("all")
+    public static long longNumberOfTrailingZeros(long value) {
+        return Long.numberOfTrailingZeros(value);
+    }
+
+    @SuppressWarnings("all")
+    public static int longBitCount(long value) {
+        return Long.bitCount(value);
+    }
+
+    @Test
+    public void testFloatSubstitutions() {
+        assertInGraph(test("floatToIntBits"), ConvertNode.class); // Java
+        test("intBitsToFloat");
+    }
+
+    @SuppressWarnings("all")
+    public static int floatToIntBits(float value) {
+        return Float.floatToIntBits(value);
+    }
+
+    @SuppressWarnings("all")
+    public static float intBitsToFloat(int value) {
+        return Float.intBitsToFloat(value);
+    }
+
+    @Test
+    public void testDoubleSubstitutions() {
+        assertInGraph(test("doubleToLongBits"), ConvertNode.class); // Java
+        test("longBitsToDouble");
+    }
+
+    @SuppressWarnings("all")
+    public static long doubleToLongBits(double value) {
+        return Double.doubleToLongBits(value);
+    }
+
+    @SuppressWarnings("all")
+    public static double longBitsToDouble(long value) {
+        return Double.longBitsToDouble(value);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/TypeCheckTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,75 @@
+/*
+ * 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.graal.replacements.test;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
+import com.oracle.graal.api.meta.ProfilingInfo.TriState;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * Base class for checkcast and instanceof test classes.
+ */
+public abstract class TypeCheckTest extends GraalCompilerTest {
+
+    protected abstract void replaceProfile(StructuredGraph graph, JavaTypeProfile profile);
+
+    protected JavaTypeProfile currentProfile;
+
+    @Override
+    protected InstalledCode getCode(final ResolvedJavaMethod method, final StructuredGraph graph) {
+        boolean forceCompile = false;
+        if (currentProfile != null) {
+            replaceProfile(graph, currentProfile);
+            forceCompile = true;
+        }
+        return super.getCode(method, graph, forceCompile);
+    }
+
+    protected JavaTypeProfile profile(Class... types) {
+        return profile(TriState.UNKNOWN, types);
+    }
+
+    protected JavaTypeProfile profile(TriState nullSeen, Class... types) {
+        if (types.length == 0) {
+            return null;
+        }
+        ProfiledType[] ptypes = new ProfiledType[types.length];
+        for (int i = 0; i < types.length; i++) {
+            ptypes[i] = new ProfiledType(runtime.lookupJavaType(types[i]), 1.0D / types.length);
+        }
+        return new JavaTypeProfile(nullSeen, 0.0D, ptypes);
+    }
+
+    protected void test(String name, JavaTypeProfile profile, Object... args) {
+        assert currentProfile == null;
+        currentProfile = profile;
+        try {
+            super.test(name, args);
+        } finally {
+            currentProfile = null;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,228 @@
+/*
+ * 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.graal.replacements.test;
+
+import java.lang.reflect.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.test.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.*;
+import com.oracle.graal.replacements.Snippet.*;
+import com.oracle.graal.word.*;
+
+/**
+ * Tests for the {@link Word} type.
+ */
+public class WordTest extends GraalCompilerTest implements Snippets {
+
+    private final ReplacementsImpl installer;
+
+    public WordTest() {
+        TargetDescription target = Graal.getRequiredCapability(CodeCacheProvider.class).getTarget();
+        installer = new ReplacementsImpl(runtime, new Assumptions(false), target);
+    }
+
+    private static final ThreadLocal<SnippetInliningPolicy> inliningPolicy = new ThreadLocal<>();
+
+    @Override
+    protected StructuredGraph parse(Method m) {
+        ResolvedJavaMethod resolvedMethod = runtime.lookupJavaMethod(m);
+        return installer.makeGraph(resolvedMethod, null, inliningPolicy.get());
+    }
+
+    @LongTest
+    public void construction() {
+        long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE, Integer.MAX_VALUE - 1L, Integer.MAX_VALUE, Integer.MAX_VALUE + 1L,
+                        Integer.MIN_VALUE - 1L, Integer.MIN_VALUE, Integer.MIN_VALUE + 1L};
+        for (long word : words) {
+            test("unsigned_long", word);
+            test("unsigned_int", (int) word);
+            test("signed_long", word);
+            test("signed_int", (int) word);
+        }
+    }
+
+    @LongTest
+    public void test_arithmetic() {
+        long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE, Integer.MAX_VALUE - 1L, Integer.MAX_VALUE, Integer.MAX_VALUE + 1L,
+                        Integer.MIN_VALUE - 1L, Integer.MIN_VALUE, Integer.MIN_VALUE + 1L};
+        for (long word : words) {
+            test("unsigned_not", word);
+            test("signed_not", word);
+            for (long addend : words) {
+                test("unsigned_plus_int", word, (int) addend);
+                test("unsigned_minus_int", word, (int) addend);
+                test("unsigned_plus_int", word, -((int) addend));
+                test("unsigned_minus_int", word, -((int) addend));
+                test("unsigned_plus_long", word, addend);
+                test("unsigned_minus_long", word, addend);
+                test("unsigned_plus_long", word, -addend);
+                test("unsigned_minus_long", word, -addend);
+                test("signed_plus_int", word, (int) addend);
+                test("signed_minus_int", word, (int) addend);
+                test("signed_plus_int", word, -((int) addend));
+                test("signed_minus_int", word, -((int) addend));
+                test("signed_plus_long", word, addend);
+                test("signed_minus_long", word, addend);
+                test("signed_plus_long", word, -addend);
+                test("signed_minus_long", word, -addend);
+
+                test("and_int", word, (int) addend);
+                test("or_int", word, (int) addend);
+                test("and_int", word, -((int) addend));
+                test("or_int", word, -((int) addend));
+                test("and_long", word, addend);
+                test("or_long", word, addend);
+                test("and_long", word, -addend);
+                test("or_long", word, -addend);
+            }
+        }
+    }
+
+    @LongTest
+    public void test_compare() {
+        long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE};
+        for (long word1 : words) {
+            for (long word2 : words) {
+                for (String method : new String[]{"aboveOrEqual", "above", "belowOrEqual", "below"}) {
+                    test(method, word1, word2);
+                    test(method, word2, word1);
+                }
+            }
+        }
+    }
+
+    @Snippet
+    public static long unsigned_long(long word) {
+        return Word.unsigned(word).rawValue();
+    }
+
+    @Snippet
+    public static long unsigned_int(int word) {
+        return Word.unsigned(word).rawValue();
+    }
+
+    @Snippet
+    public static long signed_long(long word) {
+        return Word.signed(word).rawValue();
+    }
+
+    @Snippet
+    public static long signed_int(int word) {
+        return Word.signed(word).rawValue();
+    }
+
+    @Snippet
+    public static long unsigned_plus_int(long word, int addend) {
+        return Word.unsigned(word).add(addend).rawValue();
+    }
+
+    @Snippet
+    public static long unsigned_minus_int(long word, int addend) {
+        return Word.unsigned(word).subtract(addend).rawValue();
+    }
+
+    @Snippet
+    public static long unsigned_plus_long(long word, long addend) {
+        return Word.unsigned(word).add(Word.unsigned(addend)).rawValue();
+    }
+
+    @Snippet
+    public static long unsigned_minus_long(long word, long addend) {
+        return Word.unsigned(word).subtract(Word.unsigned(addend)).rawValue();
+    }
+
+    @Snippet
+    public static long signed_plus_int(long word, int addend) {
+        return Word.signed(word).add(addend).rawValue();
+    }
+
+    @Snippet
+    public static long signed_minus_int(long word, int addend) {
+        return Word.signed(word).subtract(addend).rawValue();
+    }
+
+    @Snippet
+    public static long signed_plus_long(long word, long addend) {
+        return Word.signed(word).add(Word.signed(addend)).rawValue();
+    }
+
+    @Snippet
+    public static long signed_minus_long(long word, long addend) {
+        return Word.signed(word).subtract(Word.signed(addend)).rawValue();
+    }
+
+    @Snippet
+    public static long signed_not(long word) {
+        return Word.signed(word).not().rawValue();
+    }
+
+    @Snippet
+    public static long unsigned_not(long word) {
+        return Word.unsigned(word).not().rawValue();
+    }
+
+    @Snippet
+    public static boolean aboveOrEqual(long word1, long word2) {
+        return Word.unsigned(word1).aboveOrEqual(Word.unsigned(word2));
+    }
+
+    @Snippet
+    public static boolean above(long word1, long word2) {
+        return Word.unsigned(word1).aboveThan(Word.unsigned(word2));
+    }
+
+    @Snippet
+    public static boolean belowOrEqual(long word1, long word2) {
+        return Word.unsigned(word1).belowOrEqual(Word.unsigned(word2));
+    }
+
+    @Snippet
+    public static boolean below(long word1, long word2) {
+        return Word.unsigned(word1).belowThan(Word.unsigned(word2));
+    }
+
+    @Snippet
+    public static long and_int(long word, int addend) {
+        return Word.unsigned(word).and(addend).rawValue();
+    }
+
+    @Snippet
+    public static long or_int(long word, int addend) {
+        return Word.unsigned(word).or(addend).rawValue();
+    }
+
+    @Snippet
+    public static long and_long(long word, long addend) {
+        return Word.unsigned(word).and(Word.unsigned(addend)).rawValue();
+    }
+
+    @Snippet
+    public static long or_long(long word, long addend) {
+        return Word.unsigned(word).or(Word.unsigned(addend)).rawValue();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,243 @@
+/*
+ * 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.graal.replacements;
+
+import static com.oracle.graal.replacements.SnippetTemplate.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.replacements.Snippet.Fold;
+import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy;
+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.word.*;
+
+public class BoxingSnippets implements Snippets {
+
+    /**
+     * This snippet inlining policy differs from the default one in that it does normal inlining of
+     * boxing methods like {@link Integer#valueOf(int)} (as opposed to method substitution).
+     */
+    public static class BoxingSnippetInliningPolicy implements SnippetInliningPolicy {
+
+        @Override
+        public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) {
+            if (Modifier.isNative(method.getModifiers())) {
+                return false;
+            }
+            if (method.getAnnotation(Fold.class) != null) {
+                return false;
+            }
+            if (method.getAnnotation(NodeIntrinsic.class) != null) {
+                return false;
+            }
+            if (method.getAnnotation(Word.Operation.class) != null) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public boolean shouldUseReplacement(ResolvedJavaMethod callee, ResolvedJavaMethod methodToParse) {
+            return false;
+        }
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Boolean booleanValueOf(boolean value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Boolean.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Byte byteValueOf(byte value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Byte.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Character charValueOf(char value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Character.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Double doubleValueOf(double value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Double.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Float floatValueOf(float value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Float.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Integer intValueOf(int value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Integer.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Long longValueOf(long value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Long.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static Short shortValueOf(short value) {
+        valueOfCounter.inc();
+        return UnsafeCastNode.unsafeCast(Short.valueOf(value), StampFactory.forNodeIntrinsic());
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static boolean booleanValue(Boolean value) {
+        valueOfCounter.inc();
+        return value.booleanValue();
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static byte byteValue(Byte value) {
+        valueOfCounter.inc();
+        return value.byteValue();
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static char charValue(Character value) {
+        valueOfCounter.inc();
+        return value.charValue();
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static double doubleValue(Double value) {
+        valueOfCounter.inc();
+        return value.doubleValue();
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static float floatValue(Float value) {
+        valueOfCounter.inc();
+        return value.floatValue();
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static int intValue(Integer value) {
+        valueOfCounter.inc();
+        return value.intValue();
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static long longValue(Long value) {
+        valueOfCounter.inc();
+        return value.longValue();
+    }
+
+    @Snippet(inlining = BoxingSnippetInliningPolicy.class)
+    public static short shortValue(Short value) {
+        valueOfCounter.inc();
+        return value.shortValue();
+    }
+
+    public static FloatingNode canonicalizeBoxing(BoxNode box, MetaAccessProvider runtime) {
+        ValueNode value = box.getValue();
+        if (value.isConstant()) {
+            Constant sourceConstant = value.asConstant();
+            switch (box.getBoxingKind()) {
+                case Boolean:
+                    return ConstantNode.forObject(Boolean.valueOf(sourceConstant.asInt() != 0), runtime, box.graph());
+                case Byte:
+                    return ConstantNode.forObject(Byte.valueOf((byte) sourceConstant.asInt()), runtime, box.graph());
+                case Char:
+                    return ConstantNode.forObject(Character.valueOf((char) sourceConstant.asInt()), runtime, box.graph());
+                case Short:
+                    return ConstantNode.forObject(Short.valueOf((short) sourceConstant.asInt()), runtime, box.graph());
+                case Int:
+                    return ConstantNode.forObject(Integer.valueOf(sourceConstant.asInt()), runtime, box.graph());
+                case Long:
+                    return ConstantNode.forObject(Long.valueOf(sourceConstant.asLong()), runtime, box.graph());
+                case Float:
+                    return ConstantNode.forObject(Float.valueOf(sourceConstant.asFloat()), runtime, box.graph());
+                case Double:
+                    return ConstantNode.forObject(Double.valueOf(sourceConstant.asDouble()), runtime, box.graph());
+                default:
+                    assert false : "Unexpected source kind for boxing";
+                    break;
+            }
+        }
+        return null;
+    }
+
+    public static class Templates extends AbstractTemplates {
+
+        private final EnumMap<Kind, SnippetInfo> boxSnippets = new EnumMap<>(Kind.class);
+        private final EnumMap<Kind, SnippetInfo> unboxSnippets = new EnumMap<>(Kind.class);
+
+        public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) {
+            super(runtime, replacements, target);
+            for (Kind kind : new Kind[]{Kind.Boolean, Kind.Byte, Kind.Char, Kind.Double, Kind.Float, Kind.Int, Kind.Long, Kind.Short}) {
+                boxSnippets.put(kind, snippet(BoxingSnippets.class, kind.getJavaName() + "ValueOf"));
+                unboxSnippets.put(kind, snippet(BoxingSnippets.class, kind.getJavaName() + "Value"));
+            }
+        }
+
+        public void lower(BoxNode box) {
+            FloatingNode canonical = canonicalizeBoxing(box, runtime);
+            if (canonical != null) {
+                ((StructuredGraph) box.graph()).replaceFixedWithFloating(box, canonical);
+            } else {
+                Arguments args = new Arguments(boxSnippets.get(box.getBoxingKind()));
+                args.add("value", box.getValue());
+
+                SnippetTemplate template = template(args);
+                Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", box.graph(), box, template, args);
+                template.instantiate(runtime, box, DEFAULT_REPLACER, args);
+            }
+        }
+
+        public void lower(UnboxNode unbox) {
+            Arguments args = new Arguments(unboxSnippets.get(unbox.getBoxingKind()));
+            args.add("value", unbox.getValue());
+
+            SnippetTemplate template = template(args);
+            Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", unbox.graph(), unbox, template, args);
+            template.instantiate(runtime, unbox, DEFAULT_REPLACER, args);
+        }
+    }
+
+    private static final SnippetCounter.Group integerCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Integer intrinsifications") : null;
+    private static final SnippetCounter valueOfCounter = new SnippetCounter(integerCounters, "valueOf", "valueOf intrinsification");
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSubstitutions.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2012, 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.graal.replacements;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.nodes.extended.*;
+
+public class BoxingSubstitutions {
+
+    @ClassSubstitution(Boolean.class)
+    private static class BooleanSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Boolean valueOf(boolean value) {
+            return BoxNode.box(value, Boolean.class, Kind.Boolean);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static boolean booleanValue(Boolean value) {
+            return UnboxNode.unbox(value, Kind.Boolean);
+        }
+    }
+
+    @ClassSubstitution(Byte.class)
+    private static class ByteSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Byte valueOf(byte value) {
+            return BoxNode.box(value, Byte.class, Kind.Byte);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static byte byteValue(Byte value) {
+            return UnboxNode.unbox(value, Kind.Byte);
+        }
+    }
+
+    @ClassSubstitution(Character.class)
+    private static class CharacterSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Character valueOf(char value) {
+            return BoxNode.box(value, Character.class, Kind.Char);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static char charValue(Character value) {
+            return UnboxNode.unbox(value, Kind.Char);
+        }
+    }
+
+    @ClassSubstitution(Double.class)
+    private static class DoubleSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Double valueOf(double value) {
+            return BoxNode.box(value, Double.class, Kind.Double);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static double doubleValue(Double value) {
+            return UnboxNode.unbox(value, Kind.Double);
+        }
+    }
+
+    @ClassSubstitution(Float.class)
+    private static class FloatSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Float valueOf(float value) {
+            return BoxNode.box(value, Float.class, Kind.Float);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static float floatValue(Float value) {
+            return UnboxNode.unbox(value, Kind.Float);
+        }
+    }
+
+    @ClassSubstitution(Integer.class)
+    private static class IntegerSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Integer valueOf(int value) {
+            return BoxNode.box(value, Integer.class, Kind.Int);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static int intValue(Integer value) {
+            return UnboxNode.unbox(value, Kind.Int);
+        }
+    }
+
+    @ClassSubstitution(Long.class)
+    private static class LongSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Long valueOf(long value) {
+            return BoxNode.box(value, Long.class, Kind.Long);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static long longValue(Long value) {
+            return UnboxNode.unbox(value, Kind.Long);
+        }
+    }
+
+    @ClassSubstitution(Short.class)
+    private static class ShortSubstitutions {
+
+        @MethodSubstitution(forced = true)
+        public static Short valueOf(short value) {
+            return BoxNode.box(value, Short.class, Kind.Short);
+        }
+
+        @MethodSubstitution(isStatic = false, forced = true)
+        public static short shortValue(Short value) {
+            return UnboxNode.unbox(value, Kind.Short);
+        }
+    }
+
+    public static Class<?>[] getClasses() {
+        return new Class<?>[]{BooleanSubstitutions.class, ByteSubstitutions.class, CharacterSubstitutions.class, DoubleSubstitutions.class, FloatSubstitutions.class, IntegerSubstitutions.class,
+                        LongSubstitutions.class, ShortSubstitutions.class};
+    }
+}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java	Mon Apr 15 08:49:14 2013 +0200
@@ -33,6 +33,10 @@
 public class GraalMethodSubstitutions implements ReplacementsProvider {
 
     public void registerReplacements(Replacements replacements) {
+        for (Class<?> clazz : BoxingSubstitutions.getClasses()) {
+            replacements.registerSubstitutions(clazz);
+        }
+
         if (GraalOptions.Intrinsify) {
             replacements.registerSubstitutions(MathSubstitutionsX86.class);
             replacements.registerSubstitutions(DoubleSubstitutions.class);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Mon Apr 15 08:49:14 2013 +0200
@@ -34,7 +34,9 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.replacements.SnippetTemplate.*;
+import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.UsageReplacer;
 
 /**
  * Helper class for lowering {@link InstanceOfNode}s with snippets. The majority of the complexity
@@ -49,31 +51,16 @@
  * {@link IfNode}. This avoids materializing the instanceof test as a boolean which is then retested
  * by the {@link IfNode}.
  */
-public abstract class InstanceOfSnippetsTemplates<T extends Snippets> extends AbstractTemplates<T> {
+public abstract class InstanceOfSnippetsTemplates extends AbstractTemplates {
 
-    public InstanceOfSnippetsTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, Class<T> snippetsClass) {
-        super(runtime, replacements, target, snippetsClass);
+    public InstanceOfSnippetsTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) {
+        super(runtime, replacements, target);
     }
 
     /**
-     * The key and arguments used to retrieve and instantiate an instanceof snippet template.
+     * Gets the arguments used to retrieve and instantiate an instanceof snippet template.
      */
-    public static class KeyAndArguments {
-
-        public final Key key;
-        public final Arguments arguments;
-
-        public KeyAndArguments(Key key, Arguments arguments) {
-            this.key = key;
-            this.arguments = arguments;
-        }
-
-    }
-
-    /**
-     * Gets the key and arguments used to retrieve and instantiate an instanceof snippet template.
-     */
-    protected abstract KeyAndArguments getKeyAndArguments(InstanceOfUsageReplacer replacer, LoweringTool tool);
+    protected abstract Arguments makeArguments(InstanceOfUsageReplacer replacer, LoweringTool tool);
 
     public void lower(FloatingNode instanceOf, LoweringTool tool) {
         assert instanceOf instanceof InstanceOfNode || instanceOf instanceof InstanceOfDynamicNode;
@@ -90,9 +77,8 @@
                 // No need to re-instantiate the snippet - just re-use its result
                 replacer.replaceUsingInstantiation();
             } else {
-                KeyAndArguments keyAndArguments = getKeyAndArguments(replacer, tool);
-                SnippetTemplate template = cache.get(keyAndArguments.key);
-                template.instantiate(runtime, instanceOf, replacer, tool, keyAndArguments.arguments);
+                Arguments args = makeArguments(replacer, tool);
+                template(args).instantiate(runtime, instanceOf, replacer, tool, args);
             }
         }
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Mon Apr 15 08:49:14 2013 +0200
@@ -22,22 +22,22 @@
  */
 package com.oracle.graal.replacements;
 
-import static com.oracle.graal.api.meta.MetaUtil.*;
-
 import java.lang.reflect.*;
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
-import com.oracle.graal.replacements.Snippet.*;
+import com.oracle.graal.replacements.Snippet.Fold;
 
 /**
  * Replaces calls to {@link NodeIntrinsic}s with nodes and calls to methods annotated with
@@ -46,90 +46,77 @@
 public class NodeIntrinsificationPhase extends Phase {
 
     private final MetaAccessProvider runtime;
-    private final BoxingMethodPool pool;
 
-    public NodeIntrinsificationPhase(MetaAccessProvider runtime, BoxingMethodPool pool) {
+    public NodeIntrinsificationPhase(MetaAccessProvider runtime) {
         this.runtime = runtime;
-        this.pool = pool;
     }
 
     @Override
     protected void run(StructuredGraph graph) {
+        ArrayList<Node> cleanUpReturnList = new ArrayList<>();
         for (Invoke i : graph.getInvokes()) {
             if (i.callTarget() instanceof MethodCallTargetNode) {
-                tryIntrinsify(i);
+                tryIntrinsify(i, cleanUpReturnList);
             }
         }
+
+        for (Node node : cleanUpReturnList) {
+            cleanUpReturnCheckCast(node);
+        }
     }
 
-    public static Class<?>[] signatureToTypes(Signature signature, JavaType receiverType, ResolvedJavaType accessingClass) {
-        int count = signature.getParameterCount(receiverType != null);
-        Class<?>[] result = new Class<?>[count];
-        int j = 0;
-        if (receiverType != null) {
-            result[0] = getMirrorOrFail(receiverType.resolve(accessingClass), Thread.currentThread().getContextClassLoader());
-            j = 1;
-        }
-        for (int i = 0; i + j < result.length; ++i) {
-            result[i + j] = getMirrorOrFail(signature.getParameterType(i, accessingClass).resolve(accessingClass), Thread.currentThread().getContextClassLoader());
-        }
-        return result;
-    }
-
-    private boolean tryIntrinsify(Invoke invoke) {
+    private boolean tryIntrinsify(Invoke invoke, List<Node> cleanUpReturnList) {
         ResolvedJavaMethod target = invoke.methodCallTarget().targetMethod();
         NodeIntrinsic intrinsic = target.getAnnotation(Node.NodeIntrinsic.class);
         ResolvedJavaType declaringClass = target.getDeclaringClass();
-        JavaType receiverType = invoke.methodCallTarget().isStatic() ? null : declaringClass;
         if (intrinsic != null) {
             assert target.getAnnotation(Fold.class) == null;
+            assert Modifier.isStatic(target.getModifiers()) : "node intrinsic must be static: " + target;
 
-            // TODO mjj non-static intrinsic?
-            Class<?>[] parameterTypes = signatureToTypes(target.getSignature(), null, declaringClass);
+            ResolvedJavaType[] parameterTypes = MetaUtil.resolveJavaTypes(MetaUtil.signatureToTypes(target), declaringClass);
             ResolvedJavaType returnType = target.getSignature().getReturnType(declaringClass).resolve(declaringClass);
 
             // Prepare the arguments for the reflective constructor call on the node class.
-            Object[] nodeConstructorArguments = prepareArguments(invoke, parameterTypes, target, false);
+            Constant[] nodeConstructorArguments = prepareArguments(invoke, parameterTypes, target, false);
             if (nodeConstructorArguments == null) {
                 return false;
             }
 
             // Create the new node instance.
-            Class<?> c = getNodeClass(target, intrinsic);
-            Node newInstance = createNodeInstance(runtime, c, parameterTypes, returnType, intrinsic.setStampFromReturnType(), nodeConstructorArguments);
+            ResolvedJavaType c = getNodeClass(target, intrinsic);
+            Node newInstance = createNodeInstance(c, parameterTypes, returnType, intrinsic.setStampFromReturnType(), nodeConstructorArguments);
 
             // Replace the invoke with the new node.
-            invoke.node().graph().add(newInstance);
+            invoke.asNode().graph().add(newInstance);
             invoke.intrinsify(newInstance);
 
             // Clean up checkcast instructions inserted by javac if the return type is generic.
-            cleanUpReturnCheckCast(newInstance);
+            cleanUpReturnList.add(newInstance);
         } else if (target.getAnnotation(Fold.class) != null) {
-            Class<?>[] parameterTypes = signatureToTypes(target.getSignature(), receiverType, declaringClass);
+            ResolvedJavaType[] parameterTypes = MetaUtil.resolveJavaTypes(MetaUtil.signatureToTypes(target), declaringClass);
 
             // Prepare the arguments for the reflective method call
-            Object[] arguments = prepareArguments(invoke, parameterTypes, target, true);
+            Constant[] arguments = prepareArguments(invoke, parameterTypes, target, true);
             if (arguments == null) {
                 return false;
             }
-            Object receiver = null;
+            Constant receiver = null;
             if (!invoke.methodCallTarget().isStatic()) {
                 receiver = arguments[0];
-                arguments = Arrays.asList(arguments).subList(1, arguments.length).toArray();
-                parameterTypes = Arrays.asList(parameterTypes).subList(1, parameterTypes.length).toArray(new Class<?>[parameterTypes.length - 1]);
+                arguments = Arrays.copyOfRange(arguments, 1, arguments.length);
+                parameterTypes = Arrays.copyOfRange(parameterTypes, 1, parameterTypes.length);
             }
 
             // Call the method
-            Constant constant = callMethod(target.getSignature().getReturnKind(), getMirrorOrFail(declaringClass, Thread.currentThread().getContextClassLoader()), target.getName(), parameterTypes,
-                            receiver, arguments);
+            Constant constant = target.invoke(receiver, arguments);
 
             if (constant != null) {
                 // Replace the invoke with the result of the call
-                ConstantNode node = ConstantNode.forConstant(constant, runtime, invoke.node().graph());
+                ConstantNode node = ConstantNode.forConstant(constant, runtime, invoke.asNode().graph());
                 invoke.intrinsify(node);
 
                 // Clean up checkcast instructions inserted by javac if the return type is generic.
-                cleanUpReturnCheckCast(node);
+                cleanUpReturnList.add(node);
             } else {
                 // Remove the invoke
                 invoke.intrinsify(null);
@@ -146,15 +133,15 @@
      * @return the arguments for the reflective invocation or null if an argument of {@code invoke}
      *         that is expected to be constant isn't
      */
-    private Object[] prepareArguments(Invoke invoke, Class<?>[] parameterTypes, ResolvedJavaMethod target, boolean folding) {
+    private Constant[] prepareArguments(Invoke invoke, ResolvedJavaType[] parameterTypes, ResolvedJavaMethod target, boolean folding) {
         NodeInputList<ValueNode> arguments = invoke.callTarget().arguments();
-        Object[] reflectionCallArguments = new Object[arguments.size()];
+        Constant[] reflectionCallArguments = new Constant[arguments.size()];
         for (int i = 0; i < reflectionCallArguments.length; ++i) {
             int parameterIndex = i;
             if (!invoke.methodCallTarget().isStatic()) {
                 parameterIndex--;
             }
-            ValueNode argument = tryBoxingElimination(parameterIndex, target, arguments.get(i));
+            ValueNode argument = arguments.get(i);
             if (folding || MetaUtil.getParameterAnnotation(ConstantNodeParameter.class, parameterIndex, target) != null) {
                 if (!(argument instanceof ConstantNode)) {
                     return null;
@@ -163,171 +150,63 @@
                 Constant constant = constantNode.asConstant();
                 Object o = constant.asBoxedValue();
                 if (o instanceof Class<?>) {
-                    reflectionCallArguments[i] = runtime.lookupJavaType((Class<?>) o);
-                    parameterTypes[i] = ResolvedJavaType.class;
+                    reflectionCallArguments[i] = Constant.forObject(runtime.lookupJavaType((Class<?>) o));
+                    parameterTypes[i] = runtime.lookupJavaType(ResolvedJavaType.class);
                 } else {
-                    if (parameterTypes[i] == boolean.class) {
-                        reflectionCallArguments[i] = Boolean.valueOf(constant.asInt() != 0);
-                    } else if (parameterTypes[i] == byte.class) {
-                        reflectionCallArguments[i] = Byte.valueOf((byte) constant.asInt());
-                    } else if (parameterTypes[i] == short.class) {
-                        reflectionCallArguments[i] = Short.valueOf((short) constant.asInt());
-                    } else if (parameterTypes[i] == char.class) {
-                        reflectionCallArguments[i] = Character.valueOf((char) constant.asInt());
+                    if (parameterTypes[i].getKind() == Kind.Boolean) {
+                        reflectionCallArguments[i] = Constant.forObject(Boolean.valueOf(constant.asInt() != 0));
+                    } else if (parameterTypes[i].getKind() == Kind.Byte) {
+                        reflectionCallArguments[i] = Constant.forObject(Byte.valueOf((byte) constant.asInt()));
+                    } else if (parameterTypes[i].getKind() == Kind.Short) {
+                        reflectionCallArguments[i] = Constant.forObject(Short.valueOf((short) constant.asInt()));
+                    } else if (parameterTypes[i].getKind() == Kind.Char) {
+                        reflectionCallArguments[i] = Constant.forObject(Character.valueOf((char) constant.asInt()));
                     } else {
-                        reflectionCallArguments[i] = o;
+                        reflectionCallArguments[i] = constant;
                     }
                 }
             } else {
-                reflectionCallArguments[i] = argument;
-                parameterTypes[i] = ValueNode.class;
+                reflectionCallArguments[i] = Constant.forObject(argument);
+                parameterTypes[i] = runtime.lookupJavaType(ValueNode.class);
             }
         }
         return reflectionCallArguments;
     }
 
-    private static Class<?> getNodeClass(ResolvedJavaMethod target, NodeIntrinsic intrinsic) {
-        Class<?> result = intrinsic.value();
-        if (result == NodeIntrinsic.class) {
-            return getMirrorOrFail(target.getDeclaringClass(), Thread.currentThread().getContextClassLoader());
+    private ResolvedJavaType getNodeClass(ResolvedJavaMethod target, NodeIntrinsic intrinsic) {
+        ResolvedJavaType result;
+        if (intrinsic.value() == NodeIntrinsic.class) {
+            result = target.getDeclaringClass();
+        } else {
+            result = runtime.lookupJavaType(intrinsic.value());
         }
-        assert Node.class.isAssignableFrom(result);
+        assert runtime.lookupJavaType(ValueNode.class).isAssignableFrom(result);
         return result;
     }
 
-    private ValueNode tryBoxingElimination(int parameterIndex, ResolvedJavaMethod target, ValueNode node) {
-        if (parameterIndex >= 0) {
-            Type type = target.getGenericParameterTypes()[parameterIndex];
-            if (type instanceof TypeVariable) {
-                TypeVariable typeVariable = (TypeVariable) type;
-                if (typeVariable.getBounds().length == 1) {
-                    Type boundType = typeVariable.getBounds()[0];
-                    if (boundType instanceof Class && ((Class) boundType).getSuperclass() == null) {
-                        // Unbound generic => try boxing elimination
-                        if (node.usages().count() == 2) {
-                            if (node instanceof Invoke) {
-                                Invoke invokeNode = (Invoke) node;
-                                MethodCallTargetNode callTarget = invokeNode.methodCallTarget();
-                                if (pool.isBoxingMethod(callTarget.targetMethod())) {
-                                    FrameState stateAfter = invokeNode.stateAfter();
-                                    assert stateAfter.usages().count() == 1;
-                                    invokeNode.node().replaceAtUsages(null);
-                                    ValueNode result = callTarget.arguments().get(0);
-                                    StructuredGraph graph = (StructuredGraph) node.graph();
-                                    if (invokeNode instanceof InvokeWithExceptionNode) {
-                                        // Destroy exception edge & clear stateAfter.
-                                        InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invokeNode;
+    private Node createNodeInstance(ResolvedJavaType nodeClass, ResolvedJavaType[] parameterTypes, ResolvedJavaType returnType, boolean setStampFromReturnType, Constant[] nodeConstructorArguments) {
+        ResolvedJavaMethod constructor = null;
+        Constant[] arguments = null;
 
-                                        invokeWithExceptionNode.killExceptionEdge();
-                                        graph.removeSplit(invokeWithExceptionNode, invokeWithExceptionNode.next());
-                                    } else {
-                                        graph.removeFixed((InvokeNode) invokeNode);
-                                    }
-                                    stateAfter.safeDelete();
-                                    GraphUtil.propagateKill(callTarget);
-                                    return result;
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return node;
-    }
-
-    private static Class asBoxedType(Class type) {
-        if (!type.isPrimitive()) {
-            return type;
-        }
+        for (ResolvedJavaMethod c : nodeClass.getDeclaredConstructors()) {
+            Constant[] match = match(c, parameterTypes, nodeConstructorArguments);
 
-        if (Boolean.TYPE == type) {
-            return Boolean.class;
-        }
-        if (Character.TYPE == type) {
-            return Character.class;
-        }
-        if (Byte.TYPE == type) {
-            return Byte.class;
-        }
-        if (Short.TYPE == type) {
-            return Short.class;
-        }
-        if (Integer.TYPE == type) {
-            return Integer.class;
-        }
-        if (Long.TYPE == type) {
-            return Long.class;
-        }
-        if (Float.TYPE == type) {
-            return Float.class;
-        }
-        assert Double.TYPE == type;
-        return Double.class;
-    }
-
-    static final int VARARGS = 0x00000080;
-
-    private static Node createNodeInstance(MetaAccessProvider runtime, Class<?> nodeClass, Class<?>[] parameterTypes, ResolvedJavaType returnType, boolean setStampFromReturnType,
-                    Object[] nodeConstructorArguments) {
-        Object[] arguments = null;
-        Constructor<?> constructor = null;
-        boolean needsMetaAccessProviderArgument = false;
-        nextConstructor: for (Constructor c : nodeClass.getDeclaredConstructors()) {
-            needsMetaAccessProviderArgument = false;
-            Class[] signature = c.getParameterTypes();
-            if (signature.length != 0 && signature[0] == MetaAccessProvider.class) {
-                // Chop off the MetaAccessProvider first parameter
-                signature = Arrays.copyOfRange(signature, 1, signature.length);
-                needsMetaAccessProviderArgument = true;
-            }
-            if ((c.getModifiers() & VARARGS) != 0) {
-                int fixedArgs = signature.length - 1;
-                if (parameterTypes.length < fixedArgs) {
-                    continue nextConstructor;
+            if (match != null) {
+                if (constructor == null) {
+                    constructor = c;
+                    arguments = match;
+                } else {
+                    throw new GraalInternalError("Found multiple constructors in " + nodeClass + " compatible with signature " + Arrays.toString(parameterTypes) + ": " + constructor + ", " + c);
                 }
-
-                for (int i = 0; i < fixedArgs; i++) {
-                    if (!parameterTypes[i].equals(signature[i])) {
-                        continue nextConstructor;
-                    }
-                }
-
-                Class componentType = signature[fixedArgs].getComponentType();
-                assert componentType != null : "expected last parameter of varargs constructor " + c + " to be an array type";
-                Class boxedType = asBoxedType(componentType);
-                for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) {
-                    if (!boxedType.isInstance(nodeConstructorArguments[i])) {
-                        continue nextConstructor;
-                    }
-                }
-                arguments = Arrays.copyOf(nodeConstructorArguments, fixedArgs + 1);
-                int varargsLength = nodeConstructorArguments.length - fixedArgs;
-                Object varargs = Array.newInstance(componentType, varargsLength);
-                for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) {
-                    Array.set(varargs, i - fixedArgs, nodeConstructorArguments[i]);
-                }
-                arguments[fixedArgs] = varargs;
-                constructor = c;
-                break;
-            } else if (Arrays.equals(parameterTypes, signature)) {
-                arguments = nodeConstructorArguments;
-                constructor = c;
-                break;
             }
         }
         if (constructor == null) {
             throw new GraalInternalError("Could not find constructor in " + nodeClass + " compatible with signature " + Arrays.toString(parameterTypes));
         }
-        if (needsMetaAccessProviderArgument) {
-            Object[] copy = new Object[arguments.length + 1];
-            System.arraycopy(arguments, 0, copy, 1, arguments.length);
-            copy[0] = runtime;
-            arguments = copy;
-        }
-        constructor.setAccessible(true);
+
         try {
-            ValueNode intrinsicNode = (ValueNode) constructor.newInstance(arguments);
+            ValueNode intrinsicNode = (ValueNode) constructor.newInstance(arguments).asObject();
+
             if (setStampFromReturnType) {
                 if (returnType.getKind() == Kind.Object) {
                     intrinsicNode.setStamp(StampFactory.declared(returnType));
@@ -341,26 +220,58 @@
         }
     }
 
-    /**
-     * Calls a Java method via reflection.
-     */
-    private static Constant callMethod(Kind returnKind, Class<?> holder, String name, Class<?>[] parameterTypes, Object receiver, Object[] arguments) {
-        Method method;
-        try {
-            method = holder.getDeclaredMethod(name, parameterTypes);
-            method.setAccessible(true);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
+    private Constant[] match(ResolvedJavaMethod c, ResolvedJavaType[] parameterTypes, Constant[] nodeConstructorArguments) {
+        Constant[] arguments = null;
+        boolean needsMetaAccessProviderArgument = false;
+
+        ResolvedJavaType[] signature = MetaUtil.resolveJavaTypes(MetaUtil.signatureToTypes(c.getSignature(), null), c.getDeclaringClass());
+        if (signature.length != 0 && signature[0].equals(runtime.lookupJavaType(MetaAccessProvider.class))) {
+            // Chop off the MetaAccessProvider first parameter
+            signature = Arrays.copyOfRange(signature, 1, signature.length);
+            needsMetaAccessProviderArgument = true;
         }
-        try {
-            Object result = method.invoke(receiver, arguments);
-            if (result == null) {
+
+        if (Arrays.equals(parameterTypes, signature)) {
+            // Exact match
+            arguments = nodeConstructorArguments;
+
+        } else if (signature.length > 0 && signature[signature.length - 1].isArray()) {
+            // Last constructor parameter is an array, so check if we have a vararg match
+            int fixedArgs = signature.length - 1;
+            if (parameterTypes.length < fixedArgs) {
                 return null;
             }
-            return Constant.forBoxed(returnKind, result);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
+            for (int i = 0; i < fixedArgs; i++) {
+                if (!parameterTypes[i].equals(signature[i])) {
+                    return null;
+                }
+            }
+
+            ResolvedJavaType componentType = signature[fixedArgs].getComponentType();
+            assert componentType != null;
+            for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) {
+                if (!parameterTypes[i].equals(componentType)) {
+                    return null;
+                }
+            }
+            arguments = Arrays.copyOf(nodeConstructorArguments, fixedArgs + 1);
+            arguments[fixedArgs] = componentType.newArray(nodeConstructorArguments.length - fixedArgs);
+
+            Object varargs = arguments[fixedArgs].asObject();
+            for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) {
+                Array.set(varargs, i - fixedArgs, nodeConstructorArguments[i].asBoxedValue());
+            }
+        } else {
+            return null;
         }
+
+        if (needsMetaAccessProviderArgument) {
+            Constant[] copy = new Constant[arguments.length + 1];
+            System.arraycopy(arguments, 0, copy, 1, arguments.length);
+            copy[0] = Constant.forObject(runtime);
+            arguments = copy;
+        }
+        return arguments;
     }
 
     private static String sourceLocation(Node n) {
@@ -379,32 +290,25 @@
                     if (checkCastUsage instanceof ValueAnchorNode) {
                         ValueAnchorNode valueAnchorNode = (ValueAnchorNode) checkCastUsage;
                         graph.removeFixed(valueAnchorNode);
+                    } else if (checkCastUsage instanceof UnboxNode) {
+                        UnboxNode unbox = (UnboxNode) checkCastUsage;
+                        unbox.replaceAtUsages(newInstance);
+                        graph.removeFixed(unbox);
                     } else if (checkCastUsage instanceof MethodCallTargetNode) {
                         MethodCallTargetNode checkCastCallTarget = (MethodCallTargetNode) checkCastUsage;
-                        if (pool.isUnboxingMethod(checkCastCallTarget.targetMethod())) {
-                            Invoke invokeNode = checkCastCallTarget.invoke();
-                            invokeNode.node().replaceAtUsages(newInstance);
-                            if (invokeNode instanceof InvokeWithExceptionNode) {
-                                // Destroy exception edge & clear stateAfter.
-                                InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invokeNode;
-
-                                invokeWithExceptionNode.killExceptionEdge();
-                                graph.removeSplit(invokeWithExceptionNode, invokeWithExceptionNode.next());
-                            } else {
-                                graph.removeFixed((InvokeNode) invokeNode);
-                            }
-                            checkCastCallTarget.safeDelete();
-                        } else {
-                            assert checkCastCallTarget.targetMethod().getAnnotation(NodeIntrinsic.class) != null : "checkcast at " + sourceLocation(checkCastNode) +
-                                            " not used by an unboxing method or node intrinsic, but by a call at " + sourceLocation(checkCastCallTarget.usages().first()) + " to " +
-                                            checkCastCallTarget.targetMethod();
-                            checkCastUsage.replaceFirstInput(checkCastNode, checkCastNode.object());
-                        }
+                        assert checkCastCallTarget.targetMethod().getAnnotation(NodeIntrinsic.class) != null : "checkcast at " + sourceLocation(checkCastNode) +
+                                        " not used by an unboxing method or node intrinsic, but by a call at " + sourceLocation(checkCastCallTarget.usages().first()) + " to " +
+                                        checkCastCallTarget.targetMethod();
+                        checkCastUsage.replaceFirstInput(checkCastNode, checkCastNode.object());
                     } else if (checkCastUsage instanceof FrameState) {
                         checkCastUsage.replaceFirstInput(checkCastNode, null);
                     } else if (checkCastUsage instanceof ReturnNode && checkCastNode.object().stamp() == StampFactory.forNodeIntrinsic()) {
                         checkCastUsage.replaceFirstInput(checkCastNode, checkCastNode.object());
+                    } else if (checkCastUsage instanceof IsNullNode) {
+                        assert checkCastUsage.usages().count() == 1 && checkCastUsage.usages().first().predecessor() == checkCastNode;
+                        graph.replaceFloating((FloatingNode) checkCastUsage, LogicConstantNode.contradiction(graph));
                     } else {
+                        Debug.dump(graph, "exception");
                         assert false : sourceLocation(checkCastUsage) + " has unexpected usage " + checkCastUsage + " of checkcast at " + sourceLocation(checkCastNode);
                     }
                 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Mon Apr 15 08:49:14 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
@@ -37,7 +37,6 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
@@ -53,8 +52,6 @@
     protected final TargetDescription target;
     protected final Assumptions assumptions;
 
-    private BoxingMethodPool pool;
-
     /**
      * The preprocessed replacement graphs.
      */
@@ -63,8 +60,8 @@
     // These data structures are all fully initialized during single-threaded
     // compiler startup and so do not need to be concurrent.
     private final Map<ResolvedJavaMethod, ResolvedJavaMethod> registeredMethodSubstitutions;
-    private final Set<ResolvedJavaMethod> registeredSnippets;
     private final Map<ResolvedJavaMethod, Class<? extends FixedWithNextNode>> registerMacroSubstitutions;
+    private final Set<ResolvedJavaMethod> forcedSubstitutions;
 
     public ReplacementsImpl(MetaAccessProvider runtime, Assumptions assumptions, TargetDescription target) {
         this.runtime = runtime;
@@ -72,35 +69,20 @@
         this.assumptions = assumptions;
         this.graphs = new ConcurrentHashMap<>();
         this.registeredMethodSubstitutions = new HashMap<>();
-        this.registeredSnippets = new HashSet<>();
         this.registerMacroSubstitutions = new HashMap<>();
-    }
-
-    public void registerSnippets(Class<?> snippets) {
-        assert Snippets.class.isAssignableFrom(snippets);
-        for (Method method : snippets.getDeclaredMethods()) {
-            if (method.getAnnotation(Snippet.class) != null) {
-                int modifiers = method.getModifiers();
-                if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
-                    throw new RuntimeException("Snippet must not be abstract or native");
-                }
-                ResolvedJavaMethod snippet = runtime.lookupJavaMethod(method);
-                registeredSnippets.add(snippet);
-            }
-        }
+        this.forcedSubstitutions = new HashSet<>();
     }
 
     public StructuredGraph getSnippet(ResolvedJavaMethod method) {
-        if (!registeredSnippets.contains(method)) {
-            return null;
-        }
+        assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName();
+        assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : "Snippet must not be abstract or native";
+
         StructuredGraph graph = graphs.get(method);
         if (graph == null) {
             graphs.putIfAbsent(method, makeGraph(method, null, inliningPolicy(method)));
             graph = graphs.get(method);
         }
         return graph;
-
     }
 
     public StructuredGraph getMethodSubstitution(ResolvedJavaMethod original) {
@@ -147,17 +129,23 @@
                 }
                 String originalName = originalName(substituteMethod, methodSubstitution.value());
                 Class[] originalParameters = originalParameters(substituteMethod, methodSubstitution.signature(), methodSubstitution.isStatic());
-                Member originalMethod = originalMethod(classSubstitution, originalName, originalParameters);
+                Member originalMethod = originalMethod(classSubstitution, methodSubstitution.optional(), originalName, originalParameters);
                 if (originalMethod != null) {
-                    registerMethodSubstitution(originalMethod, substituteMethod);
+                    ResolvedJavaMethod original = registerMethodSubstitution(originalMethod, substituteMethod);
+                    if (original != null && methodSubstitution.forced()) {
+                        forcedSubstitutions.add(original);
+                    }
                 }
             }
             if (macroSubstitution != null) {
                 String originalName = originalName(substituteMethod, macroSubstitution.value());
                 Class[] originalParameters = originalParameters(substituteMethod, macroSubstitution.signature(), macroSubstitution.isStatic());
-                Member originalMethod = originalMethod(classSubstitution, originalName, originalParameters);
+                Member originalMethod = originalMethod(classSubstitution, macroSubstitution.optional(), originalName, originalParameters);
                 if (originalMethod != null) {
-                    registerMacroSubstitution(originalMethod, macroSubstitution.macro());
+                    ResolvedJavaMethod original = registerMacroSubstitution(originalMethod, macroSubstitution.macro());
+                    if (original != null && macroSubstitution.forced()) {
+                        forcedSubstitutions.add(original);
+                    }
                 }
             }
         }
@@ -168,8 +156,9 @@
      * 
      * @param originalMember a method or constructor being substituted
      * @param substituteMethod the substitute method
+     * @return the original method
      */
-    protected void registerMethodSubstitution(Member originalMember, Method substituteMethod) {
+    protected ResolvedJavaMethod registerMethodSubstitution(Member originalMember, Method substituteMethod) {
         ResolvedJavaMethod substitute = runtime.lookupJavaMethod(substituteMethod);
         ResolvedJavaMethod original;
         if (originalMember instanceof Method) {
@@ -180,6 +169,7 @@
         Debug.log("substitution: " + MetaUtil.format("%H.%n(%p)", original) + " --> " + MetaUtil.format("%H.%n(%p)", substitute));
 
         registeredMethodSubstitutions.put(original, substitute);
+        return original;
     }
 
     /**
@@ -187,8 +177,9 @@
      * 
      * @param originalMethod a method or constructor being substituted
      * @param macro the substitute macro node class
+     * @return the original method
      */
-    protected void registerMacroSubstitution(Member originalMethod, Class<? extends FixedWithNextNode> macro) {
+    protected ResolvedJavaMethod registerMacroSubstitution(Member originalMethod, Class<? extends FixedWithNextNode> macro) {
         ResolvedJavaMethod originalJavaMethod;
         if (originalMethod instanceof Method) {
             originalJavaMethod = runtime.lookupJavaMethod((Method) originalMethod);
@@ -196,6 +187,7 @@
             originalJavaMethod = runtime.lookupJavaConstructor((Constructor) originalMethod);
         }
         registerMacroSubstitutions.put(originalJavaMethod, macro);
+        return originalJavaMethod;
     }
 
     private SnippetInliningPolicy inliningPolicy(ResolvedJavaMethod method) {
@@ -205,7 +197,7 @@
             policyClass = snippet.inlining();
         }
         if (policyClass == SnippetInliningPolicy.class) {
-            return new DefaultSnippetInliningPolicy(runtime, pool());
+            return new DefaultSnippetInliningPolicy(runtime);
         }
         try {
             return policyClass.getConstructor().newInstance();
@@ -284,7 +276,7 @@
          * Does final processing of a snippet graph.
          */
         protected void finalizeGraph(StructuredGraph graph) {
-            new NodeIntrinsificationPhase(runtime, pool()).apply(graph);
+            new NodeIntrinsificationPhase(runtime).apply(graph);
             assert SnippetTemplate.hasConstantParameter(method) || NodeIntrinsificationVerificationPhase.verify(graph);
 
             if (original == null) {
@@ -318,7 +310,6 @@
             Debug.dump(graph, "%s: %s", methodToParse.getName(), GraphBuilderPhase.class.getSimpleName());
 
             new WordTypeVerificationPhase(runtime, target.wordKind).apply(graph);
-            new NodeIntrinsificationPhase(runtime, pool()).apply(graph);
 
             return graph;
         }
@@ -332,7 +323,7 @@
         protected void afterInline(StructuredGraph caller, StructuredGraph callee) {
             if (GraalOptions.OptCanonicalizer) {
                 new WordTypeRewriterPhase(runtime, target.wordKind).apply(caller);
-                new CanonicalizerPhase(runtime, assumptions).apply(caller);
+                new CanonicalizerPhase.Instance(runtime, assumptions).apply(caller);
             }
         }
 
@@ -340,13 +331,13 @@
          * Called after all inlining for a given graph is complete.
          */
         protected void afterInlining(StructuredGraph graph) {
-            new NodeIntrinsificationPhase(runtime, pool()).apply(graph);
+            new NodeIntrinsificationPhase(runtime).apply(graph);
 
             new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph);
 
             new DeadCodeEliminationPhase().apply(graph);
             if (GraalOptions.OptCanonicalizer) {
-                new CanonicalizerPhase(runtime, assumptions).apply(graph);
+                new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
             }
         }
 
@@ -367,7 +358,13 @@
                     substituteCallsOriginal = true;
                 } else {
                     if ((callTarget.invokeKind() == InvokeKind.Static || callTarget.invokeKind() == InvokeKind.Special) && policy.shouldInline(callee, methodToParse)) {
-                        StructuredGraph targetGraph = parseGraph(callee, policy);
+                        StructuredGraph targetGraph;
+                        StructuredGraph intrinsicGraph = InliningUtil.getIntrinsicGraph(ReplacementsImpl.this, callee);
+                        if (intrinsicGraph != null && policy.shouldUseReplacement(callee, methodToParse)) {
+                            targetGraph = intrinsicGraph;
+                        } else {
+                            targetGraph = parseGraph(callee, policy);
+                        }
                         InliningUtil.inline(invoke, targetGraph, true);
                         Debug.dump(graph, "after inlining %s", callee);
                         afterInline(graph, targetGraph);
@@ -448,7 +445,7 @@
         return parameters;
     }
 
-    private static Member originalMethod(ClassSubstitution classSubstitution, String name, Class[] parameters) {
+    private static Member originalMethod(ClassSubstitution classSubstitution, boolean optional, String name, Class[] parameters) {
         Class<?> originalClass = classSubstitution.value();
         if (originalClass == ClassSubstitution.class) {
             originalClass = resolveType(classSubstitution.className(), classSubstitution.optional());
@@ -464,15 +461,23 @@
                 return originalClass.getDeclaredMethod(name, parameters);
             }
         } catch (NoSuchMethodException | SecurityException e) {
+            if (optional) {
+                return null;
+            }
             throw new GraalInternalError(e);
         }
     }
 
-    protected BoxingMethodPool pool() {
-        if (pool == null) {
-            // A race to create the pool is ok
-            pool = new BoxingMethodPool(runtime);
-        }
-        return pool;
+    @Override
+    public Collection<ResolvedJavaMethod> getAllReplacements() {
+        HashSet<ResolvedJavaMethod> result = new HashSet<>();
+        result.addAll(registeredMethodSubstitutions.keySet());
+        result.addAll(registerMacroSubstitutions.keySet());
+        return result;
+    }
+
+    @Override
+    public boolean isForcedSubstitution(ResolvedJavaMethod method) {
+        return forcedSubstitutions.contains(method);
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java	Mon Apr 15 08:49:14 2013 +0200
@@ -27,8 +27,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
 
@@ -55,6 +53,13 @@
          * Determines if {@code method} should be inlined into {@code caller}.
          */
         boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller);
+
+        /**
+         * Determines if {@code method} should be inlined using its replacement graph.
+         * 
+         * @return true if the replacement graph should be used, false for normal inlining.
+         */
+        boolean shouldUseReplacement(ResolvedJavaMethod callee, ResolvedJavaMethod methodToParse);
     }
 
     /**
@@ -70,11 +75,9 @@
     public static class DefaultSnippetInliningPolicy implements SnippetInliningPolicy {
 
         private final MetaAccessProvider metaAccess;
-        private final BoxingMethodPool pool;
 
-        public DefaultSnippetInliningPolicy(MetaAccessProvider metaAccess, BoxingMethodPool pool) {
+        public DefaultSnippetInliningPolicy(MetaAccessProvider metaAccess) {
             this.metaAccess = metaAccess;
-            this.pool = pool;
         }
 
         @Override
@@ -89,16 +92,18 @@
                 return false;
             }
             if (metaAccess.lookupJavaType(Throwable.class).isAssignableFrom(method.getDeclaringClass())) {
-                if (method.getName().equals("<init>")) {
+                if (method.isConstructor()) {
                     return false;
                 }
             }
             if (method.getAnnotation(Word.Operation.class) != null) {
                 return false;
             }
-            if (pool.isSpecialMethod(method)) {
-                return false;
-            }
+            return true;
+        }
+
+        @Override
+        public boolean shouldUseReplacement(ResolvedJavaMethod callee, ResolvedJavaMethod methodToParse) {
             return true;
         }
     }
@@ -116,20 +121,6 @@
     }
 
     /**
-     * Denotes a snippet parameter that will be bound during snippet template
-     * {@linkplain SnippetTemplate#instantiate instantiation}.
-     */
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.PARAMETER)
-    public @interface Parameter {
-
-        /**
-         * The name of this parameter.
-         */
-        String value();
-    }
-
-    /**
      * Denotes a snippet parameter representing 0 or more arguments that will be bound during
      * snippet template {@linkplain SnippetTemplate#instantiate instantiation}. During snippet
      * template creation, its value must be an array whose length specifies the number of arguments
@@ -143,11 +134,6 @@
     @Retention(RetentionPolicy.RUNTIME)
     @Target(ElementType.PARAMETER)
     public @interface VarargsParameter {
-
-        /**
-         * The name of this parameter.
-         */
-        String value();
     }
 
     /**
@@ -157,61 +143,5 @@
     @Retention(RetentionPolicy.RUNTIME)
     @Target(ElementType.PARAMETER)
     public @interface ConstantParameter {
-
-        /**
-         * The name of this constant.
-         */
-        String value();
-    }
-
-    /**
-     * Wrapper for the prototype value of a {@linkplain VarargsParameter varargs} parameter.
-     */
-    public static class Varargs {
-
-        private final Object args;
-        private final Class argType;
-        private final int length;
-        private final Stamp argStamp;
-
-        public static Varargs vargargs(Object array, Stamp argStamp) {
-            return new Varargs(array, argStamp);
-        }
-
-        public Varargs(Object array, Stamp argStamp) {
-            assert array != null;
-            this.argType = array.getClass().getComponentType();
-            this.argStamp = argStamp;
-            assert this.argType != null;
-            this.length = java.lang.reflect.Array.getLength(array);
-            this.args = array;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof Varargs) {
-                Varargs other = (Varargs) obj;
-                return other.argType == argType && other.length == length;
-            }
-            return false;
-        }
-
-        public Object getArray() {
-            return args;
-        }
-
-        public Stamp getArgStamp() {
-            return argStamp;
-        }
-
-        @Override
-        public int hashCode() {
-            return argType.hashCode() ^ length;
-        }
-
-        @Override
-        public String toString() {
-            return argType.getName() + "[" + length + "]";
-        }
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Mon Apr 15 08:49:14 2013 +0200
@@ -22,11 +22,8 @@
  */
 package com.oracle.graal.replacements;
 
-import static com.oracle.graal.api.meta.MetaUtil.*;
-
 import java.lang.reflect.*;
 import java.util.*;
-import java.util.Map.Entry;
 import java.util.concurrent.*;
 
 import com.oracle.graal.api.code.*;
@@ -36,15 +33,12 @@
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
-import com.oracle.graal.replacements.Snippet.Parameter;
-import com.oracle.graal.replacements.Snippet.Varargs;
 import com.oracle.graal.replacements.Snippet.VarargsParameter;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
@@ -54,174 +48,274 @@
  * A snippet template is a graph created by parsing a snippet method and then specialized by binding
  * constants to the snippet's {@link ConstantParameter} parameters.
  * 
- * Snippet templates can be managed in a {@link Cache}.
+ * Snippet templates can be managed in a cache maintained by {@link AbstractTemplates}.
  */
 public class SnippetTemplate {
 
     /**
-     * A snippet template key encapsulates the method from which a snippet was built and the
-     * arguments used to specialize the snippet.
-     * 
-     * @see Cache
+     * Holds the {@link ResolvedJavaMethod} of the snippet, together with some information about the
+     * method that needs to be computed only once. The {@link SnippetInfo} should be created once
+     * per snippet an then cached.
      */
-    public static class Key implements Iterable<Map.Entry<String, Object>> {
+    public static class SnippetInfo {
+
+        protected final ResolvedJavaMethod method;
+        protected final boolean[] constantParameters;
+        protected final boolean[] varargsParameters;
+
+        /**
+         * The parameter names, taken from the local variables table. Only used for assertion
+         * checking, so use only within an assert statement.
+         */
+        protected final String[] names;
+
+        protected SnippetInfo(ResolvedJavaMethod method) {
+            this.method = method;
 
-        public final ResolvedJavaMethod method;
-        private final HashMap<String, Object> map = new HashMap<>();
-        private int hash;
+            assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + MetaUtil.format("%H.%n", method);
+            int count = method.getSignature().getParameterCount(false);
+            constantParameters = new boolean[count];
+            varargsParameters = new boolean[count];
+            for (int i = 0; i < count; i++) {
+                constantParameters[i] = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method) != null;
+                varargsParameters[i] = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method) != null;
+
+                assert !isConstantParameter(i) || !isVarargsParameter(i) : "Parameter cannot be annotated with both @" + ConstantParameter.class.getSimpleName() + " and @" +
+                                VarargsParameter.class.getSimpleName();
+            }
 
-        public Key(ResolvedJavaMethod method) {
-            this.method = method;
-            this.hash = method.hashCode();
+            names = new String[count];
+            // Retrieve the names only when assertions are turned on.
+            assert initNames();
+        }
+
+        private boolean initNames() {
+            int slotIdx = 0;
+            for (int i = 0; i < names.length; i++) {
+                names[i] = method.getLocalVariableTable().getLocal(slotIdx, 0).getName();
+
+                Kind kind = method.getSignature().getParameterKind(i);
+                slotIdx += kind == Kind.Long || kind == Kind.Double ? 2 : 1;
+            }
+            return true;
         }
 
-        public Key add(String name, Object value) {
-            assert !map.containsKey(name);
-            map.put(name, value);
-            hash = hash ^ name.hashCode();
-            if (value != null) {
-                hash *= (value.hashCode() + 1);
-            }
+        public ResolvedJavaMethod getMethod() {
+            return method;
+        }
+
+        public int getParameterCount() {
+            return constantParameters.length;
+        }
+
+        public boolean isConstantParameter(int paramIdx) {
+            return constantParameters[paramIdx];
+        }
+
+        public boolean isVarargsParameter(int paramIdx) {
+            return varargsParameters[paramIdx];
+        }
+    }
+
+    /**
+     * Values that are bound to the snippet method parameters. The methods {@link #add},
+     * {@link #addConst}, and {@link #addVarargs} must be called in the same order as in the
+     * signature of the snippet method. The parameter name is passed to the add methods for
+     * assertion checking, i.e., to enforce that the order matches. Which method needs to be called
+     * depends on the annotation of the snippet method parameter:
+     * <ul>
+     * <li>Use {@link #add} for a parameter without an annotation. The value is bound when the
+     * {@link SnippetTemplate} is {@link SnippetTemplate#instantiate instantiated}.
+     * <li>Use {@link #addConst} for a parameter annotated with {@link ConstantParameter}. The value
+     * is bound when the {@link SnippetTemplate} is {@link SnippetTemplate#SnippetTemplate created}.
+     * <li>Use {@link #addVarargs} for an array parameter annotated with {@link VarargsParameter}. A
+     * separate {@link SnippetTemplate} is {@link SnippetTemplate#SnippetTemplate created} for every
+     * distinct array length. The actual values are bound when the {@link SnippetTemplate} is
+     * {@link SnippetTemplate#instantiate instantiated}
+     * </ul>
+     */
+    public static class Arguments {
+
+        protected final SnippetInfo info;
+        protected final CacheKey cacheKey;
+        protected final Object[] values;
+
+        protected int nextParamIdx;
+
+        public Arguments(SnippetInfo info) {
+            this.info = info;
+            this.cacheKey = new CacheKey(info);
+            this.values = new Object[info.getParameterCount()];
+        }
+
+        public Arguments add(String name, Object value) {
+            assert check(name, false, false);
+            values[nextParamIdx] = value;
+            nextParamIdx++;
             return this;
         }
 
-        public int length() {
-            return map.size();
+        public Arguments addConst(String name, Object value) {
+            assert check(name, true, false);
+            values[nextParamIdx] = value;
+            cacheKey.setParam(nextParamIdx, value);
+            nextParamIdx++;
+            return this;
         }
 
-        public Object get(String name) {
-            return map.get(name);
+        public Arguments addVarargs(String name, Class componentType, Stamp argStamp, Object value) {
+            assert check(name, false, true);
+            Varargs varargs = new Varargs(componentType, argStamp, value);
+            values[nextParamIdx] = varargs;
+            // A separate template is necessary for every distinct array length
+            cacheKey.setParam(nextParamIdx, varargs.length);
+            nextParamIdx++;
+            return this;
+        }
+
+        private boolean check(String name, boolean constParam, boolean varargsParam) {
+            assert nextParamIdx < info.getParameterCount() : "too many parameters: " + name + "  " + this;
+            assert info.names[nextParamIdx].equals(name) : "wrong parameter name: " + name + "  " + this;
+            assert constParam == info.isConstantParameter(nextParamIdx) : "Parameter " + (constParam ? "not " : "") + "annotated with @" + ConstantParameter.class.getSimpleName() + ": " + name +
+                            "  " + this;
+            assert varargsParam == info.isVarargsParameter(nextParamIdx) : "Parameter " + (varargsParam ? "not " : "") + "annotated with @" + VarargsParameter.class.getSimpleName() + ": " + name +
+                            "  " + this;
+            return true;
         }
 
         @Override
-        public Iterator<Entry<String, Object>> iterator() {
-            return map.entrySet().iterator();
+        public String toString() {
+            StringBuilder result = new StringBuilder();
+            result.append("Parameters<").append(MetaUtil.format("%H.%n", info.method)).append(" [");
+            String sep = "";
+            for (int i = 0; i < info.getParameterCount(); i++) {
+                result.append(sep);
+                if (info.isConstantParameter(i)) {
+                    result.append("const ");
+                } else if (info.isVarargsParameter(i)) {
+                    result.append("varargs ");
+                }
+                result.append(info.names[i]).append(" = ").append(values[i]);
+                sep = ", ";
+            }
+            result.append(">");
+            return result.toString();
+        }
+    }
+
+    /**
+     * Wrapper for the prototype value of a {@linkplain VarargsParameter varargs} parameter.
+     */
+    static class Varargs {
+
+        protected final Class componentType;
+        protected final Stamp stamp;
+        protected final Object value;
+        protected final int length;
+
+        protected Varargs(Class componentType, Stamp stamp, Object value) {
+            this.componentType = componentType;
+            this.stamp = stamp;
+            this.value = value;
+            if (value instanceof List) {
+                this.length = ((List) value).size();
+            } else {
+                this.length = Array.getLength(value);
+            }
+        }
+    }
+
+    static class CacheKey {
+
+        private final ResolvedJavaMethod method;
+        private final Object[] values;
+        private int hash;
+
+        protected CacheKey(SnippetInfo info) {
+            this.method = info.method;
+            this.values = new Object[info.getParameterCount()];
+            this.hash = info.method.hashCode();
+        }
+
+        protected void setParam(int paramIdx, Object value) {
+            values[paramIdx] = value;
+            hash = (hash * 31) ^ (value == null ? 0 : value.hashCode());
         }
 
         @Override
         public boolean equals(Object obj) {
-            if (obj instanceof Key) {
-                Key other = (Key) obj;
-                return other.method == method && other.map.equals(map);
+            if (!(obj instanceof CacheKey)) {
+                return false;
+            }
+            CacheKey other = (CacheKey) obj;
+            if (method != other.method) {
+                return false;
             }
-            return false;
+            for (int i = 0; i < values.length; i++) {
+                if (values[i] != null && !values[i].equals(other.values[i])) {
+                    return false;
+                }
+            }
+            return true;
         }
 
         @Override
         public int hashCode() {
             return hash;
         }
-
-        @Override
-        public String toString() {
-            return MetaUtil.format("%h.%n", method) + map.toString();
-        }
-
-        public Set<String> names() {
-            return map.keySet();
-        }
     }
 
     /**
-     * Arguments used to instantiate a template.
+     * Base class for snippet classes. It provides a cache for {@link SnippetTemplate}s.
      */
-    public static class Arguments implements Iterable<Map.Entry<String, Object>> {
-
-        private final HashMap<String, Object> map = new HashMap<>();
-
-        public static Arguments arguments(String name, Object value) {
-            return new Arguments().add(name, value);
-        }
-
-        public Arguments add(String name, Object value) {
-            assert !map.containsKey(name);
-            map.put(name, value);
-            return this;
-        }
-
-        public int length() {
-            return map.size();
-        }
+    public abstract static class AbstractTemplates {
 
-        @Override
-        public Iterator<Entry<String, Object>> iterator() {
-            return map.entrySet().iterator();
-        }
-
-        @Override
-        public String toString() {
-            return map.toString();
-        }
-    }
+        protected final MetaAccessProvider runtime;
+        protected final Replacements replacements;
+        protected final TargetDescription target;
+        private final ConcurrentHashMap<CacheKey, SnippetTemplate> templates;
 
-    /**
-     * A collection of snippet templates accessed by a {@link Key} instance.
-     */
-    public static class Cache {
-
-        private final ConcurrentHashMap<SnippetTemplate.Key, SnippetTemplate> templates = new ConcurrentHashMap<>();
-        private final MetaAccessProvider runtime;
-        private final TargetDescription target;
-        private final Replacements replacements;
-
-        public Cache(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) {
+        protected AbstractTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) {
             this.runtime = runtime;
             this.replacements = replacements;
             this.target = target;
+            this.templates = new ConcurrentHashMap<>();
+        }
+
+        protected SnippetInfo snippet(Class<? extends Snippets> declaringClass, String methodName) {
+            Method found = null;
+            for (Method method : declaringClass.getDeclaredMethods()) {
+                if (method.getAnnotation(Snippet.class) != null && method.getName().equals(methodName)) {
+                    assert found == null : "found more than one @" + Snippet.class.getSimpleName() + " method " + methodName + " in " + declaringClass;
+                    found = method;
+                }
+            }
+            assert found != null : "did not find @" + Snippet.class.getSimpleName() + " method " + methodName + " in " + declaringClass;
+
+            return new SnippetInfo(runtime.lookupJavaMethod(found));
         }
 
         /**
          * Gets a template for a given key, creating it first if necessary.
          */
-        public SnippetTemplate get(final SnippetTemplate.Key key) {
-            SnippetTemplate template = templates.get(key);
+        protected SnippetTemplate template(final Arguments args) {
+            SnippetTemplate template = templates.get(args.cacheKey);
             if (template == null) {
-                template = Debug.scope("SnippetSpecialization", key.method, new Callable<SnippetTemplate>() {
+                template = Debug.scope("SnippetSpecialization", args.info.method, new Callable<SnippetTemplate>() {
 
                     @Override
                     public SnippetTemplate call() throws Exception {
-                        return new SnippetTemplate(runtime, replacements, target, key);
+                        return new SnippetTemplate(runtime, replacements, target, args);
                     }
                 });
-                // System.out.println(key + " -> " + template);
-                templates.put(key, template);
+                templates.put(args.cacheKey, template);
             }
             return template;
         }
     }
 
-    public abstract static class AbstractTemplates<T extends Snippets> {
-
-        protected final Cache cache;
-        protected final MetaAccessProvider runtime;
-        protected final Replacements replacements;
-        protected Class<?> snippetsClass;
-
-        public AbstractTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, Class<T> snippetsClass) {
-            this.runtime = runtime;
-            this.replacements = replacements;
-            if (snippetsClass == null) {
-                assert this instanceof Snippets;
-                this.snippetsClass = getClass();
-            } else {
-                this.snippetsClass = snippetsClass;
-            }
-            this.cache = new Cache(runtime, replacements, target);
-            replacements.registerSnippets(this.snippetsClass);
-        }
-
-        protected ResolvedJavaMethod snippet(String name, Class<?>... parameterTypes) {
-            try {
-                ResolvedJavaMethod snippet = runtime.lookupJavaMethod(snippetsClass.getDeclaredMethod(name, parameterTypes));
-                assert snippet.getAnnotation(Snippet.class) != null : "snippet is not annotated with @" + Snippet.class.getSimpleName();
-                return snippet;
-            } catch (NoSuchMethodException e) {
-                throw new GraalInternalError(e);
-            }
-        }
-    }
-
     private static final Object UNUSED_PARAMETER = "DEAD PARAMETER";
+    private static final Object CONSTANT_PARAMETER = "CONSTANT";
 
     /**
      * Determines if any parameter of a given method is annotated with {@link ConstantParameter}.
@@ -238,31 +332,25 @@
     /**
      * Creates a snippet template.
      */
-    public SnippetTemplate(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, SnippetTemplate.Key key) {
-        ResolvedJavaMethod method = key.method;
-        assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + method;
+    protected SnippetTemplate(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, Arguments args) {
+        StructuredGraph snippetGraph = replacements.getSnippet(args.info.method);
+
+        ResolvedJavaMethod method = snippetGraph.method();
         Signature signature = method.getSignature();
 
         // Copy snippet graph, replacing constant parameters with given arguments
-        StructuredGraph snippetGraph = replacements.getSnippet(method);
-        if (snippetGraph == null) {
-            throw new GraalInternalError("Snippet has not been registered: %s", format("%H.%n(%p)", method));
-        }
         StructuredGraph snippetCopy = new StructuredGraph(snippetGraph.name, snippetGraph.method());
         IdentityHashMap<Node, Node> nodeReplacements = new IdentityHashMap<>();
         nodeReplacements.put(snippetGraph.start(), snippetCopy.start());
 
-        int parameterCount = signature.getParameterCount(false);
-        assert checkTemplate(runtime, key, parameterCount, method, signature);
+        assert checkTemplate(runtime, args, method, signature);
 
-        Parameter[] parameterAnnotations = new Parameter[parameterCount];
-        VarargsParameter[] varargsParameterAnnotations = new VarargsParameter[parameterCount];
+        int parameterCount = args.info.getParameterCount();
         ConstantNode[] placeholders = new ConstantNode[parameterCount];
+
         for (int i = 0; i < parameterCount; i++) {
-            ConstantParameter c = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method);
-            if (c != null) {
-                String name = c.value();
-                Object arg = key.get(name);
+            if (args.info.isConstantParameter(i)) {
+                Object arg = args.values[i];
                 Kind kind = signature.getParameterKind(i);
                 Constant constantArg;
                 if (arg instanceof Constant) {
@@ -271,19 +359,12 @@
                     constantArg = Constant.forBoxed(kind, arg);
                 }
                 nodeReplacements.put(snippetGraph.getLocal(i), ConstantNode.forConstant(constantArg, runtime, snippetCopy));
-            } else {
-                VarargsParameter vp = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method);
-                if (vp != null) {
-                    String name = vp.value();
-                    Varargs varargs = (Varargs) key.get(name);
-                    Object array = varargs.getArray();
-                    ConstantNode placeholder = ConstantNode.forObject(array, runtime, snippetCopy);
-                    nodeReplacements.put(snippetGraph.getLocal(i), placeholder);
-                    placeholders[i] = placeholder;
-                    varargsParameterAnnotations[i] = vp;
-                } else {
-                    parameterAnnotations[i] = MetaUtil.getParameterAnnotation(Parameter.class, i, method);
-                }
+            } else if (args.info.isVarargsParameter(i)) {
+                Varargs varargs = (Varargs) args.values[i];
+                Object array = Array.newInstance(varargs.componentType, varargs.length);
+                ConstantNode placeholder = ConstantNode.forObject(array, runtime, snippetCopy);
+                nodeReplacements.put(snippetGraph.getLocal(i), placeholder);
+                placeholders[i] = placeholder;
             }
         }
         snippetCopy.addDuplicates(snippetGraph.getNodes(), nodeReplacements);
@@ -291,31 +372,31 @@
         Debug.dump(snippetCopy, "Before specialization");
         if (!nodeReplacements.isEmpty()) {
             // Do deferred intrinsification of node intrinsics
-            new NodeIntrinsificationPhase(runtime, new BoxingMethodPool(runtime)).apply(snippetCopy);
+            new NodeIntrinsificationPhase(runtime).apply(snippetCopy);
             new WordTypeRewriterPhase(runtime, target.wordKind).apply(snippetCopy);
 
-            new CanonicalizerPhase(runtime, replacements.getAssumptions(), 0, null).apply(snippetCopy);
+            new CanonicalizerPhase.Instance(runtime, replacements.getAssumptions(), 0, null).apply(snippetCopy);
         }
         assert NodeIntrinsificationVerificationPhase.verify(snippetCopy);
 
         // Gather the template parameters
-        parameters = new HashMap<>();
+        parameters = new Object[parameterCount];
         for (int i = 0; i < parameterCount; i++) {
-            VarargsParameter vp = varargsParameterAnnotations[i];
-            if (vp != null) {
+            if (args.info.isConstantParameter(i)) {
+                parameters[i] = CONSTANT_PARAMETER;
+            } else if (args.info.isVarargsParameter(i)) {
                 assert snippetCopy.getLocal(i) == null;
-                Varargs varargs = (Varargs) key.get(vp.value());
-                Object array = varargs.getArray();
-                int length = Array.getLength(array);
+                Varargs varargs = (Varargs) args.values[i];
+                int length = varargs.length;
                 LocalNode[] locals = new LocalNode[length];
-                Stamp stamp = varargs.getArgStamp();
+                Stamp stamp = varargs.stamp;
                 for (int j = 0; j < length; j++) {
                     assert (parameterCount & 0xFFFF) == parameterCount;
                     int idx = i << 16 | j;
                     LocalNode local = snippetCopy.unique(new LocalNode(idx, stamp));
                     locals[j] = local;
                 }
-                parameters.put(vp.value(), locals);
+                parameters[i] = locals;
 
                 ConstantNode placeholder = placeholders[i];
                 assert placeholder != null;
@@ -329,15 +410,12 @@
                     }
                 }
             } else {
-                Parameter p = parameterAnnotations[i];
-                if (p != null) {
-                    LocalNode local = snippetCopy.getLocal(i);
-                    if (local == null) {
-                        // Parameter value was eliminated
-                        parameters.put(p.value(), UNUSED_PARAMETER);
-                    } else {
-                        parameters.put(p.value(), local);
-                    }
+                LocalNode local = snippetCopy.getLocal(i);
+                if (local == null) {
+                    // Parameter value was eliminated
+                    parameters[i] = UNUSED_PARAMETER;
+                } else {
+                    parameters[i] = local;
                 }
             }
         }
@@ -354,7 +432,7 @@
                     LoopEx loop = new LoopsData(snippetCopy).loop(loopBegin);
                     int mark = snippetCopy.getMark();
                     LoopTransformations.fullUnroll(loop, runtime, null);
-                    new CanonicalizerPhase(runtime, replacements.getAssumptions(), mark, null).apply(snippetCopy);
+                    new CanonicalizerPhase.Instance(runtime, replacements.getAssumptions(), mark, null).apply(snippetCopy);
                 }
                 FixedNode explodeLoopNext = explodeLoop.next();
                 explodeLoop.clearSuccessors();
@@ -436,11 +514,11 @@
         return true;
     }
 
-    private static boolean checkVarargs(final ResolvedJavaMethod method, Signature signature, int i, String name, Varargs varargs) {
-        Object arg = varargs.getArray();
+    private static boolean checkVarargs(MetaAccessProvider runtime, final ResolvedJavaMethod method, Signature signature, int i, String name, Varargs varargs) {
         ResolvedJavaType type = (ResolvedJavaType) signature.getParameterType(i, method.getDeclaringClass());
         assert type.isArray() : "varargs parameter must be an array type";
-        assert type.isInstance(Constant.forObject(arg)) : "value for " + name + " is not a " + MetaUtil.toJavaName(type) + " instance: " + arg;
+        assert type.getComponentType().isAssignableFrom(runtime.lookupJavaType(varargs.componentType)) : "componentType for " + name + " not matching " + MetaUtil.toJavaName(type) + " instance: " +
+                        varargs.componentType;
         return true;
     }
 
@@ -455,7 +533,7 @@
      * {@link LocalNode} instance or a {@link LocalNode} array. For an eliminated parameter, the
      * value is identical to the key.
      */
-    private final Map<String, Object> parameters;
+    private final Object[] parameters;
 
     /**
      * The return node (if any) of the snippet.
@@ -483,33 +561,33 @@
      * 
      * @return the map that will be used to bind arguments to parameters when inlining this template
      */
-    private IdentityHashMap<Node, Node> bind(StructuredGraph replaceeGraph, MetaAccessProvider runtime, SnippetTemplate.Arguments args) {
+    private IdentityHashMap<Node, Node> bind(StructuredGraph replaceeGraph, MetaAccessProvider runtime, Arguments args) {
         IdentityHashMap<Node, Node> replacements = new IdentityHashMap<>();
-        assert args.length() == parameters.size() : "number of args (" + args.length() + ") != number of parameters (" + parameters.size() + ")";
-        for (Map.Entry<String, Object> e : args) {
-            String name = e.getKey();
-            Object parameter = parameters.get(name);
-            assert parameter != null : this + " has no parameter named " + name;
-            Object argument = e.getValue();
+        assert args.info.getParameterCount() == parameters.length : "number of args (" + args.info.getParameterCount() + ") != number of parameters (" + parameters.length + ")";
+        for (int i = 0; i < parameters.length; i++) {
+            Object parameter = parameters[i];
+            assert parameter != null : this + " has no parameter named " + args.info.names[i];
+            Object argument = args.values[i];
             if (parameter instanceof LocalNode) {
                 if (argument instanceof ValueNode) {
                     replacements.put((LocalNode) parameter, (ValueNode) argument);
                 } else {
                     Kind kind = ((LocalNode) parameter).kind();
-                    assert argument != null || kind == Kind.Object : this + " cannot accept null for non-object parameter named " + name;
-                    Constant constant = Constant.forBoxed(kind, argument);
+                    assert argument != null || kind == Kind.Object : this + " cannot accept null for non-object parameter named " + args.info.names[i];
+                    Constant constant = forBoxed(argument, kind);
                     replacements.put((LocalNode) parameter, ConstantNode.forConstant(constant, runtime, replaceeGraph));
                 }
             } else if (parameter instanceof LocalNode[]) {
                 LocalNode[] locals = (LocalNode[]) parameter;
+                Varargs varargs = (Varargs) argument;
                 int length = locals.length;
                 List list = null;
                 Object array = null;
-                if (argument instanceof List) {
-                    list = (List) argument;
+                if (varargs.value instanceof List) {
+                    list = (List) varargs.value;
                     assert list.size() == length : length + " != " + list.size();
                 } else {
-                    array = argument;
+                    array = varargs.value;
                     assert array != null && array.getClass().isArray();
                     assert Array.getLength(array) == length : length + " != " + Array.getLength(array);
                 }
@@ -521,19 +599,45 @@
                     if (value instanceof ValueNode) {
                         replacements.put(local, (ValueNode) value);
                     } else {
-                        Constant constant = Constant.forBoxed(local.kind(), value);
+                        Constant constant = forBoxed(value, local.kind());
                         ConstantNode element = ConstantNode.forConstant(constant, runtime, replaceeGraph);
                         replacements.put(local, element);
                     }
                 }
             } else {
-                assert parameter == UNUSED_PARAMETER : "unexpected entry for parameter: " + name + " -> " + parameter;
+                assert parameter == CONSTANT_PARAMETER || parameter == UNUSED_PARAMETER : "unexpected entry for parameter: " + args.info.names[i] + " -> " + parameter;
             }
         }
         return replacements;
     }
 
     /**
+     * Converts a Java boxed value to a {@link Constant} of the right kind. This adjusts for the
+     * limitation that a {@link Local}'s kind is a {@linkplain Kind#getStackKind() stack kind} and
+     * so cannot be used for re-boxing primitives smaller than an int.
+     * 
+     * @param argument a Java boxed value
+     * @param localKind the kind of the {@link Local} to which {@code argument} will be bound
+     */
+    protected Constant forBoxed(Object argument, Kind localKind) {
+        assert localKind == localKind.getStackKind();
+        if (localKind == Kind.Int && !(argument instanceof Integer)) {
+            if (argument instanceof Boolean) {
+                return Constant.forBoxed(Kind.Boolean, argument);
+            }
+            if (argument instanceof Byte) {
+                return Constant.forBoxed(Kind.Byte, argument);
+            }
+            if (argument instanceof Short) {
+                return Constant.forBoxed(Kind.Short, argument);
+            }
+            assert argument instanceof Character;
+            return Constant.forBoxed(Kind.Char, argument);
+        }
+        return Constant.forBoxed(localKind, argument);
+    }
+
+    /**
      * Logic for replacing a snippet-lowered node at its usages with the return value of the
      * snippet. An alternative to the {@linkplain SnippetTemplate#DEFAULT_REPLACER default}
      * replacement logic can be used to handle mismatches between the stamp of the node being
@@ -568,7 +672,7 @@
      * @param args the arguments to be bound to the flattened positional parameters of the snippet
      * @return the map of duplicated nodes (original -> duplicate)
      */
-    public Map<Node, Node> instantiate(MetaAccessProvider runtime, FixedNode replacee, UsageReplacer replacer, SnippetTemplate.Arguments args) {
+    public Map<Node, Node> instantiate(MetaAccessProvider runtime, FixedNode replacee, UsageReplacer replacer, Arguments args) {
 
         // Inline the snippet nodes, replacing parameters with the given args in the process
         String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}";
@@ -644,7 +748,7 @@
      * @param replacer object that replaces the usages of {@code replacee}
      * @param args the arguments to be bound to the flattened positional parameters of the snippet
      */
-    public void instantiate(MetaAccessProvider runtime, FloatingNode replacee, UsageReplacer replacer, LoweringTool tool, SnippetTemplate.Arguments args) {
+    public void instantiate(MetaAccessProvider runtime, FloatingNode replacee, UsageReplacer replacer, LoweringTool tool, Arguments args) {
 
         // Inline the snippet nodes, replacing parameters with the given args in the process
         String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}";
@@ -703,13 +807,17 @@
     public String toString() {
         StringBuilder buf = new StringBuilder(snippet.toString()).append('(');
         String sep = "";
-        for (Map.Entry<String, Object> e : parameters.entrySet()) {
-            String name = e.getKey();
-            Object value = e.getValue();
+        for (int i = 0; i < parameters.length; i++) {
+            String name = "[" + i + "]";
+            Object value = parameters[i];
             buf.append(sep);
             sep = ", ";
-            if (value == UNUSED_PARAMETER) {
+            if (value == null) {
+                buf.append("<null> ").append(name);
+            } else if (value == UNUSED_PARAMETER) {
                 buf.append("<unused> ").append(name);
+            } else if (value == CONSTANT_PARAMETER) {
+                buf.append("<constant> ").append(name);
             } else if (value instanceof LocalNode) {
                 LocalNode local = (LocalNode) value;
                 buf.append(local.kind().getJavaName()).append(' ').append(name);
@@ -722,42 +830,18 @@
         return buf.append(')').toString();
     }
 
-    private static boolean checkTemplate(MetaAccessProvider runtime, SnippetTemplate.Key key, int parameterCount, ResolvedJavaMethod method, Signature signature) {
-        Set<String> expected = new HashSet<>();
-        for (int i = 0; i < parameterCount; i++) {
-            ConstantParameter c = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method);
-            VarargsParameter vp = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method);
-            Parameter p = MetaUtil.getParameterAnnotation(Parameter.class, i, method);
-            if (c != null) {
-                assert vp == null && p == null;
-                String name = c.value();
-                expected.add(name);
+    private static boolean checkTemplate(MetaAccessProvider runtime, Arguments args, ResolvedJavaMethod method, Signature signature) {
+        for (int i = 0; i < args.info.getParameterCount(); i++) {
+            if (args.info.isConstantParameter(i)) {
                 Kind kind = signature.getParameterKind(i);
-                assert key.names().contains(name) : "key for " + method + " is missing \"" + name + "\": " + key;
-                assert checkConstantArgument(runtime, method, signature, i, c.value(), key.get(name), kind);
-            } else if (vp != null) {
-                assert p == null;
-                String name = vp.value();
-                expected.add(name);
-                assert key.names().contains(name) : "key for " + method + " is missing \"" + name + "\": " + key;
-                assert key.get(name) instanceof Varargs;
-                Varargs varargs = (Varargs) key.get(name);
-                assert checkVarargs(method, signature, i, name, varargs);
-            } else {
-                assert p != null : method + ": parameter " + i + " must be annotated with exactly one of " + "@" + ConstantParameter.class.getSimpleName() + " or " + "@" +
-                                VarargsParameter.class.getSimpleName() + " or " + "@" + Parameter.class.getSimpleName();
+                assert checkConstantArgument(runtime, method, signature, i, args.info.names[i], args.values[i], kind);
+
+            } else if (args.info.isVarargsParameter(i)) {
+                assert args.values[i] instanceof Varargs;
+                Varargs varargs = (Varargs) args.values[i];
+                assert checkVarargs(runtime, method, signature, i, args.info.names[i], varargs);
             }
         }
-        if (!key.names().containsAll(expected)) {
-            expected.removeAll(key.names());
-            assert false : expected + " missing from key " + key;
-        }
-        if (!expected.containsAll(key.names())) {
-            Set<String> namesCopy = new HashSet<>(key.names());
-            namesCopy.removeAll(expected);
-            assert false : "parameter(s) " + namesCopy + " should be annotated with @" + ConstantParameter.class.getSimpleName() + " or @" + VarargsParameter.class.getSimpleName() + " in " +
-                            MetaUtil.format("%H.%n(%p)", method);
-        }
         return true;
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.extended.WriteNode.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.word.*;
@@ -63,7 +64,7 @@
     public void lower(LoweringTool tool) {
         StructuredGraph graph = (StructuredGraph) this.graph();
         IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, value.kind(), displacement, offset, graph, 1);
-        WriteNode write = graph.add(new WriteNode(object, value, location));
+        WriteNode write = graph.add(new WriteNode(object, value, location, WriteBarrierType.NONE));
         graph.replaceFixedWithFixed(this, write);
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -41,7 +41,7 @@
     private final JavaType returnType;
 
     protected MacroNode(Invoke invoke) {
-        super(invoke.node().stamp(), invoke.stateAfter());
+        super(invoke.asNode().stamp(), invoke.stateAfter());
         this.arguments = new NodeInputList<>(this, invoke.methodCallTarget().arguments());
         this.bci = invoke.bci();
         this.targetMethod = invoke.methodCallTarget().targetMethod();
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -107,6 +107,8 @@
                     return ConstantNode.forDouble(Math.cos(value), graph());
                 case TAN:
                     return ConstantNode.forDouble(Math.tan(value), graph());
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
             }
         }
         return this;
--- a/graal/com.oracle.graal.service.processor/src/com/oracle/graal/service/processor/ServiceProviderProcessor.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.service.processor/src/com/oracle/graal/service/processor/ServiceProviderProcessor.java	Mon Apr 15 08:49:14 2013 +0200
@@ -29,6 +29,7 @@
 import javax.lang.model.*;
 import javax.lang.model.element.*;
 import javax.lang.model.type.*;
+import javax.lang.model.util.*;
 import javax.tools.Diagnostic.Kind;
 import javax.tools.*;
 
@@ -81,27 +82,57 @@
         return true;
     }
 
+    private void processElement(TypeElement serviceProvider) {
+        ServiceProvider annotation = serviceProvider.getAnnotation(ServiceProvider.class);
+        if (annotation != null) {
+            try {
+                annotation.value();
+            } catch (MirroredTypeException ex) {
+                TypeMirror serviceInterface = ex.getTypeMirror();
+                if (verifyAnnotation(serviceInterface, serviceProvider)) {
+                    String interfaceName = ex.getTypeMirror().toString();
+                    addProvider(interfaceName, serviceProvider);
+                }
+            }
+        }
+    }
+
+    private void processOldElements() {
+        Filer filer = processingEnv.getFiler();
+        Elements elements = processingEnv.getElementUtils();
+        for (String key : serviceMap.keySet()) {
+            String filename = "META-INF/services/" + key;
+            try {
+                FileObject servicesFile = filer.getResource(StandardLocation.CLASS_OUTPUT, "", filename);
+                BufferedReader reader = new BufferedReader(new InputStreamReader(servicesFile.openInputStream(), "UTF-8"));
+                String line;
+                while ((line = reader.readLine()) != null) {
+                    TypeElement serviceProvider = elements.getTypeElement(line);
+                    if (serviceProvider != null) {
+                        processElement(serviceProvider);
+                    }
+                }
+                reader.close();
+                servicesFile.delete();
+            } catch (IOException e) {
+                // old services file not found: do nothing
+            }
+        }
+    }
+
     @Override
     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
         if (roundEnv.processingOver()) {
+            processOldElements();
             generateServicesFiles();
             return true;
         }
 
         for (Element element : roundEnv.getElementsAnnotatedWith(ServiceProvider.class)) {
             assert element.getKind().isClass();
-            ServiceProvider annotation = element.getAnnotation(ServiceProvider.class);
-            try {
-                annotation.value();
-            } catch (MirroredTypeException ex) {
-                TypeMirror serviceInterface = ex.getTypeMirror();
-                TypeElement serviceProvider = (TypeElement) element;
-                if (verifyAnnotation(serviceInterface, serviceProvider)) {
-                    String interfaceName = ex.getTypeMirror().toString();
-                    addProvider(interfaceName, serviceProvider);
-                }
-            }
+            processElement((TypeElement) element);
         }
+
         return true;
     }
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/CyclicMaterializeStoreNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/CyclicMaterializeStoreNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -30,9 +30,6 @@
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
 
-/**
- * The {@code StoreFieldNode} represents a write to a static or instance field.
- */
 @NodeInfo(nameTemplate = "MaterializeStore#{p#target/s}")
 public final class CyclicMaterializeStoreNode extends FixedWithNextNode implements Lowerable, Virtualizable {
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializeObjectNode.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializeObjectNode.java	Mon Apr 15 08:49:14 2013 +0200
@@ -25,7 +25,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
@@ -44,10 +43,18 @@
         this.values = new NodeInputList<>(this, virtualObject.entryCount());
     }
 
-    public NodeInputList<ValueNode> values() {
+    public NodeInputList<ValueNode> getValues() {
         return values;
     }
 
+    public VirtualObjectNode getVirtualObject() {
+        return virtualObject;
+    }
+
+    public int getLockCount() {
+        return lockCount;
+    }
+
     @Override
     public ValueNode length() {
         assert virtualObject.type().isArray();
@@ -73,38 +80,7 @@
 
     @Override
     public void lower(LoweringTool tool) {
-        StructuredGraph graph = (StructuredGraph) graph();
-
-        boolean defaultValuesOnly = isDefault();
-
-        if (virtualObject instanceof VirtualInstanceNode) {
-            VirtualInstanceNode virtual = (VirtualInstanceNode) virtualObject;
-
-            NewInstanceNode newInstance = graph.add(new NewInstanceNode(virtual.type(), defaultValuesOnly, lockCount > 0));
-            this.replaceAtUsages(newInstance);
-            graph.addBeforeFixed(this, newInstance);
-
-            if (!defaultValuesOnly) {
-                for (int i = 0; i < virtual.entryCount(); i++) {
-                    graph.addBeforeFixed(this, graph.add(new StoreFieldNode(newInstance, virtual.field(i), values.get(i))));
-                }
-            }
-        } else {
-            assert virtualObject instanceof VirtualArrayNode;
-            VirtualArrayNode virtual = (VirtualArrayNode) virtualObject;
-
-            ResolvedJavaType element = virtual.componentType();
-            NewArrayNode newArray = graph.add(new NewArrayNode(element, ConstantNode.forInt(virtual.entryCount(), graph), defaultValuesOnly, lockCount > 0));
-            this.replaceAtUsages(newArray);
-            graph.addBeforeFixed(this, newArray);
-
-            if (!defaultValuesOnly) {
-                for (int i = 0; i < virtual.entryCount(); i++) {
-                    graph.addBeforeFixed(this, graph.add(new StoreIndexedNode(newArray, ConstantNode.forInt(i, graph), element.getKind(), values.get(i))));
-                }
-            }
-        }
-        graph.removeFixed(this);
+        virtualObject.materializeAt(this, values, isDefault(), lockCount);
     }
 
     @Override
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java	Mon Apr 15 08:49:14 2013 +0200
@@ -40,7 +40,7 @@
     private final IdentityHashMap<VirtualObjectNode, ObjectState> objectStates = new IdentityHashMap<>();
     private final IdentityHashMap<ValueNode, VirtualObjectNode> objectAliases;
     private final IdentityHashMap<ValueNode, ValueNode> scalarAliases;
-    private final HashMap<ReadCacheEntry, ValueNode> readCache;
+    final HashMap<ReadCacheEntry, ValueNode> readCache;
 
     static class ReadCacheEntry {
 
@@ -167,8 +167,6 @@
 
         ValueNode[] fieldState = obj.getEntries();
 
-        // some entries are not default constants - do the materialization
-        virtual.materializeAt(fixed);
         MaterializeObjectNode materialize = new MaterializeObjectNode(virtual, obj.getLockCount());
         ValueNode[] values = new ValueNode[obj.getEntries().length];
         materialize.setProbability(fixed.probability());
@@ -249,70 +247,13 @@
         return objectStates.values();
     }
 
-    public Iterable<VirtualObjectNode> getVirtualObjects() {
+    public Collection<VirtualObjectNode> getVirtualObjects() {
         return objectAliases.values();
     }
 
     @Override
     public String toString() {
-        return objectStates.toString();
-    }
-
-    public void mergeReadCache(List<BlockState> states, MergeNode merge, GraphEffectList effects) {
-        for (Map.Entry<ReadCacheEntry, ValueNode> entry : states.get(0).readCache.entrySet()) {
-            ReadCacheEntry key = entry.getKey();
-            ValueNode value = entry.getValue();
-            boolean phi = false;
-            for (int i = 1; i < states.size(); i++) {
-                ValueNode otherValue = states.get(i).readCache.get(key);
-                if (otherValue == null) {
-                    value = null;
-                    phi = false;
-                    break;
-                }
-                if (!phi && otherValue != value) {
-                    phi = true;
-                }
-            }
-            if (phi) {
-                PhiNode phiNode = new PhiNode(value.kind(), merge);
-                effects.addFloatingNode(phiNode);
-                for (int i = 0; i < states.size(); i++) {
-                    effects.addPhiInput(phiNode, states.get(i).getReadCache(key.object, key.identity));
-                }
-                readCache.put(key, phiNode);
-            } else if (value != null) {
-                readCache.put(key, value);
-            }
-        }
-        for (PhiNode phi : merge.phis()) {
-            if (phi.kind() == Kind.Object) {
-                for (Map.Entry<ReadCacheEntry, ValueNode> entry : states.get(0).readCache.entrySet()) {
-                    if (entry.getKey().object == phi.valueAt(0)) {
-                        mergeReadCachePhi(phi, entry.getKey().identity, states, merge, effects);
-                    }
-                }
-
-            }
-        }
-    }
-
-    private void mergeReadCachePhi(PhiNode phi, Object identity, List<BlockState> states, MergeNode merge, GraphEffectList effects) {
-        ValueNode[] values = new ValueNode[phi.valueCount()];
-        for (int i = 0; i < phi.valueCount(); i++) {
-            ValueNode value = states.get(i).getReadCache(phi.valueAt(i), identity);
-            if (value == null) {
-                return;
-            }
-            values[i] = value;
-        }
-
-        PhiNode phiNode = new PhiNode(values[0].kind(), merge);
-        effects.addFloatingNode(phiNode);
-        for (int i = 0; i < values.length; i++) {
-            effects.addPhiInput(phiNode, values[i]);
-        }
-        readCache.put(new ReadCacheEntry(identity, phi), phiNode);
+        return objectStates + " " + readCache;
     }
 
     public static BlockState meetAliases(List<BlockState> states) {
@@ -349,4 +290,38 @@
         return readCache;
     }
 
+    public boolean equivalentTo(BlockState other) {
+        if (this == other) {
+            return true;
+        }
+        boolean objectAliasesEqual = compareMaps(objectAliases, other.objectAliases);
+        boolean objectStatesEqual = compareMaps(objectStates, other.objectStates);
+        boolean readCacheEqual = compareMapsNoSize(readCache, other.readCache);
+        boolean scalarAliasesEqual = scalarAliases.equals(other.scalarAliases);
+        return objectAliasesEqual && objectStatesEqual && readCacheEqual && scalarAliasesEqual;
+    }
+
+    private static <K, V> boolean compareMaps(Map<K, V> left, Map<K, V> right) {
+        if (left.size() != right.size()) {
+            return false;
+        }
+        return compareMapsNoSize(left, right);
+    }
+
+    private static <K, V> boolean compareMapsNoSize(Map<K, V> left, Map<K, V> right) {
+        if (left == right) {
+            return true;
+        }
+        for (Map.Entry<K, V> entry : right.entrySet()) {
+            K key = entry.getKey();
+            V value = entry.getValue();
+            assert value != null;
+            V otherValue = left.get(key);
+            if (otherValue != value && !value.equals(otherValue)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectList.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectList.java	Mon Apr 15 08:49:14 2013 +0200
@@ -73,48 +73,47 @@
         public abstract void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes);
     }
 
-    private Effect[] effects = new Effect[16];
-    private int[] level = new int[16];
+    private static final Effect[] EMPTY_ARRAY = new Effect[0];
+
+    private Effect[] effects = EMPTY_ARRAY;
     private int size;
-    private int currentLevel;
+
+    private void enlarge(int elements) {
+        int length = effects.length;
+        if (size + elements > length) {
+            while (size + elements > length) {
+                length = Math.max(length * 2, 4);
+            }
+            effects = Arrays.copyOf(effects, length);
+        }
+    }
 
     public void add(Effect effect) {
-        if (effects.length == size) {
-            effects = Arrays.copyOf(effects, effects.length * 2);
-            level = Arrays.copyOf(level, effects.length);
-        }
-        level[size] = currentLevel;
+        assert effect != null;
+        enlarge(1);
         effects[size++] = effect;
     }
 
     public void addAll(Collection<? extends Effect> list) {
-        int length = effects.length;
-        if (size + list.size() > length) {
-            while (size + list.size() > length) {
-                length *= 2;
-            }
-            effects = Arrays.copyOf(effects, length);
-            level = Arrays.copyOf(level, effects.length);
-        }
+        enlarge(list.size());
         for (Effect effect : list) {
-            level[size] = currentLevel;
+            assert effect != null;
             effects[size++] = effect;
         }
     }
 
     public void addAll(EffectList list) {
-        int length = effects.length;
-        if (size + list.size > length) {
-            while (size + list.size > length) {
-                length *= 2;
-            }
-            effects = Arrays.copyOf(effects, length);
-            level = Arrays.copyOf(level, effects.length);
-        }
-        for (Effect effect : list) {
-            level[size] = currentLevel;
-            effects[size++] = effect;
-        }
+        enlarge(list.size);
+        System.arraycopy(list.effects, 0, effects, size, list.size);
+        size += list.size;
+    }
+
+    public void insertAll(EffectList list, int position) {
+        assert position >= 0 && position <= size;
+        enlarge(list.size);
+        System.arraycopy(effects, position, effects, position + list.size, size - position);
+        System.arraycopy(list.effects, 0, effects, position, list.size);
+        size += list.size;
     }
 
     public int checkpoint() {
@@ -154,14 +153,6 @@
         };
     }
 
-    public void incLevel() {
-        currentLevel++;
-    }
-
-    public void decLevel() {
-        currentLevel--;
-    }
-
     public Effect get(int index) {
         if (index >= size) {
             throw new IndexOutOfBoundsException();
@@ -169,13 +160,6 @@
         return effects[index];
     }
 
-    public int levelAt(int index) {
-        if (index >= size) {
-            throw new IndexOutOfBoundsException();
-        }
-        return level[index];
-    }
-
     public void clear() {
         size = 0;
     }
@@ -190,9 +174,6 @@
         for (int i = 0; i < size(); i++) {
             Effect effect = get(i);
             if (effect.isVisible()) {
-                for (int i2 = 0; i2 < levelAt(i); i2++) {
-                    str.append("    ");
-                }
                 str.append(effect).append('\n');
             }
         }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Mon Apr 15 08:49:14 2013 +0200
@@ -104,17 +104,17 @@
      * 
      * @param node The floating node to be added.
      */
-    public void addFloatingNode(final ValueNode node) {
+    public void addFloatingNode(final ValueNode node, final String cause) {
         add(new Effect() {
 
             @Override
             public String name() {
-                return "addFloatingNode";
+                return "addFloatingNode " + cause;
             }
 
             @Override
             public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                assert !node.isAlive() && !node.isDeleted();
+                assert !node.isAlive() && !node.isDeleted() : node + " " + cause;
                 graph.add(node);
             }
         });
@@ -142,7 +142,7 @@
                 graph.addBeforeFixed(position, graph.add(node));
                 node.setProbability(position.probability());
                 for (int i = 0; i < values.length; i++) {
-                    node.values().set(i, values[i]);
+                    node.getValues().set(i, values[i]);
                 }
             }
         });
@@ -164,7 +164,7 @@
 
             @Override
             public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                assert node.isAlive() && value.isAlive();
+                assert node.isAlive() && value.isAlive() : node + " " + value;
                 node.addInput(value);
             }
         });
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Mon Apr 15 08:49:14 2013 +0200
@@ -25,28 +25,24 @@
 import java.util.*;
 import java.util.concurrent.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
-public class IterativeInliningPhase extends Phase {
+public class IterativeInliningPhase extends BasePhase<HighTierContext> {
 
     private final PhasePlan plan;
 
-    private final GraalCodeCacheProvider runtime;
     private final Replacements replacements;
-    private final Assumptions assumptions;
     private final GraphCache cache;
     private final OptimisticOptimizations optimisticOpts;
     private final boolean readElimination;
 
-    public IterativeInliningPhase(GraalCodeCacheProvider runtime, Replacements replacements, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts, boolean readElimination) {
-        this.runtime = runtime;
+    public IterativeInliningPhase(Replacements replacements, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts, boolean readElimination) {
         this.replacements = replacements;
-        this.assumptions = assumptions;
         this.cache = cache;
         this.plan = plan;
         this.optimisticOpts = optimisticOpts;
@@ -60,12 +56,12 @@
     }
 
     @Override
-    protected void run(final StructuredGraph graph) {
-        runIterations(graph, true);
-        runIterations(graph, false);
+    protected void run(final StructuredGraph graph, final HighTierContext context) {
+        runIterations(graph, true, context);
+        runIterations(graph, false, context);
     }
 
-    private void runIterations(final StructuredGraph graph, final boolean simple) {
+    private void runIterations(final StructuredGraph graph, final boolean simple, final HighTierContext context) {
         Boolean continueIteration = true;
         for (int iteration = 0; iteration < GraalOptions.EscapeAnalysisIterations && continueIteration; iteration++) {
             continueIteration = Debug.scope("iteration " + iteration, new Callable<Boolean>() {
@@ -73,13 +69,13 @@
                 @Override
                 public Boolean call() {
                     boolean progress = false;
-                    PartialEscapeAnalysisPhase ea = new PartialEscapeAnalysisPhase(runtime, assumptions, false, readElimination);
-                    ea.apply(graph);
-                    progress |= ea.hasChanged();
+                    PartialEscapeAnalysisPhase ea = new PartialEscapeAnalysisPhase(false, readElimination);
+                    boolean eaResult = ea.runAnalysis(graph, context);
+                    progress |= eaResult;
 
                     Map<Invoke, Double> hints = GraalOptions.PEAInliningHints ? PartialEscapeAnalysisPhase.getHints(graph) : null;
 
-                    InliningPhase inlining = new InliningPhase(runtime, hints, replacements, assumptions, cache, plan, optimisticOpts);
+                    InliningPhase inlining = new InliningPhase(context.getRuntime(), hints, replacements, context.getAssumptions(), cache, plan, optimisticOpts);
                     inlining.setMaxMethodsPerInlining(simple ? 1 : Integer.MAX_VALUE);
                     inlining.apply(graph);
                     progress |= inlining.getInliningCount() > 0;
@@ -87,8 +83,8 @@
                     new DeadCodeEliminationPhase().apply(graph);
 
                     if (GraalOptions.ConditionalElimination && GraalOptions.OptCanonicalizer) {
-                        new CanonicalizerPhase(runtime, assumptions).apply(graph);
-                        new IterativeConditionalEliminationPhase(runtime, assumptions).apply(graph);
+                        new CanonicalizerPhase().apply(graph, context);
+                        new IterativeConditionalEliminationPhase(context.getRuntime(), context.getAssumptions()).apply(graph);
                     }
 
                     return progress;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java	Mon Apr 15 08:49:14 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.virtual.phases.ea;
 
+import java.util.*;
+
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.spi.Virtualizable.EscapeState;
@@ -144,4 +146,48 @@
 
         return str.append('}').toString();
     }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + Arrays.hashCode(entries);
+        result = prime * result + lockCount;
+        result = prime * result + ((materializedValue == null) ? 0 : materializedValue.hashCode());
+        result = prime * result + ((state == null) ? 0 : state.hashCode());
+        result = prime * result + ((virtual == null) ? 0 : virtual.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        ObjectState other = (ObjectState) obj;
+        if (!Arrays.equals(entries, other.entries)) {
+            return false;
+        }
+        if (lockCount != other.lockCount) {
+            return false;
+        }
+        if (materializedValue == null) {
+            if (other.materializedValue != null) {
+                return false;
+            }
+        } else if (!materializedValue.equals(other.materializedValue)) {
+            return false;
+        }
+        if (state != other.state) {
+            return false;
+        }
+        assert virtual != null && other.virtual != null;
+        if (!virtual.equals(other.virtual)) {
+            return false;
+        }
+        return true;
+    }
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java	Mon Apr 15 08:49:14 2013 +0200
@@ -25,12 +25,10 @@
 import java.util.*;
 import java.util.concurrent.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.debug.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
@@ -38,34 +36,25 @@
 import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer;
 import com.oracle.graal.phases.graph.*;
 import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.virtual.nodes.*;
-import com.oracle.graal.virtual.phases.ea.EffectList.Effect;
 
-public class PartialEscapeAnalysisPhase extends Phase {
+public class PartialEscapeAnalysisPhase extends BasePhase<HighTierContext> {
 
-    private final MetaAccessProvider runtime;
-    private final Assumptions assumptions;
-    private CustomCanonicalizer customCanonicalizer;
+    private final CustomCanonicalizer customCanonicalizer;
     private final boolean iterative;
     private final boolean readElimination;
 
-    private boolean changed;
+    public PartialEscapeAnalysisPhase(boolean iterative, boolean readElimination) {
+        this(null, iterative, readElimination);
+    }
 
-    public PartialEscapeAnalysisPhase(MetaAccessProvider runtime, Assumptions assumptions, boolean iterative, boolean readElimination) {
-        this.runtime = runtime;
-        this.assumptions = assumptions;
+    public PartialEscapeAnalysisPhase(CustomCanonicalizer customCanonicalizer, boolean iterative, boolean readElimination) {
+        this.customCanonicalizer = customCanonicalizer;
         this.iterative = iterative;
         this.readElimination = readElimination;
     }
 
-    public boolean hasChanged() {
-        return changed;
-    }
-
-    public void setCustomCanonicalizer(CustomCanonicalizer customCanonicalizer) {
-        this.customCanonicalizer = customCanonicalizer;
-    }
-
     public static final void trace(String format, Object... obj) {
         if (GraalOptions.TraceEscapeAnalysis) {
             Debug.log(format, obj);
@@ -73,9 +62,13 @@
     }
 
     @Override
-    protected void run(final StructuredGraph graph) {
+    protected void run(StructuredGraph graph, HighTierContext context) {
+        runAnalysis(graph, context);
+    }
+
+    public boolean runAnalysis(final StructuredGraph graph, final HighTierContext context) {
         if (!matches(graph, GraalOptions.EscapeAnalyzeOnly)) {
-            return;
+            return false;
         }
 
         if (!readElimination) {
@@ -87,33 +80,29 @@
                 }
             }
             if (!analyzableNodes) {
-                return;
+                return false;
             }
         }
 
-        Boolean continueIteration = true;
+        boolean continueIteration = true;
+        boolean changed = false;
         for (int iteration = 0; iteration < GraalOptions.EscapeAnalysisIterations && continueIteration; iteration++) {
-            continueIteration = Debug.scope("iteration " + iteration, new Callable<Boolean>() {
+            boolean currentChanged = Debug.scope("iteration " + iteration, new Callable<Boolean>() {
 
                 @Override
                 public Boolean call() {
 
                     SchedulePhase schedule = new SchedulePhase();
                     schedule.apply(graph, false);
-                    PartialEscapeClosure closure = new PartialEscapeClosure(graph.createNodeBitMap(), schedule, runtime, assumptions);
+                    PartialEscapeClosure closure = new PartialEscapeClosure(graph.createNodeBitMap(), schedule, context.getRuntime(), context.getAssumptions());
                     ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock(), new BlockState(), null);
 
                     if (!closure.hasChanged()) {
                         return false;
                     }
-                    changed = true;
 
                     // apply the effects collected during the escape analysis iteration
-                    ArrayList<Node> obsoleteNodes = new ArrayList<>();
-                    for (Effect effect : closure.getEffects()) {
-                        effect.apply(graph, obsoleteNodes);
-                    }
-                    trace("%s\n", closure.getEffects());
+                    List<Node> obsoleteNodes = closure.applyEffects(graph);
 
                     Debug.dump(graph, "after PartialEscapeAnalysis iteration");
                     assert noObsoleteNodes(graph, obsoleteNodes);
@@ -121,21 +110,17 @@
                     new DeadCodeEliminationPhase().apply(graph);
 
                     if (GraalOptions.OptCanonicalizer) {
-                        new CanonicalizerPhase(runtime, assumptions, null, customCanonicalizer).apply(graph);
+                        new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), null, customCanonicalizer).apply(graph);
                     }
 
-                    return iterative;
+                    return true;
                 }
             });
+            continueIteration = currentChanged && iterative;
+            changed |= currentChanged;
         }
 
-        if (DynamicCounterNode.enabled && readElimination) {
-            for (Node node : graph.getNodes()) {
-                if (node instanceof LoadFieldNode) {
-                    DynamicCounterNode.addCounterBefore("load non-elim", 1, false, (FixedNode) node);
-                }
-            }
-        }
+        return changed;
     }
 
     private static boolean matches(StructuredGraph graph, String filter) {
@@ -146,7 +131,7 @@
         return true;
     }
 
-    static boolean noObsoleteNodes(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
+    static boolean noObsoleteNodes(StructuredGraph graph, List<Node> obsoleteNodes) {
         // helper code that determines the paths that keep obsolete nodes alive:
 
         NodeFlood flood = graph.createNodeFlood();
@@ -196,14 +181,13 @@
                 }
             }
         }
-
         boolean success = true;
         for (Node node : obsoleteNodes) {
             if (flood.isMarked(node)) {
-                System.out.print("offending node path:");
+                TTY.print("offending node path:");
                 Node current = node;
                 while (current != null) {
-                    System.out.println(current.toString());
+                    TTY.println(current.toString());
                     current = path.get(current);
                     if (current != null && current instanceof FixedNode && !obsoleteNodes.contains(current)) {
                         break;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Mon Apr 15 08:49:14 2013 +0200
@@ -46,6 +46,7 @@
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.virtual.nodes.*;
 import com.oracle.graal.virtual.phases.ea.BlockState.ReadCacheEntry;
+import com.oracle.graal.virtual.phases.ea.EffectList.Effect;
 
 class PartialEscapeClosure extends BlockIteratorClosure<BlockState> {
 
@@ -65,7 +66,8 @@
     private final NodeBitMap usages;
     private final SchedulePhase schedule;
 
-    private final GraphEffectList effects = new GraphEffectList();
+    private final BlockMap<GraphEffectList> blockEffects;
+    private final IdentityHashMap<Loop, GraphEffectList> loopMergeEffects = new IdentityHashMap<>();
 
     private final VirtualizerToolImpl tool;
 
@@ -76,19 +78,57 @@
     public PartialEscapeClosure(NodeBitMap usages, SchedulePhase schedule, MetaAccessProvider metaAccess, Assumptions assumptions) {
         this.usages = usages;
         this.schedule = schedule;
-        tool = new VirtualizerToolImpl(effects, usages, metaAccess, assumptions);
+        this.tool = new VirtualizerToolImpl(usages, metaAccess, assumptions);
+        this.blockEffects = new BlockMap<>(schedule.getCFG());
+        for (Block block : schedule.getCFG().getBlocks()) {
+            blockEffects.put(block, new GraphEffectList());
+        }
     }
 
     public boolean hasChanged() {
         return changed;
     }
 
-    public GraphEffectList getEffects() {
-        return effects;
-    }
+    public List<Node> applyEffects(final StructuredGraph graph) {
+        final ArrayList<Node> obsoleteNodes = new ArrayList<>();
+        BlockIteratorClosure<Object> closure = new BlockIteratorClosure<Object>() {
+
+            private void apply(GraphEffectList effects, Object context) {
+                if (!effects.isEmpty()) {
+                    Debug.log(" ==== effects for %s", context);
+                    for (Effect effect : effects) {
+                        effect.apply(graph, obsoleteNodes);
+                        if (effect.isVisible()) {
+                            Debug.log("    %s", effect);
+                        }
+                    }
+                }
+            }
 
-    public int getNewVirtualObjectCount() {
-        return tool.getNewVirtualObjectCount();
+            @Override
+            protected void processBlock(Block block, Object currentState) {
+                apply(blockEffects.get(block), block);
+            }
+
+            @Override
+            protected Object merge(Block merge, List<Object> states) {
+                return new Object();
+            }
+
+            @Override
+            protected Object cloneState(Object oldState) {
+                return oldState;
+            }
+
+            @Override
+            protected List<Object> processLoop(Loop loop, Object initialState) {
+                LoopInfo<Object> info = ReentrantBlockIterator.processLoop(this, loop, initialState);
+                apply(loopMergeEffects.get(loop), loop);
+                return info.exitStates;
+            }
+        };
+        ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock(), new Object(), null);
+        return obsoleteNodes;
     }
 
     public Map<Invoke, Double> getHints() {
@@ -97,6 +137,9 @@
 
     @Override
     protected void processBlock(Block block, BlockState state) {
+        GraphEffectList effects = blockEffects.get(block);
+        tool.setEffects(effects);
+
         trace("\nBlock: %s (", block);
         List<ScheduledNode> nodeList = schedule.getBlockToNodesMap().get(block);
 
@@ -105,7 +148,7 @@
             boolean deleted;
             if (usages.isMarked(node) || node instanceof VirtualizableAllocation) {
                 trace("[[%s]] ", node);
-                deleted = processNode((ValueNode) node, lastFixedNode == null ? null : lastFixedNode.next(), state);
+                deleted = processNode((ValueNode) node, lastFixedNode == null ? null : lastFixedNode.next(), state, effects);
             } else {
                 trace("%s ", node);
                 deleted = false;
@@ -119,7 +162,6 @@
                         state.killReadCache(store.field());
 
                         if (cachedValue == store.value()) {
-                            effects.addCounterBefore("store elim", 1, false, lastFixedNode.next());
                             effects.deleteFixedNode(store);
                             changed = true;
                         } else {
@@ -130,7 +172,6 @@
                         ValueNode cachedValue = state.getReadCache(load.object(), load.field());
                         if (cachedValue != null) {
                             METRIC_LOADFIELD_ELIMINATED.increment();
-                            effects.addCounterBefore("load elim", 1, false, lastFixedNode.next());
                             effects.replaceAtUsages(load, cachedValue);
                             state.addScalarAlias(load, cachedValue);
                             changed = true;
@@ -154,7 +195,7 @@
         trace(")\n    end state: %s\n", state);
     }
 
-    private boolean processNode(final ValueNode node, FixedNode insertBefore, final BlockState state) {
+    private boolean processNode(final ValueNode node, FixedNode insertBefore, final BlockState state, final GraphEffectList effects) {
         tool.reset(state, node);
         if (node instanceof Virtualizable) {
             ((Virtualizable) node).virtualize(tool);
@@ -250,13 +291,13 @@
                     hints.put(invoke, 5d);
                 }
                 trace("replacing input %s at %s: %s", input, node, obj);
-                replaceWithMaterialized(input, node, insertBefore, state, obj, METRIC_MATERIALIZATIONS_UNHANDLED);
+                replaceWithMaterialized(input, node, insertBefore, state, obj, effects, METRIC_MATERIALIZATIONS_UNHANDLED);
             }
         }
         return false;
     }
 
-    private void ensureMaterialized(BlockState state, ObjectState obj, FixedNode materializeBefore, DebugMetric metric) {
+    private static void ensureMaterialized(BlockState state, ObjectState obj, FixedNode materializeBefore, GraphEffectList effects, DebugMetric metric) {
         assert obj != null;
         if (obj.getState() == EscapeState.Virtual) {
             metric.increment();
@@ -267,34 +308,204 @@
         assert !obj.isVirtual();
     }
 
-    private void replaceWithMaterialized(ValueNode value, Node usage, FixedNode materializeBefore, BlockState state, ObjectState obj, DebugMetric metric) {
-        ensureMaterialized(state, obj, materializeBefore, metric);
+    private static void replaceWithMaterialized(ValueNode value, Node usage, FixedNode materializeBefore, BlockState state, ObjectState obj, GraphEffectList effects, DebugMetric metric) {
+        ensureMaterialized(state, obj, materializeBefore, effects, metric);
         effects.replaceFirstInput(usage, value, obj.getMaterializedValue());
     }
 
     @Override
-    protected BlockState merge(MergeNode merge, List<BlockState> states) {
-        BlockState newState = BlockState.meetAliases(states);
+    protected BlockState merge(Block merge, List<BlockState> states) {
+        assert blockEffects.get(merge).isEmpty();
+        MergeProcessor processor = new MergeProcessor(merge, usages, blockEffects);
+        processor.merge(states);
+        blockEffects.get(merge).addAll(processor.mergeEffects);
+        blockEffects.get(merge).addAll(processor.afterMergeEffects);
+        return processor.newState;
+
+    }
+
+    @Override
+    protected BlockState cloneState(BlockState oldState) {
+        return oldState.cloneState();
+    }
+
+    @Override
+    protected List<BlockState> processLoop(Loop loop, BlockState initialState) {
+        BlockState loopEntryState = initialState;
+        BlockState lastMergedState = initialState;
+        MergeProcessor mergeProcessor = new MergeProcessor(loop.header, usages, blockEffects);
+        for (int iteration = 0; iteration < 10; iteration++) {
+            LoopInfo<BlockState> info = ReentrantBlockIterator.processLoop(this, loop, lastMergedState.cloneState());
+
+            List<BlockState> states = new ArrayList<>();
+            states.add(initialState);
+            states.addAll(info.endStates);
+            mergeProcessor.merge(states);
 
-        // Iterative processing:
-        // Merging the materialized/virtual state of virtual objects can lead to new
-        // materializations, which can
-        // lead to new materializations because of phis, and so on.
+            Debug.log("================== %s", loop.header);
+            Debug.log("%s", mergeProcessor.newState);
+            Debug.log("===== vs.");
+            Debug.log("%s", lastMergedState);
+
+            if (mergeProcessor.newState.equivalentTo(lastMergedState)) {
+                blockEffects.get(loop.header).insertAll(mergeProcessor.mergeEffects, 0);
+                loopMergeEffects.put(loop, mergeProcessor.afterMergeEffects);
+
+                assert info.exitStates.size() == loop.exits.size();
+                for (int i = 0; i < loop.exits.size(); i++) {
+                    BlockState exitState = info.exitStates.get(i);
+                    assert exitState != null : "no loop exit state at " + loop.exits.get(i) + " / " + loop.header;
+                    processLoopExit((LoopExitNode) loop.exits.get(i).getBeginNode(), loopEntryState, exitState, blockEffects.get(loop.exits.get(i)));
+                }
+
+                return info.exitStates;
+            } else {
+                lastMergedState = mergeProcessor.newState;
+                for (Block block : loop.blocks) {
+                    blockEffects.get(block).clear();
+                }
+            }
+        }
+        throw new GraalInternalError("too many iterations at %s", loop);
+    }
+
+    private static void processLoopExit(LoopExitNode exitNode, BlockState initialState, BlockState exitState, GraphEffectList effects) {
+        HashMap<VirtualObjectNode, ProxyNode> proxies = new HashMap<>();
 
-        boolean materialized;
-        do {
-            materialized = false;
-            // use a hash set to make the values distinct...
-            for (VirtualObjectNode object : newState.getVirtualObjects()) {
-                ObjectState resultState = newState.getObjectStateOptional(object);
-                if (resultState == null || resultState.isVirtual()) {
+        for (ProxyNode proxy : exitNode.proxies()) {
+            ObjectState obj = exitState.getObjectState(proxy.value());
+            if (obj != null) {
+                proxies.put(obj.virtual, proxy);
+            }
+        }
+        for (ObjectState obj : exitState.getStates()) {
+            ObjectState initialObj = initialState.getObjectStateOptional(obj.virtual);
+            if (obj.isVirtual()) {
+                for (int i = 0; i < obj.getEntries().length; i++) {
+                    ValueNode value = obj.getEntry(i);
+                    ObjectState valueObj = exitState.getObjectState(value);
+                    if (valueObj == null) {
+                        if (exitNode.loopBegin().isPhiAtMerge(value) || initialObj == null || !initialObj.isVirtual() || initialObj.getEntry(i) != value) {
+                            ProxyNode proxy = new ProxyNode(value, exitNode, PhiType.Value, null);
+                            obj.setEntry(i, proxy);
+                            effects.addFloatingNode(proxy, "virtualProxy");
+                        }
+                    }
+                }
+            } else {
+                if (initialObj == null || initialObj.isVirtual()) {
+                    ProxyNode proxy = proxies.get(obj.virtual);
+                    if (proxy == null) {
+                        proxy = new ProxyNode(obj.getMaterializedValue(), exitNode, PhiType.Value, null);
+                        effects.addFloatingNode(proxy, "proxy");
+                    } else {
+                        effects.replaceFirstInput(proxy, proxy.value(), obj.getMaterializedValue());
+                        // nothing to do - will be handled in processNode
+                    }
+                    obj.updateMaterializedValue(proxy);
+                } else {
+                    if (initialObj.getMaterializedValue() == obj.getMaterializedValue()) {
+                        Debug.log("materialized value changes within loop: %s vs. %s at %s", initialObj.getMaterializedValue(), obj.getMaterializedValue(), exitNode);
+                    }
+                }
+            }
+        }
+
+        for (Map.Entry<ReadCacheEntry, ValueNode> entry : exitState.getReadCache().entrySet()) {
+            if (initialState.getReadCache().get(entry.getKey()) != entry.getValue()) {
+                ProxyNode proxy = new ProxyNode(exitState.getReadCache(entry.getKey().object, entry.getKey().identity), exitNode, PhiType.Value, null);
+                effects.addFloatingNode(proxy, "readCacheProxy");
+                entry.setValue(proxy);
+            }
+        }
+    }
+
+    private static class MergeProcessor {
+
+        private final Block mergeBlock;
+        private final MergeNode merge;
+        private final NodeBitMap usages;
+        private final BlockMap<GraphEffectList> blockEffects;
+        private final GraphEffectList mergeEffects;
+        private final GraphEffectList afterMergeEffects;
+
+        private final HashMap<Object, PhiNode> materializedPhis = new HashMap<>();
+        private final IdentityHashMap<VirtualObjectNode, PhiNode[]> valuePhis = new IdentityHashMap<>();
+        private final IdentityHashMap<PhiNode, PhiNode[]> valueObjectMergePhis = new IdentityHashMap<>();
+        private final IdentityHashMap<PhiNode, VirtualObjectNode> valueObjectVirtuals = new IdentityHashMap<>();
+        private BlockState newState;
+
+        public MergeProcessor(Block mergeBlock, NodeBitMap usages, BlockMap<GraphEffectList> blockEffects) {
+            this.usages = usages;
+            this.mergeBlock = mergeBlock;
+            this.blockEffects = blockEffects;
+            this.merge = (MergeNode) mergeBlock.getBeginNode();
+            this.mergeEffects = new GraphEffectList();
+            this.afterMergeEffects = new GraphEffectList();
+        }
+
+        private <T> PhiNode getCachedPhi(T virtual, Kind kind) {
+            PhiNode result = materializedPhis.get(virtual);
+            if (result == null) {
+                result = new PhiNode(kind, merge);
+                materializedPhis.put(virtual, result);
+            }
+            return result;
+        }
+
+        private PhiNode[] getValuePhis(VirtualObjectNode virtual) {
+            PhiNode[] result = valuePhis.get(virtual);
+            if (result == null) {
+                result = new PhiNode[virtual.entryCount()];
+                valuePhis.put(virtual, result);
+            }
+            return result;
+        }
+
+        private PhiNode[] getValueObjectMergePhis(PhiNode phi, int entryCount) {
+            PhiNode[] result = valueObjectMergePhis.get(phi);
+            if (result == null) {
+                result = new PhiNode[entryCount];
+                valueObjectMergePhis.put(phi, result);
+            }
+            return result;
+        }
+
+        private VirtualObjectNode getValueObjectVirtual(PhiNode phi, VirtualObjectNode virtual) {
+            VirtualObjectNode result = valueObjectVirtuals.get(phi);
+            if (result == null) {
+                result = virtual.duplicate();
+                valueObjectVirtuals.put(phi, result);
+            }
+            return result;
+        }
+
+        private void merge(List<BlockState> states) {
+            newState = BlockState.meetAliases(states);
+
+            /*
+             * Iterative processing: Merging the materialized/virtual state of virtual objects can
+             * lead to new materializations, which can lead to new materializations because of phis,
+             * and so on.
+             */
+
+            HashSet<VirtualObjectNode> virtualObjects = new HashSet<>(newState.getVirtualObjects());
+            boolean materialized;
+            do {
+                mergeEffects.clear();
+                afterMergeEffects.clear();
+                materialized = false;
+                for (VirtualObjectNode object : virtualObjects) {
+                    ObjectState[] objStates = new ObjectState[states.size()];
+                    for (int i = 0; i < states.size(); i++) {
+                        objStates[i] = states.get(i).getObjectState(object);
+                    }
                     int virtual = 0;
-                    ObjectState startObj = states.get(0).getObjectState(object);
+                    ObjectState startObj = objStates[0];
                     int lockCount = startObj.getLockCount();
                     boolean locksMatch = true;
                     ValueNode singleValue = startObj.isVirtual() ? null : startObj.getMaterializedValue();
-                    for (BlockState state : states) {
-                        ObjectState obj = state.getObjectState(object);
+                    for (ObjectState obj : objStates) {
                         if (obj.isVirtual()) {
                             virtual++;
                             singleValue = null;
@@ -310,14 +521,15 @@
 
                     if (virtual < states.size()) {
                         if (singleValue == null) {
-                            PhiNode materializedValuePhi = new PhiNode(Kind.Object, merge);
-                            effects.addFloatingNode(materializedValuePhi);
+                            PhiNode materializedValuePhi = getCachedPhi(object, Kind.Object);
+                            mergeEffects.addFloatingNode(materializedValuePhi, "materializedPhi");
                             for (int i = 0; i < states.size(); i++) {
                                 BlockState state = states.get(i);
-                                ObjectState obj = state.getObjectState(object);
+                                ObjectState obj = objStates[i];
                                 materialized |= obj.isVirtual();
-                                ensureMaterialized(state, obj, merge.forwardEndAt(i), METRIC_MATERIALIZATIONS_MERGE);
-                                effects.addPhiInput(materializedValuePhi, obj.getMaterializedValue());
+                                Block predecessor = mergeBlock.getPredecessors().get(i);
+                                ensureMaterialized(state, obj, predecessor.getEndNode(), blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_MERGE);
+                                afterMergeEffects.addPhiInput(materializedValuePhi, obj.getMaterializedValue());
                             }
                             newState.addObject(object, new ObjectState(object, materializedValuePhi, EscapeState.Global, lockCount));
                         } else {
@@ -326,428 +538,188 @@
                     } else {
                         assert virtual == states.size();
                         ValueNode[] values = startObj.getEntries().clone();
-                        PhiNode[] phis = new PhiNode[values.length];
-                        int mismatch = 0;
-                        for (int i = 1; i < states.size(); i++) {
-                            BlockState state = states.get(i);
-                            ValueNode[] fields = state.getObjectState(object).getEntries();
-                            for (int index = 0; index < values.length; index++) {
+                        PhiNode[] phis = getValuePhis(object);
+                        for (int index = 0; index < values.length; index++) {
+                            for (int i = 1; i < states.size(); i++) {
+                                ValueNode[] fields = objStates[i].getEntries();
                                 if (phis[index] == null && values[index] != fields[index]) {
-                                    mismatch++;
                                     phis[index] = new PhiNode(values[index].kind(), merge);
-                                    effects.addFloatingNode(phis[index]);
                                 }
                             }
                         }
-                        if (mismatch > 0) {
-                            for (int i = 0; i < states.size(); i++) {
-                                BlockState state = states.get(i);
-                                ValueNode[] fields = state.getObjectState(object).getEntries();
-                                for (int index = 0; index < values.length; index++) {
-                                    if (phis[index] != null) {
-                                        ObjectState obj = state.getObjectState(fields[index]);
-                                        if (obj != null) {
-                                            materialized |= obj.isVirtual();
-                                            ensureMaterialized(state, obj, merge.forwardEndAt(i), METRIC_MATERIALIZATIONS_MERGE);
-                                            fields[index] = obj.getMaterializedValue();
-                                        }
-                                        effects.addPhiInput(phis[index], fields[index]);
+                        outer: for (int index = 0; index < values.length; index++) {
+                            if (phis[index] != null) {
+                                mergeEffects.addFloatingNode(phis[index], "virtualMergePhi");
+                                for (int i = 0; i < states.size(); i++) {
+                                    if (!objStates[i].isVirtual()) {
+                                        break outer;
                                     }
+                                    ValueNode[] fields = objStates[i].getEntries();
+                                    ObjectState obj = states.get(i).getObjectState(fields[index]);
+                                    if (obj != null) {
+                                        materialized |= obj.isVirtual();
+                                        Block predecessor = mergeBlock.getPredecessors().get(i);
+                                        ensureMaterialized(states.get(i), obj, predecessor.getEndNode(), blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_MERGE);
+                                        fields[index] = obj.getMaterializedValue();
+                                    }
+                                    afterMergeEffects.addPhiInput(phis[index], fields[index]);
                                 }
-                            }
-                            for (int index = 0; index < values.length; index++) {
-                                if (phis[index] != null) {
-                                    values[index] = phis[index];
-                                }
+                                values[index] = phis[index];
                             }
                         }
                         newState.addObject(object, new ObjectState(object, values, EscapeState.Virtual, lockCount));
                     }
                 }
-            }
-
-            for (PhiNode phi : merge.phis()) {
-                if (usages.isMarked(phi) && phi.type() == PhiType.Value) {
-                    materialized |= processPhi(newState, merge, phi, states);
-                }
-            }
-        } while (materialized);
-
-        newState.mergeReadCache(states, merge, effects);
-
-        return newState;
-    }
 
-    private boolean processPhi(BlockState newState, MergeNode merge, PhiNode phi, List<BlockState> states) {
-        assert states.size() == phi.valueCount();
-        int virtualInputs = 0;
-        boolean materialized = false;
-        VirtualObjectNode sameObject = null;
-        ResolvedJavaType sameType = null;
-        int sameEntryCount = -1;
-        for (int i = 0; i < phi.valueCount(); i++) {
-            ValueNode value = phi.valueAt(i);
-            ObjectState obj = states.get(i).getObjectState(value);
-            if (obj != null) {
-                if (obj.isVirtual()) {
-                    virtualInputs++;
-                    if (i == 0) {
-                        sameObject = obj.virtual;
-                        sameType = obj.virtual.type();
-                        sameEntryCount = obj.virtual.entryCount();
-                    } else {
-                        if (sameObject != obj.virtual) {
-                            sameObject = null;
-                        }
-                        if (sameType != obj.virtual.type()) {
-                            sameType = null;
-                        }
-                        if (sameEntryCount != obj.virtual.entryCount()) {
-                            sameEntryCount = -1;
-                        }
+                for (PhiNode phi : merge.phis()) {
+                    if (usages.isMarked(phi) && phi.type() == PhiType.Value) {
+                        materialized |= processPhi(phi, states);
                     }
-                } else {
-                    effects.setPhiInput(phi, i, obj.getMaterializedValue());
                 }
-            }
-        }
-        boolean materialize = false;
-        if (virtualInputs == 0) {
-            // nothing to do...
-        } else if (virtualInputs == phi.valueCount()) {
-            if (sameObject != null) {
-                newState.addAndMarkAlias(sameObject, phi, usages);
-            } else if (sameType != null && sameEntryCount != -1) {
-                materialize = true;
-                // throw new GraalInternalError("merge required for %s", sameType);
-            } else {
-                materialize = true;
-            }
-        } else {
-            materialize = true;
+            } while (materialized);
+
+            mergeReadCache(states);
         }
 
-        if (materialize) {
+        private boolean processPhi(PhiNode phi, List<BlockState> states) {
+            assert states.size() == phi.valueCount();
+            int virtualInputs = 0;
+            boolean materialized = false;
+            VirtualObjectNode sameObject = null;
+            ResolvedJavaType sameType = null;
+            int sameEntryCount = -1;
+            boolean hasIdentity = false;
             for (int i = 0; i < phi.valueCount(); i++) {
                 ValueNode value = phi.valueAt(i);
                 ObjectState obj = states.get(i).getObjectState(value);
                 if (obj != null) {
-                    materialized |= obj.isVirtual();
-                    replaceWithMaterialized(value, phi, merge.forwardEndAt(i), states.get(i), obj, METRIC_MATERIALIZATIONS_PHI);
-                }
-            }
-        }
-        return materialized;
-    }
-
-    @Override
-    protected BlockState cloneState(BlockState oldState) {
-        return oldState.cloneState();
-    }
-
-    @Override
-    protected List<BlockState> processLoop(Loop loop, BlockState initialState) {
-        GraphEffectList successEffects = new GraphEffectList();
-        HashSet<PhiDesc> phis = new HashSet<>();
-        for (int iteration = 0; iteration < 10; iteration++) {
-            BlockState state = initialState.cloneState();
-            int checkpoint = effects.checkpoint();
-
-            for (PhiDesc desc : phis) {
-                ObjectState obj = state.getObjectState(desc.virtualObject);
-                if (obj.isVirtual()) {
-                    ValueNode value = obj.getEntry(desc.fieldIndex);
-                    ObjectState valueObj = state.getObjectState(value);
-                    if (valueObj != null) {
-                        assert !valueObj.isVirtual();
-                        value = valueObj.getMaterializedValue();
-                    }
-
-                    PhiNode phiNode = new PhiNode(value.kind(), loop.loopBegin());
-                    effects.addFloatingNode(phiNode);
-                    effects.addPhiInput(phiNode, value);
-                    obj.setEntry(desc.fieldIndex, phiNode);
-                }
-            }
-
-            for (PhiNode phi : loop.loopBegin().phis()) {
-                if (usages.isMarked(phi) && phi.type() == PhiType.Value) {
-                    ObjectState initialObj = initialState.getObjectState(phi.valueAt(0));
-                    if (initialObj != null) {
-                        if (initialObj.isVirtual()) {
-                            state.addAndMarkAlias(initialObj.virtual, phi, usages);
+                    if (obj.isVirtual()) {
+                        virtualInputs++;
+                        if (i == 0) {
+                            sameObject = obj.virtual;
+                            sameType = obj.virtual.type();
+                            sameEntryCount = obj.virtual.entryCount();
                         } else {
-                            successEffects.setPhiInput(phi, 0, initialObj.getMaterializedValue());
+                            if (sameObject != obj.virtual) {
+                                sameObject = null;
+                            }
+                            if (sameType != obj.virtual.type()) {
+                                sameType = null;
+                            }
+                            if (sameEntryCount != obj.virtual.entryCount()) {
+                                sameEntryCount = -1;
+                            }
+                            hasIdentity |= obj.virtual.hasIdentity();
                         }
+                    } else {
+                        afterMergeEffects.setPhiInput(phi, i, obj.getMaterializedValue());
                     }
                 }
             }
-
-            effects.incLevel();
-            LoopInfo<BlockState> info = ReentrantBlockIterator.processLoop(this, loop, state.cloneState());
-
-            List<BlockState> loopEndStates = info.endStates;
-            List<Block> predecessors = loop.header.getPredecessors();
-            HashSet<VirtualObjectNode> additionalMaterializations = new HashSet<>();
-            HashSet<ReadCacheEntry> additionalKilledReads = new HashSet<>();
-            int oldPhiCount = phis.size();
-            for (int i = 1; i < predecessors.size(); i++) {
-                processLoopEnd(loop.loopBegin(), (LoopEndNode) predecessors.get(i).getEndNode(), state, loopEndStates.get(i - 1), successEffects, additionalMaterializations, additionalKilledReads,
-                                phis);
-            }
-            if (additionalMaterializations.isEmpty() && additionalKilledReads.isEmpty() && oldPhiCount == phis.size()) {
-                effects.addAll(successEffects);
+            boolean materialize = false;
+            if (virtualInputs == 0) {
+                // nothing to do...
+            } else if (virtualInputs == phi.valueCount()) {
+                if (sameObject != null) {
+                    newState.addAndMarkAlias(sameObject, phi, usages);
+                } else if (sameType != null && sameEntryCount != -1) {
+                    if (!hasIdentity) {
+                        VirtualObjectNode virtual = getValueObjectVirtual(phi, states.get(0).getObjectState(phi.valueAt(0)).virtual);
 
-                assert info.exitStates.size() == loop.exits.size();
-                for (int i = 0; i < loop.exits.size(); i++) {
-                    BlockState exitState = info.exitStates.get(i);
-                    assert exitState != null : "no loop exit state at " + loop.exits.get(i) + " / " + loop.header;
-                    processLoopExit((LoopExitNode) loop.exits.get(i).getBeginNode(), state, exitState);
+                        PhiNode[] phis = getValueObjectMergePhis(phi, virtual.entryCount());
+                        for (int i = 0; i < virtual.entryCount(); i++) {
+                            assert virtual.entryKind(i) != Kind.Object;
+                            if (phis[i] == null) {
+                                phis[i] = new PhiNode(virtual.entryKind(i), merge);
+                            }
+                            mergeEffects.addFloatingNode(phis[i], "valueObjectPhi");
+                            for (int i2 = 0; i2 < phi.valueCount(); i2++) {
+                                afterMergeEffects.addPhiInput(phis[i], states.get(i2).getObjectState(phi.valueAt(i2)).getEntry(i));
+                            }
+                        }
+                        mergeEffects.addFloatingNode(virtual, "valueObjectNode");
+                        newState.addObject(virtual, new ObjectState(virtual, Arrays.copyOf(phis, phis.length, ValueNode[].class), EscapeState.Virtual, 0));
+                        newState.addAndMarkAlias(virtual, virtual, usages);
+                        newState.addAndMarkAlias(virtual, phi, usages);
+                    } else {
+                        materialize = true;
+                    }
+                } else {
+                    materialize = true;
                 }
-
-                effects.decLevel();
-                return info.exitStates;
             } else {
-                successEffects.clear();
-                effects.backtrack(checkpoint);
-                effects.decLevel();
-                for (VirtualObjectNode virtualObject : additionalMaterializations) {
-                    ObjectState obj = initialState.getObjectState(virtualObject);
-                    if (obj.isVirtual()) {
-                        METRIC_MATERIALIZATIONS_LOOP_REITERATION.increment();
-                        initialState.materializeBefore(loop.loopBegin().forwardEnd(), virtualObject, EscapeState.Global, effects);
-                    } else {
-                        assert obj.getState() == EscapeState.Global;
+                materialize = true;
+            }
+
+            if (materialize) {
+                for (int i = 0; i < phi.valueCount(); i++) {
+                    ValueNode value = phi.valueAt(i);
+                    ObjectState obj = states.get(i).getObjectState(value);
+                    if (obj != null) {
+                        materialized |= obj.isVirtual();
+                        Block predecessor = mergeBlock.getPredecessors().get(i);
+                        replaceWithMaterialized(value, phi, predecessor.getEndNode(), states.get(i), obj, blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_PHI);
                     }
                 }
-                for (ReadCacheEntry entry : additionalKilledReads) {
-                    initialState.getReadCache().remove(entry);
+            }
+            return materialized;
+        }
+
+        private void mergeReadCache(List<BlockState> states) {
+            for (Map.Entry<ReadCacheEntry, ValueNode> entry : states.get(0).readCache.entrySet()) {
+                ReadCacheEntry key = entry.getKey();
+                ValueNode value = entry.getValue();
+                boolean phi = false;
+                for (int i = 1; i < states.size(); i++) {
+                    ValueNode otherValue = states.get(i).readCache.get(key);
+                    if (otherValue == null) {
+                        value = null;
+                        phi = false;
+                        break;
+                    }
+                    if (!phi && otherValue != value) {
+                        phi = true;
+                    }
+                }
+                if (phi) {
+                    PhiNode phiNode = getCachedPhi(entry, value.kind());
+                    mergeEffects.addFloatingNode(phiNode, "mergeReadCache");
+                    for (int i = 0; i < states.size(); i++) {
+                        afterMergeEffects.addPhiInput(phiNode, states.get(i).getReadCache(key.object, key.identity));
+                    }
+                    newState.readCache.put(key, phiNode);
+                } else if (value != null) {
+                    newState.readCache.put(key, value);
+                }
+            }
+            for (PhiNode phi : merge.phis()) {
+                if (phi.kind() == Kind.Object) {
+                    for (Map.Entry<ReadCacheEntry, ValueNode> entry : states.get(0).readCache.entrySet()) {
+                        if (entry.getKey().object == phi.valueAt(0)) {
+                            mergeReadCachePhi(phi, entry.getKey().identity, states);
+                        }
+                    }
+
                 }
             }
         }
 
-        throw new GraalInternalError("too many iterations at %s", loop);
-    }
-
-    private void processLoopExit(LoopExitNode exitNode, BlockState initialState, BlockState exitState) {
-        HashMap<VirtualObjectNode, ProxyNode> proxies = new HashMap<>();
-
-        for (ProxyNode proxy : exitNode.proxies()) {
-            ObjectState obj = exitState.getObjectState(proxy.value());
-            if (obj != null) {
-                proxies.put(obj.virtual, proxy);
-            }
-        }
-        for (ObjectState obj : exitState.getStates()) {
-            ObjectState initialObj = initialState.getObjectStateOptional(obj.virtual);
-            if (obj.isVirtual()) {
-                for (int i = 0; i < obj.getEntries().length; i++) {
-                    ValueNode value = obj.getEntry(i);
-                    ObjectState valueObj = exitState.getObjectState(value);
-                    if (valueObj == null) {
-                        if ((value instanceof PhiNode && ((PhiNode) value).merge() == exitNode.loopBegin()) || initialObj == null || !initialObj.isVirtual() || initialObj.getEntry(i) != value) {
-                            ProxyNode proxy = new ProxyNode(value, exitNode, PhiType.Value, null);
-                            obj.setEntry(i, proxy);
-                            effects.addFloatingNode(proxy);
-                        }
-                    }
+        private void mergeReadCachePhi(PhiNode phi, Object identity, List<BlockState> states) {
+            ValueNode[] values = new ValueNode[phi.valueCount()];
+            for (int i = 0; i < phi.valueCount(); i++) {
+                ValueNode value = states.get(i).getReadCache(phi.valueAt(i), identity);
+                if (value == null) {
+                    return;
                 }
-            } else {
-                if (initialObj == null || initialObj.isVirtual()) {
-                    ProxyNode proxy = proxies.get(obj.virtual);
-                    if (proxy == null) {
-                        proxy = new ProxyNode(obj.getMaterializedValue(), exitNode, PhiType.Value, null);
-                        effects.addFloatingNode(proxy);
-                    } else {
-                        effects.replaceFirstInput(proxy, proxy.value(), obj.getMaterializedValue());
-                        // nothing to do - will be handled in processNode
-                    }
-                    obj.updateMaterializedValue(proxy);
-                } else {
-                    assert initialObj.getMaterializedValue() == obj.getMaterializedValue() : "materialized value is not allowed to change within loops: " + initialObj.getMaterializedValue() +
-                                    " vs. " + obj.getMaterializedValue() + " at " + exitNode;
-                }
-            }
-        }
-
-        for (Map.Entry<ReadCacheEntry, ValueNode> entry : exitState.getReadCache().entrySet()) {
-            if (initialState.getReadCache().get(entry.getKey()) != entry.getValue()) {
-                ProxyNode proxy = new ProxyNode(exitState.getReadCache(entry.getKey().object, entry.getKey().identity), exitNode, PhiType.Value, null);
-                effects.addFloatingNode(proxy);
-                entry.setValue(proxy);
+                values[i] = value;
             }
-        }
-    }
-
-    private final class PhiDesc {
-
-        public final VirtualObjectNode virtualObject;
-        public final int fieldIndex;
-
-        public PhiDesc(VirtualObjectNode virtualObject, int fieldIndex) {
-            this.virtualObject = virtualObject;
-            this.fieldIndex = fieldIndex;
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = fieldIndex;
-            result = prime * result + ((virtualObject == null) ? 0 : virtualObject.hashCode());
-            return result;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj == null || getClass() != obj.getClass()) {
-                return false;
-            }
-            PhiDesc other = (PhiDesc) obj;
-            return virtualObject == other.virtualObject && fieldIndex == other.fieldIndex;
-        }
-    }
-
-    private void processLoopEnd(LoopBeginNode loopBegin, LoopEndNode loopEnd, BlockState initialState, BlockState loopEndState, GraphEffectList successEffects,
-                    Set<VirtualObjectNode> additionalMaterializations, HashSet<ReadCacheEntry> additionalKilledReads, HashSet<PhiDesc> phis) {
-        assert loopEnd.loopBegin() == loopBegin;
-        boolean materialized;
-        do {
-            materialized = false;
-            for (ObjectState state : initialState.getStates()) {
-                ObjectState endState = loopEndState.getObjectState(state.virtual);
-                if (state.isVirtual()) {
-                    if (endState.isVirtual()) {
-                        assert state.getEntries().length == endState.getEntries().length;
-                        for (int i = 0; endState.isVirtual() && i < state.getEntries().length; i++) {
-                            ValueNode value = state.getEntry(i);
-                            ValueNode endValue = endState.getEntry(i);
-                            ObjectState valueObj = initialState.getObjectState(value);
-                            ObjectState endValueObj = loopEndState.getObjectState(endValue);
 
-                            if (valueObj != null) {
-                                if (valueObj.isVirtual()) {
-                                    if (endValueObj == null || !endValueObj.isVirtual() || valueObj.virtual != endValueObj.virtual) {
-                                        additionalMaterializations.add(valueObj.virtual);
-                                    } else {
-                                        // endValue is also virtual and refers to the same virtual
-                                        // object, so we're
-                                        // good.
-                                    }
-                                }
-                            } else {
-                                if (value instanceof PhiNode && ((PhiNode) value).merge() == loopBegin) {
-                                    if (endValueObj != null) {
-                                        if (endValueObj.isVirtual()) {
-                                            METRIC_MATERIALIZATIONS_LOOP_END.increment();
-                                            loopEndState.materializeBefore(loopEnd, endValueObj.virtual, EscapeState.Global, successEffects);
-                                            materialized = true;
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                    } else {
-                        additionalMaterializations.add(state.virtual);
-                    }
-                }
-            }
-            for (PhiNode phi : loopBegin.phis()) {
-                if (usages.isMarked(phi) && phi.type() == PhiType.Value) {
-                    ObjectState initialObj = initialState.getObjectState(phi.valueAt(0));
-                    boolean initialMaterialized = initialObj == null || !initialObj.isVirtual();
-
-                    ObjectState loopEndObj = loopEndState.getObjectState(phi.valueAt(loopEnd));
-                    if (loopEndObj == null || !loopEndObj.isVirtual()) {
-                        if (loopEndObj != null) {
-                            successEffects.setPhiInput(phi, loopBegin.phiPredecessorIndex(loopEnd), loopEndObj.getMaterializedValue());
-                        }
-                        if (!initialMaterialized) {
-                            additionalMaterializations.add(initialObj.virtual);
-                        }
-                    } else {
-                        if (initialMaterialized) {
-                            loopEndState.materializeBefore(loopEnd, loopEndObj.virtual, EscapeState.Global, successEffects);
-                            materialized = true;
-                        } else {
-                            if (loopEndObj.virtual != initialObj.virtual) {
-                                additionalMaterializations.add(initialObj.virtual);
-                            }
-                        }
-                    }
-                }
+            PhiNode phiNode = getCachedPhi(new ReadCacheEntry(identity, phi), values[0].kind());
+            mergeEffects.addFloatingNode(phiNode, "mergeReadCachePhi");
+            for (int i = 0; i < values.length; i++) {
+                afterMergeEffects.addPhiInput(phiNode, values[i]);
             }
-        } while (materialized);
-
-        for (ObjectState state : initialState.getStates()) {
-            ObjectState endState = loopEndState.getObjectState(state.virtual);
-            if (state.isVirtual()) {
-                if (endState.isVirtual()) {
-                    assert state.getEntries().length == endState.getEntries().length;
-                    for (int i = 0; i < state.getEntries().length; i++) {
-                        ValueNode value = state.getEntry(i);
-                        ValueNode endValue = endState.getEntry(i);
-                        ObjectState valueObj = initialState.getObjectState(value);
-                        ObjectState endValueObj = loopEndState.getObjectState(endValue);
-
-                        if (valueObj != null) {
-                            if (valueObj.isVirtual()) {
-                                if (endValueObj == null || !endValueObj.isVirtual() || valueObj.virtual != endValueObj.virtual) {
-                                    assert !additionalMaterializations.isEmpty();
-                                } else {
-                                    // endValue is also virtual and refers to the same virtual
-                                    // object, so we're
-                                    // good.
-                                }
-                            } else {
-                                if ((endValueObj != null && endValueObj.getMaterializedValue() != valueObj.getMaterializedValue()) ||
-                                                (endValueObj == null && valueObj.getMaterializedValue() != endValue)) {
-                                    phis.add(new PhiDesc(state.virtual, i));
-                                } else {
-                                    // either endValue has the same materialized value as value or
-                                    // endValue is the
-                                    // same as the materialized value, so we're good.
-                                }
-                            }
-                        } else {
-                            if (value instanceof PhiNode && ((PhiNode) value).merge() == loopBegin) {
-                                if (endValueObj != null) {
-                                    if (endValueObj.isVirtual()) {
-                                        assert !additionalMaterializations.isEmpty();
-                                    }
-                                    successEffects.addPhiInput((PhiNode) value, endValueObj.getMaterializedValue());
-                                } else {
-                                    successEffects.addPhiInput((PhiNode) value, endValue);
-                                }
-                            } else if (value != endValue) {
-                                phis.add(new PhiDesc(state.virtual, i));
-                            }
-                        }
-                    }
-                } else {
-                    // endState.materializedValue != null
-                    assert !additionalMaterializations.isEmpty();
-                }
-            } else {
-                // state.materializedValue != null
-                if (endState.isVirtual()) {
-                    // throw new GraalInternalError("un-materialized object state at %s", loopEnd);
-                } else {
-                    if (state.getMaterializedValue() != endState.getMaterializedValue()) {
-                        // throw new
-                        // GraalInternalError("changed materialized value during loop: %s vs %s",
-                        // state.materializedValue, endState.materializedValue);
-                    }
-                }
-            }
-        }
-
-        for (Map.Entry<ReadCacheEntry, ValueNode> entry : initialState.getReadCache().entrySet()) {
-            if (loopEndState.getReadCache().get(entry.getKey()) != entry.getValue()) {
-                additionalKilledReads.add(entry.getKey());
-            }
+            newState.readCache.put(new ReadCacheEntry(identity, phi), phiNode);
         }
     }
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java	Mon Apr 15 08:49:14 2013 +0200
@@ -36,13 +36,12 @@
 
 class VirtualizerToolImpl implements VirtualizerTool {
 
-    private final GraphEffectList effects;
     private final NodeBitMap usages;
     private final MetaAccessProvider metaAccess;
     private final Assumptions assumptions;
+    private GraphEffectList effects;
 
-    VirtualizerToolImpl(GraphEffectList effects, NodeBitMap usages, MetaAccessProvider metaAccess, Assumptions assumptions) {
-        this.effects = effects;
+    VirtualizerToolImpl(NodeBitMap usages, MetaAccessProvider metaAccess, Assumptions assumptions) {
         this.usages = usages;
         this.metaAccess = metaAccess;
         this.assumptions = assumptions;
@@ -52,7 +51,6 @@
     private boolean customAction;
     private BlockState state;
     private ValueNode current;
-    private int newVirtualObjectCount = 0;
 
     @Override
     public MetaAccessProvider getMetaAccessProvider() {
@@ -64,6 +62,10 @@
         return assumptions;
     }
 
+    public void setEffects(GraphEffectList effects) {
+        this.effects = effects;
+    }
+
     public void reset(BlockState newState, ValueNode newCurrent) {
         deleted = false;
         customAction = false;
@@ -79,10 +81,6 @@
         return customAction;
     }
 
-    public int getNewVirtualObjectCount() {
-        return newVirtualObjectCount;
-    }
-
     @Override
     public State getObjectState(ValueNode value) {
         return state.getObjectState(value);
@@ -155,7 +153,7 @@
         if (virtualObject.isAlive()) {
             state.addAndMarkAlias(virtualObject, virtualObject, usages);
         } else {
-            effects.addFloatingNode(virtualObject);
+            effects.addFloatingNode(virtualObject, "newVirtualObject");
         }
         for (int i = 0; i < entryState.length; i++) {
             entryState[i] = state.getScalarAlias(entryState[i]);
@@ -163,7 +161,6 @@
         state.addObject(virtualObject, new ObjectState(virtualObject, entryState, EscapeState.Virtual, lockCount));
         state.addAndMarkAlias(virtualObject, virtualObject, usages);
         PartialEscapeClosure.METRIC_ALLOCATION_REMOVED.increment();
-        newVirtualObjectCount++;
     }
 
     @Override
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Mon Apr 15 08:49:14 2013 +0200
@@ -29,6 +29,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.extended.WriteNode.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
@@ -183,7 +184,7 @@
 
                     case TO_OBJECT:
                         assert arguments.size() == 1;
-                        replace(invoke, graph.unique(new UnsafeCastNode(arguments.get(0), invoke.node().stamp())));
+                        replace(invoke, graph.unique(new UnsafeCastNode(arguments.get(0), invoke.asNode().stamp())));
                         break;
 
                     default:
@@ -227,7 +228,7 @@
             Constructor<? extends ValueNode> constructor = nodeClass.getConstructor(Kind.class, ValueNode.class, ValueNode.class);
             ValueNode result = graph.add(constructor.newInstance(wordKind, left, right));
             if (result instanceof FixedWithNextNode) {
-                graph.addBeforeFixed(invoke.node(), (FixedWithNextNode) result);
+                graph.addBeforeFixed(invoke.asNode(), (FixedWithNextNode) result);
             }
             return result;
         } catch (Throwable ex) {
@@ -267,28 +268,28 @@
 
     private static ValueNode readOp(StructuredGraph graph, ValueNode base, ValueNode offset, Invoke invoke, Kind readKind, Object locationIdentity) {
         IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, readKind, 0, offset, graph, 1);
-        ReadNode read = graph.add(new ReadNode(base, location, invoke.node().stamp()));
-        graph.addBeforeFixed(invoke.node(), read);
+        ReadNode read = graph.add(new ReadNode(base, location, invoke.asNode().stamp()));
+        graph.addBeforeFixed(invoke.asNode(), read);
         // The read must not float outside its block otherwise it may float above an explicit zero
         // check on its base address
-        read.dependencies().add(BeginNode.prevBegin(invoke.node()));
+        read.dependencies().add(BeginNode.prevBegin(invoke.asNode()));
         return read;
     }
 
     private static ValueNode writeOp(StructuredGraph graph, ValueNode base, ValueNode offset, ValueNode value, Invoke invoke, Kind writeKind, Object locationIdentity) {
         IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, writeKind, 0, offset, graph, 1);
-        WriteNode write = graph.add(new WriteNode(base, value, location));
+        WriteNode write = graph.add(new WriteNode(base, value, location, WriteBarrierType.NONE));
         write.setStateAfter(invoke.stateAfter());
-        graph.addBeforeFixed(invoke.node(), write);
+        graph.addBeforeFixed(invoke.asNode(), write);
         return write;
     }
 
     private static void replace(Invoke invoke, ValueNode value) {
         FixedNode next = invoke.next();
         invoke.setNext(null);
-        invoke.node().replaceAtPredecessor(next);
-        invoke.node().replaceAtUsages(value);
-        GraphUtil.killCFG(invoke.node());
+        invoke.asNode().replaceAtPredecessor(next);
+        invoke.asNode().replaceAtUsages(value);
+        GraphUtil.killCFG(invoke.asNode());
     }
 
     public boolean isWord(ValueNode node) {
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Mon Apr 15 08:49:14 2013 +0200
@@ -80,9 +80,9 @@
                             ValueNode receiver = arguments.get(argc);
                             if (receiver == node && isWord(node)) {
                                 ResolvedJavaMethod resolvedMethod = wordAccess.getWordImplType().resolveMethod(method);
-                                verify(resolvedMethod != null, node, invoke.node(), "cannot resolve method on Word class: " + MetaUtil.format("%H.%n(%P) %r", method));
+                                verify(resolvedMethod != null, node, invoke.asNode(), "cannot resolve method on Word class: " + MetaUtil.format("%H.%n(%P) %r", method));
                                 Operation operation = resolvedMethod.getAnnotation(Word.Operation.class);
-                                verify(operation != null, node, invoke.node(), "cannot dispatch on word value to non @Operation annotated method " + resolvedMethod);
+                                verify(operation != null, node, invoke.asNode(), "cannot dispatch on word value to non @Operation annotated method " + resolvedMethod);
                             }
                             argc++;
                         }
@@ -91,7 +91,7 @@
                             ValueNode argument = arguments.get(argc);
                             if (argument == node) {
                                 ResolvedJavaType type = (ResolvedJavaType) signature.getParameterType(i, method.getDeclaringClass());
-                                verify(isWord(type) == isWord(argument), node, invoke.node(), "cannot pass word value to non-word parameter " + i + " or vice-versa");
+                                verify(isWord(type) == isWord(argument), node, invoke.asNode(), "cannot pass word value to non-word parameter " + i + " or vice-versa");
                             }
                             argc++;
                         }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java	Mon Apr 15 08:49:14 2013 +0200
@@ -61,7 +61,7 @@
 
             dom = db.newDocument();
         } catch (ParserConfigurationException ex) {
-            System.out.println("Error while trying to instantiate DocumentBuilder " + ex);
+            throw new RuntimeException(ex);
         }
 
         graphDocument = dom.createElement("graphDocument");
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElement.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElement.java	Mon Apr 15 08:49:14 2013 +0200
@@ -103,19 +103,29 @@
         return annotations;
     }
 
-    /* Support JDK8 langtools. */
-    @SuppressWarnings("unused")
+    /**
+     * Support JDK8 langtools.
+     * 
+     * @param annotationType
+     */
     public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) {
         throw new UnsupportedOperationException();
     }
 
-    /* Support for some JDK8 builds. (remove after jdk8 is released) */
-    @SuppressWarnings("unused")
+    /**
+     * Support for some JDK8 builds. (remove after jdk8 is released)
+     * 
+     * @param annotationType
+     */
     public <A extends Annotation> A[] getAnnotations(Class<A> annotationType) {
         throw new UnsupportedOperationException();
     }
 
-    @Override
+    /**
+     * Support for some JDK8 builds. (remove after jdk8 is released)
+     * 
+     * @param annotationType
+     */
     public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
         throw new UnsupportedOperationException();
     }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java	Mon Apr 15 08:49:14 2013 +0200
@@ -225,4 +225,7 @@
         return copy;
     }
 
+    public TypeMirror getReceiverType() {
+        throw new UnsupportedOperationException();
+    }
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeMirror.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeMirror.java	Mon Apr 15 08:49:14 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.codegen.processor.ast;
 
+import java.lang.annotation.*;
 import java.util.*;
 
 import javax.lang.model.element.*;
@@ -92,4 +93,21 @@
 
     }
 
+    public List<? extends AnnotationMirror> getAnnotationMirrors() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @param annotationType
+     */
+    public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @param annotationType
+     */
+    public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) {
+        throw new UnsupportedOperationException();
+    }
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Mon Apr 15 08:49:14 2013 +0200
@@ -62,7 +62,9 @@
                 if (node != null) {
                     String dump = parsed.dump();
                     log.message(Kind.ERROR, null, null, null, dump);
+                    // CheckStyle: stop system..print check
                     System.out.println(dump);
+                    // CheckStyle: resume system..print check
                 }
             }
         } finally {
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SimpleLanguage.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SimpleLanguage.java	Mon Apr 15 08:49:14 2013 +0200
@@ -37,7 +37,9 @@
 
     public static void run(InputStream input, PrintStream printOutput, int repeats, boolean log) {
         if (log) {
+            // CheckStyle: stop system..print check
             System.out.printf("== running on %s\n", Truffle.getRuntime().getName());
+            // CheckStyle: resume system..print check
         }
 
         NodeFactory factory = new NodeFactory(printOutput);
@@ -63,7 +65,9 @@
                     printOutput.println(result);
                 }
                 if (log) {
+                    // CheckStyle: stop system..print check
                     System.out.printf("== iteration %d: %.3f ms\n", (i + 1), (end - start) / 1000000.0);
+                    // CheckStyle: resume system..print check
                 }
             }
 
--- a/make/bsd/makefiles/compiler1.make	Mon Apr 08 17:48:46 2013 +0200
+++ b/make/bsd/makefiles/compiler1.make	Mon Apr 15 08:49:14 2013 +0200
@@ -32,4 +32,6 @@
 
 ifndef OMIT_GRAAL
   CFLAGS += -DGRAAL
+else
+  VM_SUBDIR = client-nograal
 endif
\ No newline at end of file
--- a/make/bsd/makefiles/compiler2.make	Mon Apr 08 17:48:46 2013 +0200
+++ b/make/bsd/makefiles/compiler2.make	Mon Apr 15 08:49:14 2013 +0200
@@ -32,4 +32,6 @@
 
 ifndef OMIT_GRAAL
   CFLAGS += -DGRAAL
+else
+  VM_SUBDIR = server-nograal
 endif
\ No newline at end of file
--- a/make/bsd/makefiles/tiered.make	Mon Apr 08 17:48:46 2013 +0200
+++ b/make/bsd/makefiles/tiered.make	Mon Apr 15 08:49:14 2013 +0200
@@ -32,4 +32,6 @@
 
 ifndef OMIT_GRAAL
   CFLAGS += -DGRAAL
+else
+  VM_SUBDIR = server-nograal
 endif
--- a/make/hotspot_version	Mon Apr 08 17:48:46 2013 +0200
+++ b/make/hotspot_version	Mon Apr 15 08:49:14 2013 +0200
@@ -35,7 +35,7 @@
 
 HS_MAJOR_VER=25
 HS_MINOR_VER=0
-HS_BUILD_NUMBER=26
+HS_BUILD_NUMBER=28
 
 JDK_MAJOR_VER=1
 JDK_MINOR_VER=8
--- a/make/linux/makefiles/compiler1.make	Mon Apr 08 17:48:46 2013 +0200
+++ b/make/linux/makefiles/compiler1.make	Mon Apr 15 08:49:14 2013 +0200
@@ -32,4 +32,6 @@
 
 ifndef OMIT_GRAAL
   CFLAGS += -DGRAAL
+else
+  VM_SUBDIR = client-nograal
 endif
\ No newline at end of file
--- a/make/linux/makefiles/compiler2.make	Mon Apr 08 17:48:46 2013 +0200
+++ b/make/linux/makefiles/compiler2.make	Mon Apr 15 08:49:14 2013 +0200
@@ -32,4 +32,6 @@
 
 ifndef OMIT_GRAAL
   CFLAGS += -DGRAAL
+else
+  VM_SUBDIR = server-nograal
 endif
\ No newline at end of file
--- a/make/linux/makefiles/gcc.make	Mon Apr 08 17:48:46 2013 +0200
+++ b/make/linux/makefiles/gcc.make	Mon Apr 15 08:49:14 2013 +0200
@@ -126,14 +126,12 @@
 # Compiler warnings are treated as errors
 WARNINGS_ARE_ERRORS = -Werror
 
-# Except for a few acceptable ones
+WARNING_FLAGS = -Wpointer-arith -Wsign-compare -Wundef -Wunused-function
+
 # Since GCC 4.3, -Wconversion has changed its meanings to warn these implicit
-# conversions which might affect the values. To avoid that, we need to turn
-# it off explicitly. 
-ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0"
-WARNING_FLAGS = -Wpointer-arith -Wsign-compare -Wundef
-else
-WARNING_FLAGS = -Wpointer-arith -Wconversion -Wsign-compare -Wundef
+# conversions which might affect the values. Only enable it in earlier versions.
+ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0"
+WARNING_FLAGS += -Wconversion
 endif
 
 CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS) $(WARNING_FLAGS)
--- a/make/linux/makefiles/tiered.make	Mon Apr 08 17:48:46 2013 +0200
+++ b/make/linux/makefiles/tiered.make	Mon Apr 15 08:49:14 2013 +0200
@@ -32,4 +32,6 @@
 
 ifndef OMIT_GRAAL
   CFLAGS += -DGRAAL
+else
+  VM_SUBDIR = server-nograal
 endif
\ No newline at end of file
--- a/make/solaris/makefiles/compiler1.make	Mon Apr 08 17:48:46 2013 +0200
+++ b/make/solaris/makefiles/compiler1.make	Mon Apr 15 08:49:14 2013 +0200
@@ -32,4 +32,6 @@
 
 ifndef OMIT_GRAAL
   CFLAGS += -DGRAAL
+else
+  VM_SUBDIR = client-nograal
 endif
--- a/make/solaris/makefiles/compiler2.make	Mon Apr 08 17:48:46 2013 +0200
+++ b/make/solaris/makefiles/compiler2.make	Mon Apr 15 08:49:14 2013 +0200
@@ -32,4 +32,6 @@
 
 ifndef OMIT_GRAAL
   CFLAGS += -DGRAAL
+else
+  VM_SUBDIR = server-nograal
 endif
--- a/make/solaris/makefiles/tiered.make	Mon Apr 08 17:48:46 2013 +0200
+++ b/make/solaris/makefiles/tiered.make	Mon Apr 15 08:49:14 2013 +0200
@@ -32,4 +32,6 @@
 
 ifndef OMIT_GRAAL
   CFLAGS += -DGRAAL
+else
+  VM_SUBDIR = server-nograal
 endif
--- a/make/windows/create.bat	Mon Apr 08 17:48:46 2013 +0200
+++ b/make/windows/create.bat	Mon Apr 15 08:49:14 2013 +0200
@@ -37,10 +37,14 @@
 REM that "grep" be accessible on the PATH. An MKS install does this.
 REM 
 
-cl 2>NUL >NUL
-if %errorlevel% == 0 goto nexttest
-echo Make sure cl.exe is in your PATH before running this script.
-goto end
+
+
+REM (cwirth) does not return a proper error code, so build fails all the time
+REM
+REM cl 2>NUL >NUL
+REM if %errorlevel% == 0 goto nexttest
+REM echo Make sure cl.exe is in your PATH before running this script.
+REM goto end
 
 :nexttest
 grep -V 2>NUL >NUL
--- a/mx/commands.py	Mon Apr 08 17:48:46 2013 +0200
+++ b/mx/commands.py	Mon Apr 15 08:49:14 2013 +0200
@@ -38,13 +38,19 @@
 """ Used to distinguish an exported GraalVM (see 'mx export'). """
 _vmSourcesAvailable = exists(join(_graal_home, 'make')) and exists(join(_graal_home, 'src'))
 
-""" The VM that will be run by the 'vm' command: graal(default), client or server.
+""" The VMs that can be built and run - default is first in list """
+_vmChoices = ['graal', 'server', 'client', 'server-nograal', 'client-nograal', 'boot']
+
+""" The VM that will be run by the 'vm' command and built by default by the 'build' command.
     This can be set via the global '--vm' option. """
-_vm = 'graal'
+_vm = _vmChoices[0]
 
-""" The VM build that will be run by the 'vm' command: product(default), fastdebug or debug.
-    This can be set via the global '--fastdebug' and '--debug' options. """
-_vmbuild = 'product'
+""" The VM builds that will be run by the 'vm' command - default is first in list """
+_vmbuildChoices = ['product', 'fastdebug', 'debug']
+
+""" The VM build that will be run by the 'vm' command.
+    This can be set via the global '--product', '--fastdebug' and '--debug' options. """
+_vmbuild = _vmbuildChoices[0]
 
 _jacoco = 'off'
 
@@ -66,11 +72,16 @@
     """clean the GraalVM source tree"""
     opts = mx.clean(args, parser=ArgumentParser(prog='mx clean'))
     if opts.native:
-        os.environ.update(ARCH_DATA_MODEL='64', LANG='C', HOTSPOT_BUILD_JOBS='16')
-        mx.run([mx.gmake_cmd(), 'clean'], cwd=join(_graal_home, 'make'))
-        jdks = join(_graal_home, 'jdk' + str(mx.java().version))
-        if exists(jdks):
-            shutil.rmtree(jdks)
+        def rmIfExists(name):
+            if os.path.isdir(name):
+                shutil.rmtree(name)
+            elif os.path.isfile(name):
+                os.unlink(name)
+                
+        rmIfExists(join(_graal_home, 'build'))
+        rmIfExists(join(_graal_home, 'build-nograal'))
+        rmIfExists(join(_graal_home, 'jdk' + str(mx.java().version)))
+        rmIfExists(mx.distribution('GRAAL').path)
 
 def export(args):
     """create a GraalVM zip file for distribution"""
@@ -328,14 +339,15 @@
                         assert len(parts) == 2, parts
                         assert parts[1] == 'KNOWN', parts[1]
                         defaultVM = parts[0][1:]
-                        jvmCfgLines += ['-' + defaultVM + '0 KNOWN\n']
+                        jvmCfgLines += ['# boot VM is a copy of the unmodified ' + defaultVM + ' VM\n']
+                        jvmCfgLines += ['-boot KNOWN\n']
                     else:
                         jvmCfgLines += [line]
 
             assert defaultVM is not None, 'Could not find default VM in ' + jvmCfg
             if mx.get_os() != 'windows':
                 chmodRecursive(jdk, 0755)
-            shutil.move(join(_vmLibDirInJdk(jdk), defaultVM), join(_vmLibDirInJdk(jdk), defaultVM + '0'))
+            shutil.move(join(_vmLibDirInJdk(jdk), defaultVM), join(_vmLibDirInJdk(jdk), 'boot'))
             
 
             with open(jvmCfg, 'w') as fp:
@@ -539,9 +551,9 @@
     if vm is None:
         vm = _vm
 
-    if vm == 'server' or vm == 'server0':
+    if vm.startswith('server') or vm == 'boot':
         buildSuffix = ''
-    elif vm == 'client':
+    elif vm.startswith('client'):
         buildSuffix = '1'
     else:
         assert vm == 'graal', vm
@@ -556,10 +568,12 @@
                 mx.log('[skipping build from IDE as IDE_BUILD_TARGET environment variable is ""]')
                 continue
 
-        if vm == 'server0':
-            assert build == 'product', 'can not "build" a non-product server0'
+        jdk = _jdk(build, create=True)
 
-        jdk = _jdk(build, create=True)
+        if vm == 'boot':
+            if build != 'product':
+                mx.log('only product build of boot VM exists')
+            continue
 
         vmDir = join(_vmLibDirInJdk(jdk), vm)
         if not exists(vmDir):
@@ -574,9 +588,7 @@
 
         # Check if a build really needs to be done
         timestampFile = join(vmDir, '.build-timestamp')
-        if vm == 'server0':
-            mustBuild = False
-        elif opts2.force or not exists(timestampFile):
+        if opts2.force or not exists(timestampFile):
             mustBuild = True
         else:
             mustBuild = False
@@ -626,7 +638,10 @@
             env.setdefault('HOTSPOT_BUILD_JOBS', str(cpus))
             env['ALT_BOOTDIR'] = mx.java().jdk
             env['JAVA_HOME'] = jdk
-            if not env.has_key('OMIT_GRAAL'):
+            if vm.endswith('nograal'):
+                env['OMIT_GRAAL'] = 'true'
+                env.setdefault('ALT_OUTPUTDIR', join(_graal_home, 'build-nograal', mx.get_os()))
+            else:
                 env['GRAAL'] = join(_graal_home, 'graal') # needed for TEST_IN_BUILD
             env.setdefault('INSTALL', 'y')
             if mx.get_os() == 'solaris' :
@@ -657,8 +672,8 @@
         if not exists(jvmCfg):
             mx.abort(jvmCfg + ' does not exist')
 
-        prefix = '-' + vm
-        vmKnown = prefix + ' KNOWN\n'
+        prefix = '-' + vm + ' '
+        vmKnown = prefix + 'KNOWN\n'
         lines = []
         found = False
         with open(jvmCfg) as f:
@@ -668,7 +683,7 @@
                 lines.append(line)
                 
         if not found:
-            mx.log('Appending "' + prefix + ' KNOWN" to ' + jvmCfg)
+            mx.log('Appending "' + prefix + 'KNOWN" to ' + jvmCfg)
             if mx.get_os() != 'windows':
                 os.chmod(jvmCfg, 0755)
             with open(jvmCfg, 'w') as f:
@@ -776,12 +791,14 @@
     name = 'JUnitWrapper'
     javaSource = join(mxdir, name + '.java')
     javaClass = join(mxdir, name + '.class')
-    (_, testfile) = tempfile.mkstemp(".testclasses", "graal")
+    testfile = os.environ.get('MX_TESTFILE', None)
+    if testfile is None:
+        (_, testfile) = tempfile.mkstemp(".testclasses", "graal")
 
     def harness(projectscp, vmArgs):
         if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource):
             subprocess.check_call([mx.java().javac, '-cp', projectscp, '-d', mxdir, javaSource])
-        if _vm == 'server0':
+        if _vm == 'boot' or _vm.endswith('nograal'):
             prefixArgs = ['-esa', '-ea']
         else:
             prefixArgs = ['-XX:-BootstrapGraal', '-esa', '-ea']
@@ -790,7 +807,8 @@
     try:
         _run_tests(args, harness, annotations, testfile)
     finally:
-        os.remove(testfile)
+        if os.environ.get('MX_TESTFILE') is None:
+            os.remove(testfile)
 
 def unittest(args):
     """run the JUnit tests (all testcases)
@@ -822,9 +840,14 @@
 def buildvms(args):
     """build one or more VMs in various configurations"""
 
+    vmsDefault = ','.join(_vmChoices)
+    vmbuildsDefault = ','.join(_vmbuildChoices)
+    
     parser = ArgumentParser(prog='mx buildvms');
-    parser.add_argument('--vms', help='a comma separated list of VMs to build (default: server,client,graal)', default='server,client,graal')
-    parser.add_argument('--builds', help='a comma separated list of build types (default: product,fastdebug,debug)', default='product,fastdebug,debug')
+    parser.add_argument('--vms', help='a comma separated list of VMs to build (default: ' + vmsDefault + ')', metavar='<args>', default=vmsDefault)
+    parser.add_argument('--builds', help='a comma separated list of build types (default: ' + vmbuildsDefault + ')', metavar='<args>', default=vmbuildsDefault)
+    parser.add_argument('-n', '--no-check', action='store_true', help='omit running "java -version" after each build')
+    parser.add_argument('-c', '--console', action='store_true', help='send build output to console instead of log file')
 
     args = parser.parse_args(args)
     vms = args.vms.split(',')
@@ -833,14 +856,26 @@
     allStart = time.time()
     for v in vms:
         for vmbuild in builds:
-            logFile = join(v + '-' + vmbuild + '.log')
-            log = open(join(_graal_home, logFile), 'wb')
-            start = time.time()
-            mx.log('BEGIN: ' + v + '-' + vmbuild + '\t(see: ' + logFile + ')')
-            # Run as subprocess so that output can be directed to a file
-            subprocess.check_call([sys.executable, '-u', join('mxtool', 'mx.py'), '--vm', v, 'build', vmbuild], cwd=_graal_home, stdout=log, stderr=subprocess.STDOUT)
-            duration = datetime.timedelta(seconds=time.time() - start)
-            mx.log('END:   ' + v + '-' + vmbuild + '\t[' + str(duration) + ']')
+            if v == 'boot' and vmbuild != 'product':
+                continue
+            if not args.console:
+                logFile = join(v + '-' + vmbuild + '.log')
+                log = open(join(_graal_home, logFile), 'wb')
+                start = time.time()
+                mx.log('BEGIN: ' + v + '-' + vmbuild + '\t(see: ' + logFile + ')')
+                # Run as subprocess so that output can be directed to a file
+                subprocess.check_call([sys.executable, '-u', join('mxtool', 'mx.py'), '--vm', v, 'build', vmbuild], cwd=_graal_home, stdout=log, stderr=subprocess.STDOUT)
+                duration = datetime.timedelta(seconds=time.time() - start)
+                mx.log('END:   ' + v + '-' + vmbuild + '\t[' + str(duration) + ']')
+            else:
+                global _vm
+                _vm = v
+                build([vmbuild])
+            if not args.no_check:
+                vmargs = ['-version']
+                if v == 'graal':
+                    vmargs.insert(0, '-XX:-BootstrapGraal')
+                vm(vmargs, vm=v, vmbuild=vmbuild)
     allDuration = datetime.timedelta(seconds=time.time() - allStart)
     mx.log('TOTAL TIME:   ' + '[' + str(allDuration) + ']')
 
@@ -1288,18 +1323,16 @@
     mx.add_argument('--jacoco', help='instruments com.oracle.* classes using JaCoCo', default='off', choices=['off', 'on', 'append'])
 
     if (_vmSourcesAvailable):
-        mx.add_argument('--vm', action='store', dest='vm', default='graal', choices=['graal', 'server', 'client', 'server0'], help='the VM to build/run (default: graal)')
-        mx.add_argument('--product', action='store_const', dest='vmbuild', const='product', help='select the product build of the VM')
-        mx.add_argument('--debug', action='store_const', dest='vmbuild', const='debug', help='select the debug build of the VM')
-        mx.add_argument('--fastdebug', action='store_const', dest='vmbuild', const='fastdebug', help='select the fast debug build of the VM')
+        mx.add_argument('--vm', action='store', dest='vm', default='graal', choices=_vmChoices, help='the VM to build/run (default: ' + _vmChoices[0] + ')')
+        for c in _vmbuildChoices:
+            mx.add_argument('--' + c, action='store_const', dest='vmbuild', const=c, help='select the ' + c + ' build of the VM')
         mx.add_argument('--ecl', action='store_true', dest='make_eclipse_launch', help='create launch configuration for running VM execution(s) in Eclipse')
         mx.add_argument('--native-dbg', action='store', dest='native_dbg', help='Start the vm inside a debugger', metavar='<debugger>')
         mx.add_argument('--gdb', action='store_const', const='/usr/bin/gdb --args', dest='native_dbg', help='alias for --native-dbg /usr/bin/gdb -- args')
-        
 
         commands.update({
             'export': [export, '[-options] [zipfile]'],
-            'build': [build, '[-options] [product|debug|fastdebug]...']
+            'build': [build, '[-options] [' + '|'.join(_vmbuildChoices) + ']...']
         })
 
     mx.commands.update(commands)
--- a/mx/projects	Mon Apr 08 17:48:46 2013 +0200
+++ b/mx/projects	Mon Apr 15 08:49:14 2013 +0200
@@ -125,7 +125,7 @@
 # graal.hotspot.test
 project@com.oracle.graal.hotspot.test@subDir=graal
 project@com.oracle.graal.hotspot.test@sourceDirs=src
-project@com.oracle.graal.hotspot.test@dependencies=com.oracle.graal.replacements.test,com.oracle.graal.hotspot
+project@com.oracle.graal.hotspot.test@dependencies=com.oracle.graal.replacements.test
 project@com.oracle.graal.hotspot.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.test@javaCompliance=1.7
 
@@ -155,6 +155,13 @@
 project@com.oracle.graal.debug@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.debug@javaCompliance=1.7
 
+# graal.debug.test
+project@com.oracle.graal.debug.test@subDir=graal
+project@com.oracle.graal.debug.test@sourceDirs=src
+project@com.oracle.graal.debug.test@dependencies=JUNIT,com.oracle.graal.debug
+project@com.oracle.graal.debug.test@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.debug.test@javaCompliance=1.7
+
 # graal.lir
 project@com.oracle.graal.lir@subDir=graal
 project@com.oracle.graal.lir@sourceDirs=src
@@ -215,7 +222,7 @@
 # graal.replacements.test
 project@com.oracle.graal.replacements.test@subDir=graal
 project@com.oracle.graal.replacements.test@sourceDirs=src
-project@com.oracle.graal.replacements.test@dependencies=com.oracle.graal.replacements,com.oracle.graal.compiler.test
+project@com.oracle.graal.replacements.test@dependencies=com.oracle.graal.compiler.test
 project@com.oracle.graal.replacements.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.replacements.test@javaCompliance=1.7
 
@@ -333,7 +340,7 @@
 # graal.compiler.test
 project@com.oracle.graal.compiler.test@subDir=graal
 project@com.oracle.graal.compiler.test@sourceDirs=src
-project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.printer,com.oracle.graal.test
+project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.test,com.oracle.graal.hotspot
 project@com.oracle.graal.compiler.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler.test@javaCompliance=1.7
 
--- a/mxtool/mx.py	Mon Apr 08 17:48:46 2013 +0200
+++ b/mxtool/mx.py	Mon Apr 15 08:49:14 2013 +0200
@@ -1344,7 +1344,7 @@
     parser = parser if parser is not None else ArgumentParser(prog='mx build')
     parser.add_argument('-f', action='store_true', dest='force', help='force build (disables timestamp checking)')
     parser.add_argument('-c', action='store_true', dest='clean', help='removes existing build output')
-    parser.add_argument('--source', dest='compliance', help='Java compliance level', default=str(javaCompliance))
+    parser.add_argument('--source', dest='compliance', help='Java compliance level for projects without an explicit one', default=str(javaCompliance))
     parser.add_argument('--Wapi', action='store_true', dest='warnAPI', help='show warnings about using internal APIs')
     parser.add_argument('--projects', action='store', help='comma separated projects to build (omit to build all projects)')
     parser.add_argument('--only', action='store', help='comma separated projects to build, without checking their dependencies (omit to build all projects)')
@@ -1502,16 +1502,17 @@
 
         toBeDeleted = [argfileName]
         try:
+            compliance = str(p.javaCompliance) if p.javaCompliance is not None else args.compliance
             if jdtJar is None:
                 log('Compiling Java sources for {0} with javac...'.format(p.name))
-                javacCmd = [java().javac, '-g', '-J-Xmx1g', '-source', args.compliance, '-classpath', cp, '-d', outputDir] + javacArgs + ['@' + argfile.name]
+                javacCmd = [java().javac, '-g', '-J-Xmx1g', '-source', compliance, '-classpath', cp, '-d', outputDir] + javacArgs + ['@' + argfile.name]
                 if not args.warnAPI:
                     javacCmd.append('-XDignore.symbol.file')
                 run(javacCmd)
             else:
                 log('Compiling Java sources for {0} with JDT...'.format(p.name))
                 jdtArgs = [java().java, '-Xmx1g', '-jar', jdtJar,
-                         '-' + args.compliance,
+                         '-' + compliance,
                          '-cp', cp, '-g', '-enableJavadoc',
                          '-d', outputDir] + javacArgs
                 jdtProperties = join(p.dir, '.settings', 'org.eclipse.jdt.core.prefs')
@@ -1561,6 +1562,13 @@
         args.eclipse_exe = os.environ.get('ECLIPSE_EXE')
     if args.eclipse_exe is None:
         abort('Could not find Eclipse executable. Use -e option or ensure ECLIPSE_EXE environment variable is set.')
+        
+    # Maybe an Eclipse installation dir was specified - look for the executable in it
+    if join(args.eclipse_exe, exe_suffix('eclipse')):
+        args.eclipse_exe = join(args.eclipse_exe, exe_suffix('eclipse'))
+        
+    if not os.path.isfile(args.eclipse_exe) or not os.access(args.eclipse_exe, os.X_OK):
+        abort('Not an executable file: ' + args.eclipse_exe)
 
     eclipseinit([], buildProcessorJars=False)
 
@@ -1813,11 +1821,6 @@
                 log('[all Java sources in {0} already checked - skipping]'.format(sourceDir))
                 continue
 
-            if exists(timestampFile):
-                os.utime(timestampFile, None)
-            else:
-                file(timestampFile, 'a')
-
             dotCheckstyleXML = xml.dom.minidom.parse(dotCheckstyle)
             localCheckConfig = dotCheckstyleXML.getElementsByTagName('local-check-config')[0]
             configLocation = localCheckConfig.getAttribute('location')
@@ -1883,6 +1886,11 @@
                                 if len(warnings) != 0:
                                     map(log, warnings)
                                     return 1
+                                else:
+                                    if exists(timestampFile):
+                                        os.utime(timestampFile, None)
+                                    else:
+                                        file(timestampFile, 'a')
             finally:
                 if exists(auditfileName):
                     os.unlink(auditfileName)
@@ -3010,9 +3018,10 @@
         if exists(tmpbase):
             shutil.rmtree(tmpbase)
 
-def findclass(args):
+def findclass(args, logToConsole=True):
     """find all classes matching a given substring"""
 
+    matches = []
     for entry, filename in classpath_walk(includeBootClasspath=True):
         if filename.endswith('.class'):
             if isinstance(entry, zipfile.ZipFile):
@@ -3022,20 +3031,19 @@
             classname = classname[:-len('.class')]
             for a in args:
                 if a in classname:
-                    log(classname)
+                    matches.append(classname)
+                    if logToConsole:
+                        log(classname)
+    return matches
 
 def javap(args):
-    """launch javap with a -classpath option denoting all available classes
-
-    Run the JDK javap class file disassembler with the following prepended options:
-
-        -private -verbose -classpath <path to project classes>"""
+    """disassemble classes matching given pattern with javap"""
 
     javap = java().javap
     if not exists(javap):
         abort('The javap executable does not exists: ' + javap)
     else:
-        run([javap, '-private', '-verbose', '-classpath', classpath()] + args)
+        run([javap, '-private', '-verbose', '-classpath', classpath()] + findclass(args, logToConsole=False))
 
 def show_projects(args):
     """show all loaded projects"""
@@ -3073,7 +3081,7 @@
     'ideinit': [ideinit, ''],
     'archive': [archive, '[options]'],
     'projectgraph': [projectgraph, ''],
-    'javap': [javap, ''],
+    'javap': [javap, '<class name patterns>'],
     'javadoc': [javadoc, '[options]'],
     'site': [site, '[options]'],
     'netbeansinit': [netbeansinit, ''],
--- a/src/cpu/sparc/vm/interpreter_sparc.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/cpu/sparc/vm/interpreter_sparc.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -381,6 +381,9 @@
     case Interpreter::zerolocals_synchronized: synchronized = true;                                                        break;
     case Interpreter::native                 : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(false);  break;
     case Interpreter::native_synchronized    : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(true);   break;
+#ifdef GRAAL
+    case Interpreter::execute_compiled_method: entry_point = ((InterpreterGenerator*)this)->generate_execute_compiled_method_entry();   break;
+#endif
     case Interpreter::empty                  : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry();        break;
     case Interpreter::accessor               : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry();     break;
     case Interpreter::abstract               : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry();     break;
--- a/src/cpu/x86/vm/assembler_x86.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/cpu/x86/vm/assembler_x86.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -214,14 +214,6 @@
   return enc;
 }
 
-static int encode(XMMRegister r) {
-  int enc = r->encoding();
-  if (enc >= 8) {
-    enc -= 8;
-  }
-  return enc;
-}
-
 void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) {
   assert(dst->has_byte_register(), "must have byte register");
   assert(isByte(op1) && isByte(op2), "wrong opcode");
--- a/src/cpu/x86/vm/graalRuntime_x86.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/cpu/x86/vm/graalRuntime_x86.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -879,30 +879,10 @@
 
         // This is called via call_runtime so the arguments
         // will be place in C abi locations
-
-#ifdef _LP64
         __ verify_oop(j_rarg0);
-        __ mov(rax, j_rarg0);
-#else
-        // The object is passed on the stack and we haven't pushed a
-        // frame yet so it's one work away from top of stack.
-        __ movptr(rax, Address(rsp, 1 * BytesPerWord));
-        __ verify_oop(rax);
-#endif // _LP64
-
-        // load the klass and check the has finalizer flag
-        Label register_finalizer;
-        Register t = rsi;
-        __ load_klass(t, rax);
-        __ movl(t, Address(t, Klass::access_flags_offset()));
-        __ testl(t, JVM_ACC_HAS_FINALIZER);
-        __ jcc(Assembler::notZero, register_finalizer);
-        __ ret(0);
-
-        __ bind(register_finalizer);
         __ enter();
         OopMap* oop_map = save_live_registers(sasm, 2 /*num_rt_args */);
-        int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, SharedRuntime::register_finalizer), rax);
+        int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, SharedRuntime::register_finalizer), j_rarg0);
         oop_maps = new OopMapSet();
         oop_maps->add_gc_map(call_offset, oop_map);
 
@@ -950,6 +930,7 @@
 		OopMap* oop_map = save_live_registers(sasm, 0);
 		int call_offset = __ call_RT(rax, noreg, (address)create_null_exception, 0);
 		oop_maps->add_gc_map(call_offset, oop_map);
+		restore_live_registers_except_rax(sasm);
 		__ leave();
 		__ ret(0);
       break;
@@ -958,9 +939,10 @@
     case create_out_of_bounds_exception_id: {
 		__ enter();
 		oop_maps = new OopMapSet();
-		OopMap* oop_map = save_live_registers(sasm, 0);
+		OopMap* oop_map = save_live_registers(sasm, 1);
 		int call_offset = __ call_RT(rax, noreg, (address)create_out_of_bounds_exception, j_rarg0);
 		oop_maps->add_gc_map(call_offset, oop_map);
+		restore_live_registers_except_rax(sasm);
 		__ leave();
 		__ ret(0);
       break;
@@ -969,7 +951,7 @@
     case vm_error_id: {
       __ enter();
       oop_maps = new OopMapSet();
-      OopMap* oop_map = save_live_registers(sasm, 0);
+      OopMap* oop_map = save_live_registers(sasm, 3);
       int call_offset = __ call_RT(noreg, noreg, (address)vm_error, j_rarg0, j_rarg1, j_rarg2);
       oop_maps->add_gc_map(call_offset, oop_map);
       restore_live_registers(sasm);
@@ -981,7 +963,7 @@
     case log_printf_id: {
       __ enter();
       oop_maps = new OopMapSet();
-      OopMap* oop_map = save_live_registers(sasm, 0);
+      OopMap* oop_map = save_live_registers(sasm, 4);
       int call_offset = __ call_RT(noreg, noreg, (address)log_printf, j_rarg0, j_rarg1, j_rarg2, j_rarg3);
       oop_maps->add_gc_map(call_offset, oop_map);
       restore_live_registers(sasm);
@@ -993,7 +975,7 @@
     case log_primitive_id: {
       __ enter();
       oop_maps = new OopMapSet();
-      OopMap* oop_map = save_live_registers(sasm, 0);
+      OopMap* oop_map = save_live_registers(sasm, 3);
       int call_offset = __ call_RT(noreg, noreg, (address)log_primitive, j_rarg0, j_rarg1, j_rarg2);
       oop_maps->add_gc_map(call_offset, oop_map);
       restore_live_registers(sasm);
@@ -1005,7 +987,7 @@
     case log_object_id: {
       __ enter();
       oop_maps = new OopMapSet();
-      OopMap* oop_map = save_live_registers(sasm, 0);
+      OopMap* oop_map = save_live_registers(sasm, 2);
       int call_offset = __ call_RT(noreg, noreg, (address)log_object, j_rarg0, j_rarg1);
       oop_maps->add_gc_map(call_offset, oop_map);
       restore_live_registers(sasm);
--- a/src/cpu/x86/vm/interpreterGenerator_x86.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/cpu/x86/vm/interpreterGenerator_x86.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -36,6 +36,9 @@
 
   address generate_normal_entry(bool synchronized);
   address generate_native_entry(bool synchronized);
+#ifdef GRAAL
+  address generate_execute_compiled_method_entry();
+#endif
   address generate_abstract_entry(void);
   address generate_math_entry(AbstractInterpreter::MethodKind kind);
   address generate_empty_entry(void);
--- a/src/cpu/x86/vm/methodHandles_x86.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/cpu/x86/vm/methodHandles_x86.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -41,11 +41,6 @@
 
 #define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
 
-// Workaround for C++ overloading nastiness on '0' for RegisterOrConstant.
-static RegisterOrConstant constant(int value) {
-  return RegisterOrConstant(value);
-}
-
 void MethodHandles::load_klass_from_Class(MacroAssembler* _masm, Register klass_reg) {
   if (VerifyMethodHandles)
     verify_klass(_masm, klass_reg, SystemDictionary::WK_KLASS_ENUM_NAME(java_lang_Class),
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -1670,6 +1670,17 @@
   verify_oop_args(masm, method, sig_bt, regs);
   vmIntrinsics::ID iid = method->intrinsic_id();
 
+#ifdef GRAAL
+  if (iid == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) {
+    // We are called from compiled code here. The three object arguments
+    // are already in the correct registers (j_rarg0, jrarg1, jrarg2). The
+    // fourth argument (j_rarg3) is a raw pointer to the nmethod. Make a tail
+    // call to its verified entry point.
+    __ jmp(Address(j_rarg3, nmethod::verified_entry_point_offset()));
+    return;
+  }
+#endif
+
   // Now write the args into the outgoing interpreter space
   bool     has_receiver   = false;
   Register receiver_reg   = noreg;
--- a/src/cpu/x86/vm/templateInterpreter_x86.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/cpu/x86/vm/templateInterpreter_x86.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -34,7 +34,7 @@
   // Run with +PrintInterpreter to get the VM to print out the size.
   // Max size with JVMTI
 #ifdef AMD64
-  const static int InterpreterCodeSize = 224 * 1024;
+  const static int InterpreterCodeSize = 240 * 1024;
 #else
   const static int InterpreterCodeSize = 168 * 1024;
 #endif // AMD64
--- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -873,6 +873,46 @@
   return generate_accessor_entry();
 }
 
+#ifdef GRAAL
+
+// Interpreter stub for calling a compiled method with 3 object arguments
+address InterpreterGenerator::generate_execute_compiled_method_entry() {
+  address entry_point = __ pc();
+
+  // Pick up the return address
+  __ movptr(rax, Address(rsp, 0));
+
+  // Must preserve original SP for loading incoming arguments because
+  // we need to align the outgoing SP for compiled code.
+  __ movptr(r11, rsp);
+
+  // Ensure compiled code always sees stack at proper alignment
+  __ andptr(rsp, -16);
+
+  // push the return address and misalign the stack that youngest frame always sees
+  // as far as the placement of the call instruction
+  __ push(rax);
+
+  // Move first object argument from interpreter calling convention to compiled
+  // code calling convention.
+  __ movq(j_rarg0, Address(r11, Interpreter::stackElementSize*5));
+
+  // Move second object argument.
+  __ movq(j_rarg1, Address(r11, Interpreter::stackElementSize*4));
+
+  // Move third object argument.
+  __ movq(j_rarg2, Address(r11, Interpreter::stackElementSize*3));
+
+  // Load the raw pointer to the nmethod.
+  __ movq(j_rarg3, Address(r11, Interpreter::stackElementSize));
+
+  // Perform a tail call to the verified entry point of the nmethod.
+  __ jmp(Address(j_rarg3, nmethod::verified_entry_point_offset()));
+
+  return entry_point;
+}
+
+#endif
 
 // Interpreter stub for calling a native method. (asm interpreter)
 // This sets up a somewhat different looking stack for calling the
@@ -1561,6 +1601,9 @@
   switch (kind) {
   case Interpreter::zerolocals             :                                                                             break;
   case Interpreter::zerolocals_synchronized: synchronized = true;                                                        break;
+#ifdef GRAAL
+  case Interpreter::execute_compiled_method: entry_point = ((InterpreterGenerator*)this)->generate_execute_compiled_method_entry(); break;
+#endif
   case Interpreter::native                 : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(false); break;
   case Interpreter::native_synchronized    : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(true);  break;
   case Interpreter::empty                  : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry();       break;
--- a/src/cpu/x86/vm/x86_64.ad	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/cpu/x86/vm/x86_64.ad	Mon Apr 15 08:49:14 2013 +0200
@@ -1693,17 +1693,6 @@
   return PTR_RBP_REG_mask();
 }
 
-static Address build_address(int b, int i, int s, int d) {
-  Register index = as_Register(i);
-  Address::ScaleFactor scale = (Address::ScaleFactor)s;
-  if (index == rsp) {
-    index = noreg;
-    scale = Address::no_scale;
-  }
-  Address addr(as_Register(b), index, scale, d);
-  return addr;
-}
-
 %}
 
 //----------ENCODING BLOCK-----------------------------------------------------
--- a/src/os/bsd/vm/os_bsd.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/os/bsd/vm/os_bsd.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -152,7 +152,6 @@
 // utility functions
 
 static int SR_initialize();
-static int SR_finalize();
 
 julong os::available_memory() {
   return Bsd::available_memory();
@@ -1200,6 +1199,9 @@
   } else if (strchr(pname, *os::path_separator()) != NULL) {
     int n;
     char** pelements = split_path(pname, &n);
+    if (pelements == NULL) {
+      return false;
+    }
     for (int i = 0 ; i < n ; i++) {
       // Really shouldn't be NULL, but check can't hurt
       if (pelements[i] == NULL || strlen(pelements[i]) == 0) {
@@ -2766,10 +2768,6 @@
   return 0;
 }
 
-static int SR_finalize() {
-  return 0;
-}
-
 
 // returns true on success and false on error - really an error is fatal
 // but this seems the normal response to library errors
@@ -3578,16 +3576,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // debug support
 
-static address same_page(address x, address y) {
-  int page_bits = -os::vm_page_size();
-  if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits))
-    return x;
-  else if (x > y)
-    return (address)(intptr_t(y) | ~page_bits) + 1;
-  else
-    return (address)(intptr_t(y) & page_bits);
-}
-
 bool os::find(address addr, outputStream* st) {
   Dl_info dlinfo;
   memset(&dlinfo, 0, sizeof(dlinfo));
@@ -3611,8 +3599,8 @@
 
     if (Verbose) {
       // decode some bytes around the PC
-      address begin = same_page(addr-40, addr);
-      address end   = same_page(addr+40, addr);
+      address begin = clamp_address_in_page(addr-40, addr, os::vm_page_size());
+      address end   = clamp_address_in_page(addr+40, addr, os::vm_page_size());
       address       lowest = (address) dlinfo.dli_sname;
       if (!lowest)  lowest = (address) dlinfo.dli_fbase;
       if (begin < lowest)  begin = lowest;
--- a/src/os/bsd/vm/perfMemory_bsd.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/os/bsd/vm/perfMemory_bsd.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -672,15 +672,15 @@
   RESTARTABLE(::open(filename, oflags), result);
   if (result == OS_ERR) {
     if (errno == ENOENT) {
-      THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
-                  "Process not found");
+      THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
+                  "Process not found", OS_ERR);
     }
     else if (errno == EACCES) {
-      THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
-                  "Permission denied");
+      THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
+                  "Permission denied", OS_ERR);
     }
     else {
-      THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno));
+      THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR);
     }
   }
 
@@ -828,7 +828,7 @@
   char* mapAddress;
   int result;
   int fd;
-  size_t size;
+  size_t size = 0;
   const char* luser = NULL;
 
   int mmap_prot;
@@ -899,9 +899,12 @@
 
   if (*sizep == 0) {
     size = sharedmem_filesize(fd, CHECK);
-    assert(size != 0, "unexpected size");
+  } else {
+    size = *sizep;
   }
 
+  assert(size > 0, "unexpected size <= 0");
+
   mapAddress = (char*)::mmap((char*)0, size, mmap_prot, MAP_SHARED, fd, 0);
 
   // attempt to close the file - restart if it gets interrupted,
--- a/src/os/linux/vm/os_linux.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/os/linux/vm/os_linux.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -176,7 +176,6 @@
 // utility functions
 
 static int SR_initialize();
-static int SR_finalize();
 
 julong os::available_memory() {
   return Linux::available_memory();
@@ -1633,6 +1632,9 @@
   } else if (strchr(pname, *os::path_separator()) != NULL) {
     int n;
     char** pelements = split_path(pname, &n);
+    if (pelements == NULL) {
+      return false;
+    }
     for (int i = 0 ; i < n ; i++) {
       // Really shouldn't be NULL, but check can't hurt
       if (pelements[i] == NULL || strlen(pelements[i]) == 0) {
@@ -3655,10 +3657,6 @@
   return 0;
 }
 
-static int SR_finalize() {
-  return 0;
-}
-
 
 // returns true on success and false on error - really an error is fatal
 // but this seems the normal response to library errors
@@ -4500,16 +4498,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // debug support
 
-static address same_page(address x, address y) {
-  int page_bits = -os::vm_page_size();
-  if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits))
-    return x;
-  else if (x > y)
-    return (address)(intptr_t(y) | ~page_bits) + 1;
-  else
-    return (address)(intptr_t(y) & page_bits);
-}
-
 bool os::find(address addr, outputStream* st) {
   Dl_info dlinfo;
   memset(&dlinfo, 0, sizeof(dlinfo));
@@ -4533,8 +4521,8 @@
 
     if (Verbose) {
       // decode some bytes around the PC
-      address begin = same_page(addr-40, addr);
-      address end   = same_page(addr+40, addr);
+      address begin = clamp_address_in_page(addr-40, addr, os::vm_page_size());
+      address end   = clamp_address_in_page(addr+40, addr, os::vm_page_size());
       address       lowest = (address) dlinfo.dli_sname;
       if (!lowest)  lowest = (address) dlinfo.dli_fbase;
       if (begin < lowest)  begin = lowest;
--- a/src/os/linux/vm/perfMemory_linux.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/os/linux/vm/perfMemory_linux.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -672,15 +672,15 @@
   RESTARTABLE(::open(filename, oflags), result);
   if (result == OS_ERR) {
     if (errno == ENOENT) {
-      THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
-                  "Process not found");
+      THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
+                  "Process not found", OS_ERR);
     }
     else if (errno == EACCES) {
-      THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
-                  "Permission denied");
+      THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
+                  "Permission denied", OS_ERR);
     }
     else {
-      THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno));
+      THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR);
     }
   }
 
@@ -828,7 +828,7 @@
   char* mapAddress;
   int result;
   int fd;
-  size_t size;
+  size_t size = 0;
   const char* luser = NULL;
 
   int mmap_prot;
@@ -899,9 +899,12 @@
 
   if (*sizep == 0) {
     size = sharedmem_filesize(fd, CHECK);
-    assert(size != 0, "unexpected size");
+  } else {
+    size = *sizep;
   }
 
+  assert(size > 0, "unexpected size <= 0");
+
   mapAddress = (char*)::mmap((char*)0, size, mmap_prot, MAP_SHARED, fd, 0);
 
   // attempt to close the file - restart if it gets interrupted,
--- a/src/os/solaris/vm/os_solaris.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/os/solaris/vm/os_solaris.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -1885,6 +1885,9 @@
   } else if (strchr(pname, *os::path_separator()) != NULL) {
     int n;
     char** pelements = split_path(pname, &n);
+    if (pelements == NULL) {
+      return false;
+    }
     for (int i = 0 ; i < n ; i++) {
       // really shouldn't be NULL but what the heck, check can't hurt
       if (pelements[i] == NULL || strlen(pelements[i]) == 0) {
@@ -5787,16 +5790,6 @@
 
 //---------------------------------------------------------------------------------
 
-static address same_page(address x, address y) {
-  intptr_t page_bits = -os::vm_page_size();
-  if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits))
-    return x;
-  else if (x > y)
-    return (address)(intptr_t(y) | ~page_bits) + 1;
-  else
-    return (address)(intptr_t(y) & page_bits);
-}
-
 bool os::find(address addr, outputStream* st) {
   Dl_info dlinfo;
   memset(&dlinfo, 0, sizeof(dlinfo));
@@ -5822,8 +5815,8 @@
 
     if (Verbose) {
       // decode some bytes around the PC
-      address begin = same_page(addr-40, addr);
-      address end   = same_page(addr+40, addr);
+      address begin = clamp_address_in_page(addr-40, addr, os::vm_page_size());
+      address end   = clamp_address_in_page(addr+40, addr, os::vm_page_size());
       address       lowest = (address) dlinfo.dli_sname;
       if (!lowest)  lowest = (address) dlinfo.dli_fbase;
       if (begin < lowest)  begin = lowest;
--- a/src/os/solaris/vm/perfMemory_solaris.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/os/solaris/vm/perfMemory_solaris.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -687,15 +687,15 @@
   RESTARTABLE(::open(filename, oflags), result);
   if (result == OS_ERR) {
     if (errno == ENOENT) {
-      THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
-                  "Process not found");
+      THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
+                  "Process not found", OS_ERR);
     }
     else if (errno == EACCES) {
-      THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
-                  "Permission denied");
+      THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
+                  "Permission denied", OS_ERR);
     }
     else {
-      THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno));
+      THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR);
     }
   }
 
@@ -843,7 +843,7 @@
   char* mapAddress;
   int result;
   int fd;
-  size_t size;
+  size_t size = 0;
   const char* luser = NULL;
 
   int mmap_prot;
@@ -914,9 +914,12 @@
 
   if (*sizep == 0) {
     size = sharedmem_filesize(fd, CHECK);
-    assert(size != 0, "unexpected size");
+  } else {
+    size = *sizep;
   }
 
+  assert(size > 0, "unexpected size <= 0");
+
   mapAddress = (char*)::mmap((char*)0, size, mmap_prot, MAP_SHARED, fd, 0);
 
   // attempt to close the file - restart if it gets interrupted,
--- a/src/os/windows/vm/os_windows.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/os/windows/vm/os_windows.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -1182,6 +1182,9 @@
   } else if (strchr(pname, *os::path_separator()) != NULL) {
     int n;
     char** pelements = split_path(pname, &n);
+    if (pelements == NULL) {
+      return false;
+    }
     for (int i = 0 ; i < n ; i++) {
       char* path = pelements[i];
       // Really shouldn't be NULL, but check can't hurt
--- a/src/os/windows/vm/perfMemory_windows.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/os/windows/vm/perfMemory_windows.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -1581,7 +1581,7 @@
   ResourceMark rm;
 
   void *mapAddress = 0;
-  size_t size;
+  size_t size = 0;
   HANDLE fmh;
   DWORD ofm_access;
   DWORD mv_access;
@@ -1652,9 +1652,12 @@
 
   if (*sizep == 0) {
     size = sharedmem_filesize(rfilename, CHECK);
-    assert(size != 0, "unexpected size");
+  } else {
+    size = *sizep;
   }
 
+  assert(size > 0, "unexpected size <= 0");
+
   // Open the file mapping object with the given name
   fmh = open_sharedmem_object(robjectname, ofm_access, CHECK);
 
--- a/src/share/tools/launcher/wildcard.c	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/tools/launcher/wildcard.c	Mon Apr 15 08:49:14 2013 +0200
@@ -368,8 +368,10 @@
     const char *basename;
     FileList fl = FileList_new(16);
     WildcardIterator it = WildcardIterator_for(wildcard);
-    if (it == NULL)
+    if (it == NULL) {
+        FileList_free(fl);
         return NULL;
+    }
     while ((basename = WildcardIterator_next(it)) != NULL)
         if (isJarFileName(basename))
             FileList_add(fl, wildcardConcat(wildcard, basename));
--- a/src/share/vm/adlc/output_c.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/adlc/output_c.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -63,11 +63,10 @@
     RegDef *reg_def = NULL;
     RegDef *next = NULL;
     registers->reset_RegDefs();
-    for( reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next ) {
+    for (reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next) {
       next = registers->iter_RegDefs();
       const char *comma = (next != NULL) ? "," : " // no trailing comma";
-      fprintf(fp,"  \"%s\"%s\n",
-                 reg_def->_regname, comma );
+      fprintf(fp,"  \"%s\"%s\n", reg_def->_regname, comma);
     }
 
     // Finish defining enumeration
@@ -79,10 +78,10 @@
     reg_def = NULL;
     next = NULL;
     registers->reset_RegDefs();
-    for( reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next ) {
+    for (reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next) {
       next = registers->iter_RegDefs();
       const char *comma = (next != NULL) ? "," : " // no trailing comma";
-      fprintf(fp,"\t%s%s\n", reg_def->_concrete, comma );
+      fprintf(fp,"\t%s%s\n", reg_def->_concrete, comma);
     }
     // Finish defining array
     fprintf(fp,"\t};\n");
@@ -104,19 +103,17 @@
     RegDef *reg_def = NULL;
     RegDef *next    = NULL;
     registers->reset_RegDefs();
-    for( reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next ) {
+    for (reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next) {
       next = registers->iter_RegDefs();
       const char* register_encode = reg_def->register_encode();
       const char *comma = (next != NULL) ? "," : " // no trailing comma";
       int encval;
       if (!ADLParser::is_int_token(register_encode, encval)) {
-        fprintf(fp,"  %s%s  // %s\n",
-                register_encode, comma, reg_def->_regname );
+        fprintf(fp,"  %s%s  // %s\n", register_encode, comma, reg_def->_regname);
       } else {
         // Output known constants in hex char format (backward compatibility).
         assert(encval < 256, "Exceeded supported width for register encoding");
-        fprintf(fp,"  (unsigned char)'\\x%X'%s  // %s\n",
-                encval,          comma, reg_def->_regname );
+        fprintf(fp,"  (unsigned char)'\\x%X'%s  // %s\n", encval, comma, reg_def->_regname);
       }
     }
     // Finish defining enumeration
@@ -133,9 +130,10 @@
     fprintf(fp,"// Enumeration of register class names\n");
     fprintf(fp, "enum machRegisterClass {\n");
     registers->_rclasses.reset();
-    for( const char *class_name = NULL;
-         (class_name = registers->_rclasses.iter()) != NULL; ) {
-      fprintf(fp,"  %s,\n", toUpper( class_name ));
+    for (const char *class_name = NULL; (class_name = registers->_rclasses.iter()) != NULL;) {
+      const char * class_name_to_upper = toUpper(class_name);
+      fprintf(fp,"  %s,\n", class_name_to_upper);
+      delete[] class_name_to_upper;
     }
     // Finish defining enumeration
     fprintf(fp, "  _last_Mach_Reg_Class\n");
@@ -148,7 +146,7 @@
 void ArchDesc::declare_register_masks(FILE *fp_hpp) {
   const char  *rc_name;
 
-  if( _register ) {
+  if (_register) {
     // Build enumeration of user-defined register classes.
     defineRegClassEnum(fp_hpp, _register);
 
@@ -156,24 +154,27 @@
     fprintf(fp_hpp,"\n");
     fprintf(fp_hpp,"// Register masks, one for each register class.\n");
     _register->_rclasses.reset();
-    for( rc_name = NULL;
-         (rc_name = _register->_rclasses.iter()) != NULL; ) {
-      const char *prefix    = "";
-      RegClass   *reg_class = _register->getRegClass(rc_name);
-      assert( reg_class, "Using an undefined register class");
+    for (rc_name = NULL; (rc_name = _register->_rclasses.iter()) != NULL;) {
+      const char *prefix = "";
+      RegClass *reg_class = _register->getRegClass(rc_name);
+      assert(reg_class, "Using an undefined register class");
+
+      const char* rc_name_to_upper = toUpper(rc_name);
 
       if (reg_class->_user_defined == NULL) {
-        fprintf(fp_hpp, "extern const RegMask _%s%s_mask;\n", prefix, toUpper( rc_name ) );
-        fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { return _%s%s_mask; }\n", prefix, toUpper( rc_name ), prefix, toUpper( rc_name ));
+        fprintf(fp_hpp, "extern const RegMask _%s%s_mask;\n", prefix,  rc_name_to_upper);
+        fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { return _%s%s_mask; }\n", prefix, rc_name_to_upper, prefix, rc_name_to_upper);
       } else {
-        fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { %s }\n", prefix, toUpper( rc_name ), reg_class->_user_defined);
+        fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { %s }\n", prefix, rc_name_to_upper, reg_class->_user_defined);
       }
 
-      if( reg_class->_stack_or_reg ) {
+      if (reg_class->_stack_or_reg) {
         assert(reg_class->_user_defined == NULL, "no user defined reg class here");
-        fprintf(fp_hpp, "extern const RegMask _%sSTACK_OR_%s_mask;\n", prefix, toUpper( rc_name ) );
-        fprintf(fp_hpp, "inline const RegMask &%sSTACK_OR_%s_mask() { return _%sSTACK_OR_%s_mask; }\n", prefix, toUpper( rc_name ), prefix, toUpper( rc_name ) );
+        fprintf(fp_hpp, "extern const RegMask _%sSTACK_OR_%s_mask;\n", prefix, rc_name_to_upper);
+        fprintf(fp_hpp, "inline const RegMask &%sSTACK_OR_%s_mask() { return _%sSTACK_OR_%s_mask; }\n", prefix, rc_name_to_upper, prefix, rc_name_to_upper);
       }
+      delete[] rc_name_to_upper;
+
     }
   }
 }
@@ -183,34 +184,41 @@
 void ArchDesc::build_register_masks(FILE *fp_cpp) {
   const char  *rc_name;
 
-  if( _register ) {
+  if (_register) {
     // Generate a list of register masks, one for each class.
     fprintf(fp_cpp,"\n");
     fprintf(fp_cpp,"// Register masks, one for each register class.\n");
     _register->_rclasses.reset();
-    for( rc_name = NULL;
-         (rc_name = _register->_rclasses.iter()) != NULL; ) {
-      const char *prefix    = "";
-      RegClass   *reg_class = _register->getRegClass(rc_name);
-      assert( reg_class, "Using an undefined register class");
-
-      if (reg_class->_user_defined != NULL) continue;
+    for (rc_name = NULL; (rc_name = _register->_rclasses.iter()) != NULL;) {
+      const char *prefix = "";
+      RegClass *reg_class = _register->getRegClass(rc_name);
+      assert(reg_class, "Using an undefined register class");
+
+      if (reg_class->_user_defined != NULL) {
+        continue;
+      }
 
       int len = RegisterForm::RegMask_Size();
-      fprintf(fp_cpp, "const RegMask _%s%s_mask(", prefix, toUpper( rc_name ) );
-      { int i;
-        for( i = 0; i < len-1; i++ )
-          fprintf(fp_cpp," 0x%x,",reg_class->regs_in_word(i,false));
-        fprintf(fp_cpp," 0x%x );\n",reg_class->regs_in_word(i,false));
+      const char* rc_name_to_upper = toUpper(rc_name);
+      fprintf(fp_cpp, "const RegMask _%s%s_mask(", prefix, rc_name_to_upper);
+
+      {
+        int i;
+        for(i = 0; i < len - 1; i++) {
+          fprintf(fp_cpp," 0x%x,", reg_class->regs_in_word(i, false));
+        }
+        fprintf(fp_cpp," 0x%x );\n", reg_class->regs_in_word(i, false));
       }
 
-      if( reg_class->_stack_or_reg ) {
+      if (reg_class->_stack_or_reg) {
         int i;
-        fprintf(fp_cpp, "const RegMask _%sSTACK_OR_%s_mask(", prefix, toUpper( rc_name ) );
-        for( i = 0; i < len-1; i++ )
-          fprintf(fp_cpp," 0x%x,",reg_class->regs_in_word(i,true));
-        fprintf(fp_cpp," 0x%x );\n",reg_class->regs_in_word(i,true));
+        fprintf(fp_cpp, "const RegMask _%sSTACK_OR_%s_mask(", prefix, rc_name_to_upper);
+        for(i = 0; i < len - 1; i++) {
+          fprintf(fp_cpp," 0x%x,",reg_class->regs_in_word(i, true));
+        }
+        fprintf(fp_cpp," 0x%x );\n",reg_class->regs_in_word(i, true));
       }
+      delete[] rc_name_to_upper;
     }
   }
 }
@@ -2676,7 +2684,9 @@
       if (strcmp(first_reg_class, "stack_slots") == 0) {
         fprintf(fp,"  return &(Compile::current()->FIRST_STACK_mask());\n");
       } else {
-        fprintf(fp,"  return &%s_mask();\n", toUpper(first_reg_class));
+        const char* first_reg_class_to_upper = toUpper(first_reg_class);
+        fprintf(fp,"  return &%s_mask();\n", first_reg_class_to_upper);
+        delete[] first_reg_class_to_upper;
       }
     } else {
       // Build a switch statement to return the desired mask.
@@ -2688,7 +2698,9 @@
         if( !strcmp(reg_class, "stack_slots") ) {
           fprintf(fp, "  case %d: return &(Compile::current()->FIRST_STACK_mask());\n", index);
         } else {
-          fprintf(fp, "  case %d: return &%s_mask();\n", index, toUpper(reg_class));
+          const char* reg_class_to_upper = toUpper(reg_class);
+          fprintf(fp, "  case %d: return &%s_mask();\n", index, reg_class_to_upper);
+          delete[] reg_class_to_upper;
         }
       }
       fprintf(fp,"  }\n");
--- a/src/share/vm/adlc/output_h.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/adlc/output_h.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -2069,9 +2069,21 @@
   void closing()     { fprintf(_cpp, "  _LAST_MACH_OPER\n");
                        OutputMap::closing();
   }
-  void map(OpClassForm &opc)  { fprintf(_cpp, "  %s", _AD.machOperEnum(opc._ident) ); }
-  void map(OperandForm &oper) { fprintf(_cpp, "  %s", _AD.machOperEnum(oper._ident) ); }
-  void map(char        *name) { fprintf(_cpp, "  %s", _AD.machOperEnum(name)); }
+  void map(OpClassForm &opc)  {
+    const char* opc_ident_to_upper = _AD.machOperEnum(opc._ident);
+    fprintf(_cpp, "  %s", opc_ident_to_upper);
+    delete[] opc_ident_to_upper;
+  }
+  void map(OperandForm &oper) {
+    const char* oper_ident_to_upper = _AD.machOperEnum(oper._ident);
+    fprintf(_cpp, "  %s", oper_ident_to_upper);
+    delete[] oper_ident_to_upper;
+  }
+  void map(char *name) {
+    const char* name_to_upper = _AD.machOperEnum(name);
+    fprintf(_cpp, "  %s", name_to_upper);
+    delete[] name_to_upper;
+  }
 
   bool do_instructions()      { return false; }
   void map(InstructForm &inst){ assert( false, "ShouldNotCallThis()"); }
--- a/src/share/vm/c1/c1_LIRGenerator.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/c1/c1_LIRGenerator.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -711,25 +711,6 @@
   }
 }
 
-static Value maxvalue(IfOp* ifop) {
-  switch (ifop->cond()) {
-    case If::eql: return NULL;
-    case If::neq: return NULL;
-    case If::lss: // x <  y ? x : y
-    case If::leq: // x <= y ? x : y
-      if (ifop->x() == ifop->tval() &&
-          ifop->y() == ifop->fval()) return ifop->y();
-      return NULL;
-
-    case If::gtr: // x >  y ? y : x
-    case If::geq: // x >= y ? y : x
-      if (ifop->x() == ifop->tval() &&
-          ifop->y() == ifop->fval()) return ifop->y();
-      return NULL;
-
-  }
-}
-
 static ciType* phi_declared_type(Phi* phi) {
   ciType* t = phi->operand_at(0)->declared_type();
   if (t == NULL) {
--- a/src/share/vm/c1/c1_ValueMap.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/c1/c1_ValueMap.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -316,6 +316,7 @@
   ShortLoopOptimizer*   _short_loop_optimizer;
   Instruction*          _insertion_point;
   ValueStack *          _state;
+  bool                  _insert_is_pred;
 
   void set_invariant(Value v) const    { _gvn->set_processed(v); }
   bool is_invariant(Value v) const     { return _gvn->is_processed(v); }
@@ -339,6 +340,7 @@
 
   assert(insertion_block->end()->as_Base() == NULL, "cannot insert into entry block");
   _insertion_point = insertion_block->end()->prev();
+  _insert_is_pred = loop_header->is_predecessor(insertion_block);
 
   BlockEnd *block_end = insertion_block->end();
   _state = block_end->state_before();
@@ -379,13 +381,13 @@
     } else if (cur->as_LoadField() != NULL) {
       LoadField* lf = (LoadField*)cur;
       // deoptimizes on NullPointerException
-      cur_invariant = !lf->needs_patching() && !lf->field()->is_volatile() && !_short_loop_optimizer->has_field_store(lf->field()->type()->basic_type()) && is_invariant(lf->obj());
+      cur_invariant = !lf->needs_patching() && !lf->field()->is_volatile() && !_short_loop_optimizer->has_field_store(lf->field()->type()->basic_type()) && is_invariant(lf->obj()) && _insert_is_pred;
     } else if (cur->as_ArrayLength() != NULL) {
       ArrayLength *length = cur->as_ArrayLength();
       cur_invariant = is_invariant(length->array());
     } else if (cur->as_LoadIndexed() != NULL) {
       LoadIndexed *li = (LoadIndexed *)cur->as_LoadIndexed();
-      cur_invariant = !_short_loop_optimizer->has_indexed_store(as_BasicType(cur->type())) && is_invariant(li->array()) && is_invariant(li->index());
+      cur_invariant = !_short_loop_optimizer->has_indexed_store(as_BasicType(cur->type())) && is_invariant(li->array()) && is_invariant(li->index()) && _insert_is_pred;
     }
 
     if (cur_invariant) {
--- a/src/share/vm/classfile/classFileParser.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/classfile/classFileParser.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -1723,9 +1723,6 @@
       } else {
         coll->set_contended_group(0); // default contended group
       }
-      coll->set_contended(true);
-    } else {
-      coll->set_contended(false);
     }
   }
 }
--- a/src/share/vm/classfile/classFileParser.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/classfile/classFileParser.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -150,7 +150,6 @@
     void set_contended_group(u2 group) { _contended_group = group; }
     u2 contended_group() { return _contended_group; }
 
-    void set_contended(bool contended) { set_annotation(_sun_misc_Contended); }
     bool is_contended() { return has_annotation(_sun_misc_Contended); }
   };
 
--- a/src/share/vm/classfile/classLoaderData.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/classfile/classLoaderData.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -70,15 +70,19 @@
   _is_anonymous(is_anonymous), _keep_alive(is_anonymous), // initially
   _metaspace(NULL), _unloading(false), _klasses(NULL),
   _claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL),
-  _next(NULL), _dependencies(NULL),
+  _next(NULL), _dependencies(),
   _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true)) {
     // empty
 }
 
 void ClassLoaderData::init_dependencies(TRAPS) {
+  _dependencies.init(CHECK);
+}
+
+void ClassLoaderData::Dependencies::init(TRAPS) {
   // Create empty dependencies array to add to. CMS requires this to be
   // an oop so that it can track additions via card marks.  We think.
-  _dependencies = (oop)oopFactory::new_objectArray(2, CHECK);
+  _list_head = oopFactory::new_objectArray(2, CHECK);
 }
 
 bool ClassLoaderData::claim() {
@@ -95,13 +99,17 @@
   }
 
   f->do_oop(&_class_loader);
-  f->do_oop(&_dependencies);
+  _dependencies.oops_do(f);
   _handles->oops_do(f);
   if (klass_closure != NULL) {
     classes_do(klass_closure);
   }
 }
 
+void ClassLoaderData::Dependencies::oops_do(OopClosure* f) {
+  f->do_oop((oop*)&_list_head);
+}
+
 void ClassLoaderData::classes_do(KlassClosure* klass_closure) {
   for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
     klass_closure->do_klass(k);
@@ -154,14 +162,14 @@
   // It's a dependency we won't find through GC, add it. This is relatively rare
   // Must handle over GC point.
   Handle dependency(THREAD, to);
-  from_cld->add_dependency(dependency, CHECK);
+  from_cld->_dependencies.add(dependency, CHECK);
 }
 
 
-void ClassLoaderData::add_dependency(Handle dependency, TRAPS) {
+void ClassLoaderData::Dependencies::add(Handle dependency, TRAPS) {
   // Check first if this dependency is already in the list.
   // Save a pointer to the last to add to under the lock.
-  objArrayOop ok = (objArrayOop)_dependencies;
+  objArrayOop ok = _list_head;
   objArrayOop last = NULL;
   while (ok != NULL) {
     last = ok;
@@ -184,16 +192,17 @@
   objArrayHandle new_dependency(THREAD, deps);
 
   // Add the dependency under lock
-  locked_add_dependency(last_handle, new_dependency);
+  locked_add(last_handle, new_dependency, THREAD);
 }
 
-void ClassLoaderData::locked_add_dependency(objArrayHandle last_handle,
-                                            objArrayHandle new_dependency) {
+void ClassLoaderData::Dependencies::locked_add(objArrayHandle last_handle,
+                                               objArrayHandle new_dependency,
+                                               Thread* THREAD) {
 
   // Have to lock and put the new dependency on the end of the dependency
   // array so the card mark for CMS sees that this dependency is new.
   // Can probably do this lock free with some effort.
-  MutexLockerEx ml(metaspace_lock(),  Mutex::_no_safepoint_check_flag);
+  ObjectLocker ol(Handle(THREAD, _list_head), THREAD);
 
   oop loader_or_mirror = new_dependency->obj_at(0);
 
--- a/src/share/vm/classfile/classLoaderData.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/classfile/classLoaderData.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -93,6 +93,18 @@
 class ClassLoaderData : public CHeapObj<mtClass> {
   friend class VMStructs;
  private:
+  class Dependencies VALUE_OBJ_CLASS_SPEC {
+    objArrayOop _list_head;
+    void locked_add(objArrayHandle last,
+                    objArrayHandle new_dependency,
+                    Thread* THREAD);
+   public:
+    Dependencies() : _list_head(NULL) {}
+    void add(Handle dependency, TRAPS);
+    void init(TRAPS);
+    void oops_do(OopClosure* f);
+  };
+
   friend class ClassLoaderDataGraph;
   friend class ClassLoaderDataGraphMetaspaceIterator;
   friend class MetaDataFactory;
@@ -100,10 +112,11 @@
 
   static ClassLoaderData * _the_null_class_loader_data;
 
-  oop _class_loader;       // oop used to uniquely identify a class loader
-                           // class loader or a canonical class path
-  oop _dependencies;       // oop to hold dependencies from this class loader
-                           // data to others.
+  oop _class_loader;          // oop used to uniquely identify a class loader
+                              // class loader or a canonical class path
+  Dependencies _dependencies; // holds dependencies from this class loader
+                              // data to others.
+
   Metaspace * _metaspace;  // Meta-space where meta-data defined by the
                            // classes in the class loader are allocated.
   Mutex* _metaspace_lock;  // Locks the metaspace for allocations and setup.
@@ -134,9 +147,6 @@
   static Metaspace* _ro_metaspace;
   static Metaspace* _rw_metaspace;
 
-  void add_dependency(Handle dependency, TRAPS);
-  void locked_add_dependency(objArrayHandle last, objArrayHandle new_dependency);
-
   void set_next(ClassLoaderData* next) { _next = next; }
   ClassLoaderData* next() const        { return _next; }
 
--- a/src/share/vm/classfile/systemDictionary.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/classfile/systemDictionary.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -1592,9 +1592,10 @@
 // Used for assertions and verification only
 Klass* SystemDictionary::find_class(Symbol* class_name, ClassLoaderData* loader_data) {
   #ifndef ASSERT
-  guarantee(VerifyBeforeGC   ||
-            VerifyDuringGC   ||
-            VerifyBeforeExit ||
+  guarantee(VerifyBeforeGC      ||
+            VerifyDuringGC      ||
+            VerifyBeforeExit    ||
+            VerifyDuringStartup ||
             VerifyAfterGC, "too expensive");
   #endif
   assert_locked_or_safepoint(SystemDictionary_lock);
--- a/src/share/vm/classfile/systemDictionary.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/classfile/systemDictionary.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -199,8 +199,10 @@
   /* graal.api.code */                                                                                               \
   do_klass(Assumptions_klass,                     com_oracle_graal_api_code_Assumptions,                        Opt) \
   do_klass(Assumptions_ConcreteMethod_klass,      com_oracle_graal_api_code_Assumptions_ConcreteMethod,         Opt) \
+  do_klass(Assumptions_NoFinalizableSubclass_klass, com_oracle_graal_api_code_Assumptions_NoFinalizableSubclass, Opt) \
   do_klass(Assumptions_ConcreteSubtype_klass,     com_oracle_graal_api_code_Assumptions_ConcreteSubtype,        Opt) \
   do_klass(Assumptions_MethodContents_klass,      com_oracle_graal_api_code_Assumptions_MethodContents,         Opt) \
+  do_klass(Assumptions_CallSiteTargetValue_klass, com_oracle_graal_api_code_Assumptions_CallSiteTargetValue,    Opt) \
   do_klass(BytecodePosition_klass,                com_oracle_graal_api_code_BytecodePosition,                   Opt) \
   do_klass(DebugInfo_klass,                       com_oracle_graal_api_code_DebugInfo,                          Opt) \
   do_klass(BytecodeFrame_klass,                   com_oracle_graal_api_code_BytecodeFrame,                      Opt) \
@@ -209,8 +211,9 @@
   do_klass(CompilationResult_DataPatch_klass,     com_oracle_graal_api_code_CompilationResult_DataPatch,        Opt) \
   do_klass(CompilationResult_ExceptionHandler_klass, com_oracle_graal_api_code_CompilationResult_ExceptionHandler, Opt) \
   do_klass(CompilationResult_Mark_klass,          com_oracle_graal_api_code_CompilationResult_Mark,             Opt) \
-  do_klass(CompilationResult_Safepoint_klass,     com_oracle_graal_api_code_CompilationResult_Safepoint,        Opt) \
+  do_klass(CompilationResult_Infopoint_klass,     com_oracle_graal_api_code_CompilationResult_Infopoint,        Opt) \
   do_klass(CompilationResult_Site_klass,          com_oracle_graal_api_code_CompilationResult_Site,             Opt) \
+  do_klass(InfopointReason_klass,                 com_oracle_graal_api_code_InfopointReason,                    Opt) \
   do_klass(code_Register_klass,                   com_oracle_graal_api_code_Register,                           Opt) \
   do_klass(RegisterValue_klass,                   com_oracle_graal_api_code_RegisterValue,                      Opt) \
   do_klass(StackSlot_klass,                       com_oracle_graal_api_code_StackSlot,                          Opt) \
--- a/src/share/vm/classfile/verifier.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/classfile/verifier.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -63,6 +63,7 @@
 
 #define NOFAILOVER_MAJOR_VERSION                       51
 #define NONZERO_PADDING_BYTES_IN_SWITCH_MAJOR_VERSION  51
+#define STATIC_METHOD_IN_INTERFACE_MAJOR_VERSION       52
 
 // Access to external entry for VerifyClassCodes - old byte code verifier
 
@@ -2320,6 +2321,11 @@
       types = (1 << JVM_CONSTANT_InterfaceMethodref) |
               (1 << JVM_CONSTANT_Methodref);
       break;
+    case Bytecodes::_invokestatic:
+      types = (_klass->major_version() < STATIC_METHOD_IN_INTERFACE_MAJOR_VERSION) ?
+        (1 << JVM_CONSTANT_Methodref) :
+        ((1 << JVM_CONSTANT_InterfaceMethodref) | (1 << JVM_CONSTANT_Methodref));
+      break;
     default:
       types = 1 << JVM_CONSTANT_Methodref;
   }
--- a/src/share/vm/classfile/vmSymbols.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -299,6 +299,7 @@
   template(com_oracle_graal_hotspot_HotSpotCompilationResult,        "com/oracle/graal/hotspot/HotSpotCompilationResult")             \
   template(com_oracle_graal_hotspot_HotSpotRuntimeCallTarget,        "com/oracle/graal/hotspot/HotSpotRuntimeCallTarget")             \
   template(com_oracle_graal_hotspot_bridge_VMToCompiler,             "com/oracle/graal/hotspot/bridge/VMToCompiler")                  \
+  template(com_oracle_graal_hotspot_bridge_CompilerToVMImpl,         "com/oracle/graal/hotspot/bridge/CompilerToVMImpl")              \
   template(com_oracle_graal_hotspot_meta_HotSpotCodeInfo,            "com/oracle/graal/hotspot/meta/HotSpotCodeInfo")                 \
   template(com_oracle_graal_hotspot_meta_HotSpotInstalledCode,       "com/oracle/graal/hotspot/meta/HotSpotInstalledCode")            \
   template(com_oracle_graal_hotspot_meta_HotSpotJavaType,            "com/oracle/graal/hotspot/meta/HotSpotJavaType")                 \
@@ -322,14 +323,17 @@
   template(com_oracle_graal_api_code_Assumptions,                    "com/oracle/graal/api/code/Assumptions")                         \
   template(com_oracle_graal_api_code_Assumptions_MethodContents,     "com/oracle/graal/api/code/Assumptions$MethodContents")          \
   template(com_oracle_graal_api_code_Assumptions_ConcreteSubtype,    "com/oracle/graal/api/code/Assumptions$ConcreteSubtype")         \
+  template(com_oracle_graal_api_code_Assumptions_NoFinalizableSubclass, "com/oracle/graal/api/code/Assumptions$NoFinalizableSubclass") \
   template(com_oracle_graal_api_code_Assumptions_ConcreteMethod,     "com/oracle/graal/api/code/Assumptions$ConcreteMethod")          \
+  template(com_oracle_graal_api_code_Assumptions_CallSiteTargetValue,"com/oracle/graal/api/code/Assumptions$CallSiteTargetValue")     \
   template(com_oracle_graal_api_code_CompilationResult,              "com/oracle/graal/api/code/CompilationResult")                   \
   template(com_oracle_graal_api_code_CompilationResult_Call,         "com/oracle/graal/api/code/CompilationResult$Call")              \
   template(com_oracle_graal_api_code_CompilationResult_DataPatch,    "com/oracle/graal/api/code/CompilationResult$DataPatch")         \
   template(com_oracle_graal_api_code_CompilationResult_ExceptionHandler, "com/oracle/graal/api/code/CompilationResult$ExceptionHandler") \
   template(com_oracle_graal_api_code_CompilationResult_Mark,         "com/oracle/graal/api/code/CompilationResult$Mark")              \
-  template(com_oracle_graal_api_code_CompilationResult_Safepoint,    "com/oracle/graal/api/code/CompilationResult$Safepoint")         \
+  template(com_oracle_graal_api_code_CompilationResult_Infopoint,    "com/oracle/graal/api/code/CompilationResult$Infopoint")         \
   template(com_oracle_graal_api_code_CompilationResult_Site,         "com/oracle/graal/api/code/CompilationResult$Site")              \
+  template(com_oracle_graal_api_code_InfopointReason,                "com/oracle/graal/api/code/InfopointReason")                     \
   template(com_oracle_graal_api_code_BytecodeFrame,                  "com/oracle/graal/api/code/BytecodeFrame")                       \
   template(com_oracle_graal_api_code_BytecodePosition,               "com/oracle/graal/api/code/BytecodePosition")                    \
   template(com_oracle_graal_api_code_DebugInfo,                      "com/oracle/graal/api/code/DebugInfo")                           \
@@ -337,6 +341,7 @@
   template(com_oracle_graal_api_code_RegisterValue,                  "com/oracle/graal/api/code/RegisterValue")                       \
   template(com_oracle_graal_api_code_StackSlot,                      "com/oracle/graal/api/code/StackSlot")                           \
   template(com_oracle_graal_api_code_VirtualObject,                  "com/oracle/graal/api/code/VirtualObject")                       \
+  template(com_oracle_graal_api_code_InvalidInstalledCodeException,  "com/oracle/graal/api/code/InvalidInstalledCodeException")       \
   template(startCompiler_name,                    "startCompiler")                                                                    \
   template(bootstrap_name,                        "bootstrap")                                                                        \
   template(shutdownCompiler_name,                 "shutdownCompiler")                                                                 \
@@ -377,7 +382,6 @@
   template(forObject_name,                        "forObject")                                                                        \
   template(callbackInternal_name,                 "callbackInternal")                                                                 \
   template(callback_signature,                    "(Ljava/lang/Object;)Ljava/lang/Object;")                                           \
-  template(MethodInvalidatedException,            "com/oracle/graal/api/code/InstalledCode$MethodInvalidatedException")               \
   /* graal.api.interpreter */                                                                                                         \
   template(com_oracle_graal_api_interpreter_Interpreter,             "com/oracle/graal/api/interpreter/Interpreter")                  \
   template(interpreter_execute_name,              "execute")                                                                          \
@@ -1126,6 +1130,9 @@
   do_intrinsic(_Double_valueOf,           java_lang_Double,       valueOf_name, Double_valueOf_signature, F_S)          \
    do_name(     Double_valueOf_signature,                        "(D)Ljava/lang/Double;")                               \
                                                                                                                         \
+  do_intrinsic(_CompilerToVMImpl_executeCompiledMethod,           com_oracle_graal_hotspot_bridge_CompilerToVMImpl, executeCompiledMethod_name, CompilerToVMImpl_executeCompiledMethod_signature, F_SN)\
+   do_name(     CompilerToVMImpl_executeCompiledMethod_signature, "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;J)Ljava/lang/Object;")                               \
+   do_name(     executeCompiledMethod_name,                       "executeCompiledMethodIntrinsic")                     \
     /*end*/
 
 
--- a/src/share/vm/code/dependencies.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/code/dependencies.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -144,6 +144,11 @@
   assert_common_1(evol_method, DepValue(_oop_recorder, m));
 }
 
+void Dependencies::assert_has_no_finalizable_subclasses(Klass* ctxk) {
+  check_ctxk(ctxk);
+  assert_common_1(no_finalizable_subclasses, DepValue(_oop_recorder, ctxk));
+}
+
 void Dependencies::assert_leaf_type(Klass* ctxk) {
   if (ctxk->oop_is_array()) {
     // As a special case, support this assertion on an array type,
@@ -170,6 +175,10 @@
   check_ctxk(ctxk);
   assert_common_2(unique_concrete_method, DepValue(_oop_recorder, ctxk), DepValue(_oop_recorder, uniqm));
 }
+
+void Dependencies::assert_call_site_target_value(oop call_site, oop method_handle) {
+  assert_common_2(call_site_target_value, DepValue(_oop_recorder, JNIHandles::make_local(call_site)), DepValue(_oop_recorder, JNIHandles::make_local(method_handle)));
+}
 #endif // GRAAL
 
 
--- a/src/share/vm/code/dependencies.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/code/dependencies.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -360,9 +360,11 @@
 
  public:
   void assert_evol_method(Method* m);
+  void assert_has_no_finalizable_subclasses(Klass* ctxk);
   void assert_leaf_type(Klass* ctxk);
   void assert_unique_concrete_method(Klass* ctxk, Method* uniqm);
   void assert_abstract_with_unique_concrete_subtype(Klass* ctxk, Klass* conck);
+  void assert_call_site_target_value(oop callSite, oop methodHandle);
 #endif // GRAAL
 
   // Define whether a given method or type is concrete.
--- a/src/share/vm/code/nmethod.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/code/nmethod.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -1307,10 +1307,12 @@
   }
 
 #ifdef GRAAL
-    if (_graal_installed_code != NULL) {
-      HotSpotInstalledCode::set_nmethod(_graal_installed_code, 0);
-      _graal_installed_code = NULL;
-    }
+  // The method can only be unloaded after the pointer to the installed code
+  // Java wrapper is no longer alive. Here we need to clear out this weak
+  // reference to the dead object.
+  if (_graal_installed_code != NULL) {
+    _graal_installed_code = NULL;
+  }
 #endif
 
   // Make the class unloaded - i.e., change state and notify sweeper
@@ -1394,18 +1396,17 @@
       return false;
     }
 
-#ifdef GRAAL
-    if (_graal_installed_code != NULL) {
-      HotSpotInstalledCode::set_nmethod(_graal_installed_code, 0);
-      _graal_installed_code = NULL;
-    }
-#endif
-
     // The caller can be calling the method statically or through an inline
     // cache call.
     if (!is_osr_method() && !is_not_entrant()) {
-      NativeJump::patch_verified_entry(entry_point(), verified_entry_point(),
-                  SharedRuntime::get_handle_wrong_method_stub());
+      address stub = SharedRuntime::get_handle_wrong_method_stub();
+#ifdef GRAAL
+      if (_graal_installed_code != NULL && !HotSpotInstalledCode::isDefault(_graal_installed_code)) {
+        // This was manually installed machine code. Patch entry with stub that throws an exception.
+        stub = SharedRuntime::get_deoptimized_installed_code_stub();
+      }
+#endif
+      NativeJump::patch_verified_entry(entry_point(), verified_entry_point(), stub);
     }
 
     if (is_in_use()) {
--- a/src/share/vm/compiler/compileBroker.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/compiler/compileBroker.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -1225,12 +1225,9 @@
   assert(method->method_holder()->oop_is_instance(), "not an instance method");
   assert(osr_bci == InvocationEntryBci || (0 <= osr_bci && osr_bci < method->code_size()), "bci out of range");
   assert(!method->is_abstract() && (osr_bci == InvocationEntryBci || !method->is_native()), "cannot compile abstract/native methods");
-  assert(!method->method_holder()->is_not_initialized(), "method holder must be initialized");
-
-  if (!TieredCompilation) {
-    comp_level = CompLevel_highest_tier;
-  }
-
+  assert(!method->method_holder()->is_not_initialized() || method->intrinsic_id() == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod, "method holder must be initialized");
+  // allow any levels for WhiteBox
+  assert(WhiteBoxAPI || TieredCompilation || comp_level == CompLevel_highest_tier, "only CompLevel_highest_tier must be used in non-tiered");
   // return quickly if possible
 
   // lock, make sure that the compilation
--- a/src/share/vm/compiler/compileLog.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/compiler/compileLog.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -60,28 +60,6 @@
 }
 
 
-// Advance kind up to a null or space, return this tail.
-// Make sure kind is null-terminated, not space-terminated.
-// Use the buffer if necessary.
-static const char* split_attrs(const char* &kind, char* buffer) {
-  const char* attrs = strchr(kind, ' ');
-  // Tease apart the first word from the rest:
-  if (attrs == NULL) {
-    return "";  // no attrs, no split
-  } else if (kind == buffer) {
-    ((char*) attrs)[-1] = 0;
-    return attrs;
-  } else {
-    // park it in the buffer, so we can put a null on the end
-    assert(!(kind >= buffer && kind < buffer+100), "not obviously in buffer");
-    int klen = attrs - kind;
-    strncpy(buffer, kind, klen);
-    buffer[klen] = 0;
-    kind = buffer;  // return by reference
-    return attrs;
-  }
-}
-
 // see_tag, pop_tag:  Override the default do-nothing methods on xmlStream.
 // These methods provide a hook for managing the the extra context markup.
 void CompileLog::see_tag(const char* tag, bool push) {
--- a/src/share/vm/compiler/compilerOracle.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/compiler/compilerOracle.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -237,13 +237,6 @@
   "help"
 };
 
-static const char * command_name(OracleCommand command) {
-  if (command < OracleFirstCommand || command >= OracleCommandCount) {
-    return "unknown command";
-  }
-  return command_names[command];
-}
-
 class MethodMatcher;
 static MethodMatcher* lists[OracleCommandCount] = { 0, };
 
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -48,6 +48,7 @@
 #include "memory/iterator.hpp"
 #include "memory/referencePolicy.hpp"
 #include "memory/resourceArea.hpp"
+#include "memory/tenuredGeneration.hpp"
 #include "oops/oop.inline.hpp"
 #include "prims/jvmtiExport.hpp"
 #include "runtime/globals_extension.hpp"
@@ -916,7 +917,31 @@
     return;
   }
 
-  size_t expand_bytes = 0;
+  // Compute some numbers about the state of the heap.
+  const size_t used_after_gc = used();
+  const size_t capacity_after_gc = capacity();
+
+  CardGeneration::compute_new_size();
+
+  // Reset again after a possible resizing
+  cmsSpace()->reset_after_compaction();
+
+  assert(used() == used_after_gc && used_after_gc <= capacity(),
+         err_msg("used: " SIZE_FORMAT " used_after_gc: " SIZE_FORMAT
+         " capacity: " SIZE_FORMAT, used(), used_after_gc, capacity()));
+}
+
+void ConcurrentMarkSweepGeneration::compute_new_size_free_list() {
+  assert_locked_or_safepoint(Heap_lock);
+
+  // If incremental collection failed, we just want to expand
+  // to the limit.
+  if (incremental_collection_failed()) {
+    clear_incremental_collection_failed();
+    grow_to_reserved();
+    return;
+  }
+
   double free_percentage = ((double) free()) / capacity();
   double desired_free_percentage = (double) MinHeapFreeRatio / 100;
   double maximum_free_percentage = (double) MaxHeapFreeRatio / 100;
@@ -925,9 +950,7 @@
   if (free_percentage < desired_free_percentage) {
     size_t desired_capacity = (size_t)(used() / ((double) 1 - desired_free_percentage));
     assert(desired_capacity >= capacity(), "invalid expansion size");
-    expand_bytes = MAX2(desired_capacity - capacity(), MinHeapDeltaBytes);
-  }
-  if (expand_bytes > 0) {
+    size_t expand_bytes = MAX2(desired_capacity - capacity(), MinHeapDeltaBytes);
     if (PrintGCDetails && Verbose) {
       size_t desired_capacity = (size_t)(used() / ((double) 1 - desired_free_percentage));
       gclog_or_tty->print_cr("\nFrom compute_new_size: ");
@@ -961,6 +984,14 @@
       gclog_or_tty->print_cr("  Expanded free fraction %f",
         ((double) free()) / capacity());
     }
+  } else {
+    size_t desired_capacity = (size_t)(used() / ((double) 1 - desired_free_percentage));
+    assert(desired_capacity <= capacity(), "invalid expansion size");
+    size_t shrink_bytes = capacity() - desired_capacity;
+    // Don't shrink unless the delta is greater than the minimum shrink we want
+    if (shrink_bytes >= MinHeapDeltaBytes) {
+      shrink_free_list_by(shrink_bytes);
+    }
   }
 }
 
@@ -1872,7 +1903,7 @@
   assert_locked_or_safepoint(Heap_lock);
   FreelistLocker z(this);
   MetaspaceGC::compute_new_size();
-  _cmsGen->compute_new_size();
+  _cmsGen->compute_new_size_free_list();
 }
 
 // A work method used by foreground collection to determine
@@ -2601,6 +2632,10 @@
 }
 
 void ConcurrentMarkSweepGeneration::gc_prologue(bool full) {
+
+  _capacity_at_prologue = capacity();
+  _used_at_prologue = used();
+
   // Delegate to CMScollector which knows how to coordinate between
   // this and any other CMS generations that it is responsible for
   // collecting.
@@ -2774,6 +2809,23 @@
   }
 }
 
+
+void
+CMSCollector::print_on_error(outputStream* st) {
+  CMSCollector* collector = ConcurrentMarkSweepGeneration::_collector;
+  if (collector != NULL) {
+    CMSBitMap* bitmap = &collector->_markBitMap;
+    st->print_cr("Marking Bits: (CMSBitMap*) " PTR_FORMAT, bitmap);
+    bitmap->print_on_error(st, " Bits: ");
+
+    st->cr();
+
+    CMSBitMap* mut_bitmap = &collector->_modUnionTable;
+    st->print_cr("Mod Union Table: (CMSBitMap*) " PTR_FORMAT, mut_bitmap);
+    mut_bitmap->print_on_error(st, " Bits: ");
+  }
+}
+
 ////////////////////////////////////////////////////////
 // CMS Verification Support
 ////////////////////////////////////////////////////////
@@ -3300,6 +3352,26 @@
 }
 
 
+void ConcurrentMarkSweepGeneration::shrink_by(size_t bytes) {
+  assert_locked_or_safepoint(ExpandHeap_lock);
+  // Shrink committed space
+  _virtual_space.shrink_by(bytes);
+  // Shrink space; this also shrinks the space's BOT
+  _cmsSpace->set_end((HeapWord*) _virtual_space.high());
+  size_t new_word_size = heap_word_size(_cmsSpace->capacity());
+  // Shrink the shared block offset array
+  _bts->resize(new_word_size);
+  MemRegion mr(_cmsSpace->bottom(), new_word_size);
+  // Shrink the card table
+  Universe::heap()->barrier_set()->resize_covered_region(mr);
+
+  if (Verbose && PrintGC) {
+    size_t new_mem_size = _virtual_space.committed_size();
+    size_t old_mem_size = new_mem_size + bytes;
+    gclog_or_tty->print_cr("Shrinking %s from " SIZE_FORMAT "K to " SIZE_FORMAT "K",
+                  name(), old_mem_size/K, new_mem_size/K);
+  }
+}
 
 void ConcurrentMarkSweepGeneration::shrink(size_t bytes) {
   assert_locked_or_safepoint(Heap_lock);
@@ -3351,7 +3423,7 @@
   return success;
 }
 
-void ConcurrentMarkSweepGeneration::shrink_by(size_t bytes) {
+void ConcurrentMarkSweepGeneration::shrink_free_list_by(size_t bytes) {
   assert_locked_or_safepoint(Heap_lock);
   assert_lock_strong(freelistLock());
   // XXX Fix when compaction is implemented.
@@ -6476,6 +6548,10 @@
   }
 }
 
+void CMSBitMap::print_on_error(outputStream* st, const char* prefix) const {
+  _bm.print_on_error(st, prefix);
+}
+
 #ifndef PRODUCT
 void CMSBitMap::assert_locked() const {
   CMSLockVerifier::assert_locked(lock());
@@ -9074,51 +9150,6 @@
   }
 }
 
-// The desired expansion delta is computed so that:
-// . desired free percentage or greater is used
-void ASConcurrentMarkSweepGeneration::compute_new_size() {
-  assert_locked_or_safepoint(Heap_lock);
-
-  GenCollectedHeap* gch = (GenCollectedHeap*) GenCollectedHeap::heap();
-
-  // If incremental collection failed, we just want to expand
-  // to the limit.
-  if (incremental_collection_failed()) {
-    clear_incremental_collection_failed();
-    grow_to_reserved();
-    return;
-  }
-
-  assert(UseAdaptiveSizePolicy, "Should be using adaptive sizing");
-
-  assert(gch->kind() == CollectedHeap::GenCollectedHeap,
-    "Wrong type of heap");
-  int prev_level = level() - 1;
-  assert(prev_level >= 0, "The cms generation is the lowest generation");
-  Generation* prev_gen = gch->get_gen(prev_level);
-  assert(prev_gen->kind() == Generation::ASParNew,
-    "Wrong type of young generation");
-  ParNewGeneration* younger_gen = (ParNewGeneration*) prev_gen;
-  size_t cur_eden = younger_gen->eden()->capacity();
-  CMSAdaptiveSizePolicy* size_policy = cms_size_policy();
-  size_t cur_promo = free();
-  size_policy->compute_tenured_generation_free_space(cur_promo,
-                                                       max_available(),
-                                                       cur_eden);
-  resize(cur_promo, size_policy->promo_size());
-
-  // Record the new size of the space in the cms generation
-  // that is available for promotions.  This is temporary.
-  // It should be the desired promo size.
-  size_policy->avg_cms_promo()->sample(free());
-  size_policy->avg_old_live()->sample(used());
-
-  if (UsePerfData) {
-    CMSGCAdaptivePolicyCounters* counters = gc_adaptive_policy_counters();
-    counters->update_cms_capacity_counter(capacity());
-  }
-}
-
 void ASConcurrentMarkSweepGeneration::shrink_by(size_t desired_bytes) {
   assert_locked_or_safepoint(Heap_lock);
   assert_lock_strong(freelistLock());
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -60,6 +60,7 @@
 class FreeChunk;
 class PromotionInfo;
 class ScanMarkedObjectsAgainCarefullyClosure;
+class TenuredGeneration;
 
 // A generic CMS bit map. It's the basis for both the CMS marking bit map
 // as well as for the mod union table (in each case only a subset of the
@@ -150,6 +151,8 @@
   size_t    heapWordToOffset(HeapWord* addr) const;
   size_t    heapWordDiffToOffsetDiff(size_t diff) const;
 
+  void print_on_error(outputStream* st, const char* prefix) const;
+
   // debugging
   // is this address range covered by the bit-map?
   NOT_PRODUCT(
@@ -810,9 +813,6 @@
   // used regions of each generation to limit the extent of sweep
   void save_sweep_limits();
 
-  // Resize the generations included in the collector.
-  void compute_new_size();
-
   // A work method used by foreground collection to determine
   // what type of collection (compacting or not, continuing or fresh)
   // it should do.
@@ -909,6 +909,9 @@
   void releaseFreelistLocks() const;
   bool haveFreelistLocks() const;
 
+  // Adjust size of underlying generation
+  void compute_new_size();
+
   // GC prologue and epilogue
   void gc_prologue(bool full);
   void gc_epilogue(bool full);
@@ -983,6 +986,8 @@
   CMSAdaptiveSizePolicy* size_policy();
   CMSGCAdaptivePolicyCounters* gc_adaptive_policy_counters();
 
+  static void print_on_error(outputStream* st);
+
   // debugging
   void verify();
   bool verify_after_remark();
@@ -1082,7 +1087,7 @@
 
  protected:
   // Shrink generation by specified size (returns false if unable to shrink)
-  virtual void shrink_by(size_t bytes);
+  void shrink_free_list_by(size_t bytes);
 
   // Update statistics for GC
   virtual void update_gc_stats(int level, bool full);
@@ -1233,6 +1238,7 @@
     CMSExpansionCause::Cause cause);
   virtual bool expand(size_t bytes, size_t expand_bytes);
   void shrink(size_t bytes);
+  void shrink_by(size_t bytes);
   HeapWord* expand_and_par_lab_allocate(CMSParGCThreadState* ps, size_t word_sz);
   bool expand_and_ensure_spooling_space(PromotionInfo* promo);
 
@@ -1293,7 +1299,13 @@
   bool must_be_youngest() const { return false; }
   bool must_be_oldest()   const { return true; }
 
-  void compute_new_size();
+  // Resize the generation after a compacting GC.  The
+  // generation can be treated as a contiguous space
+  // after the compaction.
+  virtual void compute_new_size();
+  // Resize the generation after a non-compacting
+  // collection.
+  void compute_new_size_free_list();
 
   CollectionTypes debug_collection_type() { return _debug_collection_type; }
   void rotate_debug_collection_type();
@@ -1315,7 +1327,6 @@
   virtual void shrink_by(size_t bytes);
 
  public:
-  virtual void compute_new_size();
   ASConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size,
                                   int level, CardTableRS* ct,
                                   bool use_adaptive_freelists,
--- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -101,6 +101,10 @@
 }
 #endif
 
+void CMBitMapRO::print_on_error(outputStream* st, const char* prefix) const {
+  _bm.print_on_error(st, prefix);
+}
+
 bool CMBitMap::allocate(ReservedSpace heap_rs) {
   _bmStartWord = (HeapWord*)(heap_rs.base());
   _bmWordSize  = heap_rs.size()/HeapWordSize;    // heap_rs.size() is in bytes
@@ -3277,6 +3281,13 @@
   }
 }
 
+void ConcurrentMark::print_on_error(outputStream* st) const {
+  st->print_cr("Marking Bits (Prev, Next): (CMBitMap*) " PTR_FORMAT ", (CMBitMap*) " PTR_FORMAT,
+      _prevMarkBitMap, _nextMarkBitMap);
+  _prevMarkBitMap->print_on_error(st, " Prev Bits: ");
+  _nextMarkBitMap->print_on_error(st, " Next Bits: ");
+}
+
 // We take a break if someone is trying to stop the world.
 bool ConcurrentMark::do_yield_check(uint worker_id) {
   if (should_yield()) {
--- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -113,6 +113,8 @@
     return res;
   }
 
+  void print_on_error(outputStream* st, const char* prefix) const;
+
   // debugging
   NOT_PRODUCT(bool covers(ReservedSpace rs) const;)
 };
@@ -829,6 +831,8 @@
 
   void print_worker_threads_on(outputStream* st) const;
 
+  void print_on_error(outputStream* st) const;
+
   // The following indicate whether a given verbose level has been
   // set. Notice that anything above stats is conditional to
   // _MARKING_VERBOSE_ having been set to 1
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -3437,6 +3437,15 @@
   heap_region_iterate(&blk);
 }
 
+void G1CollectedHeap::print_on_error(outputStream* st) const {
+  this->CollectedHeap::print_on_error(st);
+
+  if (_cm != NULL) {
+    st->cr();
+    _cm->print_on_error(st);
+  }
+}
+
 void G1CollectedHeap::print_gc_threads_on(outputStream* st) const {
   if (G1CollectedHeap::use_parallel_gc_threads()) {
     workers()->print_worker_threads_on(st);
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -1581,6 +1581,7 @@
   virtual void verify(bool silent);
   virtual void print_on(outputStream* st) const;
   virtual void print_extended_on(outputStream* st) const;
+  virtual void print_on_error(outputStream* st) const;
 
   virtual void print_gc_threads_on(outputStream* st) const;
   virtual void gc_threads_do(ThreadClosure* tc) const;
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -1359,18 +1359,6 @@
 #endif // PRODUCT
 }
 
-#ifndef PRODUCT
-// for debugging, bit of a hack...
-static char*
-region_num_to_mbs(int length) {
-  static char buffer[64];
-  double bytes = (double) (length * HeapRegion::GrainBytes);
-  double mbs = bytes / (double) (1024 * 1024);
-  sprintf(buffer, "%7.2lfMB", mbs);
-  return buffer;
-}
-#endif // PRODUCT
-
 uint G1CollectorPolicy::max_regions(int purpose) {
   switch (purpose) {
     case GCAllocForSurvived:
--- a/src/share/vm/gc_implementation/g1/ptrQueue.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/gc_implementation/g1/ptrQueue.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -53,15 +53,6 @@
 }
 
 
-static int byte_index_to_index(int ind) {
-  assert((ind % oopSize) == 0, "Invariant.");
-  return ind / oopSize;
-}
-
-static int index_to_byte_index(int byte_ind) {
-  return byte_ind * oopSize;
-}
-
 void PtrQueue::enqueue_known_active(void* ptr) {
   assert(0 <= _index && _index <= _sz, "Invariant.");
   assert(_index == 0 || _buf != NULL, "invariant");
--- a/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -173,6 +173,12 @@
   void reset_counters();
 #endif  // #ifndef PRODUCT
 
+  void print_on_error(outputStream* st) const {
+    st->print_cr("Marking Bits: (ParMarkBitMap*) " PTR_FORMAT, this);
+    _beg_bits.print_on_error(st, " Begin Bits: ");
+    _end_bits.print_on_error(st, " End Bits:   ");
+  }
+
 #ifdef  ASSERT
   void verify_clear() const;
   inline void verify_bit(idx_t bit) const;
--- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -648,6 +648,15 @@
   MetaspaceAux::print_on(st);
 }
 
+void ParallelScavengeHeap::print_on_error(outputStream* st) const {
+  this->CollectedHeap::print_on_error(st);
+
+  if (UseParallelOldGC) {
+    st->cr();
+    PSParallelCompact::print_on_error(st);
+  }
+}
+
 void ParallelScavengeHeap::gc_threads_do(ThreadClosure* tc) const {
   PSScavenge::gc_task_manager()->threads_do(tc);
 }
--- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -220,6 +220,7 @@
 
   void prepare_for_verify();
   virtual void print_on(outputStream* st) const;
+  virtual void print_on_error(outputStream* st) const;
   virtual void print_gc_threads_on(outputStream* st) const;
   virtual void gc_threads_do(ThreadClosure* tc) const;
   virtual void print_tracing_info() const;
--- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -165,6 +165,10 @@
 #endif  // #ifdef ASSERT
 
 
+void PSParallelCompact::print_on_error(outputStream* st) {
+  _mark_bitmap.print_on_error(st);
+}
+
 #ifndef PRODUCT
 const char* PSParallelCompact::space_names[] = {
   "old ", "eden", "from", "to  "
--- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -1163,6 +1163,8 @@
   // Time since last full gc (in milliseconds).
   static jlong millis_since_last_gc();
 
+  static void print_on_error(outputStream* st);
+
 #ifndef PRODUCT
   // Debugging support.
   static const char* space_names[last_space_id];
--- a/src/share/vm/gc_interface/collectedHeap.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/gc_interface/collectedHeap.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -567,6 +567,14 @@
     print_on(st);
   }
 
+  virtual void print_on_error(outputStream* st) const {
+    st->print_cr("Heap:");
+    print_extended_on(st);
+    st->cr();
+
+    _barrier_set->print_on(st);
+  }
+
   // Print all GC threads (other than the VM thread)
   // used by this heap.
   virtual void print_gc_threads_on(outputStream* st) const = 0;
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -236,7 +236,7 @@
     for (jint i = 0; i < values->length(); i++) {
       ScopeValue* cur_second = NULL;
       ScopeValue* value = get_hotspot_value(((oop*) values->base(T_OBJECT))[i], total_frame_size, objects, cur_second, oop_recorder);
-      
+
       if (isLongArray && cur_second == NULL) {
         // we're trying to put ints into a long array... this isn't really valid, but it's used for some optimizations.
         // add an int 0 constant
@@ -294,10 +294,14 @@
       if (!assumption.is_null()) {
         if (assumption->klass() == Assumptions_MethodContents::klass()) {
           assumption_MethodContents(assumption);
+        } else if (assumption->klass() == Assumptions_NoFinalizableSubclass::klass()) {
+          assumption_NoFinalizableSubclass(assumption);
         } else if (assumption->klass() == Assumptions_ConcreteSubtype::klass()) {
           assumption_ConcreteSubtype(assumption);
         } else if (assumption->klass() == Assumptions_ConcreteMethod::klass()) {
           assumption_ConcreteMethod(assumption);
+        } else if (assumption->klass() == Assumptions_CallSiteTargetValue::klass()) {
+          assumption_CallSiteTargetValue(assumption);
         } else {
           assumption->print();
           fatal("unexpected Assumption subclass");
@@ -350,7 +354,7 @@
 // constructor used to create a stub
 CodeInstaller::CodeInstaller(Handle& target_method, BufferBlob*& blob, jlong& id) {
   No_Safepoint_Verifier no_safepoint;
-  
+
   _oop_recorder = new OopRecorder(&_arena);
   initialize_fields(target_method(), NULL);
   assert(_name != NULL, "installMethod needs NON-NULL name");
@@ -398,7 +402,7 @@
 
   _debug_recorder = new DebugInformationRecorder(_oop_recorder);
   _debug_recorder->set_oopmaps(new OopMapSet());
-  
+
   buffer.initialize_oop_recorder(_oop_recorder);
 
   _instructions = buffer.insts();
@@ -416,9 +420,17 @@
     if (site->is_a(CompilationResult_Call::klass())) {
       TRACE_graal_4("call at %i", pc_offset);
       site_Call(buffer, pc_offset, site);
-    } else if (site->is_a(CompilationResult_Safepoint::klass())) {
-      TRACE_graal_4("safepoint at %i", pc_offset);
-      site_Safepoint(buffer, pc_offset, site);
+    } else if (site->is_a(CompilationResult_Infopoint::klass())) {
+      // three reasons for infopoints denote actual safepoints
+      oop reason = CompilationResult_Infopoint::reason(site);
+      if (InfopointReason::SAFEPOINT() == reason || InfopointReason::CALL() == reason || InfopointReason::IMPLICIT_EXCEPTION() == reason) {
+        TRACE_graal_4("safepoint at %i", pc_offset);
+        site_Safepoint(buffer, pc_offset, site);
+      } else {
+        // if the infopoint is not an actual safepoint, it must have one of the other reasons
+        // (safeguard against new safepoint types that require handling above)
+        assert(InfopointReason::METHOD_START() == reason || InfopointReason::METHOD_END() == reason || InfopointReason::LINE_NUMBER() == reason, "");
+      }
     } else if (site->is_a(CompilationResult_DataPatch::klass())) {
       TRACE_graal_4("datapatch at %i", pc_offset);
       site_DataPatch(buffer, pc_offset, site);
@@ -437,6 +449,12 @@
   _dependencies->assert_evol_method(method());
 }
 
+void CodeInstaller::assumption_NoFinalizableSubclass(Handle assumption) {
+  Handle receiverType_handle = Assumptions_NoFinalizableSubclass::receiverType(assumption());
+  Klass* receiverType = asKlass(HotSpotResolvedObjectType::metaspaceKlass(receiverType_handle));
+  _dependencies->assert_has_no_finalizable_subclasses(receiverType);
+}
+
 void CodeInstaller::assumption_ConcreteSubtype(Handle assumption) {
   Handle context_handle = Assumptions_ConcreteSubtype::context(assumption());
   Handle subtype_handle = Assumptions_ConcreteSubtype::subtype(assumption());
@@ -460,6 +478,13 @@
   _dependencies->assert_unique_concrete_method(context, impl());
 }
 
+void CodeInstaller::assumption_CallSiteTargetValue(Handle assumption) {
+  Handle callSite = Assumptions_CallSiteTargetValue::callSite(assumption());
+  Handle methodHandle = Assumptions_CallSiteTargetValue::methodHandle(assumption());
+
+  _dependencies->assert_call_site_target_value(callSite(), methodHandle());
+}
+
 void CodeInstaller::process_exception_handlers() {
   // allocate some arrays for use by the collection code.
   const int num_handlers = 5;
@@ -578,7 +603,7 @@
 }
 
 void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site) {
-  oop debug_info = CompilationResult_Safepoint::debugInfo(site);
+  oop debug_info = CompilationResult_Infopoint::debugInfo(site);
   assert(debug_info != NULL, "debug info expected");
 
   // address instruction = _instructions->start() + pc_offset;
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -93,8 +93,10 @@
   void initialize_buffer(CodeBuffer& buffer);
 
   void assumption_MethodContents(Handle assumption);
+  void assumption_NoFinalizableSubclass(Handle assumption);
   void assumption_ConcreteSubtype(Handle assumption);
   void assumption_ConcreteMethod(Handle assumption);
+  void assumption_CallSiteTargetValue(Handle assumption);
 
   void site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site);
   void site_Call(CodeBuffer& buffer, jint pc_offset, oop site);
--- a/src/share/vm/graal/graalCompiler.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/graal/graalCompiler.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -91,6 +91,10 @@
       VMToCompiler::startCompiler();
       _initialized = true;
       if (BootstrapGraal) {
+        // We turn off CompileTheWorld and complete the VM startup so that
+        // Graal can be compiled by C1/C2 when we do a CTW.
+        NOT_PRODUCT(CompileTheWorld = false);
+        CompilationPolicy::completed_vm_startup();
         VMToCompiler::bootstrap();
       }
     }
--- a/src/share/vm/graal/graalCompiler.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/graal/graalCompiler.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -68,7 +68,7 @@
 
   // Print compilation timers and statistics
   virtual void print_timers();
-  
+
   static Handle get_JavaTypeFromSignature(Symbol* signature, KlassHandle accessor, TRAPS);
   static Handle get_JavaType(constantPoolHandle cp, int index, KlassHandle accessor, TRAPS);
   static Handle get_JavaType(Symbol* klass_name, TRAPS);
@@ -93,6 +93,26 @@
     return ((index & 0xFF) << 8) | (index >> 8);
   }
 
+  static int to_index_u4(int index) {
+    // Swap.
+    return ((index & 0xFF) << 24) | ((index & 0xFF00) << 8) | ((index & 0xFF0000) >> 8) | ((index & 0xFF000000) >> 24);
+  }
+
+  static int to_cp_index(int raw_index, Bytecodes::Code bc) {
+    int cp_index;
+    if (bc == Bytecodes::_invokedynamic) {
+      cp_index = to_index_u4(raw_index);
+      assert(ConstantPool::is_invokedynamic_index(cp_index), "not an invokedynamic constant pool index");
+    } else {
+      assert(bc == Bytecodes::_getfield        || bc == Bytecodes::_putfield  ||
+             bc == Bytecodes::_getstatic       || bc == Bytecodes::_putstatic ||
+             bc == Bytecodes::_invokeinterface || bc == Bytecodes::_invokevirtual ||
+             bc == Bytecodes::_invokespecial   || bc == Bytecodes::_invokestatic, err_msg("unexpected invoke opcode: %d %s", bc, Bytecodes::name(bc)));
+      cp_index = to_cp_index_u2(raw_index);
+    }
+    return cp_index;
+  }
+
   static void initialize_buffer_blob();
 };
 
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -62,7 +62,7 @@
 C2V_ENTRY(jbyteArray, initializeBytecode, (JNIEnv *env, jobject, jlong metaspace_method, jbyteArray result))
   methodHandle method = asMethod(metaspace_method);
   ResourceMark rm;
-  
+
   int code_size = method->code_size();
   jbyte* reconstituted_code = NULL;
 
@@ -320,6 +320,11 @@
   return code == NULL ? 0 : code->insts_size();
 C2V_END
 
+C2V_VMENTRY(jint, constantPoolLength, (JNIEnv *env, jobject, jobject type))
+  ConstantPool* cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants();
+  return cp->length();
+C2V_END
+
 C2V_VMENTRY(jobject, lookupType, (JNIEnv *env, jobject, jstring jname, jobject accessingClass, jboolean eagerResolve))
   ResourceMark rm;
 
@@ -416,12 +421,22 @@
   return JNIHandles::make_local(THREAD, result);
 C2V_END
 
+C2V_VMENTRY(jobject, lookupAppendixInPool, (JNIEnv *env, jobject, jobject type, jint index, jbyte opcode))
+  Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF);
+  index = GraalCompiler::to_cp_index(index, bc);
+  constantPoolHandle cpool(InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants());
+  oop appendix_oop = ConstantPool::appendix_at_if_loaded(cpool, index);
+
+  return JNIHandles::make_local(THREAD, appendix_oop);
+C2V_END
+
 C2V_VMENTRY(jobject, lookupMethodInPool, (JNIEnv *env, jobject, jobject type, jint index, jbyte opcode))
-  index = GraalCompiler::to_cp_index_u2(index);
   constantPoolHandle cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants();
   instanceKlassHandle pool_holder(cp->pool_holder());
 
   Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF);
+  index = GraalCompiler::to_cp_index(index, bc);
+
   methodHandle method = GraalEnv::get_method_by_index(cp, index, bc, pool_holder);
   if (!method.is_null()) {
     Handle holder = GraalCompiler::get_JavaType(method->method_holder(), CHECK_NULL);
@@ -430,8 +445,13 @@
     // Get the method's name and signature.
     Handle name = java_lang_String::create_from_symbol(cp->name_ref_at(index), CHECK_NULL);
     Handle signature  = java_lang_String::create_from_symbol(cp->signature_ref_at(index), CHECK_NULL);
-    int holder_index = cp->klass_ref_index_at(index);
-    Handle type = GraalCompiler::get_JavaType(cp, holder_index, cp->pool_holder(), CHECK_NULL);
+    Handle type;
+    if (bc != Bytecodes::_invokedynamic) {
+      int holder_index = cp->klass_ref_index_at(index);
+      type = GraalCompiler::get_JavaType(cp, holder_index, cp->pool_holder(), CHECK_NULL);
+    } else {
+      type = Handle(SystemDictionary::MethodHandle_klass()->java_mirror());
+    }
     return JNIHandles::make_local(THREAD, VMToCompiler::createUnresolvedJavaMethod(name, signature, type, THREAD));
   }
 C2V_END
@@ -445,11 +465,11 @@
 
 C2V_VMENTRY(void, lookupReferencedTypeInPool, (JNIEnv *env, jobject, jobject type, jint index, jbyte op))
   ConstantPool* cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants();
-  int opcode = (op & 0xFF);
-  if (opcode != Bytecodes::_checkcast && opcode != Bytecodes::_instanceof && opcode != Bytecodes::_new && opcode != Bytecodes::_anewarray
-      && opcode != Bytecodes::_multianewarray && opcode != Bytecodes::_ldc && opcode != Bytecodes::_ldc_w && opcode != Bytecodes::_ldc2_w)
+  Bytecodes::Code bc = (Bytecodes::Code) (((int) op) & 0xFF);
+  if (bc != Bytecodes::_checkcast && bc != Bytecodes::_instanceof && bc != Bytecodes::_new && bc != Bytecodes::_anewarray
+      && bc != Bytecodes::_multianewarray && bc != Bytecodes::_ldc && bc != Bytecodes::_ldc_w && bc != Bytecodes::_ldc2_w)
   {
-    index = cp->remap_instruction_operand_from_cache(GraalCompiler::to_cp_index_u2(index));
+    index = cp->remap_instruction_operand_from_cache(GraalCompiler::to_cp_index(index, bc));
   }
   constantTag tag = cp->tag_at(index);
   if (tag.is_field_or_method()) {
@@ -479,7 +499,7 @@
   int holder_index = cp->klass_ref_index_at(index);
   Handle holder = GraalCompiler::get_JavaType(cp, holder_index, cp->pool_holder(), CHECK_NULL);
   instanceKlassHandle holder_klass;
-  
+
   Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF);
   int offset = -1;
   AccessFlags flags;
@@ -499,7 +519,7 @@
       holder = GraalCompiler::get_JavaType(holder_klass, CHECK_NULL);
     }
   }
-  
+
   Handle type = GraalCompiler::get_JavaTypeFromSignature(signature, cp->pool_holder(), CHECK_NULL);
   Handle field_handle = GraalCompiler::get_JavaField(offset, flags.as_int(), name, holder, type, THREAD);
 
@@ -606,6 +626,11 @@
 #endif
   set_boolean("verifyOops", VerifyOops);
   set_boolean("ciTime", CITime);
+  set_boolean("compileTheWorld", CompileTheWorld);
+  set_int("compileTheWorldStartAt", CompileTheWorldStartAt);
+  set_int("compileTheWorldStopAt", CompileTheWorldStopAt);
+  set_boolean("printCompilation", PrintCompilation);
+  set_boolean("printInlining", PrintInlining);
   set_boolean("useFastLocking", GraalUseFastLocking);
   set_boolean("useBiasedLocking", UseBiasedLocking);
   set_boolean("usePopCountInstruction", UsePopCountInstruction);
@@ -640,6 +665,7 @@
   set_int("constMethodMaxStackOffset", in_bytes(ConstMethod::max_stack_offset()));
   set_int("extraStackEntries", Method::extra_stack_entries());
   set_int("methodAccessFlagsOffset", in_bytes(Method::access_flags_offset()));
+  set_int("methodIntrinsicIdOffset", Method::intrinsic_id_offset_in_bytes());
   set_int("klassHasFinalizerFlag", JVM_ACC_HAS_FINALIZER);
   set_int("threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset()));
   set_int("threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset()));
@@ -663,7 +689,7 @@
   set_int("arrayKlassLayoutHelperIdentifier", 0x80000000);
   assert((Klass::_lh_array_tag_obj_value & Klass::_lh_array_tag_type_value & 0x80000000) != 0, "obj_array and type_array must have first bit set");
   set_int("arrayKlassComponentMirrorOffset", in_bytes(ArrayKlass::component_mirror_offset()));
-  
+
 
   set_int("pendingDeoptimizationOffset", in_bytes(ThreadShadow::pending_deoptimization_offset()));
 
@@ -763,6 +789,13 @@
   set_int("deoptActionReinterpret", Deoptimization::Action_reinterpret);
   set_int("deoptActionMakeNotEntrant", Deoptimization::Action_make_not_entrant);
   set_int("deoptActionMakeNotCompilable", Deoptimization::Action_make_not_compilable);
+
+  set_int("vmIntrinsicInvokeBasic", vmIntrinsics::_invokeBasic);
+  set_int("vmIntrinsicLinkToVirtual", vmIntrinsics::_linkToVirtual);
+  set_int("vmIntrinsicLinkToStatic", vmIntrinsics::_linkToStatic);
+  set_int("vmIntrinsicLinkToSpecial", vmIntrinsics::_linkToSpecial);
+  set_int("vmIntrinsicLinkToInterface", vmIntrinsics::_linkToInterface);
+
   set_int("g1CardQueueIndexOffset", in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_index()));
   set_int("g1CardQueueBufferOffset", in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_buf()));
   set_int("logOfHRGrainBytes", HeapRegion::LogOfHRGrainBytes);
@@ -882,23 +915,17 @@
   return JNIHandles::make_local(element);
 C2V_END
 
-C2V_VMENTRY(jobject, executeCompiledMethodVarargs, (JNIEnv *env, jobject, jlong metaspace_method, jlong metaspace_nmethod, jobject args))
+C2V_VMENTRY(jobject, executeCompiledMethodVarargs, (JNIEnv *env, jobject, jobject args, jlong nativeMethod))
   ResourceMark rm;
   HandleMark hm;
 
-  assert(metaspace_method != 0, "just checking");
-  methodHandle mh = asMethod(metaspace_method);
+  nmethod* nm = (nmethod*) (address) nativeMethod;
+  methodHandle mh = nm->method();
   Symbol* signature = mh->signature();
   JavaCallArguments jca(mh->size_of_parameters());
 
   JavaArgumentUnboxer jap(signature, &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static());
   JavaValue result(jap.get_ret_type());
-
-  nmethod* nm = (nmethod*) (address) metaspace_nmethod;
-  if (nm == NULL || !nm->is_alive()) {
-    THROW_0(vmSymbols::MethodInvalidatedException());
-  }
-
   jca.set_alternative_target(nm);
   JavaCalls::call(&result, mh, &jca, CHECK_NULL);
 
@@ -912,29 +939,6 @@
   }
 C2V_END
 
-C2V_VMENTRY(jobject, executeCompiledMethod, (JNIEnv *env, jobject, jlong metaspace_method, jlong metaspace_nmethod, jobject arg1, jobject arg2, jobject arg3))
-  ResourceMark rm;
-  HandleMark hm;
-
-  methodHandle method = asMethod(metaspace_method);
-  assert(!method.is_null(), "just checking");
-  JavaValue result(T_OBJECT);
-  JavaCallArguments args;
-  args.push_oop(JNIHandles::resolve(arg1));
-  args.push_oop(JNIHandles::resolve(arg2));
-  args.push_oop(JNIHandles::resolve(arg3));
-
-  nmethod* nm = (nmethod*) (address) metaspace_nmethod;
-  if (nm == NULL || !nm->is_alive()) {
-    THROW_0(vmSymbols::MethodInvalidatedException());
-  }
-
-  args.set_alternative_target(nm);
-  JavaCalls::call(&result, method, &args, CHECK_NULL);
-
-  return JNIHandles::make_local((oop) result.get_jobject());
-C2V_END
-
 C2V_VMENTRY(jint, getVtableEntryOffset, (JNIEnv *, jobject, jlong metaspace_method))
 
   Method* method = asMethod(metaspace_method);
@@ -1005,10 +1009,10 @@
     u2 typeCPIdx = table[i].descriptor_cp_index;
     u2 slot = table[i].slot;
 
-    char* name = method->constants()->string_at_noresolve(nameCPIdx);
+    char* name = method->constants()->symbol_at(nameCPIdx)->as_C_string();
     Handle nameHandle = java_lang_String::create_from_str(name, CHECK_NULL);
 
-    char* typeInfo = method->constants()->string_at_noresolve(typeCPIdx);
+    char* typeInfo = method->constants()->symbol_at(typeCPIdx)->as_C_string();
     Handle typeHandle = java_lang_String::create_from_str(typeInfo, CHECK_NULL);
 
     Handle holderHandle = GraalCompiler::createHotSpotResolvedObjectType(method, CHECK_0);
@@ -1053,6 +1057,20 @@
 C2V_END
 
 
+C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv *env, jobject, jlong nativeMethod))
+  nmethod* m = (nmethod*)nativeMethod;
+  if (!m->is_not_entrant()) {
+    m->mark_for_deoptimization();
+    VM_Deoptimize op;
+    VMThread::execute(&op);
+  }
+C2V_END
+
+
+C2V_VMENTRY(jboolean, isInstalledCodeValid, (JNIEnv *env, jobject, jlong nativeMethod))
+  nmethod* m = (nmethod*)nativeMethod;
+  return m->is_alive() && !m->is_not_entrant();
+C2V_END
 
 #define CC (char*)  /*cast a literal from (const char*)*/
 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f))
@@ -1102,8 +1120,10 @@
   {CC"getInvocationCount",            CC"("METASPACE_METHOD")I",                                        FN_PTR(getInvocationCount)},
   {CC"getCompiledCodeSize",           CC"("METASPACE_METHOD")I",                                        FN_PTR(getCompiledCodeSize)},
   {CC"getVtableEntryOffset",          CC"("METASPACE_METHOD")I",                                        FN_PTR(getVtableEntryOffset)},
+  {CC"constantPoolLength",            CC"("HS_RESOLVED_TYPE")I",                                        FN_PTR(constantPoolLength)},
   {CC"lookupType",                    CC"("STRING HS_RESOLVED_TYPE"Z)"TYPE,                             FN_PTR(lookupType)},
   {CC"lookupConstantInPool",          CC"("HS_RESOLVED_TYPE"I)"OBJECT,                                  FN_PTR(lookupConstantInPool)},
+  {CC"lookupAppendixInPool",          CC"("HS_RESOLVED_TYPE"IB)"OBJECT,                                 FN_PTR(lookupAppendixInPool)},
   {CC"lookupMethodInPool",            CC"("HS_RESOLVED_TYPE"IB)"METHOD,                                 FN_PTR(lookupMethodInPool)},
   {CC"lookupTypeInPool",              CC"("HS_RESOLVED_TYPE"I)"TYPE,                                    FN_PTR(lookupTypeInPool)},
   {CC"lookupReferencedTypeInPool",    CC"("HS_RESOLVED_TYPE"IB)V",                                      FN_PTR(lookupReferencedTypeInPool)},
@@ -1121,14 +1141,15 @@
   {CC"installCode0",                  CC"("HS_COMP_RESULT HS_INSTALLED_CODE"[Z)I",                      FN_PTR(installCode0)},
   {CC"getCode",                       CC"(J)[B",                                                        FN_PTR(getCode)},
   {CC"disassembleNMethod",            CC"(J)"STRING,                                                    FN_PTR(disassembleNMethod)},
-  {CC"executeCompiledMethod",         CC"("METASPACE_METHOD NMETHOD OBJECT OBJECT OBJECT")"OBJECT,      FN_PTR(executeCompiledMethod)},
-  {CC"executeCompiledMethodVarargs",  CC"("METASPACE_METHOD NMETHOD "["OBJECT")"OBJECT,                 FN_PTR(executeCompiledMethodVarargs)},
+  {CC"executeCompiledMethodVarargs",  CC"(["OBJECT NMETHOD")"OBJECT,                                    FN_PTR(executeCompiledMethodVarargs)},
   {CC"getDeoptedLeafGraphIds",        CC"()[J",                                                         FN_PTR(getDeoptedLeafGraphIds)},
   {CC"getLineNumberTable",            CC"("HS_RESOLVED_METHOD")[J",                                     FN_PTR(getLineNumberTable)},
   {CC"getLocalVariableTable",         CC"("HS_RESOLVED_METHOD")["LOCAL,                                 FN_PTR(getLocalVariableTable)},
   {CC"getFileName",                   CC"("HS_RESOLVED_JAVA_TYPE")"STRING,                              FN_PTR(getFileName)},
   {CC"clearQueuedForCompilation",     CC"("HS_RESOLVED_METHOD")V",                                      FN_PTR(clearQueuedForCompilation)},
   {CC"reprofile",                     CC"("METASPACE_METHOD")V",                                        FN_PTR(reprofile)},
+  {CC"invalidateInstalledCode",       CC"(J)V",                                                         FN_PTR(invalidateInstalledCode)},
+  {CC"isInstalledCodeValid",          CC"(J)Z",                                                         FN_PTR(isInstalledCodeValid)},
 };
 
 int CompilerToVM_methods_count() {
--- a/src/share/vm/graal/graalEnv.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/graal/graalEnv.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -319,6 +319,19 @@
 methodHandle GraalEnv::get_method_by_index_impl(constantPoolHandle& cpool,
                                           int index, Bytecodes::Code bc,
                                           instanceKlassHandle& accessor) {
+  if (bc == Bytecodes::_invokedynamic) {
+    ConstantPoolCacheEntry* cpce = cpool->invokedynamic_cp_cache_entry_at(index);
+    bool is_resolved = !cpce->is_f1_null();
+    if (is_resolved) {
+      // Get the invoker Method* from the constant pool.
+      // (The appendix argument, if any, will be noted in the method's signature.)
+      Method* adapter = cpce->f1_as_method();
+      return methodHandle(adapter);
+    }
+
+    return NULL;
+  }
+
   int holder_index = cpool->klass_ref_index_at(index);
   bool holder_is_accessible;
   KlassHandle holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor);
@@ -327,6 +340,27 @@
   Symbol* name_sym = cpool->name_ref_at(index);
   Symbol* sig_sym  = cpool->signature_ref_at(index);
 
+  if (cpool->has_preresolution()
+      || (holder() == SystemDictionary::MethodHandle_klass() &&
+          MethodHandles::is_signature_polymorphic_name(holder(), name_sym))) {
+    // Short-circuit lookups for JSR 292-related call sites.
+    // That is, do not rely only on name-based lookups, because they may fail
+    // if the names are not resolvable in the boot class loader (7056328).
+    switch (bc) {
+    case Bytecodes::_invokevirtual:
+    case Bytecodes::_invokeinterface:
+    case Bytecodes::_invokespecial:
+    case Bytecodes::_invokestatic:
+      {
+        Method* m = ConstantPool::method_at_if_loaded(cpool, index);
+        if (m != NULL) {
+          return m;
+        }
+      }
+      break;
+    }
+  }
+
   if (holder_is_accessible) { // Our declared holder is loaded.
     instanceKlassHandle lookup = get_instance_klass_for_declared_method_holder(holder);
     methodHandle m = lookup_method(accessor, lookup, name_sym, sig_sym, bc);
@@ -369,7 +403,6 @@
                                      int index, Bytecodes::Code bc,
                                      instanceKlassHandle& accessor) {
   ResourceMark rm;
-  assert(bc != Bytecodes::_invokedynamic, "invokedynamic not yet supported");
   return get_method_by_index_impl(cpool, index, bc, accessor);
 }
 
--- a/src/share/vm/graal/graalJavaAccess.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -110,6 +110,9 @@
   start_class(Assumptions_MethodContents)                                                                                                                      \
     oop_field(Assumptions_MethodContents, method, "Lcom/oracle/graal/api/meta/ResolvedJavaMethod;")                                                            \
   end_class                                                                                                                                                    \
+  start_class(Assumptions_NoFinalizableSubclass)                                                                                                               \
+    oop_field(Assumptions_NoFinalizableSubclass, receiverType, "Lcom/oracle/graal/api/meta/ResolvedJavaType;")                                                 \
+  end_class                                                                                                                                                    \
   start_class(Assumptions_ConcreteSubtype)                                                                                                                     \
     oop_field(Assumptions_ConcreteSubtype, context, "Lcom/oracle/graal/api/meta/ResolvedJavaType;")                                                            \
     oop_field(Assumptions_ConcreteSubtype, subtype, "Lcom/oracle/graal/api/meta/ResolvedJavaType;")                                                            \
@@ -119,6 +122,10 @@
     oop_field(Assumptions_ConcreteMethod, context, "Lcom/oracle/graal/api/meta/ResolvedJavaType;")                                                             \
     oop_field(Assumptions_ConcreteMethod, impl, "Lcom/oracle/graal/api/meta/ResolvedJavaMethod;")                                                              \
   end_class                                                                                                                                                    \
+  start_class(Assumptions_CallSiteTargetValue)                                                                                                                 \
+    oop_field(Assumptions_CallSiteTargetValue, callSite, "Ljava/lang/invoke/CallSite;")                                                                        \
+    oop_field(Assumptions_CallSiteTargetValue, methodHandle, "Ljava/lang/invoke/MethodHandle;")                                                                \
+  end_class                                                                                                                                                    \
   start_class(CompilationResult_Site)                                                                                                                          \
     int_field(CompilationResult_Site, pcOffset)                                                                                                                \
   end_class                                                                                                                                                    \
@@ -131,8 +138,18 @@
     int_field(CompilationResult_DataPatch, alignment)                                                                                                          \
     boolean_field(CompilationResult_DataPatch, inlined)                                                                                                        \
   end_class                                                                                                                                                    \
-  start_class(CompilationResult_Safepoint)                                                                                                                     \
-    oop_field(CompilationResult_Safepoint, debugInfo, "Lcom/oracle/graal/api/code/DebugInfo;")                                                                 \
+  start_class(InfopointReason)                                                                                                                                 \
+    static_oop_field(InfopointReason, UNKNOWN, "Lcom/oracle/graal/api/code/InfopointReason;")                                                                  \
+    static_oop_field(InfopointReason, SAFEPOINT, "Lcom/oracle/graal/api/code/InfopointReason;")                                                                \
+    static_oop_field(InfopointReason, CALL, "Lcom/oracle/graal/api/code/InfopointReason;")                                                                     \
+    static_oop_field(InfopointReason, IMPLICIT_EXCEPTION, "Lcom/oracle/graal/api/code/InfopointReason;")                                                       \
+    static_oop_field(InfopointReason, METHOD_START, "Lcom/oracle/graal/api/code/InfopointReason;")                                                             \
+    static_oop_field(InfopointReason, METHOD_END, "Lcom/oracle/graal/api/code/InfopointReason;")                                                               \
+    static_oop_field(InfopointReason, LINE_NUMBER, "Lcom/oracle/graal/api/code/InfopointReason;")                                                              \
+  end_class                                                                                                                                                    \
+  start_class(CompilationResult_Infopoint)                                                                                                                     \
+    oop_field(CompilationResult_Infopoint, debugInfo, "Lcom/oracle/graal/api/code/DebugInfo;")                                                                 \
+    oop_field(CompilationResult_Infopoint, reason, "Lcom/oracle/graal/api/code/InfopointReason;")                                                              \
   end_class                                                                                                                                                    \
   start_class(CompilationResult_ExceptionHandler)                                                                                                              \
     int_field(CompilationResult_ExceptionHandler, handlerPos)                                                                                                  \
--- a/src/share/vm/interpreter/abstractInterpreter.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/interpreter/abstractInterpreter.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -85,6 +85,9 @@
     zerolocals_synchronized,                                    // method needs locals initialization & is synchronized
     native,                                                     // native method
     native_synchronized,                                        // native method & is synchronized
+#ifdef GRAAL
+    execute_compiled_method,                                    // direct call to compiled method address
+#endif
     empty,                                                      // empty method (code: _return)
     accessor,                                                   // accessor method (code: _aload_0, _getfield, _(a|i)return)
     abstract,                                                   // abstract method (throws an AbstractMethodException)
--- a/src/share/vm/interpreter/interpreter.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/interpreter/interpreter.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -188,6 +188,13 @@
   // Method handle primitive?
   if (m->is_method_handle_intrinsic()) {
     vmIntrinsics::ID id = m->intrinsic_id();
+#ifdef GRAAL
+    if (id == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) {
+      // Special method kind for directly executing the verified entry point
+      // of a given nmethod.
+      return AbstractInterpreter::execute_compiled_method;
+    }
+#endif
     assert(MethodHandles::is_signature_polymorphic(id), "must match an intrinsic");
     MethodKind kind = (MethodKind)( method_handle_invoke_FIRST +
                                     ((int)id - vmIntrinsics::FIRST_MH_SIG_POLY) );
@@ -287,6 +294,9 @@
     case zerolocals_synchronized: tty->print("zerolocals_synchronized"); break;
     case native                 : tty->print("native"                 ); break;
     case native_synchronized    : tty->print("native_synchronized"    ); break;
+#ifdef GRAAL
+    case execute_compiled_method: tty->print("execute_compiled_method"); break;
+#endif
     case empty                  : tty->print("empty"                  ); break;
     case accessor               : tty->print("accessor"               ); break;
     case abstract               : tty->print("abstract"               ); break;
--- a/src/share/vm/interpreter/interpreterRuntime.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/interpreter/interpreterRuntime.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -568,11 +568,6 @@
 // be shared by method invocation and synchronized blocks.
 //%note synchronization_3
 
-static void trace_locking(Handle& h_locking_obj, bool is_locking) {
-  ObjectSynchronizer::trace_locking(h_locking_obj, false, true, is_locking);
-}
-
-
 //%note monitor_1
 IRT_ENTRY_NO_ASYNC(void, InterpreterRuntime::monitorenter(JavaThread* thread, BasicObjectLock* elem))
 #ifdef ASSERT
--- a/src/share/vm/interpreter/linkResolver.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/interpreter/linkResolver.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -217,6 +217,7 @@
                                              TRAPS) {
   vmIntrinsics::ID iid = MethodHandles::signature_polymorphic_name_id(name);
   if (TraceMethodHandles) {
+    ResourceMark rm(THREAD);
     tty->print_cr("lookup_polymorphic_method iid=%s %s.%s%s",
                   vmIntrinsics::name_at(iid), klass->external_name(),
                   name->as_C_string(), full_signature->as_C_string());
@@ -231,6 +232,7 @@
       TempNewSymbol basic_signature =
         MethodHandles::lookup_basic_type_signature(full_signature, keep_last_arg, CHECK);
       if (TraceMethodHandles) {
+        ResourceMark rm(THREAD);
         tty->print_cr("lookup_polymorphic_method %s %s => basic %s",
                       name->as_C_string(),
                       full_signature->as_C_string(),
@@ -283,6 +285,8 @@
       }
       if (result.not_null()) {
 #ifdef ASSERT
+        ResourceMark rm(THREAD);
+
         TempNewSymbol basic_signature =
           MethodHandles::lookup_basic_type_signature(full_signature, CHECK);
         int actual_size_of_params = result->size_of_parameters();
@@ -1222,8 +1226,10 @@
   Symbol* method_signature = NULL;
   KlassHandle  current_klass;
   resolve_pool(resolved_klass, method_name,  method_signature, current_klass, pool, index, CHECK);
-  if (TraceMethodHandles)
+  if (TraceMethodHandles) {
+    ResourceMark rm(THREAD);
     tty->print_cr("resolve_invokehandle %s %s", method_name->as_C_string(), method_signature->as_C_string());
+  }
   resolve_handle_call(result, resolved_klass, method_name, method_signature, current_klass, CHECK);
 }
 
--- a/src/share/vm/interpreter/templateInterpreter.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/interpreter/templateInterpreter.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -360,6 +360,9 @@
   method_entry(zerolocals)
   method_entry(zerolocals_synchronized)
   method_entry(empty)
+#ifdef GRAAL
+  method_entry(execute_compiled_method)
+#endif
   method_entry(accessor)
   method_entry(abstract)
   method_entry(java_lang_math_sin  )
--- a/src/share/vm/memory/allocation.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/memory/allocation.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -611,4 +611,23 @@
   void check()    PRODUCT_RETURN;
 };
 
+// Helper class to allocate arrays that may become large.
+// Uses the OS malloc for allocations smaller than ArrayAllocatorMallocLimit
+// and uses mapped memory for larger allocations.
+// Most OS mallocs do something similar but Solaris malloc does not revert
+// to mapped memory for large allocations. By default ArrayAllocatorMallocLimit
+// is set so that we always use malloc except for Solaris where we set the
+// limit to get mapped memory.
+template <class E, MEMFLAGS F>
+class ArrayAllocator : StackObj {
+  char* _addr;
+  bool _use_malloc;
+  size_t _size;
+ public:
+  ArrayAllocator() : _addr(NULL), _use_malloc(false), _size(0) { }
+  ~ArrayAllocator() { free(); }
+  E* allocate(size_t length);
+  void free();
+};
+
 #endif // SHARE_VM_MEMORY_ALLOCATION_HPP
--- a/src/share/vm/memory/allocation.inline.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/memory/allocation.inline.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -108,5 +108,49 @@
    FreeHeap(p, F);
 }
 
+template <class E, MEMFLAGS F>
+E* ArrayAllocator<E, F>::allocate(size_t length) {
+  assert(_addr == NULL, "Already in use");
+
+  _size = sizeof(E) * length;
+  _use_malloc = _size < ArrayAllocatorMallocLimit;
+
+  if (_use_malloc) {
+    _addr = AllocateHeap(_size, F);
+    if (_addr == NULL && _size >=  (size_t)os::vm_allocation_granularity()) {
+      // malloc failed let's try with mmap instead
+      _use_malloc = false;
+    } else {
+      return (E*)_addr;
+    }
+  }
+
+  int alignment = os::vm_allocation_granularity();
+  _size = align_size_up(_size, alignment);
+
+  _addr = os::reserve_memory(_size, NULL, alignment);
+  if (_addr == NULL) {
+    vm_exit_out_of_memory(_size, "Allocator (reserve)");
+  }
+
+  bool success = os::commit_memory(_addr, _size, false /* executable */);
+  if (!success) {
+    vm_exit_out_of_memory(_size, "Allocator (commit)");
+  }
+
+  return (E*)_addr;
+}
+
+template<class E, MEMFLAGS F>
+void ArrayAllocator<E, F>::free() {
+  if (_addr != NULL) {
+    if (_use_malloc) {
+      FreeHeap(_addr, F);
+    } else {
+      os::release_memory(_addr, _size);
+    }
+    _addr = NULL;
+  }
+}
 
 #endif // SHARE_VM_MEMORY_ALLOCATION_INLINE_HPP
--- a/src/share/vm/memory/genCollectedHeap.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/memory/genCollectedHeap.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -819,12 +819,13 @@
 // Returns "TRUE" iff "p" points into the committed areas of the heap.
 bool GenCollectedHeap::is_in(const void* p) const {
   #ifndef ASSERT
-  guarantee(VerifyBeforeGC   ||
-            VerifyDuringGC   ||
-            VerifyBeforeExit ||
-            PrintAssembly    ||
-            tty->count() != 0 ||   // already printing
-            VerifyAfterGC    ||
+  guarantee(VerifyBeforeGC      ||
+            VerifyDuringGC      ||
+            VerifyBeforeExit    ||
+            VerifyDuringStartup ||
+            PrintAssembly       ||
+            tty->count() != 0   ||   // already printing
+            VerifyAfterGC       ||
     VMError::fatal_error_in_progress(), "too expensive");
 
   #endif
@@ -1132,6 +1133,17 @@
 #endif // INCLUDE_ALL_GCS
 }
 
+void GenCollectedHeap::print_on_error(outputStream* st) const {
+  this->CollectedHeap::print_on_error(st);
+
+#if INCLUDE_ALL_GCS
+  if (UseConcMarkSweepGC) {
+    st->cr();
+    CMSCollector::print_on_error(st);
+  }
+#endif // INCLUDE_ALL_GCS
+}
+
 void GenCollectedHeap::print_tracing_info() const {
   if (TraceGen0Time) {
     get_gen(0)->print_summary_info();
--- a/src/share/vm/memory/genCollectedHeap.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/memory/genCollectedHeap.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -344,6 +344,7 @@
   virtual void print_gc_threads_on(outputStream* st) const;
   virtual void gc_threads_do(ThreadClosure* tc) const;
   virtual void print_tracing_info() const;
+  virtual void print_on_error(outputStream* st) const;
 
   // PrintGC, PrintGCDetails support
   void print_heap_change(size_t prev_used) const;
--- a/src/share/vm/memory/generation.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/memory/generation.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -382,7 +382,9 @@
 CardGeneration::CardGeneration(ReservedSpace rs, size_t initial_byte_size,
                                int level,
                                GenRemSet* remset) :
-  Generation(rs, initial_byte_size, level), _rs(remset)
+  Generation(rs, initial_byte_size, level), _rs(remset),
+  _shrink_factor(0), _min_heap_delta_bytes(), _capacity_at_prologue(),
+  _used_at_prologue()
 {
   HeapWord* start = (HeapWord*)rs.base();
   size_t reserved_byte_size = rs.size();
@@ -406,6 +408,9 @@
     // the end if we try.
     guarantee(_rs->is_aligned(reserved_mr.end()), "generation must be card aligned");
   }
+  _min_heap_delta_bytes = MinHeapDeltaBytes;
+  _capacity_at_prologue = initial_byte_size;
+  _used_at_prologue = 0;
 }
 
 bool CardGeneration::expand(size_t bytes, size_t expand_bytes) {
@@ -457,6 +462,160 @@
 }
 
 
+void CardGeneration::compute_new_size() {
+  assert(_shrink_factor <= 100, "invalid shrink factor");
+  size_t current_shrink_factor = _shrink_factor;
+  _shrink_factor = 0;
+
+  // We don't have floating point command-line arguments
+  // Note:  argument processing ensures that MinHeapFreeRatio < 100.
+  const double minimum_free_percentage = MinHeapFreeRatio / 100.0;
+  const double maximum_used_percentage = 1.0 - minimum_free_percentage;
+
+  // Compute some numbers about the state of the heap.
+  const size_t used_after_gc = used();
+  const size_t capacity_after_gc = capacity();
+
+  const double min_tmp = used_after_gc / maximum_used_percentage;
+  size_t minimum_desired_capacity = (size_t)MIN2(min_tmp, double(max_uintx));
+  // Don't shrink less than the initial generation size
+  minimum_desired_capacity = MAX2(minimum_desired_capacity,
+                                  spec()->init_size());
+  assert(used_after_gc <= minimum_desired_capacity, "sanity check");
+
+  if (PrintGC && Verbose) {
+    const size_t free_after_gc = free();
+    const double free_percentage = ((double)free_after_gc) / capacity_after_gc;
+    gclog_or_tty->print_cr("TenuredGeneration::compute_new_size: ");
+    gclog_or_tty->print_cr("  "
+                  "  minimum_free_percentage: %6.2f"
+                  "  maximum_used_percentage: %6.2f",
+                  minimum_free_percentage,
+                  maximum_used_percentage);
+    gclog_or_tty->print_cr("  "
+                  "   free_after_gc   : %6.1fK"
+                  "   used_after_gc   : %6.1fK"
+                  "   capacity_after_gc   : %6.1fK",
+                  free_after_gc / (double) K,
+                  used_after_gc / (double) K,
+                  capacity_after_gc / (double) K);
+    gclog_or_tty->print_cr("  "
+                  "   free_percentage: %6.2f",
+                  free_percentage);
+  }
+
+  if (capacity_after_gc < minimum_desired_capacity) {
+    // If we have less free space than we want then expand
+    size_t expand_bytes = minimum_desired_capacity - capacity_after_gc;
+    // Don't expand unless it's significant
+    if (expand_bytes >= _min_heap_delta_bytes) {
+      expand(expand_bytes, 0); // safe if expansion fails
+    }
+    if (PrintGC && Verbose) {
+      gclog_or_tty->print_cr("    expanding:"
+                    "  minimum_desired_capacity: %6.1fK"
+                    "  expand_bytes: %6.1fK"
+                    "  _min_heap_delta_bytes: %6.1fK",
+                    minimum_desired_capacity / (double) K,
+                    expand_bytes / (double) K,
+                    _min_heap_delta_bytes / (double) K);
+    }
+    return;
+  }
+
+  // No expansion, now see if we want to shrink
+  size_t shrink_bytes = 0;
+  // We would never want to shrink more than this
+  size_t max_shrink_bytes = capacity_after_gc - minimum_desired_capacity;
+
+  if (MaxHeapFreeRatio < 100) {
+    const double maximum_free_percentage = MaxHeapFreeRatio / 100.0;
+    const double minimum_used_percentage = 1.0 - maximum_free_percentage;
+    const double max_tmp = used_after_gc / minimum_used_percentage;
+    size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx));
+    maximum_desired_capacity = MAX2(maximum_desired_capacity,
+                                    spec()->init_size());
+    if (PrintGC && Verbose) {
+      gclog_or_tty->print_cr("  "
+                             "  maximum_free_percentage: %6.2f"
+                             "  minimum_used_percentage: %6.2f",
+                             maximum_free_percentage,
+                             minimum_used_percentage);
+      gclog_or_tty->print_cr("  "
+                             "  _capacity_at_prologue: %6.1fK"
+                             "  minimum_desired_capacity: %6.1fK"
+                             "  maximum_desired_capacity: %6.1fK",
+                             _capacity_at_prologue / (double) K,
+                             minimum_desired_capacity / (double) K,
+                             maximum_desired_capacity / (double) K);
+    }
+    assert(minimum_desired_capacity <= maximum_desired_capacity,
+           "sanity check");
+
+    if (capacity_after_gc > maximum_desired_capacity) {
+      // Capacity too large, compute shrinking size
+      shrink_bytes = capacity_after_gc - maximum_desired_capacity;
+      // We don't want shrink all the way back to initSize if people call
+      // System.gc(), because some programs do that between "phases" and then
+      // we'd just have to grow the heap up again for the next phase.  So we
+      // damp the shrinking: 0% on the first call, 10% on the second call, 40%
+      // on the third call, and 100% by the fourth call.  But if we recompute
+      // size without shrinking, it goes back to 0%.
+      shrink_bytes = shrink_bytes / 100 * current_shrink_factor;
+      assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size");
+      if (current_shrink_factor == 0) {
+        _shrink_factor = 10;
+      } else {
+        _shrink_factor = MIN2(current_shrink_factor * 4, (size_t) 100);
+      }
+      if (PrintGC && Verbose) {
+        gclog_or_tty->print_cr("  "
+                      "  shrinking:"
+                      "  initSize: %.1fK"
+                      "  maximum_desired_capacity: %.1fK",
+                      spec()->init_size() / (double) K,
+                      maximum_desired_capacity / (double) K);
+        gclog_or_tty->print_cr("  "
+                      "  shrink_bytes: %.1fK"
+                      "  current_shrink_factor: %d"
+                      "  new shrink factor: %d"
+                      "  _min_heap_delta_bytes: %.1fK",
+                      shrink_bytes / (double) K,
+                      current_shrink_factor,
+                      _shrink_factor,
+                      _min_heap_delta_bytes / (double) K);
+      }
+    }
+  }
+
+  if (capacity_after_gc > _capacity_at_prologue) {
+    // We might have expanded for promotions, in which case we might want to
+    // take back that expansion if there's room after GC.  That keeps us from
+    // stretching the heap with promotions when there's plenty of room.
+    size_t expansion_for_promotion = capacity_after_gc - _capacity_at_prologue;
+    expansion_for_promotion = MIN2(expansion_for_promotion, max_shrink_bytes);
+    // We have two shrinking computations, take the largest
+    shrink_bytes = MAX2(shrink_bytes, expansion_for_promotion);
+    assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size");
+    if (PrintGC && Verbose) {
+      gclog_or_tty->print_cr("  "
+                             "  aggressive shrinking:"
+                             "  _capacity_at_prologue: %.1fK"
+                             "  capacity_after_gc: %.1fK"
+                             "  expansion_for_promotion: %.1fK"
+                             "  shrink_bytes: %.1fK",
+                             capacity_after_gc / (double) K,
+                             _capacity_at_prologue / (double) K,
+                             expansion_for_promotion / (double) K,
+                             shrink_bytes / (double) K);
+    }
+  }
+  // Don't shrink unless it's significant
+  if (shrink_bytes >= _min_heap_delta_bytes) {
+    shrink(shrink_bytes);
+  }
+}
+
 // Currently nothing to do.
 void CardGeneration::prepare_for_verify() {}
 
--- a/src/share/vm/memory/generation.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/memory/generation.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -634,6 +634,17 @@
   // This is local to this generation.
   BlockOffsetSharedArray* _bts;
 
+  // current shrinking effect: this damps shrinking when the heap gets empty.
+  size_t _shrink_factor;
+
+  size_t _min_heap_delta_bytes;   // Minimum amount to expand.
+
+  // Some statistics from before gc started.
+  // These are gathered in the gc_prologue (and should_collect)
+  // to control growing/shrinking policy in spite of promotions.
+  size_t _capacity_at_prologue;
+  size_t _used_at_prologue;
+
   CardGeneration(ReservedSpace rs, size_t initial_byte_size, int level,
                  GenRemSet* remset);
 
@@ -644,6 +655,11 @@
   // necessarily the full "bytes") was done.
   virtual bool expand(size_t bytes, size_t expand_bytes);
 
+  // Shrink generation with specified size (returns false if unable to shrink)
+  virtual void shrink(size_t bytes) = 0;
+
+  virtual void compute_new_size();
+
   virtual void clear_remembered_set();
 
   virtual void invalidate_remembered_set();
@@ -667,7 +683,6 @@
   friend class VM_PopulateDumpSharedSpace;
 
  protected:
-  size_t     _min_heap_delta_bytes;   // Minimum amount to expand.
   ContiguousSpace*  _the_space;       // actual space holding objects
   WaterMark  _last_gc;                // watermark between objects allocated before
                                       // and after last GC.
@@ -688,11 +703,10 @@
 
  public:
   OneContigSpaceCardGeneration(ReservedSpace rs, size_t initial_byte_size,
-                               size_t min_heap_delta_bytes,
                                int level, GenRemSet* remset,
                                ContiguousSpace* space) :
     CardGeneration(rs, initial_byte_size, level, remset),
-    _the_space(space), _min_heap_delta_bytes(min_heap_delta_bytes)
+    _the_space(space)
   {}
 
   inline bool is_in(const void* p) const;
--- a/src/share/vm/memory/heap.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/memory/heap.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -79,13 +79,6 @@
 }
 
 
-static size_t align_to_allocation_size(size_t size) {
-  const size_t alignment = (size_t)os::vm_allocation_granularity();
-  assert(is_power_of_2(alignment), "no kidding ???");
-  return (size + alignment - 1) & ~(alignment - 1);
-}
-
-
 void CodeHeap::on_code_mapping(char* base, size_t size) {
 #ifdef LINUX
   extern void linux_wrap_code(char* base, size_t size);
--- a/src/share/vm/memory/tenuredGeneration.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/memory/tenuredGeneration.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -39,7 +39,7 @@
                                      size_t initial_byte_size, int level,
                                      GenRemSet* remset) :
   OneContigSpaceCardGeneration(rs, initial_byte_size,
-                               MinHeapDeltaBytes, level, remset, NULL)
+                               level, remset, NULL)
 {
   HeapWord* bottom = (HeapWord*) _virtual_space.low();
   HeapWord* end    = (HeapWord*) _virtual_space.high();
@@ -86,162 +86,6 @@
   return "tenured generation";
 }
 
-void TenuredGeneration::compute_new_size() {
-  assert(_shrink_factor <= 100, "invalid shrink factor");
-  size_t current_shrink_factor = _shrink_factor;
-  _shrink_factor = 0;
-
-  // We don't have floating point command-line arguments
-  // Note:  argument processing ensures that MinHeapFreeRatio < 100.
-  const double minimum_free_percentage = MinHeapFreeRatio / 100.0;
-  const double maximum_used_percentage = 1.0 - minimum_free_percentage;
-
-  // Compute some numbers about the state of the heap.
-  const size_t used_after_gc = used();
-  const size_t capacity_after_gc = capacity();
-
-  const double min_tmp = used_after_gc / maximum_used_percentage;
-  size_t minimum_desired_capacity = (size_t)MIN2(min_tmp, double(max_uintx));
-  // Don't shrink less than the initial generation size
-  minimum_desired_capacity = MAX2(minimum_desired_capacity,
-                                  spec()->init_size());
-  assert(used_after_gc <= minimum_desired_capacity, "sanity check");
-
-  if (PrintGC && Verbose) {
-    const size_t free_after_gc = free();
-    const double free_percentage = ((double)free_after_gc) / capacity_after_gc;
-    gclog_or_tty->print_cr("TenuredGeneration::compute_new_size: ");
-    gclog_or_tty->print_cr("  "
-                  "  minimum_free_percentage: %6.2f"
-                  "  maximum_used_percentage: %6.2f",
-                  minimum_free_percentage,
-                  maximum_used_percentage);
-    gclog_or_tty->print_cr("  "
-                  "   free_after_gc   : %6.1fK"
-                  "   used_after_gc   : %6.1fK"
-                  "   capacity_after_gc   : %6.1fK",
-                  free_after_gc / (double) K,
-                  used_after_gc / (double) K,
-                  capacity_after_gc / (double) K);
-    gclog_or_tty->print_cr("  "
-                  "   free_percentage: %6.2f",
-                  free_percentage);
-  }
-
-  if (capacity_after_gc < minimum_desired_capacity) {
-    // If we have less free space than we want then expand
-    size_t expand_bytes = minimum_desired_capacity - capacity_after_gc;
-    // Don't expand unless it's significant
-    if (expand_bytes >= _min_heap_delta_bytes) {
-      expand(expand_bytes, 0); // safe if expansion fails
-    }
-    if (PrintGC && Verbose) {
-      gclog_or_tty->print_cr("    expanding:"
-                    "  minimum_desired_capacity: %6.1fK"
-                    "  expand_bytes: %6.1fK"
-                    "  _min_heap_delta_bytes: %6.1fK",
-                    minimum_desired_capacity / (double) K,
-                    expand_bytes / (double) K,
-                    _min_heap_delta_bytes / (double) K);
-    }
-    return;
-  }
-
-  // No expansion, now see if we want to shrink
-  size_t shrink_bytes = 0;
-  // We would never want to shrink more than this
-  size_t max_shrink_bytes = capacity_after_gc - minimum_desired_capacity;
-
-  if (MaxHeapFreeRatio < 100) {
-    const double maximum_free_percentage = MaxHeapFreeRatio / 100.0;
-    const double minimum_used_percentage = 1.0 - maximum_free_percentage;
-    const double max_tmp = used_after_gc / minimum_used_percentage;
-    size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx));
-    maximum_desired_capacity = MAX2(maximum_desired_capacity,
-                                    spec()->init_size());
-    if (PrintGC && Verbose) {
-      gclog_or_tty->print_cr("  "
-                             "  maximum_free_percentage: %6.2f"
-                             "  minimum_used_percentage: %6.2f",
-                             maximum_free_percentage,
-                             minimum_used_percentage);
-      gclog_or_tty->print_cr("  "
-                             "  _capacity_at_prologue: %6.1fK"
-                             "  minimum_desired_capacity: %6.1fK"
-                             "  maximum_desired_capacity: %6.1fK",
-                             _capacity_at_prologue / (double) K,
-                             minimum_desired_capacity / (double) K,
-                             maximum_desired_capacity / (double) K);
-    }
-    assert(minimum_desired_capacity <= maximum_desired_capacity,
-           "sanity check");
-
-    if (capacity_after_gc > maximum_desired_capacity) {
-      // Capacity too large, compute shrinking size
-      shrink_bytes = capacity_after_gc - maximum_desired_capacity;
-      // We don't want shrink all the way back to initSize if people call
-      // System.gc(), because some programs do that between "phases" and then
-      // we'd just have to grow the heap up again for the next phase.  So we
-      // damp the shrinking: 0% on the first call, 10% on the second call, 40%
-      // on the third call, and 100% by the fourth call.  But if we recompute
-      // size without shrinking, it goes back to 0%.
-      shrink_bytes = shrink_bytes / 100 * current_shrink_factor;
-      assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size");
-      if (current_shrink_factor == 0) {
-        _shrink_factor = 10;
-      } else {
-        _shrink_factor = MIN2(current_shrink_factor * 4, (size_t) 100);
-      }
-      if (PrintGC && Verbose) {
-        gclog_or_tty->print_cr("  "
-                      "  shrinking:"
-                      "  initSize: %.1fK"
-                      "  maximum_desired_capacity: %.1fK",
-                      spec()->init_size() / (double) K,
-                      maximum_desired_capacity / (double) K);
-        gclog_or_tty->print_cr("  "
-                      "  shrink_bytes: %.1fK"
-                      "  current_shrink_factor: %d"
-                      "  new shrink factor: %d"
-                      "  _min_heap_delta_bytes: %.1fK",
-                      shrink_bytes / (double) K,
-                      current_shrink_factor,
-                      _shrink_factor,
-                      _min_heap_delta_bytes / (double) K);
-      }
-    }
-  }
-
-  if (capacity_after_gc > _capacity_at_prologue) {
-    // We might have expanded for promotions, in which case we might want to
-    // take back that expansion if there's room after GC.  That keeps us from
-    // stretching the heap with promotions when there's plenty of room.
-    size_t expansion_for_promotion = capacity_after_gc - _capacity_at_prologue;
-    expansion_for_promotion = MIN2(expansion_for_promotion, max_shrink_bytes);
-    // We have two shrinking computations, take the largest
-    shrink_bytes = MAX2(shrink_bytes, expansion_for_promotion);
-    assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size");
-    if (PrintGC && Verbose) {
-      gclog_or_tty->print_cr("  "
-                             "  aggressive shrinking:"
-                             "  _capacity_at_prologue: %.1fK"
-                             "  capacity_after_gc: %.1fK"
-                             "  expansion_for_promotion: %.1fK"
-                             "  shrink_bytes: %.1fK",
-                             capacity_after_gc / (double) K,
-                             _capacity_at_prologue / (double) K,
-                             expansion_for_promotion / (double) K,
-                             shrink_bytes / (double) K);
-    }
-  }
-  // Don't shrink unless it's significant
-  if (shrink_bytes >= _min_heap_delta_bytes) {
-    shrink(shrink_bytes);
-  }
-  assert(used() == used_after_gc && used_after_gc <= capacity(),
-         "sanity check");
-}
-
 void TenuredGeneration::gc_prologue(bool full) {
   _capacity_at_prologue = capacity();
   _used_at_prologue = used();
@@ -312,6 +156,19 @@
                                         size, is_tlab);
 }
 
+void TenuredGeneration::compute_new_size() {
+  assert_locked_or_safepoint(Heap_lock);
+
+  // Compute some numbers about the state of the heap.
+  const size_t used_after_gc = used();
+  const size_t capacity_after_gc = capacity();
+
+  CardGeneration::compute_new_size();
+
+  assert(used() == used_after_gc && used_after_gc <= capacity(),
+         err_msg("used: " SIZE_FORMAT " used_after_gc: " SIZE_FORMAT
+         " capacity: " SIZE_FORMAT, used(), used_after_gc, capacity()));
+}
 void TenuredGeneration::update_gc_stats(int current_level,
                                         bool full) {
   // If the next lower level(s) has been collected, gather any statistics
--- a/src/share/vm/memory/tenuredGeneration.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/memory/tenuredGeneration.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -38,13 +38,6 @@
 class TenuredGeneration: public OneContigSpaceCardGeneration {
   friend class VMStructs;
  protected:
-  // current shrinking effect: this damps shrinking when the heap gets empty.
-  size_t _shrink_factor;
-  // Some statistics from before gc started.
-  // These are gathered in the gc_prologue (and should_collect)
-  // to control growing/shrinking policy in spite of promotions.
-  size_t _capacity_at_prologue;
-  size_t _used_at_prologue;
 
 #if INCLUDE_ALL_GCS
   // To support parallel promotion: an array of parallel allocation
@@ -80,9 +73,6 @@
     return !CollectGen0First;
   }
 
-  // Mark sweep support
-  void compute_new_size();
-
   virtual void gc_prologue(bool full);
   virtual void gc_epilogue(bool full);
   bool should_collect(bool   full,
@@ -93,6 +83,7 @@
                        bool clear_all_soft_refs,
                        size_t size,
                        bool is_tlab);
+  virtual void compute_new_size();
 
 #if INCLUDE_ALL_GCS
   // Overrides.
--- a/src/share/vm/memory/universe.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/memory/universe.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -1326,6 +1326,8 @@
 static uintptr_t _verify_klass_data[2] = {0, (uintptr_t)-1};
 
 
+#ifndef PRODUCT
+
 static void calculate_verify_data(uintptr_t verify_data[2],
                                   HeapWord* low_boundary,
                                   HeapWord* high_boundary) {
@@ -1360,9 +1362,7 @@
   verify_data[1] = bits;
 }
 
-
 // Oop verification (see MacroAssembler::verify_oop)
-#ifndef PRODUCT
 
 uintptr_t Universe::verify_oop_mask() {
   MemRegion m = heap()->reserved_region();
--- a/src/share/vm/oops/constantPool.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/oops/constantPool.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -1378,12 +1378,13 @@
 
 // JVMTI GetConstantPool support
 
-// For temporary use until code is stable.
-#define DBG(code)
+// For debugging of constant pool
+const bool debug_cpool = false;
 
-static const char* WARN_MSG = "Must not be such entry!";
+#define DBG(code) do { if (debug_cpool) { (code); } } while(0)
 
 static void print_cpool_bytes(jint cnt, u1 *bytes) {
+  const char* WARN_MSG = "Must not be such entry!";
   jint size = 0;
   u2   idx1, idx2;
 
@@ -1669,8 +1670,7 @@
         idx1 = tbl->symbol_to_value(sym);
         assert(idx1 != 0, "Have not found a hashtable entry");
         Bytes::put_Java_u2((address) (bytes+1), idx1);
-        DBG(char *str = sym->as_utf8());
-        DBG(printf("JVM_CONSTANT_String: idx=#%03hd, %s", idx1, str));
+        DBG(printf("JVM_CONSTANT_String: idx=#%03hd, %s", idx1, sym->as_utf8()));
         break;
       }
       case JVM_CONSTANT_Fieldref:
@@ -1745,6 +1745,8 @@
   return (int)(bytes - start_bytes);
 } /* end copy_cpool_bytes */
 
+#undef DBG
+
 
 void ConstantPool::set_on_stack(const bool value) {
   if (value) {
--- a/src/share/vm/oops/instanceKlass.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/oops/instanceKlass.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -3157,7 +3157,7 @@
     Array<int>* method_ordering = this->method_ordering();
     int length = method_ordering->length();
     if (JvmtiExport::can_maintain_original_method_order() ||
-        (UseSharedSpaces && length != 0)) {
+        ((UseSharedSpaces || DumpSharedSpaces) && length != 0)) {
       guarantee(length == methods()->length(), "invalid method ordering length");
       jlong sum = 0;
       for (int j = 0; j < length; j++) {
--- a/src/share/vm/oops/method.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/oops/method.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -722,7 +722,7 @@
   if (number_of_breakpoints() > 0)
     return true;
   if (is_method_handle_intrinsic())
-    return !is_synthetic();  // the generated adapters must be compiled
+    return !is_synthetic() && intrinsic_id() != vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod;  // the generated adapters must be compiled
   if (comp_level == CompLevel_any)
     return is_not_c1_compilable() || is_not_c2_compilable();
   if (is_c1_compile(comp_level))
@@ -851,6 +851,14 @@
 
   // ONLY USE the h_method now as make_adapter may have blocked
 
+#ifdef GRAAL
+  // Check for special intrinsic that executes a compiled method.
+  if (h_method->intrinsic_id() == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) {
+    // Actively install the stub for calling the intrinsic from compiled code.
+    CompileBroker::compile_method(h_method, InvocationEntryBci, CompLevel_highest_tier,
+                                  methodHandle(), CompileThreshold, "executeCompiledMethod", CHECK);
+  }
+#endif
 }
 
 address Method::make_adapters(methodHandle mh, TRAPS) {
@@ -1014,8 +1022,8 @@
 // Test if this method is an internal MH primitive method.
 bool Method::is_method_handle_intrinsic() const {
   vmIntrinsics::ID iid = intrinsic_id();
-  return (MethodHandles::is_signature_polymorphic(iid) &&
-          MethodHandles::is_signature_polymorphic_intrinsic(iid));
+  return ((MethodHandles::is_signature_polymorphic(iid) &&
+          MethodHandles::is_signature_polymorphic_intrinsic(iid))) || iid == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod;
 }
 
 bool Method::has_member_arg() const {
--- a/src/share/vm/oops/method.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/oops/method.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -776,15 +776,19 @@
   void print_made_not_compilable(int comp_level, bool is_osr, bool report, const char* reason);
 
  public:
-  bool  is_not_c1_compilable() const          { return access_flags().is_not_c1_compilable(); }
-  void set_not_c1_compilable()                {       _access_flags.set_not_c1_compilable();  }
-  bool  is_not_c2_compilable() const          { return access_flags().is_not_c2_compilable(); }
-  void set_not_c2_compilable()                {       _access_flags.set_not_c2_compilable();  }
+  bool   is_not_c1_compilable() const         { return access_flags().is_not_c1_compilable();  }
+  void  set_not_c1_compilable()               {       _access_flags.set_not_c1_compilable();   }
+  void clear_not_c1_compilable()              {       _access_flags.clear_not_c1_compilable(); }
+  bool   is_not_c2_compilable() const         { return access_flags().is_not_c2_compilable();  }
+  void  set_not_c2_compilable()               {       _access_flags.set_not_c2_compilable();   }
+  void clear_not_c2_compilable()              {       _access_flags.clear_not_c2_compilable(); }
 
-  bool  is_not_c1_osr_compilable() const      { return is_not_c1_compilable(); }  // don't waste an accessFlags bit
-  void set_not_c1_osr_compilable()            {       set_not_c1_compilable(); }  // don't waste an accessFlags bit
-  bool  is_not_c2_osr_compilable() const      { return access_flags().is_not_c2_osr_compilable(); }
-  void set_not_c2_osr_compilable()            {       _access_flags.set_not_c2_osr_compilable();  }
+  bool    is_not_c1_osr_compilable() const    { return is_not_c1_compilable(); }  // don't waste an accessFlags bit
+  void   set_not_c1_osr_compilable()          {       set_not_c1_compilable(); }  // don't waste an accessFlags bit
+  void clear_not_c1_osr_compilable()          {     clear_not_c1_compilable(); }  // don't waste an accessFlags bit
+  bool   is_not_c2_osr_compilable() const     { return access_flags().is_not_c2_osr_compilable();  }
+  void  set_not_c2_osr_compilable()           {       _access_flags.set_not_c2_osr_compilable();   }
+  void clear_not_c2_osr_compilable()          {       _access_flags.clear_not_c2_osr_compilable(); }
 
   // Background compilation support
   bool queued_for_compilation() const  { return access_flags().queued_for_compilation(); }
--- a/src/share/vm/oops/methodData.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/oops/methodData.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -676,29 +676,9 @@
   No_Safepoint_Verifier no_safepoint;  // init function atomic wrt GC
   ResourceMark rm;
 
-  _invocation_counter.init();
-  _backedge_counter.init();
-  _invocation_counter_start = 0;
-  _backedge_counter_start = 0;
-  _num_loops = 0;
-  _num_blocks = 0;
-  _highest_comp_level = 0;
-  _highest_osr_comp_level = 0;
-  _would_profile = true;
+  init();
   set_creation_mileage(mileage_of(method()));
 
-  // Initialize flags and trap history.
-  _nof_decompiles = 0;
-  _nof_overflow_recompiles = 0;
-  _nof_overflow_traps = 0;
-  _eflags = 0;
-  _arg_local = 0;
-  _arg_stack = 0;
-  _arg_returned = 0;
-  assert(sizeof(_trap_hist) % sizeof(HeapWord) == 0, "align");
-  Copy::zero_to_words((HeapWord*) &_trap_hist,
-                      sizeof(_trap_hist) / sizeof(HeapWord));
-
   // Go through the bytecodes and allocate and initialize the
   // corresponding data cells.
   int data_size = 0;
@@ -743,7 +723,27 @@
   post_initialize(&stream);
 
   set_size(object_size);
+}
 
+void MethodData::init() {
+  _invocation_counter.init();
+  _backedge_counter.init();
+  _invocation_counter_start = 0;
+  _backedge_counter_start = 0;
+  _num_loops = 0;
+  _num_blocks = 0;
+  _highest_comp_level = 0;
+  _highest_osr_comp_level = 0;
+  _would_profile = true;
+
+  // Initialize flags and trap history.
+  _nof_decompiles = 0;
+  _nof_overflow_recompiles = 0;
+  _nof_overflow_traps = 0;
+  clear_escape_info();
+  assert(sizeof(_trap_hist) % sizeof(HeapWord) == 0, "align");
+  Copy::zero_to_words((HeapWord*) &_trap_hist,
+                      sizeof(_trap_hist) / sizeof(HeapWord));
 }
 
 bool MethodData::is_empty_data(int size_in_bytes, Bytecodes::Code code) {
--- a/src/share/vm/oops/methodData.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/oops/methodData.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -1304,7 +1304,10 @@
   static bool bytecode_has_profile(Bytecodes::Code code) {
     return bytecode_cell_count(code) != no_profile_data;
   }
-  
+
+  // reset into original state
+  void init();
+
   // My size
   int size_in_bytes() const { return _size; }
   int size() const    { return align_object_size(align_size_up(_size, BytesPerWord)/BytesPerWord); }
@@ -1384,6 +1387,7 @@
   intx arg_stack()                               { return _arg_stack; }
   intx arg_returned()                            { return _arg_returned; }
   uint arg_modified(int a)                       { ArgInfoData *aid = arg_info();
+                                                   assert(aid != NULL, "arg_info must be not null");
                                                    assert(a >= 0 && a < aid->number_of_args(), "valid argument number");
                                                    return aid->arg_modified(a); }
 
@@ -1392,8 +1396,8 @@
   void set_arg_stack(intx v)                     { _arg_stack = v; }
   void set_arg_returned(intx v)                  { _arg_returned = v; }
   void set_arg_modified(int a, uint v)           { ArgInfoData *aid = arg_info();
+                                                   assert(aid != NULL, "arg_info must be not null");
                                                    assert(a >= 0 && a < aid->number_of_args(), "valid argument number");
-
                                                    aid->set_arg_modified(a, v); }
 
   void clear_escape_info()                       { _eflags = _arg_local = _arg_stack = _arg_returned = 0; }
--- a/src/share/vm/opto/block.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/opto/block.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -1028,26 +1028,6 @@
 }
 
 #ifndef PRODUCT
-static void edge_dump(GrowableArray<CFGEdge *> *edges) {
-  tty->print_cr("---- Edges ----");
-  for (int i = 0; i < edges->length(); i++) {
-    CFGEdge *e = edges->at(i);
-    if (e != NULL) {
-      edges->at(i)->dump();
-    }
-  }
-}
-
-static void trace_dump(Trace *traces[], int count) {
-  tty->print_cr("---- Traces ----");
-  for (int i = 0; i < count; i++) {
-    Trace *tr = traces[i];
-    if (tr != NULL) {
-      tr->dump();
-    }
-  }
-}
-
 void Trace::dump( ) const {
   tty->print_cr("Trace (freq %f)", first_block()->_freq);
   for (Block *b = first_block(); b != NULL; b = next(b)) {
--- a/src/share/vm/opto/compile.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/opto/compile.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -2326,12 +2326,14 @@
   int  get_inner_loop_count() const { return _inner_loop_count; }
 };
 
+#ifdef ASSERT
 static bool oop_offset_is_sane(const TypeInstPtr* tp) {
   ciInstanceKlass *k = tp->klass()->as_instance_klass();
   // Make sure the offset goes inside the instance layout.
   return k->contains_field_offset(tp->offset());
   // Note that OffsetBot and OffsetTop are very negative.
 }
+#endif
 
 // Eliminate trivially redundant StoreCMs and accumulate their
 // precedence edges.
--- a/src/share/vm/opto/connode.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/opto/connode.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -465,29 +465,6 @@
   return (phase->type(in(1)) == phase->type(this)) ? in(1) : this;
 }
 
-// Determine whether "n" is a node which can cause an alias of one of its inputs.  Node types
-// which can create aliases are: CheckCastPP, Phi, and any store (if there is also a load from
-// the location.)
-// Note:  this checks for aliases created in this compilation, not ones which may
-//        be potentially created at call sites.
-static bool can_cause_alias(Node *n, PhaseTransform *phase) {
-  bool possible_alias = false;
-
-  if (n->is_Store()) {
-    possible_alias = !n->as_Store()->value_never_loaded(phase);
-  } else {
-    int opc = n->Opcode();
-    possible_alias = n->is_Phi() ||
-        opc == Op_CheckCastPP ||
-        opc == Op_StorePConditional ||
-        opc == Op_CompareAndSwapP ||
-        opc == Op_CompareAndSwapN ||
-        opc == Op_GetAndSetP ||
-        opc == Op_GetAndSetN;
-  }
-  return possible_alias;
-}
-
 //------------------------------Value------------------------------------------
 // Take 'join' of input and cast-up type, unless working with an Interface
 const Type *CheckCastPPNode::Value( PhaseTransform *phase ) const {
--- a/src/share/vm/opto/subnode.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/opto/subnode.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -1078,16 +1078,6 @@
   return (_test._test == b->_test._test);
 }
 
-//------------------------------clone_cmp--------------------------------------
-// Clone a compare/bool tree
-static Node *clone_cmp( Node *cmp, Node *cmp1, Node *cmp2, PhaseGVN *gvn, BoolTest::mask test ) {
-  Node *ncmp = cmp->clone();
-  ncmp->set_req(1,cmp1);
-  ncmp->set_req(2,cmp2);
-  ncmp = gvn->transform( ncmp );
-  return new (gvn->C) BoolNode( ncmp, test );
-}
-
 //-------------------------------make_predicate--------------------------------
 Node* BoolNode::make_predicate(Node* test_value, PhaseGVN* phase) {
   if (test_value->is_Con())   return test_value;
--- a/src/share/vm/prims/jni.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/prims/jni.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -1292,32 +1292,6 @@
   JNI_NONVIRTUAL
 };
 
-static methodHandle jni_resolve_interface_call(Handle recv, methodHandle method, TRAPS) {
-  assert(!method.is_null() , "method should not be null");
-
-  KlassHandle recv_klass; // Default to NULL (use of ?: can confuse gcc)
-  if (recv.not_null()) recv_klass = KlassHandle(THREAD, recv->klass());
-  KlassHandle spec_klass (THREAD, method->method_holder());
-  Symbol*  name  = method->name();
-  Symbol*  signature  = method->signature();
-  CallInfo info;
-  LinkResolver::resolve_interface_call(info, recv, recv_klass,  spec_klass, name, signature, KlassHandle(), false, true, CHECK_(methodHandle()));
-  return info.selected_method();
-}
-
-static methodHandle jni_resolve_virtual_call(Handle recv, methodHandle method, TRAPS) {
-  assert(!method.is_null() , "method should not be null");
-
-  KlassHandle recv_klass; // Default to NULL (use of ?: can confuse gcc)
-  if (recv.not_null()) recv_klass = KlassHandle(THREAD, recv->klass());
-  KlassHandle spec_klass (THREAD, method->method_holder());
-  Symbol*  name  = method->name();
-  Symbol*  signature  = method->signature();
-  CallInfo info;
-  LinkResolver::resolve_virtual_call(info, recv, recv_klass,  spec_klass, name, signature, KlassHandle(), false, true, CHECK_(methodHandle()));
-  return info.selected_method();
-}
-
 
 
 static void jni_invoke_static(JNIEnv *env, JavaValue* result, jobject receiver, JNICallType call_type, jmethodID method_id, JNI_ArgumentPusher *args, TRAPS) {
@@ -5056,6 +5030,7 @@
 void execute_internal_vm_tests() {
   if (ExecuteInternalVMTests) {
     tty->print_cr("Running internal VM tests");
+    run_unit_test(GlobalDefinitions::test_globals());
     run_unit_test(arrayOopDesc::test_max_array_length());
     run_unit_test(CollectedHeap::test_is_in());
     run_unit_test(QuickSort::test_quick_sort());
--- a/src/share/vm/prims/jniCheck.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/prims/jniCheck.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -33,7 +33,7 @@
   // within IN_VM macro), one to be called when in NATIVE state.
 
   // When in VM state:
-  static void ReportJNIFatalError(JavaThread* thr, const char *msg) {
+  static inline void ReportJNIFatalError(JavaThread* thr, const char *msg) {
     tty->print_cr("FATAL ERROR in native method: %s", msg);
     thr->print_stack();
     os::abort(true);
--- a/src/share/vm/prims/unsafe.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/prims/unsafe.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -116,7 +116,11 @@
 inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) {
   jlong byte_offset = field_offset_to_byte_offset(field_offset);
   // Don't allow unsafe to be used to read or write the header word of oops
+  // unless running GRAAL which wants to read the misc word for example when
+  // interpreting computeHashCode().
+#ifndef GRAAL
   assert(p == NULL || field_offset >= oopDesc::header_size(), "offset must be outside of header");
+#endif
 #ifdef ASSERT
   if (p != NULL) {
     assert(byte_offset >= 0 && byte_offset <= (jlong)MAX_OBJECT_SIZE, "sane offset");
--- a/src/share/vm/prims/whitebox.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/prims/whitebox.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -49,6 +49,7 @@
 #endif // INCLUDE_NMT
 
 #include "compiler/compileBroker.hpp"
+#include "runtime/compilationPolicy.hpp"
 
 bool WhiteBox::_used = false;
 
@@ -118,45 +119,46 @@
 #endif // INCLUDE_ALL_GCS
 
 #ifdef INCLUDE_NMT
-// Keep track of the 3 allocations in NMTAllocTest so we can free them later
-// on and verify that they're not visible anymore
-static void* nmtMtTest1 = NULL, *nmtMtTest2 = NULL, *nmtMtTest3 = NULL;
-
 // Alloc memory using the test memory type so that we can use that to see if
 // NMT picks it up correctly
-WB_ENTRY(jboolean, WB_NMTAllocTest(JNIEnv* env))
-  void *mem;
+WB_ENTRY(jlong, WB_NMTMalloc(JNIEnv* env, jobject o, jlong size))
+  jlong addr = 0;
 
-  if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) {
-    return false;
+  if (MemTracker::is_on() && !MemTracker::shutdown_in_progress()) {
+    addr = (jlong)(uintptr_t)os::malloc(size, mtTest);
   }
 
-  // Allocate 2 * 128k + 256k + 1024k and free the 1024k one to make sure we track
-  // everything correctly. Total should be 512k held alive.
-  nmtMtTest1 = os::malloc(128 * 1024, mtTest);
-  mem = os::malloc(1024 * 1024, mtTest);
-  nmtMtTest2 = os::malloc(256 * 1024, mtTest);
-  os::free(mem, mtTest);
-  nmtMtTest3 = os::malloc(128 * 1024, mtTest);
-
-  return true;
+  return addr;
 WB_END
 
 // Free the memory allocated by NMTAllocTest
-WB_ENTRY(jboolean, WB_NMTFreeTestMemory(JNIEnv* env))
+WB_ENTRY(void, WB_NMTFree(JNIEnv* env, jobject o, jlong mem))
+  os::free((void*)(uintptr_t)mem, mtTest);
+WB_END
 
-  if (nmtMtTest1 == NULL || nmtMtTest2 == NULL || nmtMtTest3 == NULL) {
-    return false;
+WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size))
+  jlong addr = 0;
+
+  if (MemTracker::is_on() && !MemTracker::shutdown_in_progress()) {
+    addr = (jlong)(uintptr_t)os::reserve_memory(size);
+    MemTracker::record_virtual_memory_type((address)addr, mtTest);
   }
 
-  os::free(nmtMtTest1, mtTest);
-  nmtMtTest1 = NULL;
-  os::free(nmtMtTest2, mtTest);
-  nmtMtTest2 = NULL;
-  os::free(nmtMtTest3, mtTest);
-  nmtMtTest3 = NULL;
+  return addr;
+WB_END
+
 
-  return true;
+WB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
+  os::commit_memory((char *)(uintptr_t)addr, size);
+  MemTracker::record_virtual_memory_type((address)(uintptr_t)addr, mtTest);
+WB_END
+
+WB_ENTRY(void, WB_NMTUncommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
+  os::uncommit_memory((char *)(uintptr_t)addr, size);
+WB_END
+
+WB_ENTRY(void, WB_NMTReleaseMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
+  os::release_memory((char *)(uintptr_t)addr, size);
 WB_END
 
 // Block until the current generation of NMT data to be merged, used to reliably test the NMT feature
@@ -213,11 +215,11 @@
   return (code->is_alive() && !code->is_marked_for_deoptimization());
 WB_END
 
-WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method))
+WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level))
   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
   MutexLockerEx mu(Compile_lock);
   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
-  return !mh->is_not_compilable();
+  return CompilationPolicy::can_be_compiled(mh, comp_level);
 WB_END
 
 WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method))
@@ -241,7 +243,7 @@
   mh->set_not_compilable();
 WB_END
 
-WB_ENTRY(jboolean, WB_SetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
+WB_ENTRY(jboolean, WB_TestSetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
   bool result = mh->dont_inline();
@@ -254,6 +256,54 @@
          CompileBroker::queue_size(CompLevel_full_profile) /* C1 */;
 WB_END
 
+
+WB_ENTRY(jboolean, WB_TestSetForceInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
+  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
+  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
+  bool result = mh->force_inline();
+  mh->set_force_inline(value == JNI_TRUE);
+  return result;
+WB_END
+
+WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level))
+  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
+  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
+  nmethod* nm = CompileBroker::compile_method(mh, InvocationEntryBci, comp_level, mh, mh->invocation_count(), "WhiteBox", THREAD);
+  MutexLockerEx mu(Compile_lock);
+  return (mh->queued_for_compilation() || nm != NULL);
+WB_END
+
+WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
+  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
+  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
+  MutexLockerEx mu(Compile_lock);
+  MethodData* mdo = mh->method_data();
+
+  if (mdo != NULL) {
+    mdo->init();
+    ResourceMark rm;
+    int arg_count = mdo->method()->size_of_parameters();
+    for (int i = 0; i < arg_count; i++) {
+      mdo->set_arg_modified(i, 0);
+    }
+  }
+
+  mh->backedge_counter()->init();
+  mh->invocation_counter()->init();
+  mh->set_interpreter_invocation_count(0);
+  mh->set_interpreter_throwout_count(0);
+  mh->clear_not_c1_compilable();
+  mh->clear_not_c2_compilable();
+  mh->clear_not_c2_osr_compilable();
+  NOT_PRODUCT(mh->set_compiled_invocation_count(0));
+
+#ifdef TIERED
+  mh->set_rate(0.0F);
+  mh->set_prev_event_count(0);
+  mh->set_prev_time(0);
+#endif
+WB_END
+
 WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString))
   ResourceMark rm(THREAD);
   int len;
@@ -271,7 +321,6 @@
   Universe::heap()->collect(GCCause::_last_ditch_collection);
 WB_END
 
-
 //Some convenience methods to deal with objects from java
 int WhiteBox::offset_for_field(const char* field_name, oop object,
     Symbol* signature_symbol) {
@@ -340,27 +389,37 @@
   {CC"g1RegionSize",       CC"()I",                   (void*)&WB_G1RegionSize      },
 #endif // INCLUDE_ALL_GCS
 #ifdef INCLUDE_NMT
-  {CC"NMTAllocTest",       CC"()Z",                   (void*)&WB_NMTAllocTest      },
-  {CC"NMTFreeTestMemory",  CC"()Z",                   (void*)&WB_NMTFreeTestMemory },
-  {CC"NMTWaitForDataMerge",CC"()Z",                   (void*)&WB_NMTWaitForDataMerge},
+  {CC"NMTMalloc",           CC"(J)J",                 (void*)&WB_NMTMalloc          },
+  {CC"NMTFree",             CC"(J)V",                 (void*)&WB_NMTFree            },
+  {CC"NMTReserveMemory",    CC"(J)J",                 (void*)&WB_NMTReserveMemory   },
+  {CC"NMTCommitMemory",     CC"(JJ)V",                (void*)&WB_NMTCommitMemory    },
+  {CC"NMTUncommitMemory",   CC"(JJ)V",                (void*)&WB_NMTUncommitMemory  },
+  {CC"NMTReleaseMemory",    CC"(JJ)V",                (void*)&WB_NMTReleaseMemory   },
+  {CC"NMTWaitForDataMerge", CC"()Z",                  (void*)&WB_NMTWaitForDataMerge},
 #endif // INCLUDE_NMT
   {CC"deoptimizeAll",      CC"()V",                   (void*)&WB_DeoptimizeAll     },
   {CC"deoptimizeMethod",   CC"(Ljava/lang/reflect/Method;)I",
                                                       (void*)&WB_DeoptimizeMethod  },
   {CC"isMethodCompiled",   CC"(Ljava/lang/reflect/Method;)Z",
                                                       (void*)&WB_IsMethodCompiled  },
-  {CC"isMethodCompilable", CC"(Ljava/lang/reflect/Method;)Z",
+  {CC"isMethodCompilable", CC"(Ljava/lang/reflect/Method;I)Z",
                                                       (void*)&WB_IsMethodCompilable},
   {CC"isMethodQueuedForCompilation",
       CC"(Ljava/lang/reflect/Method;)Z",              (void*)&WB_IsMethodQueuedForCompilation},
   {CC"makeMethodNotCompilable",
       CC"(Ljava/lang/reflect/Method;)V",              (void*)&WB_MakeMethodNotCompilable},
-  {CC"setDontInlineMethod",
-      CC"(Ljava/lang/reflect/Method;Z)Z",             (void*)&WB_SetDontInlineMethod},
+  {CC"testSetDontInlineMethod",
+      CC"(Ljava/lang/reflect/Method;Z)Z",             (void*)&WB_TestSetDontInlineMethod},
   {CC"getMethodCompilationLevel",
       CC"(Ljava/lang/reflect/Method;)I",              (void*)&WB_GetMethodCompilationLevel},
   {CC"getCompileQueuesSize",
       CC"()I",                                        (void*)&WB_GetCompileQueuesSize},
+  {CC"testSetForceInlineMethod",
+      CC"(Ljava/lang/reflect/Method;Z)Z",             (void*)&WB_TestSetForceInlineMethod},
+  {CC"enqueueMethodForCompilation",
+      CC"(Ljava/lang/reflect/Method;I)Z",             (void*)&WB_EnqueueMethodForCompilation},
+  {CC"clearMethodState",
+      CC"(Ljava/lang/reflect/Method;)V",              (void*)&WB_ClearMethodState},
   {CC"isInStringTable",   CC"(Ljava/lang/String;)Z",  (void*)&WB_IsInStringTable  },
   {CC"fullGC",   CC"()V",                             (void*)&WB_FullGC },
 };
--- a/src/share/vm/runtime/arguments.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/runtime/arguments.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -1763,11 +1763,15 @@
   return false;
 }
 
+#if !INCLUDE_ALL_GCS
+#ifdef ASSERT
 static bool verify_serial_gc_flags() {
   return (UseSerialGC &&
         !(UseParNewGC || (UseConcMarkSweepGC || CMSIncrementalMode) || UseG1GC ||
           UseParallelGC || UseParallelOldGC));
 }
+#endif // ASSERT
+#endif // INCLUDE_ALL_GCS
 
 // check if do gclog rotation
 // +UseGCLogFileRotation is a must,
@@ -2015,11 +2019,12 @@
   // than just disable the lock verification. This will be fixed under
   // bug 4788986.
   if (UseConcMarkSweepGC && FLSVerifyAllHeapReferences) {
-    if (VerifyGCStartAt == 0) {
+    if (VerifyDuringStartup) {
       warning("Heap verification at start-up disabled "
               "(due to current incompatibility with FLSVerifyAllHeapReferences)");
-      VerifyGCStartAt = 1;      // Disable verification at start-up
+      VerifyDuringStartup = false; // Disable verification at start-up
     }
+
     if (VerifyBeforeExit) {
       warning("Heap verification at shutdown disabled "
               "(due to current incompatibility with FLSVerifyAllHeapReferences)");
@@ -3158,6 +3163,7 @@
   }                                                                   \
 } while(0)
 
+#if !INCLUDE_ALL_GCS
 static void force_serial_gc() {
   FLAG_SET_DEFAULT(UseSerialGC, true);
   FLAG_SET_DEFAULT(CMSIncrementalMode, false);  // special CMS suboption
@@ -3167,6 +3173,7 @@
   UNSUPPORTED_GC_OPTION(UseConcMarkSweepGC);
   UNSUPPORTED_GC_OPTION(UseParNewGC);
 }
+#endif // INCLUDE_ALL_GCS
 
 // Parse entry point called from JNI_CreateJavaVM
 
--- a/src/share/vm/runtime/compilationPolicy.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/runtime/compilationPolicy.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -130,9 +130,10 @@
   }
   if (comp_level == CompLevel_all) {
     return !m->is_not_compilable(CompLevel_simple) && !m->is_not_compilable(CompLevel_full_optimization);
-  } else {
+  } else if (is_compile(comp_level)) {
     return !m->is_not_compilable(comp_level);
   }
+  return false;
 }
 
 bool CompilationPolicy::is_compilation_enabled() {
--- a/src/share/vm/runtime/compilationPolicy.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/runtime/compilationPolicy.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -96,7 +96,7 @@
   void reset_counter_for_back_branch_event(methodHandle method);
 public:
   NonTieredCompPolicy() : _compiler_count(0) { }
-  virtual CompLevel initial_compile_level() { return CompLevel_initial_compile; }
+  virtual CompLevel initial_compile_level() { return CompLevel_highest_tier; }
   virtual int compiler_count(CompLevel comp_level);
   virtual void do_safepoint_work();
   virtual void reprofile(ScopeDesc* trap_scope, bool is_osr);
--- a/src/share/vm/runtime/globals.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/runtime/globals.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -2140,6 +2140,10 @@
   product(intx, PrefetchFieldsAhead, -1,                                    \
           "How many fields ahead to prefetch in oop scan (<= 0 means off)") \
                                                                             \
+  diagnostic(bool, VerifyDuringStartup, false,                              \
+          "Verify memory system before executing any Java code "            \
+          "during VM initialization")                                       \
+                                                                            \
   diagnostic(bool, VerifyBeforeExit, trueInDebug,                           \
           "Verify system before exiting")                                   \
                                                                             \
@@ -3333,10 +3337,10 @@
           "ConcurrentMarkSweep thread runs at critical scheduling priority")\
                                                                             \
   /* compiler debugging */                                                  \
-  notproduct(intx, CompileTheWorldStartAt,     1,                           \
+  develop(intx, CompileTheWorldStartAt, 1,                                  \
           "First class to consider when using +CompileTheWorld")            \
                                                                             \
-  notproduct(intx, CompileTheWorldStopAt, max_jint,                         \
+  develop(intx, CompileTheWorldStopAt, max_jint,                            \
           "Last class to consider when using +CompileTheWorld")             \
                                                                             \
   develop(intx, NewCodeParameter,      0,                                   \
@@ -3684,8 +3688,13 @@
   product(bool, PrintGCCause, true,                                         \
           "Include GC cause in GC logging")                                 \
                                                                             \
-  product(bool, AllowNonVirtualCalls, false,                                \
-          "Obey the ACC_SUPER flag and allow invokenonvirtual calls")
+  product(bool , AllowNonVirtualCalls, false,                               \
+          "Obey the ACC_SUPER flag and allow invokenonvirtual calls")       \
+                                                                            \
+  experimental(uintx, ArrayAllocatorMallocLimit,                            \
+          SOLARIS_ONLY(64*K) NOT_SOLARIS(max_uintx),                        \
+          "Allocation less than this value will be allocated "              \
+          "using malloc. Larger allocations will use mmap.")
 
 /*
  *  Macros for factoring of globals
--- a/src/share/vm/runtime/javaCalls.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/runtime/javaCalls.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -412,7 +412,7 @@
       ((JavaThread*) THREAD)->set_graal_alternate_call_target(nm->verified_entry_point());
       entry_point = method->adapter()->get_i2c_entry();
     } else {
-      THROW(vmSymbols::MethodInvalidatedException());
+      THROW(vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException());
     }
   }
 #endif
--- a/src/share/vm/runtime/safepoint.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/runtime/safepoint.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -735,6 +735,9 @@
 // Exception handlers
 
 #ifndef PRODUCT
+
+#ifdef SPARC
+
 #ifdef _LP64
 #define PTR_PAD ""
 #else
@@ -755,7 +758,6 @@
                 newptr, is_oop?"oop":"   ", (wasoop && !is_oop) ? "STALE" : ((wasoop==false&&is_oop==false&&oldptr !=newptr)?"STOMP":"     "));
 }
 
-#ifdef SPARC
 static void print_me(intptr_t *new_sp, intptr_t *old_sp, bool *was_oops) {
 #ifdef _LP64
   tty->print_cr("--------+------address-----+------before-----------+-------after----------+");
--- a/src/share/vm/runtime/sharedRuntime.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -83,6 +83,7 @@
 #endif
 
 // Shared stub locations
+RuntimeStub*        SharedRuntime::_deoptimized_installed_code_blob;
 RuntimeStub*        SharedRuntime::_wrong_method_blob;
 RuntimeStub*        SharedRuntime::_ic_miss_blob;
 RuntimeStub*        SharedRuntime::_resolve_opt_virtual_call_blob;
@@ -101,6 +102,7 @@
 
 //----------------------------generate_stubs-----------------------------------
 void SharedRuntime::generate_stubs() {
+  _deoptimized_installed_code_blob     = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_deoptimized_installed_code), "deoptimized_installed_code");
   _wrong_method_blob                   = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_wrong_method),         "wrong_method_stub");
   _ic_miss_blob                        = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_wrong_method_ic_miss), "ic_miss_stub");
   _resolve_opt_virtual_call_blob       = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_opt_virtual_call_C),  "resolve_opt_virtual_call");
@@ -969,6 +971,11 @@
 
 
 JRT_ENTRY_NO_ASYNC(void, SharedRuntime::register_finalizer(JavaThread* thread, oopDesc* obj))
+#ifdef GRAAL
+  if (!obj->klass()->has_finalizer()) {
+    return;
+  }
+#endif
   assert(obj->is_oop(), "must be a valid oop");
   assert(obj->klass()->has_finalizer(), "shouldn't be here otherwise");
   InstanceKlass::register_finalizer(instanceOop(obj), CHECK);
@@ -1345,6 +1352,12 @@
   return callee_method->verified_code_entry();
 JRT_END
 
+// Installed code has been deoptimized
+JRT_BLOCK_ENTRY(address, SharedRuntime::handle_deoptimized_installed_code(JavaThread* thread))
+  JavaThread* THREAD = thread;
+  ThreadInVMfromJava tiv(THREAD);
+  THROW_(vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL);
+JRT_END
 
 // Handle call site that has been made non-entrant
 JRT_BLOCK_ENTRY(address, SharedRuntime::handle_wrong_method(JavaThread* thread))
--- a/src/share/vm/runtime/sharedRuntime.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/runtime/sharedRuntime.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -55,6 +55,7 @@
 
   // Shared stub locations
 
+  static RuntimeStub*        _deoptimized_installed_code_blob;
   static RuntimeStub*        _wrong_method_blob;
   static RuntimeStub*        _ic_miss_blob;
   static RuntimeStub*        _resolve_opt_virtual_call_blob;
@@ -209,6 +210,11 @@
     return _wrong_method_blob->entry_point();
   }
 
+  static address get_deoptimized_installed_code_stub() {
+    assert(_deoptimized_installed_code_blob!= NULL, "oops");
+    return _deoptimized_installed_code_blob->entry_point();
+  }
+
 #ifdef COMPILER2
   static void generate_uncommon_trap_blob(void);
   static UncommonTrapBlob* uncommon_trap_blob()                  { return _uncommon_trap_blob; }
@@ -486,6 +492,9 @@
   static address handle_wrong_method(JavaThread* thread);
   static address handle_wrong_method_ic_miss(JavaThread* thread);
 
+  // handle deoptimized installed code
+  static address handle_deoptimized_installed_code(JavaThread* thread);
+
 #ifndef PRODUCT
 
   // Collect and print inline cache miss statistics
--- a/src/share/vm/runtime/synchronizer.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/runtime/synchronizer.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -449,8 +449,6 @@
 // and explicit fences (barriers) to control for architectural reordering performed
 // by the CPU(s) or platform.
 
-static int  MBFence (int x) { OrderAccess::fence(); return x; }
-
 struct SharedGlobals {
     // These are highly shared mostly-read variables.
     // To avoid false-sharing they need to be the sole occupants of a $ line.
@@ -1639,11 +1637,6 @@
 
 #ifndef PRODUCT
 
-void ObjectSynchronizer::trace_locking(Handle locking_obj, bool is_compiled,
-                                       bool is_method, bool is_locking) {
-  // Don't know what to do here
-}
-
 // Verify all monitors in the monitor cache, the verification is weak.
 void ObjectSynchronizer::verify() {
   ObjectMonitor* block = gBlockList;
--- a/src/share/vm/runtime/synchronizer.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/runtime/synchronizer.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -121,7 +121,6 @@
   static void oops_do(OopClosure* f);
 
   // debugging
-  static void trace_locking(Handle obj, bool is_compiled, bool is_method, bool is_locking) PRODUCT_RETURN;
   static void verify() PRODUCT_RETURN;
   static int  verify_objmon_isinpool(ObjectMonitor *addr) PRODUCT_RETURN0;
 
--- a/src/share/vm/runtime/thread.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/runtime/thread.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -3449,9 +3449,9 @@
   }
 
   assert (Universe::is_fully_initialized(), "not initialized");
-  if (VerifyBeforeGC && VerifyGCStartAt == 0) {
-    Universe::heap()->prepare_for_verify();
-    Universe::verify();   // make sure we're starting with a clean slate
+  if (VerifyDuringStartup) {
+    VM_Verify verify_op(false /* silent */);   // make sure we're starting with a clean slate
+    VMThread::execute(&verify_op);
   }
 
   EXCEPTION_MARK;
--- a/src/share/vm/runtime/vmStructs.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/runtime/vmStructs.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -478,6 +478,9 @@
                                                                                                                                      \
   nonstatic_field(CardGeneration,              _rs,                                           GenRemSet*)                            \
   nonstatic_field(CardGeneration,              _bts,                                          BlockOffsetSharedArray*)               \
+  nonstatic_field(CardGeneration,              _shrink_factor,                                size_t)                                \
+  nonstatic_field(CardGeneration,              _capacity_at_prologue,                         size_t)                                \
+  nonstatic_field(CardGeneration,              _used_at_prologue,                             size_t)                                \
                                                                                                                                      \
   nonstatic_field(CardTableModRefBS,           _whole_heap,                                   const MemRegion)                       \
   nonstatic_field(CardTableModRefBS,           _guard_index,                                  const size_t)                          \
@@ -548,8 +551,6 @@
   nonstatic_field(Space,                       _bottom,                                       HeapWord*)                             \
   nonstatic_field(Space,                       _end,                                          HeapWord*)                             \
                                                                                                                                      \
-  nonstatic_field(TenuredGeneration,           _shrink_factor,                                size_t)                                \
-  nonstatic_field(TenuredGeneration,           _capacity_at_prologue,                         size_t)                                \
   nonstatic_field(ThreadLocalAllocBuffer,      _start,                                        HeapWord*)                             \
   nonstatic_field(ThreadLocalAllocBuffer,      _top,                                          HeapWord*)                             \
   nonstatic_field(ThreadLocalAllocBuffer,      _end,                                          HeapWord*)                             \
--- a/src/share/vm/runtime/vm_operations.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/runtime/vm_operations.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -177,7 +177,8 @@
 }
 
 void VM_Verify::doit() {
-  Universe::verify();
+  Universe::heap()->prepare_for_verify();
+  Universe::verify(_silent);
 }
 
 bool VM_PrintThreads::doit_prologue() {
--- a/src/share/vm/runtime/vm_operations.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/runtime/vm_operations.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -301,9 +301,9 @@
 
 class VM_Verify: public VM_Operation {
  private:
-  KlassHandle _dependee;
+  bool _silent;
  public:
-  VM_Verify() {}
+  VM_Verify(bool silent) : _silent(silent) {}
   VMOp_Type type() const { return VMOp_Verify; }
   void doit();
 };
--- a/src/share/vm/services/memTracker.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/services/memTracker.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -127,12 +127,15 @@
   assert(_state == NMT_bootstrapping_multi_thread, "wrong state");
 
   _snapshot = new (std::nothrow)MemSnapshot();
-  if (_snapshot != NULL && !_snapshot->out_of_memory()) {
-    if (start_worker()) {
+  if (_snapshot != NULL) {
+    if (!_snapshot->out_of_memory() && start_worker()) {
       _state = NMT_started;
       NMT_track_callsite = (_tracking_level == NMT_detail && can_walk_stack());
       return;
     }
+
+    delete _snapshot;
+    _snapshot = NULL;
   }
 
   // fail to start native memory tracking, shut it down
@@ -544,7 +547,10 @@
   assert(_worker_thread == NULL, "Just Check");
   _worker_thread = new (std::nothrow) MemTrackWorker();
   if (_worker_thread == NULL || _worker_thread->has_error()) {
-    shutdown(NMT_initialization);
+    if (_worker_thread != NULL) {
+      delete _worker_thread;
+      _worker_thread = NULL;
+    }
     return false;
   }
   _worker_thread->start();
--- a/src/share/vm/utilities/accessFlags.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/utilities/accessFlags.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -194,6 +194,9 @@
   void set_is_obsolete()               { atomic_set_bits(JVM_ACC_IS_OBSOLETE);             }
   void set_is_prefixed_native()        { atomic_set_bits(JVM_ACC_IS_PREFIXED_NATIVE);      }
 
+  void clear_not_c1_compilable()       { atomic_clear_bits(JVM_ACC_NOT_C1_COMPILABLE);       }
+  void clear_not_c2_compilable()       { atomic_clear_bits(JVM_ACC_NOT_C2_COMPILABLE);       }
+  void clear_not_c2_osr_compilable()   { atomic_clear_bits(JVM_ACC_NOT_C2_OSR_COMPILABLE);   }
   // Klass* flags
   void set_has_vanilla_constructor()   { atomic_set_bits(JVM_ACC_HAS_VANILLA_CONSTRUCTOR); }
   void set_has_finalizer()             { atomic_set_bits(JVM_ACC_HAS_FINALIZER);           }
--- a/src/share/vm/utilities/bitMap.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/utilities/bitMap.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -516,6 +516,10 @@
   return sum;
 }
 
+void BitMap::print_on_error(outputStream* st, const char* prefix) const {
+  st->print_cr("%s[" PTR_FORMAT ", " PTR_FORMAT ")",
+      prefix, map(), (char*)map() + (size() >> LogBitsPerByte));
+}
 
 #ifndef PRODUCT
 
--- a/src/share/vm/utilities/bitMap.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/utilities/bitMap.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -262,6 +262,7 @@
   bool is_full() const;
   bool is_empty() const;
 
+  void print_on_error(outputStream* st, const char* prefix) const;
 
 #ifndef PRODUCT
  public:
--- a/src/share/vm/utilities/debug.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/utilities/debug.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -608,18 +608,6 @@
   return  CodeCache::find_nmethod((address)addr);
 }
 
-static address same_page(address x, address y) {
-  intptr_t page_bits = -os::vm_page_size();
-  if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) {
-    return x;
-  } else if (x > y) {
-    return (address)(intptr_t(y) | ~page_bits) + 1;
-  } else {
-    return (address)(intptr_t(y) & page_bits);
-  }
-}
-
-
 // Another interface that isn't ambiguous in dbx.
 // Can we someday rename the other find to hsfind?
 extern "C" void hsfind(intptr_t x) {
--- a/src/share/vm/utilities/globalDefinitions.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/utilities/globalDefinitions.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -355,3 +355,33 @@
 
     return size_t(result);
 }
+
+#ifndef PRODUCT
+
+void GlobalDefinitions::test_globals() {
+  intptr_t page_sizes[] = { os::vm_page_size(), 4096, 8192, 65536, 2*1024*1024 };
+  const int num_page_sizes = sizeof(page_sizes) / sizeof(page_sizes[0]);
+
+  for (int i = 0; i < num_page_sizes; i++) {
+    intptr_t page_size = page_sizes[i];
+
+    address a_page = (address)(10*page_size);
+
+    // Check that address within page is returned as is
+    assert(clamp_address_in_page(a_page, a_page, page_size) == a_page, "incorrect");
+    assert(clamp_address_in_page(a_page + 128, a_page, page_size) == a_page + 128, "incorrect");
+    assert(clamp_address_in_page(a_page + page_size - 1, a_page, page_size) == a_page + page_size - 1, "incorrect");
+
+    // Check that address above page returns start of next page
+    assert(clamp_address_in_page(a_page + page_size, a_page, page_size) == a_page + page_size, "incorrect");
+    assert(clamp_address_in_page(a_page + page_size + 1, a_page, page_size) == a_page + page_size, "incorrect");
+    assert(clamp_address_in_page(a_page + page_size*5 + 1, a_page, page_size) == a_page + page_size, "incorrect");
+
+    // Check that address below page returns start of page
+    assert(clamp_address_in_page(a_page - 1, a_page, page_size) == a_page, "incorrect");
+    assert(clamp_address_in_page(a_page - 2*page_size - 1, a_page, page_size) == a_page, "incorrect");
+    assert(clamp_address_in_page(a_page - 5*page_size - 1, a_page, page_size) == a_page, "incorrect");
+  }
+}
+
+#endif // PRODUCT
--- a/src/share/vm/utilities/globalDefinitions.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/utilities/globalDefinitions.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -419,6 +419,24 @@
   return align_size_up(offset, HeapWordsPerLong);
 }
 
+// Clamp an address to be within a specific page
+// 1. If addr is on the page it is returned as is
+// 2. If addr is above the page_address the start of the *next* page will be returned
+// 3. Otherwise, if addr is below the page_address the start of the page will be returned
+inline address clamp_address_in_page(address addr, address page_address, intptr_t page_size) {
+  if (align_size_down(intptr_t(addr), page_size) == align_size_down(intptr_t(page_address), page_size)) {
+    // address is in the specified page, just return it as is
+    return addr;
+  } else if (addr > page_address) {
+    // address is above specified page, return start of next page
+    return (address)align_size_down(intptr_t(page_address), page_size) + page_size;
+  } else {
+    // address is below specified page, return start of page
+    return (address)align_size_down(intptr_t(page_address), page_size);
+  }
+}
+
+
 // The expected size in bytes of a cache line, used to pad data structures.
 #define DEFAULT_CACHE_LINE_SIZE 64
 
@@ -827,6 +845,10 @@
   return comp_level == CompLevel_highest_tier;
 }
 
+inline bool is_compile(int comp_level) {
+  return is_c1_compile(comp_level) || is_c2_compile(comp_level);
+}
+
 //----------------------------------------------------------------------------------------------------
 // 'Forward' declarations of frequently used classes
 // (in order to reduce interface dependencies & reduce
@@ -1296,4 +1318,15 @@
   return *(void**)addr;
 }
 
+
+#ifndef PRODUCT
+
+// For unit testing only
+class GlobalDefinitions {
+public:
+  static void test_globals();
+};
+
+#endif // PRODUCT
+
 #endif // SHARE_VM_UTILITIES_GLOBALDEFINITIONS_HPP
--- a/src/share/vm/utilities/taskqueue.hpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/utilities/taskqueue.hpp	Mon Apr 15 08:49:14 2013 +0200
@@ -253,6 +253,7 @@
 
 template <class E, MEMFLAGS F, unsigned int N = TASKQUEUE_SIZE>
 class GenericTaskQueue: public TaskQueueSuper<N, F> {
+  ArrayAllocator<E, F> _array_allocator;
 protected:
   typedef typename TaskQueueSuper<N, F>::Age Age;
   typedef typename TaskQueueSuper<N, F>::idx_t idx_t;
@@ -314,7 +315,7 @@
 
 template<class E, MEMFLAGS F, unsigned int N>
 void GenericTaskQueue<E, F, N>::initialize() {
-  _elems = NEW_C_HEAP_ARRAY(E, N, F);
+  _elems = _array_allocator.allocate(N);
 }
 
 template<class E, MEMFLAGS F, unsigned int N>
--- a/src/share/vm/utilities/vmError.cpp	Mon Apr 08 17:48:46 2013 +0200
+++ b/src/share/vm/utilities/vmError.cpp	Mon Apr 15 08:49:14 2013 +0200
@@ -685,13 +685,7 @@
   STEP(190, "(printing heap information)" )
 
      if (_verbose && Universe::is_fully_initialized()) {
-       // Print heap information before vm abort. As we'd like as much
-       // information as possible in the report we ask for the
-       // extended (i.e., more detailed) version.
-       Universe::print_on(st, true /* extended */);
-       st->cr();
-
-       Universe::heap()->barrier_set()->print_on(st);
+       Universe::heap()->print_on_error(st);
        st->cr();
 
        st->print_cr("Polling page: " INTPTR_FORMAT, os::get_polling_page());
--- a/test/compiler/6863420/Test.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/test/compiler/6863420/Test.java	Mon Apr 15 08:49:14 2013 +0200
@@ -27,17 +27,35 @@
  * @bug 6863420
  * @summary os::javaTimeNanos() go backward on Solaris x86
  *
- * @run main/othervm Test
+ * Notice the internal timeout in timeout thread Test.TOT.
+ * @run main/othervm/timeout=300 Test
  */
 
 public class Test {
+
+    static final int INTERNAL_TIMEOUT=240;
+    static class TOT extends Thread {
+       public void run() {
+           try {
+               Thread.sleep(INTERNAL_TIMEOUT*1000);
+           } catch (InterruptedException ex) {
+           }
+           done = true;
+       }
+    }
+
     static long value = 0;
     static boolean got_backward_time = false;
+    static volatile boolean done = false;
 
     public static void main(String args[]) {
         final int count = 100000;
 
-        for (int numThreads = 1; numThreads <= 32; numThreads++) {
+        TOT tot = new TOT();
+        tot.setDaemon(true);
+        tot.start();
+
+        for (int numThreads = 1; !done && numThreads <= 32; numThreads++) {
             final int numRuns = 1;
             for (int t=1; t <= numRuns; t++) {
                 final int curRun = t;
@@ -48,7 +66,7 @@
                     Runnable thread =
                         new Runnable() {
                             public void run() {
-                                for (long l = 0; l < 100000; l++) {
+                                for (long l = 0; !done && l < 100000; l++) {
                                     final long start = System.nanoTime();
                                     if (value == 12345678) {
                                         System.out.println("Wow!");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/8011706/Test8011706.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8011706
+ * @summary loop invariant code motion may move load before store to the same field
+ * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation Test8011706
+ *
+ */
+
+public class Test8011706 {
+    int[] array;
+
+    void m(boolean test, int[] array1, int[] array2) {
+        int i = 0;
+        if (test) {
+            array = array1;
+        } else {
+            array = array2;
+        }
+
+        while(true) {
+            int v = array[i];
+            i++;
+            if (i >= 10) return;
+        }
+    }
+
+    static public void main(String[] args) {
+        int[] new_array = new int[10];
+        Test8011706 ti = new Test8011706();
+        boolean failed = false;
+        try {
+            for (int i = 0; i < 10000; i++) {
+                ti.array = null;
+                ti.m(true, new_array, new_array);
+            }
+        } catch(NullPointerException ex) {
+            throw new RuntimeException("TEST FAILED", ex);
+        }
+        System.out.println("TEST PASSED");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/whitebox/ClearMethodStateTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test ClearMethodStateTest
+ * @library /testlibrary /testlibrary/whitebox
+ * @build ClearMethodStateTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ClearMethodStateTest
+ * @author igor.ignatyev@oracle.com
+ */
+public class ClearMethodStateTest extends CompilerWhiteBoxTest {
+    public static void main(String[] args) throws Exception {
+        // to prevent inlining #method into #compile() and #test()
+        WHITE_BOX.testSetDontInlineMethod(METHOD, true);
+        new ClearMethodStateTest().runTest();
+    }
+
+    protected void test() throws Exception {
+        checkNotCompiled(METHOD);
+        compile();
+        checkCompiled(METHOD);
+        WHITE_BOX.clearMethodState(METHOD);
+        WHITE_BOX.deoptimizeMethod(METHOD);
+        checkNotCompiled(METHOD);
+
+
+        if (!TIERED_COMPILATION) {
+            WHITE_BOX.clearMethodState(METHOD);
+            compile(COMPILE_THRESHOLD);
+            checkCompiled(METHOD);
+
+            WHITE_BOX.deoptimizeMethod(METHOD);
+            checkNotCompiled(METHOD);
+            WHITE_BOX.clearMethodState(METHOD);
+
+            if (COMPILE_THRESHOLD > 1) {
+                compile(COMPILE_THRESHOLD - 1);
+                checkNotCompiled(METHOD);
+            } else {
+               System.err.println("Warning: 'CompileThreshold' <= 1");
+            }
+
+            method();
+            checkCompiled(METHOD);
+        } else {
+            System.err.println(
+                    "Warning: part of test is not applicable in Tiered");
+        }
+    }
+}
--- a/test/compiler/whitebox/CompilerWhiteBoxTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/test/compiler/whitebox/CompilerWhiteBoxTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -37,6 +37,8 @@
             = Integer.parseInt(getVMOption("CompileThreshold", "10000"));
     protected static final boolean BACKGROUND_COMPILATION
             = Boolean.valueOf(getVMOption("BackgroundCompilation", "true"));
+    protected static final boolean TIERED_COMPILATION
+            = Boolean.valueOf(getVMOption("TieredCompilation", "false"));
 
     protected static Method getMethod(String name) {
         try {
@@ -81,6 +83,9 @@
     }
 
     protected static void checkNotCompiled(Method method) {
+        if (WHITE_BOX.isMethodQueuedForCompilation(method)) {
+            throw new RuntimeException(method + " must not be in queue");
+        }
         if (WHITE_BOX.isMethodCompiled(method)) {
             throw new RuntimeException(method + " must be not compiled");
         }
@@ -139,8 +144,11 @@
     protected abstract void test() throws Exception;
 
     protected final int compile() {
+        return compile(Math.max(COMPILE_THRESHOLD, 150000));
+    }
+
+    protected final int compile(int count) {
         int result = 0;
-        int count = Math.max(COMPILE_THRESHOLD, 150000);
         for (int i = 0; i < count; ++i) {
             result += method();
         }
--- a/test/compiler/whitebox/DeoptimizeAllTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/test/compiler/whitebox/DeoptimizeAllTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -33,7 +33,7 @@
 
     public static void main(String[] args) throws Exception {
         // to prevent inlining #method into #compile()
-        WHITE_BOX.setDontInlineMethod(METHOD, true);
+        WHITE_BOX.testSetDontInlineMethod(METHOD, true);
         new DeoptimizeAllTest().runTest();
     }
 
--- a/test/compiler/whitebox/DeoptimizeMethodTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/test/compiler/whitebox/DeoptimizeMethodTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -33,7 +33,7 @@
 
     public static void main(String[] args) throws Exception {
         // to prevent inlining #method into #compile()
-        WHITE_BOX.setDontInlineMethod(METHOD, true);
+        WHITE_BOX.testSetDontInlineMethod(METHOD, true);
         new DeoptimizeMethodTest().runTest();
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/whitebox/EnqueueMethodForCompilationTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test EnqueueMethodForCompilationTest
+ * @library /testlibrary /testlibrary/whitebox
+ * @build EnqueueMethodForCompilationTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI EnqueueMethodForCompilationTest
+ * @author igor.ignatyev@oracle.com
+ */
+public class EnqueueMethodForCompilationTest extends CompilerWhiteBoxTest {
+    public static void main(String[] args) throws Exception {
+        // to prevent inlining #method into #compile()
+        WHITE_BOX.testSetDontInlineMethod(METHOD, true);
+        new EnqueueMethodForCompilationTest().runTest();
+    }
+
+    protected void test() throws Exception {
+        checkNotCompiled(METHOD);
+
+        WHITE_BOX.enqueueMethodForCompilation(METHOD, 0);
+        if (WHITE_BOX.isMethodCompilable(METHOD, 0)) {
+          throw new RuntimeException(METHOD + " is compilable at level 0");
+        }
+        checkNotCompiled(METHOD);
+
+        WHITE_BOX.enqueueMethodForCompilation(METHOD, -1);
+        checkNotCompiled(METHOD);
+
+        WHITE_BOX.enqueueMethodForCompilation(METHOD, 5);
+        if (!WHITE_BOX.isMethodCompilable(METHOD, 5)) {
+          checkNotCompiled(METHOD);
+          compile();
+          checkCompiled(METHOD);
+        } else {
+          checkCompiled(METHOD);
+        }
+
+        int compLevel = WHITE_BOX.getMethodCompilationLevel(METHOD);
+        WHITE_BOX.deoptimizeMethod(METHOD);
+        checkNotCompiled(METHOD);
+
+        WHITE_BOX.enqueueMethodForCompilation(METHOD, compLevel);
+        checkCompiled(METHOD);
+        WHITE_BOX.deoptimizeMethod(METHOD);
+        checkNotCompiled(METHOD);
+
+        compile();
+        checkCompiled(METHOD);
+        WHITE_BOX.deoptimizeMethod(METHOD);
+        checkNotCompiled(METHOD);
+    }
+}
--- a/test/compiler/whitebox/IsMethodCompilableTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/test/compiler/whitebox/IsMethodCompilableTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -45,7 +45,7 @@
 
     public static void main(String[] args) throws Exception {
         // to prevent inlining #method into #compile()
-        WHITE_BOX.setDontInlineMethod(METHOD, true);
+        WHITE_BOX.testSetDontInlineMethod(METHOD, true);
         new IsMethodCompilableTest().runTest();
     }
 
@@ -60,26 +60,47 @@
                     "Warning: test is not applicable if PerMethodRecompilationCutoff == Inf");
             return;
         }
-        boolean madeNotCompilable = false;
+
+        // deoptimze 'PerMethodRecompilationCutoff' times and clear state
+        for (long i = 0L, n = PER_METHOD_RECOMPILATION_CUTOFF - 1; i < n; ++i) {
+            compileAndDeoptimaze();
+        }
+        if (!WHITE_BOX.isMethodCompilable(METHOD)) {
+            throw new RuntimeException(METHOD + " is not compilable after "
+                    + (PER_METHOD_RECOMPILATION_CUTOFF - 1) + " iterations");
+        }
+        WHITE_BOX.clearMethodState(METHOD);
 
-        for (long i = 0; i < PER_METHOD_RECOMPILATION_CUTOFF; ++i) {
-            compile();
-            waitBackgroundCompilation(METHOD);
-            WHITE_BOX.deoptimizeMethod(METHOD);
-            if (!WHITE_BOX.isMethodCompilable(METHOD)) {
-                madeNotCompilable = true;
-                break;
-            }
+        // deoptimze 'PerMethodRecompilationCutoff' + 1 times
+        long i;
+        for (i = 0L; i < PER_METHOD_RECOMPILATION_CUTOFF
+                && WHITE_BOX.isMethodCompilable(METHOD); ++i) {
+            compileAndDeoptimaze();
         }
-        if (!madeNotCompilable) {
+        if (i != PER_METHOD_RECOMPILATION_CUTOFF) {
+           throw new RuntimeException(METHOD + " is not compilable after "
+                   + i + " iterations, but must only after "
+                   + PER_METHOD_RECOMPILATION_CUTOFF);
+        }
+        if (WHITE_BOX.isMethodCompilable(METHOD)) {
             throw new RuntimeException(METHOD + " is still compilable after "
                     + PER_METHOD_RECOMPILATION_CUTOFF + " iterations");
         }
         compile();
-        if (WHITE_BOX.isMethodCompiled(METHOD)) {
-            printInfo(METHOD);
-            throw new RuntimeException(
-                    METHOD + " is not compilable but compiled");
+        checkNotCompiled(METHOD);
+
+        WHITE_BOX.clearMethodState(METHOD);
+        if (!WHITE_BOX.isMethodCompilable(METHOD)) {
+            throw new RuntimeException(METHOD
+                    + " is compilable after clearMethodState()");
         }
+        compile();
+        checkCompiled(METHOD);
+    }
+
+    private void compileAndDeoptimaze() throws Exception {
+        compile();
+        waitBackgroundCompilation(METHOD);
+        WHITE_BOX.deoptimizeMethod(METHOD);
     }
 }
--- a/test/compiler/whitebox/MakeMethodNotCompilableTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/test/compiler/whitebox/MakeMethodNotCompilableTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -33,7 +33,7 @@
 
     public static void main(String[] args) throws Exception {
         // to prevent inlining #method into #compile()
-        WHITE_BOX.setDontInlineMethod(METHOD, true);
+        WHITE_BOX.testSetDontInlineMethod(METHOD, true);
         new MakeMethodNotCompilableTest().runTest();
     }
 
@@ -46,9 +46,6 @@
             throw new RuntimeException(METHOD + " must be not compilable");
         }
         compile();
-        if (WHITE_BOX.isMethodQueuedForCompilation(METHOD)) {
-            throw new RuntimeException(METHOD + " must not be in queue");
-        }
         checkNotCompiled(METHOD);
         if (WHITE_BOX.isMethodCompilable(METHOD)) {
             throw new RuntimeException(METHOD + " must be not compilable");
--- a/test/compiler/whitebox/SetDontInlineMethodTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/test/compiler/whitebox/SetDontInlineMethodTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -36,23 +36,23 @@
     }
 
     protected void test() throws Exception {
-        if (WHITE_BOX.setDontInlineMethod(METHOD, true)) {
+        if (WHITE_BOX.testSetDontInlineMethod(METHOD, true)) {
             throw new RuntimeException("on start " + METHOD
                     + " must be inlineable");
         }
-        if (!WHITE_BOX.setDontInlineMethod(METHOD, true)) {
+        if (!WHITE_BOX.testSetDontInlineMethod(METHOD, true)) {
             throw new RuntimeException("after first change to true " + METHOD
                     + " must be not inlineable");
         }
-        if (!WHITE_BOX.setDontInlineMethod(METHOD, false)) {
+        if (!WHITE_BOX.testSetDontInlineMethod(METHOD, false)) {
             throw new RuntimeException("after second change to true " + METHOD
                     + " must be still not inlineable");
         }
-        if (WHITE_BOX.setDontInlineMethod(METHOD, false)) {
+        if (WHITE_BOX.testSetDontInlineMethod(METHOD, false)) {
             throw new RuntimeException("after first change to false" + METHOD
                     + " must be inlineable");
         }
-        if (WHITE_BOX.setDontInlineMethod(METHOD, false)) {
+        if (WHITE_BOX.testSetDontInlineMethod(METHOD, false)) {
             throw new RuntimeException("after second change to false " + METHOD
                     + " must be inlineable");
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/whitebox/SetForceInlineMethodTest.java	Mon Apr 15 08:49:14 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.
+ */
+
+/*
+ * @test SetForceInlineMethodTest
+ * @library /testlibrary /testlibrary/whitebox
+ * @build SetForceInlineMethodTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SetForceInlineMethodTest
+ * @author igor.ignatyev@oracle.com
+ */
+public class SetForceInlineMethodTest extends CompilerWhiteBoxTest {
+
+    public static void main(String[] args) throws Exception {
+        new SetForceInlineMethodTest().runTest();
+    }
+
+    protected void test() throws Exception {
+        if (WHITE_BOX.testSetForceInlineMethod(METHOD, true)) {
+            throw new RuntimeException("on start " + METHOD
+                    + " must be not force inlineable");
+        }
+        if (!WHITE_BOX.testSetForceInlineMethod(METHOD, true)) {
+            throw new RuntimeException("after first change to true " + METHOD
+                    + " must be force inlineable");
+        }
+        if (!WHITE_BOX.testSetForceInlineMethod(METHOD, false)) {
+            throw new RuntimeException("after second change to true " + METHOD
+                    + " must be still force inlineable");
+        }
+        if (WHITE_BOX.testSetForceInlineMethod(METHOD, false)) {
+            throw new RuntimeException("after first change to false" + METHOD
+                    + " must be not force inlineable");
+        }
+        if (WHITE_BOX.testSetForceInlineMethod(METHOD, false)) {
+            throw new RuntimeException("after second change to false " + METHOD
+                    + " must be not force inlineable");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/6941923/Test6941923.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test Test6941923.java
+ * @bug 6941923
+ * @summary test flags for gc log rotation
+ * @library /testlibrary
+ * @run main/othervm/timeout=600 Test6941923
+ *
+ */
+import com.oracle.java.testlibrary.*;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+class GCLoggingGenerator {
+
+    public static void main(String[] args) throws Exception {
+
+        long sizeOfLog = Long.parseLong(args[0]);
+        long lines = sizeOfLog / 80;
+        // full.GC generates ad least 1-line which is not shorter then 80 chars
+        // for some GC 2 shorter lines are generated
+        for (long i = 0; i < lines; i++) {
+            System.gc();
+        }
+    }
+}
+
+public class Test6941923 {
+
+    static final File currentDirectory = new File(".");
+    static final String logFileName = "test.log";
+    static final int logFileSizeK = 16;
+    static FilenameFilter logFilter = new FilenameFilter() {
+        @Override
+        public boolean accept(File dir, String name) {
+            return name.startsWith(logFileName);
+        }
+    };
+
+    public static void cleanLogs() {
+        for (File log : currentDirectory.listFiles(logFilter)) {
+            if (!log.delete()) {
+                throw new Error("Unable to delete " + log.getAbsolutePath());
+            }
+        }
+    }
+
+    public static void runTest(int numberOfFiles) throws Exception {
+
+        ArrayList<String> args = new ArrayList();
+        String[] logOpts = new String[]{
+            "-cp", System.getProperty("java.class.path"),
+            "-Xloggc:" + logFileName,
+            "-XX:-DisableExplicitGC", // to sure that System.gc() works
+            "-XX:+PrintGC", "-XX:+PrintGCDetails", "-XX:+UseGCLogFileRotation",
+            "-XX:NumberOfGCLogFiles=" + numberOfFiles,
+            "-XX:GCLogFileSize=" + logFileSizeK + "K", "-Xmx128M"};
+        // System.getProperty("test.java.opts") is '' if no options is set
+        // need to skip such empty
+        String[] externalVMopts = System.getProperty("test.java.opts").length() == 0
+                ? new String[0]
+                : System.getProperty("test.java.opts").split(" ");
+        args.addAll(Arrays.asList(externalVMopts));
+        args.addAll(Arrays.asList(logOpts));
+        args.add(GCLoggingGenerator.class.getName());
+        args.add(String.valueOf(numberOfFiles * logFileSizeK * 1024));
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args.toArray(new String[0]));
+        pb.redirectErrorStream(true);
+        pb.redirectOutput(new File(GCLoggingGenerator.class.getName() + ".log"));
+        Process process = pb.start();
+        int result = process.waitFor();
+        if (result != 0) {
+            throw new Error("Unexpected exit code = " + result);
+        }
+        File[] logs = currentDirectory.listFiles(logFilter);
+        int smallFilesNumber = 0;
+        for (File log : logs) {
+            if (log.length() < logFileSizeK * 1024) {
+                smallFilesNumber++;
+            }
+        }
+        if (logs.length != numberOfFiles) {
+            throw new Error("There are only " + logs.length + " logs instead " + numberOfFiles);
+        }
+        if (smallFilesNumber > 1) {
+            throw new Error("There should maximum one log with size < " + logFileSizeK + "K");
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        cleanLogs();
+        runTest(1);
+        cleanLogs();
+        runTest(3);
+        cleanLogs();
+    }
+}
--- a/test/gc/6941923/test6941923.sh	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,166 +0,0 @@
-##
-## @test @(#)test6941923.sh
-## @bug 6941923 
-## @summary test new added flags for gc log rotation 
-## @author yqi 
-## @run shell test6941923.sh
-##
-## some tests require path to find test source dir
-if [ "${TESTSRC}" = "" ]
-then
-  TESTSRC=${PWD}
-  echo "TESTSRC not set.  Using "${TESTSRC}" as default"
-fi
-echo "TESTSRC=${TESTSRC}"
-## Adding common setup Variables for running shell tests.
-. ${TESTSRC}/../../test_env.sh
-
-## skip on windows
-OS=`uname -s`
-case "$OS" in
-  Windows_* | CYGWIN_* )
-    echo "Test skipped for Windows"
-    exit 0 
-    ;;
-esac
-
-# create a small test case
-testname="Test"
-if [ -e ${testname}.java ]; then
-  rm -rf ${testname}.*
-fi
-
-cat >> ${testname}.java << __EOF__
-import java.util.Vector;
-
-public class Test implements Runnable
-{
-  private boolean _should_stop = false;
-
-  public static void main(String[] args) throws Exception {
-
-    long limit = Long.parseLong(args[0]) * 60L * 1000L;   // minutes
-    Test t = new Test();
-    t.set_stop(false);
-    Thread thr = new Thread(t);
-    thr.start();
-
-    long time1 = System.currentTimeMillis();
-    long time2 = System.currentTimeMillis();
-    while (time2 - time1 < limit) {
-      try {
-        Thread.sleep(2000); // 2 seconds
-      }
-      catch(Exception e) {}
-      time2 = System.currentTimeMillis();
-      System.out.print("\r... " + (time2 - time1)/1000 + " seconds");
-    }
-    System.out.println();
-    t.set_stop(true);
-  }
-  public void set_stop(boolean value) { _should_stop = value; }
-  public void run() {
-    int cap = 20000;
-    int fix_size = 2048;
-    int loop = 0;
-    Vector< byte[] > v = new Vector< byte[] >(cap);
-    while(!_should_stop) {
-      byte[] g = new byte[fix_size];
-      v.add(g);
-      loop++;
-      if (loop > cap) {
-         v = null;
-         cap *= 2;
-         if (cap > 80000) cap = 80000;
-         v = new Vector< byte[] >(cap);
-      }
-    }
-  }
-}
-__EOF__
-
-msgsuccess="succeeded"
-msgfail="failed"
-gclogsize="16K"
-filesize=$((16*1024))
-${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} ${testname}.java > $NULL 2>&1
-
-if [ $? != 0 ]; then
-  echo "${COMPILEJAVA}/bin/javac ${testname}.java $fail"
-  exit -1
-fi
-
-# test for 2 minutes, it will complete circulation of gc log rotation
-tts=2
-logfile="test.log"
-hotspotlog="hotspot.log"
-
-if [ -e $logfile  ]; then
-  rm -rf $logfile
-fi
-
-#also delete $hotspotlog if it exists
-if [ -f $hotspotlog ]; then 
-  rm -rf $hotspotlog
-fi
-
-options="-Xloggc:$logfile -XX:+UseConcMarkSweepGC -XX:+PrintGC -XX:+PrintGCDetails -XX:+UseGCLogFileRotation  -XX:NumberOfGCLogFiles=1 -XX:GCLogFileSize=$gclogsize"
-echo "Test gc log rotation in same file, wait for $tts minutes ...."
-${TESTJAVA}/bin/java $options $testname $tts
-if [ $? != 0 ]; then
-  echo "$msgfail"
-  exit -1
-fi
-
-# rotation file will be $logfile.0 
-if [ -f $logfile.0 ]; then
-  outfilesize=`ls -l $logfile.0 | awk '{print $5 }'`
-  if [ $((outfilesize)) -ge $((filesize)) ]; then
-    echo $msgsuccess
-  else
-    echo $msgfail
-  fi
-else 
-  echo $msgfail
-  exit -1
-fi
-
-# delete log file 
-rm -rf $logfile.0
-if [ -f $hotspotlog ]; then
-  rm -rf $hotspotlog
-fi
-
-#multiple log files
-numoffiles=3
-options="-Xloggc:$logfile -XX:+UseConcMarkSweepGC -XX:+PrintGC -XX:+PrintGCDetails -XX:+UseGCLogFileRotation  -XX:NumberOfGCLogFiles=$numoffiles -XX:GCLogFileSize=$gclogsize"
-echo "Test gc log rotation in $numoffiles files, wait for $tts minutes ...."
-${TESTJAVA}/bin/java $options $testname $tts
-if [ $? != 0 ]; then
-  echo "$msgfail"
-  exit -1
-fi
-
-atleast=0    # at least size of numoffile-1 files >= $gclogsize
-tk=0
-while [ $(($tk)) -lt $(($numoffiles)) ]
-do
-  if [ -f $logfile.$tk ]; then
-    outfilesize=`ls -l $logfile.$tk | awk '{ print $5 }'`
-    if [ $(($outfilesize)) -ge $(($filesize)) ]; then
-      atleast=$((atleast+1))
-    fi
-  fi
-  tk=$((tk+1))
-done
-
-rm -rf $logfile.*
-rm -rf $testname.*
-rm -rf $hotspotlog
-
-if [ $(($atleast)) -ge $(($numoffiles-1)) ]; then
-  echo $msgsuccess
-else
-  echo $msgfail
-  exit -1
-fi
--- a/test/gc/TestVerifyBeforeGCDuringStartup.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +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.
- */
-
-/* @test TestVerifyBeforeGCDuringStartup.java
- * @key gc
- * @bug 8010463
- * @summary Simple test run with -XX:+VerifyBeforeGC -XX:-UseTLAB to verify 8010463
- * @library /testlibrary
- */
-
-import com.oracle.java.testlibrary.OutputAnalyzer;
-import com.oracle.java.testlibrary.ProcessTools;
-
-public class TestVerifyBeforeGCDuringStartup {
-  public static void main(String args[]) throws Exception {
-    ProcessBuilder pb =
-      ProcessTools.createJavaProcessBuilder(System.getProperty("test.vm.opts"),
-                                            "-XX:-UseTLAB",
-                                            "-XX:+UnlockDiagnosticVMOptions",
-                                            "-XX:+VerifyBeforeGC", "-version");
-    OutputAnalyzer output = new OutputAnalyzer(pb.start());
-    output.shouldContain("[Verifying");
-    output.shouldHaveExitValue(0);
-  }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/TestVerifyDuringStartup.java	Mon Apr 15 08:49:14 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.
+ */
+
+/* @test TestVerifyDuringStartup.java
+ * @key gc
+ * @bug 8010463
+ * @summary Simple test run with -XX:+VerifyDuringStartup -XX:-UseTLAB to verify 8010463
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+public class TestVerifyDuringStartup {
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb =
+      ProcessTools.createJavaProcessBuilder(System.getProperty("test.vm.opts"),
+                                            "-XX:-UseTLAB",
+                                            "-XX:+UnlockDiagnosticVMOptions",
+                                            "-XX:+VerifyDuringStartup", "-version");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldContain("[Verifying");
+    output.shouldHaveExitValue(0);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/metaspace/G1AddMetaspaceDependency.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test G1AddMetaspaceDependency
+ * @bug 8010196
+ * @summary Checks that we don't get locking problems when adding metaspace dependencies with the G1 update buffer monitor
+ * @run main/othervm -XX:+UseG1GC -XX:G1UpdateBufferSize=1 G1AddMetaspaceDependency
+ */
+
+import java.io.InputStream;
+
+public class G1AddMetaspaceDependency {
+
+  static byte[] getClassBytes(String name) {
+    byte[] b = null;
+    try (InputStream is = ClassLoader.getSystemResourceAsStream(name)) {
+      byte[] tmp = new byte[is.available()];
+      is.read(tmp);
+      b = tmp;
+    } finally {
+      if (b == null) {
+        throw new RuntimeException("Unable to load class file");
+      }
+      return b;
+    }
+  }
+
+  static final String a_name = G1AddMetaspaceDependency.class.getName() + "$A";
+  static final String b_name = G1AddMetaspaceDependency.class.getName() + "$B";
+
+  public static void main(String... args) throws Exception {
+    final byte[] a_bytes = getClassBytes(a_name + ".class");
+    final byte[] b_bytes = getClassBytes(b_name + ".class");
+
+    for (int i = 0; i < 1000; i += 1) {
+      runTest(a_bytes, b_bytes);
+    }
+  }
+
+  static class Loader extends ClassLoader {
+    private final String myClass;
+    private final byte[] myBytes;
+    private final String friendClass;
+    private final ClassLoader friendLoader;
+
+    Loader(String myClass, byte[] myBytes,
+           String friendClass, ClassLoader friendLoader) {
+      this.myClass = myClass;
+      this.myBytes = myBytes;
+      this.friendClass = friendClass;
+      this.friendLoader = friendLoader;
+    }
+
+    Loader(String myClass, byte[] myBytes) {
+      this(myClass, myBytes, null, null);
+    }
+
+    @Override
+    public Class<?> loadClass(String name) throws ClassNotFoundException {
+      Class<?> c = findLoadedClass(name);
+      if (c != null) {
+        return c;
+      }
+
+      if (name.equals(friendClass)) {
+        return friendLoader.loadClass(name);
+      }
+
+      if (name.equals(myClass)) {
+        c = defineClass(name, myBytes, 0, myBytes.length);
+        resolveClass(c);
+        return c;
+      }
+
+      return findSystemClass(name);
+    }
+
+  }
+
+  private static void runTest(final byte[] a_bytes, final byte[] b_bytes) throws Exception {
+    Loader a_loader = new Loader(a_name, a_bytes);
+    Loader b_loader = new Loader(b_name, b_bytes, a_name, a_loader);
+    Loader c_loader = new Loader(b_name, b_bytes, a_name, a_loader);
+    Loader d_loader = new Loader(b_name, b_bytes, a_name, a_loader);
+    Loader e_loader = new Loader(b_name, b_bytes, a_name, a_loader);
+    Loader f_loader = new Loader(b_name, b_bytes, a_name, a_loader);
+    Loader g_loader = new Loader(b_name, b_bytes, a_name, a_loader);
+
+    byte[] b = new byte[20 * 2 << 20];
+    Class<?> c;
+    c = b_loader.loadClass(b_name);
+    c = c_loader.loadClass(b_name);
+    c = d_loader.loadClass(b_name);
+    c = e_loader.loadClass(b_name);
+    c = f_loader.loadClass(b_name);
+    c = g_loader.loadClass(b_name);
+  }
+  public class A {
+  }
+  class B extends A {
+  }
+}
--- a/test/runtime/NMT/AllocTestType.java	Mon Apr 08 17:48:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +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.
- */
-
-/*
- * @test
- * @summary Test consistency of NMT by leaking a few select allocations of the Test type and then verify visibility with jcmd
- * @key nmt jcmd
- * @library /testlibrary /testlibrary/whitebox
- * @build AllocTestType
- * @run main ClassFileInstaller sun.hotspot.WhiteBox
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail AllocTestType
- */
-
-import com.oracle.java.testlibrary.*;
-import sun.hotspot.WhiteBox;
-
-public class AllocTestType {
-
-  public static void main(String args[]) throws Exception {
-    OutputAnalyzer output;
-
-    // Grab my own PID
-    String pid = Integer.toString(ProcessTools.getProcessId());
-    ProcessBuilder pb = new ProcessBuilder();
-
-    // Use WB API to alloc with the mtTest type
-    if (!WhiteBox.getWhiteBox().NMTAllocTest()) {
-      throw new Exception("Call to WB API NMTAllocTest() failed");
-    }
-
-    // Use WB API to ensure that all data has been merged before we continue
-    if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) {
-      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
-    }
-
-    // Run 'jcmd <pid> VM.native_memory summary'
-    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"});
-    output = new OutputAnalyzer(pb.start());
-    output.shouldContain("Test (reserved=512KB, committed=512KB)");
-
-    // Free the memory allocated by NMTAllocTest
-    if (!WhiteBox.getWhiteBox().NMTFreeTestMemory()) {
-      throw new Exception("Call to WB API NMTFreeTestMemory() failed");
-    }
-
-    // Use WB API to ensure that all data has been merged before we continue
-    if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) {
-      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
-    }
-    output = new OutputAnalyzer(pb.start());
-    output.shouldNotContain("Test (reserved=");
-  }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/MallocTestType.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @summary Test consistency of NMT by leaking a few select allocations of the Test type and then verify visibility with jcmd
+ * @key nmt jcmd
+ * @library /testlibrary /testlibrary/whitebox
+ * @build MallocTestType
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocTestType
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.hotspot.WhiteBox;
+
+public class MallocTestType {
+
+  public static void main(String args[]) throws Exception {
+    OutputAnalyzer output;
+    WhiteBox wb = WhiteBox.getWhiteBox();
+
+    // Grab my own PID
+    String pid = Integer.toString(ProcessTools.getProcessId());
+    ProcessBuilder pb = new ProcessBuilder();
+
+    // Use WB API to alloc and free with the mtTest type
+    long memAlloc3 = wb.NMTMalloc(128 * 1024);
+    long memAlloc2 = wb.NMTMalloc(256 * 1024);
+    wb.NMTFree(memAlloc3);
+    long memAlloc1 = wb.NMTMalloc(512 * 1024);
+    wb.NMTFree(memAlloc2);
+
+    // Use WB API to ensure that all data has been merged before we continue
+    if (!wb.NMTWaitForDataMerge()) {
+      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
+    }
+
+    // Run 'jcmd <pid> VM.native_memory summary'
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Test (reserved=512KB, committed=512KB)");
+
+    // Free the memory allocated by NMTAllocTest
+    wb.NMTFree(memAlloc1);
+
+    // Use WB API to ensure that all data has been merged before we continue
+    if (!wb.NMTWaitForDataMerge()) {
+      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
+    }
+    output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("Test (reserved=");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/ThreadedMallocTestType.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @key nmt jcmd
+ * @library /testlibrary /testlibrary/whitebox
+ * @build ThreadedMallocTestType
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail ThreadedMallocTestType
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.hotspot.WhiteBox;
+
+public class ThreadedMallocTestType {
+  public static long memAlloc1;
+  public static long memAlloc2;
+  public static long memAlloc3;
+
+  public static void main(String args[]) throws Exception {
+    OutputAnalyzer output;
+    final WhiteBox wb = WhiteBox.getWhiteBox();
+
+    // Grab my own PID
+    String pid = Integer.toString(ProcessTools.getProcessId());
+    ProcessBuilder pb = new ProcessBuilder();
+
+    Thread allocThread = new Thread() {
+      public void run() {
+        // Alloc memory using the WB api
+        memAlloc1 = wb.NMTMalloc(128 * 1024);
+        memAlloc2 = wb.NMTMalloc(256 * 1024);
+        memAlloc3 = wb.NMTMalloc(512 * 1024);
+      }
+    };
+
+    allocThread.start();
+    allocThread.join();
+
+    // Use WB API to ensure that all data has been merged before we continue
+    if (!wb.NMTWaitForDataMerge()) {
+      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
+    }
+
+    // Run 'jcmd <pid> VM.native_memory summary'
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Test (reserved=896KB, committed=896KB)");
+
+    Thread freeThread = new Thread() {
+      public void run() {
+        // Free the memory allocated by NMTMalloc
+        wb.NMTFree(memAlloc1);
+        wb.NMTFree(memAlloc2);
+        wb.NMTFree(memAlloc3);
+      }
+    };
+
+    freeThread.start();
+    freeThread.join();
+
+    // Use WB API to ensure that all data has been merged before we continue
+    if (!wb.NMTWaitForDataMerge()) {
+      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
+    }
+
+    output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("Test (reserved=");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/ThreadedVirtualAllocTestType.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @key nmt jcmd
+ * @library /testlibrary /testlibrary/whitebox
+ * @build ThreadedVirtualAllocTestType
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail ThreadedVirtualAllocTestType
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.hotspot.WhiteBox;
+
+public class ThreadedVirtualAllocTestType {
+  public static long addr;
+  public static final WhiteBox wb = WhiteBox.getWhiteBox();
+  public static final long commitSize = 128 * 1024;
+  public static final long reserveSize = 512 * 1024;
+
+  public static void main(String args[]) throws Exception {
+    OutputAnalyzer output;
+
+    String pid = Integer.toString(ProcessTools.getProcessId());
+    ProcessBuilder pb = new ProcessBuilder();
+
+    Thread reserveThread = new Thread() {
+      public void run() {
+        addr = wb.NMTReserveMemory(reserveSize);
+      }
+    };
+    reserveThread.start();
+    reserveThread.join();
+
+    mergeData();
+
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Test (reserved=512KB, committed=0KB)");
+    output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved 512KB for Test");
+
+    Thread commitThread = new Thread() {
+      public void run() {
+        wb.NMTCommitMemory(addr, commitSize);
+      }
+    };
+    commitThread.start();
+    commitThread.join();
+
+    mergeData();
+
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Test (reserved=512KB, committed=128KB)");
+    output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed 128KB");
+
+    Thread uncommitThread = new Thread() {
+      public void run() {
+        wb.NMTUncommitMemory(addr, commitSize);
+      }
+    };
+    uncommitThread.start();
+    uncommitThread.join();
+
+    mergeData();
+
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Test (reserved=512KB, committed=0KB)");
+    output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed");
+
+    Thread releaseThread = new Thread() {
+      public void run() {
+        wb.NMTReleaseMemory(addr, reserveSize);
+      }
+    };
+    releaseThread.start();
+    releaseThread.join();
+
+    mergeData();
+
+    output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("Test (reserved=");
+    output.shouldNotContain("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved");
+  }
+
+  public static void mergeData() throws Exception {
+    // Use WB API to ensure that all data has been merged before we continue
+    if (!wb.NMTWaitForDataMerge()) {
+      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/VirtualAllocTestType.java	Mon Apr 15 08:49:14 2013 +0200
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @summary Test Reserve/Commit/Uncommit/Release of virtual memory and that we track it correctly
+ * @key nmt jcmd
+ * @library /testlibrary /testlibrary/whitebox
+ * @build VirtualAllocTestType
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail VirtualAllocTestType
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.hotspot.WhiteBox;
+
+public class VirtualAllocTestType {
+
+  public static WhiteBox wb = WhiteBox.getWhiteBox();
+  public static void main(String args[]) throws Exception {
+    OutputAnalyzer output;
+    long commitSize = 128 * 1024;
+    long reserveSize = 256 * 1024;
+    long addr;
+
+    String pid = Integer.toString(ProcessTools.getProcessId());
+    ProcessBuilder pb = new ProcessBuilder();
+
+    addr = wb.NMTReserveMemory(reserveSize);
+    mergeData();
+
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Test (reserved=256KB, committed=0KB)");
+    output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved 256KB for Test");
+
+    wb.NMTCommitMemory(addr, commitSize);
+
+    mergeData();
+
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Test (reserved=256KB, committed=128KB)");
+    output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed 128KB");
+
+    wb.NMTUncommitMemory(addr, commitSize);
+
+    mergeData();
+
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Test (reserved=256KB, committed=0KB)");
+    output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed");
+
+    wb.NMTReleaseMemory(addr, reserveSize);
+
+    mergeData();
+
+    output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("Test (reserved=");
+    output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved");
+  }
+
+  public static void mergeData() throws Exception {
+    // Use WB API to ensure that all data has been merged before we continue
+    if (!wb.NMTWaitForDataMerge()) {
+      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
+    }
+  }
+}
--- a/test/testlibrary/OutputAnalyzerTest.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/test/testlibrary/OutputAnalyzerTest.java	Mon Apr 15 08:49:14 2013 +0200
@@ -36,6 +36,11 @@
     String stdout = "aaaaaa";
     String stderr = "bbbbbb";
 
+    // Regexps used for testing pattern matching of the test input
+    String stdoutPattern = "[a]";
+    String stderrPattern = "[b]";
+    String nonExistingPattern = "[c]";
+
     OutputAnalyzer output = new OutputAnalyzer(stdout, stderr);
 
     if (!stdout.equals(output.getStdout())) {
@@ -99,10 +104,73 @@
     }
 
     try {
-      output.stderrShouldNotContain(stderr);
-      throw new Exception("shouldContain() failed to throw exception");
+        output.stderrShouldNotContain(stderr);
+        throw new Exception("shouldContain() failed to throw exception");
+    } catch (RuntimeException e) {
+        // expected
+    }
+
+    // Should match
+    try {
+        output.shouldMatch(stdoutPattern);
+        output.stdoutShouldMatch(stdoutPattern);
+        output.shouldMatch(stderrPattern);
+        output.stderrShouldMatch(stderrPattern);
+    } catch (RuntimeException e) {
+        throw new Exception("shouldMatch() failed", e);
+    }
+
+    try {
+        output.shouldMatch(nonExistingPattern);
+        throw new Exception("shouldMatch() failed to throw exception");
+    } catch (RuntimeException e) {
+        // expected
+    }
+
+    try {
+        output.stdoutShouldMatch(stderrPattern);
+        throw new Exception(
+                "stdoutShouldMatch() failed to throw exception");
     } catch (RuntimeException e) {
-      // expected
+        // expected
+    }
+
+    try {
+        output.stderrShouldMatch(stdoutPattern);
+        throw new Exception(
+                "stderrShouldMatch() failed to throw exception");
+    } catch (RuntimeException e) {
+        // expected
+    }
+
+    // Should not match
+    try {
+        output.shouldNotMatch(nonExistingPattern);
+        output.stdoutShouldNotMatch(nonExistingPattern);
+        output.stderrShouldNotMatch(nonExistingPattern);
+    } catch (RuntimeException e) {
+        throw new Exception("shouldNotMatch() failed", e);
+    }
+
+    try {
+        output.shouldNotMatch(stdoutPattern);
+        throw new Exception("shouldNotMatch() failed to throw exception");
+    } catch (RuntimeException e) {
+        // expected
+    }
+
+    try {
+        output.stdoutShouldNotMatch(stdoutPattern);
+        throw new Exception("shouldNotMatch() failed to throw exception");
+    } catch (RuntimeException e) {
+        // expected
+    }
+
+    try {
+        output.stderrShouldNotMatch(stderrPattern);
+        throw new Exception("shouldNotMatch() failed to throw exception");
+    } catch (RuntimeException e) {
+        // expected
     }
   }
 }
--- a/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java	Mon Apr 15 08:49:14 2013 +0200
@@ -24,6 +24,8 @@
 package com.oracle.java.testlibrary;
 
 import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 public final class OutputAnalyzer {
 
@@ -142,15 +144,112 @@
   }
 
   /**
+   * Verify that the stdout and stderr contents of output buffer matches
+   * the pattern
+   *
+   * @param pattern
+   * @throws RuntimeException If the pattern was not found
+   */
+  public void shouldMatch(String pattern) {
+      Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+      Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+      if (!stdoutMatcher.find() && !stderrMatcher.find()) {
+          throw new RuntimeException("'" + pattern
+                  + "' missing from stdout/stderr: [" + stdout + stderr
+                  + "]\n");
+      }
+  }
+
+  /**
+   * Verify that the stdout contents of output buffer matches the
+   * pattern
+   *
+   * @param pattern
+   * @throws RuntimeException If the pattern was not found
+   */
+  public void stdoutShouldMatch(String pattern) {
+      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+      if (!matcher.find()) {
+          throw new RuntimeException("'" + pattern
+                  + "' missing from stdout: [" + stdout + "]\n");
+      }
+  }
+
+  /**
+   * Verify that the stderr contents of output buffer matches the
+   * pattern
+   *
+   * @param pattern
+   * @throws RuntimeException If the pattern was not found
+   */
+  public void stderrShouldMatch(String pattern) {
+      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+      if (!matcher.find()) {
+          throw new RuntimeException("'" + pattern
+                  + "' missing from stderr: [" + stderr + "]\n");
+      }
+  }
+
+  /**
+   * Verify that the stdout and stderr contents of output buffer does not
+   * match the pattern
+   *
+   * @param pattern
+   * @throws RuntimeException If the pattern was found
+   */
+  public void shouldNotMatch(String pattern) {
+      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+      if (matcher.find()) {
+          throw new RuntimeException("'" + pattern
+                  + "' found in stdout: [" + stdout + "]\n");
+      }
+      matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+      if (matcher.find()) {
+          throw new RuntimeException("'" + pattern
+                  + "' found in stderr: [" + stderr + "]\n");
+      }
+  }
+
+  /**
+   * Verify that the stdout contents of output buffer does not match the
+   * pattern
+   *
+   * @param pattern
+   * @throws RuntimeException If the pattern was found
+   */
+  public void stdoutShouldNotMatch(String pattern) {
+      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+      if (matcher.find()) {
+          throw new RuntimeException("'" + pattern
+                  + "' found in stdout: [" + stdout + "]\n");
+      }
+  }
+
+  /**
+   * Verify that the stderr contents of output buffer does not match the
+   * pattern
+   *
+   * @param pattern
+   * @throws RuntimeException If the pattern was found
+   */
+  public void stderrShouldNotMatch(String pattern) {
+      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+      if (matcher.find()) {
+          throw new RuntimeException("'" + pattern
+                  + "' found in stderr: [" + stderr + "]\n");
+      }
+  }
+
+  /**
    * Verifiy the exit value of the process
    *
    * @param expectedExitValue Expected exit value from process
    * @throws RuntimeException If the exit value from the process did not match the expected value
    */
   public void shouldHaveExitValue(int expectedExitValue) {
-    if (getExitValue() != expectedExitValue) {
-      throw new RuntimeException("Exit value " + getExitValue() + " , expected to get " + expectedExitValue);
-    }
+      if (getExitValue() != expectedExitValue) {
+          throw new RuntimeException("Exit value " + getExitValue() + " , expected to get " + expectedExitValue);
+      }
   }
 
   /**
--- a/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java	Mon Apr 08 17:48:46 2013 +0200
+++ b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java	Mon Apr 15 08:49:14 2013 +0200
@@ -80,20 +80,30 @@
   public native Object[]    parseCommandLine(String commandline, DiagnosticCommand[] args);
 
   // NMT
-  public native boolean NMTAllocTest();
-  public native boolean NMTFreeTestMemory();
+  public native long NMTMalloc(long size);
+  public native void NMTFree(long mem);
+  public native long NMTReserveMemory(long size);
+  public native void NMTCommitMemory(long addr, long size);
+  public native void NMTUncommitMemory(long addr, long size);
+  public native void NMTReleaseMemory(long addr, long size);
   public native boolean NMTWaitForDataMerge();
 
   // Compiler
   public native void    deoptimizeAll();
   public native boolean isMethodCompiled(Method method);
-  public native boolean isMethodCompilable(Method method);
+  public boolean isMethodCompilable(Method method) {
+      return isMethodCompilable(method, -1 /*any*/);
+  }
+  public native boolean isMethodCompilable(Method method, int compLevel);
   public native boolean isMethodQueuedForCompilation(Method method);
   public native int     deoptimizeMethod(Method method);
   public native void    makeMethodNotCompilable(Method method);
   public native int     getMethodCompilationLevel(Method method);
-  public native boolean setDontInlineMethod(Method method, boolean value);
+  public native boolean testSetDontInlineMethod(Method method, boolean value);
   public native int     getCompileQueuesSize();
+  public native boolean testSetForceInlineMethod(Method method, boolean value);
+  public native boolean enqueueMethodForCompilation(Method method, int compLevel);
+  public native void    clearMethodState(Method method);
 
   //Intered strings
   public native boolean isInStringTable(String str);