changeset 10445:f158703c308c

Merge.
author Christian Humer <christian.humer@gmail.com>
date Tue, 18 Jun 2013 10:12:27 +0200
parents ad48251630cd (current diff) 25de9c96a032 (diff)
children 746fa60be266
files graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64TailcallOp.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPost.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPostStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPre.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPreStubCall.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InlineableElement.java graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProvider.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CullFrameStatesPhase.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java
diffstat 319 files changed, 7123 insertions(+), 3544 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Tue Jun 18 10:11:28 2013 +0200
+++ b/.hgignore	Tue Jun 18 10:12:27 2013 +0200
@@ -72,3 +72,6 @@
 *.jar.*
 eclipse-build.xml
 rebuild-launch.out
+coverage
+jacoco.exec
+workingsets.xml
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java	Tue Jun 18 10:12:27 2013 +0200
@@ -82,6 +82,13 @@
      */
     public final int numLocks;
 
+    /**
+     * True if this is a position inside an exception handler before the exception object has been
+     * consumed. In this case, {@link #numStack == 1} and {@link #getStackValue(int)
+     * getStackValue(0)} is the location of the exception object. If deoptimization happens at this
+     * position, the interpreter will rethrow the exception instead of executing the bytecode
+     * instruction at this position.
+     */
     public final boolean rethrowException;
 
     public final boolean duringCall;
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java	Tue Jun 18 10:12:27 2013 +0200
@@ -53,7 +53,7 @@
      * @return {@code true} if the value is a power of two; {@code false} otherwise
      */
     public static boolean isPowerOf2(int val) {
-        return val != 0 && (val & val - 1) == 0;
+        return val > 0 && (val & val - 1) == 0;
     }
 
     /**
@@ -63,7 +63,7 @@
      * @return {@code true} if the value is a power of two; {@code false} otherwise
      */
     public static boolean isPowerOf2(long val) {
-        return val != 0 && (val & val - 1) == 0;
+        return val > 0 && (val & val - 1) == 0;
     }
 
     /**
@@ -74,7 +74,7 @@
      * @return the log base 2 of the value
      */
     public static int log2(int val) {
-        assert val > 0 && isPowerOf2(val);
+        assert val > 0;
         return 31 - Integer.numberOfLeadingZeros(val);
     }
 
@@ -86,7 +86,7 @@
      * @return the log base 2 of the value
      */
     public static int log2(long val) {
-        assert val > 0 && isPowerOf2(val);
+        assert val > 0;
         return 63 - Long.numberOfLeadingZeros(val);
     }
 
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DeoptimizationAction.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DeoptimizationAction.java	Tue Jun 18 10:12:27 2013 +0200
@@ -32,28 +32,39 @@
      * it's highly likely nothing will change the likelihood of the deoptimization happening again.
      * For example, a compiled array allocation where the size is negative.
      */
-    None,
+    None(false),
 
     /**
      * Do not invalidate the machine code, but schedule a recompilation if this deoptimization is
      * triggered too often.
      */
-    RecompileIfTooManyDeopts,
+    RecompileIfTooManyDeopts(true),
 
     /**
      * Invalidate the machine code and reset the profiling information.
      */
-    InvalidateReprofile,
+    InvalidateReprofile(true),
 
     /**
      * Invalidate the machine code and immediately schedule a recompilation. This is typically used
      * when deoptimizing to resolve an unresolved symbol in which case extra profiling is not
      * required to determine that the deoptimization will not re-occur.
      */
-    InvalidateRecompile,
+    InvalidateRecompile(true),
 
     /**
      * Invalidate the machine code and stop compiling the outermost method of this compilation.
      */
-    InvalidateStopCompiling;
+    InvalidateStopCompiling(true);
+
+    private final boolean invalidatesCompilation;
+
+    private DeoptimizationAction(boolean invalidatesCompilation) {
+        this.invalidatesCompilation = invalidatesCompilation;
+    }
+
+    public boolean doesInvalidateCompilation() {
+        return invalidatesCompilation;
+    }
+
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ForeignCallLinkage.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ForeignCallLinkage.java	Tue Jun 18 10:12:27 2013 +0200
@@ -55,4 +55,11 @@
      *         this target
      */
     boolean destroysRegisters();
+
+    /**
+     * Determines if this is call to a function that does not deoptimize, and therefore also does
+     * not lock, GC or throw exceptions. That is, the thread's execution state during the call is
+     * never inspected by another thread.
+     */
+    boolean canDeoptimize();
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java	Tue Jun 18 10:12:27 2013 +0200
@@ -47,7 +47,7 @@
         public final ResolvedJavaType type;
 
         /**
-         * Specifies if {@link #type} was a sub-type of the checked type.
+         * Specifies if {@link #type} is a sub-type of the checked type.
          */
         public final boolean positive;
 
@@ -60,11 +60,11 @@
     private static final Hint[] NO_HINTS = {};
 
     /**
-     * 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.
+     * If non-null, then this is the only 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 and this value is
+     * the only concrete subclass of the target type.
      */
-    public final boolean exact;
+    public final ResolvedJavaType exact;
 
     /**
      * The most likely types that the type check instruction will see.
@@ -72,6 +72,16 @@
     public final Hint[] hints;
 
     /**
+     * The profile from which this information was derived.
+     */
+    public final JavaTypeProfile profile;
+
+    /**
+     * The total probability that the type check will hit one of the types in {@link #hints}.
+     */
+    public final double hintHitProbability;
+
+    /**
      * Derives hint information for use when generating the code for a type check instruction.
      * 
      * @param targetType the target type of the type check
@@ -84,50 +94,58 @@
      * @param maxHints the maximum length of {@link #hints}
      */
     public TypeCheckHints(ResolvedJavaType targetType, JavaTypeProfile profile, Assumptions assumptions, double minHintHitProbability, int maxHints) {
+        this.profile = profile;
         if (targetType != null && !canHaveSubtype(targetType)) {
-            hints = new Hint[]{new Hint(targetType, true)};
-            exact = true;
+            exact = targetType;
         } else {
             ResolvedJavaType uniqueSubtype = targetType == null ? null : targetType.findUniqueConcreteSubtype();
             if (uniqueSubtype != null) {
-                hints = new Hint[]{new Hint(uniqueSubtype, true)};
                 if (assumptions.useOptimisticAssumptions()) {
                     assumptions.recordConcreteSubtype(targetType, uniqueSubtype);
-                    exact = true;
+                    exact = uniqueSubtype;
                 } else {
-                    exact = false;
+                    exact = null;
                 }
             } else {
-                exact = false;
-                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) {
-                        hintsBuf = new Hint[ptypes.length];
-                        int hintCount = 0;
-                        double totalHintProbability = 0.0d;
-                        for (ProfiledType ptype : ptypes) {
-                            if (targetType != null) {
-                                ResolvedJavaType hintType = ptype.getType();
-                                hintsBuf[hintCount++] = new Hint(hintType, targetType.isAssignableFrom(hintType));
-                                totalHintProbability += ptype.getProbability();
-                            }
-                        }
-                        if (totalHintProbability >= minHintHitProbability) {
-                            if (hintsBuf.length != hintCount || hintCount > maxHints) {
-                                hintsBuf = Arrays.copyOf(hintsBuf, Math.min(maxHints, hintCount));
-                            }
-                        } else {
-                            hintsBuf = NO_HINTS;
-                        }
+                exact = null;
+            }
+        }
+        Double[] hitProbability = {null};
+        this.hints = makeHints(targetType, profile, minHintHitProbability, maxHints, hitProbability);
+        this.hintHitProbability = hitProbability[0];
+    }
 
+    private static Hint[] makeHints(ResolvedJavaType targetType, JavaTypeProfile profile, double minHintHitProbability, int maxHints, Double[] hitProbability) {
+        double hitProb = 0.0d;
+        Hint[] hintsBuf = NO_HINTS;
+        if (profile != null) {
+            double notRecordedTypes = profile.getNotRecordedProbability();
+            ProfiledType[] ptypes = profile.getTypes();
+            if (notRecordedTypes < (1D - minHintHitProbability) && ptypes != null && ptypes.length > 0) {
+                hintsBuf = new Hint[ptypes.length];
+                int hintCount = 0;
+                for (ProfiledType ptype : ptypes) {
+                    if (targetType != null) {
+                        ResolvedJavaType hintType = ptype.getType();
+                        hintsBuf[hintCount++] = new Hint(hintType, targetType.isAssignableFrom(hintType));
+                        hitProb += ptype.getProbability();
+                    }
+                    if (hintCount == maxHints) {
+                        break;
                     }
                 }
-                this.hints = hintsBuf;
+                if (hitProb >= minHintHitProbability) {
+                    if (hintsBuf.length != hintCount || hintCount > maxHints) {
+                        hintsBuf = Arrays.copyOf(hintsBuf, Math.min(maxHints, hintCount));
+                    }
+                } else {
+                    hintsBuf = NO_HINTS;
+                    hitProb = 0.0d;
+                }
             }
         }
+        hitProbability[0] = hitProb;
+        return hintsBuf;
     }
 
     /**
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java	Tue Jun 18 10:12:27 2013 +0200
@@ -132,6 +132,18 @@
     }
 
     @Test
+    public void isSyntheticTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertEquals(e.getKey().isSynthetic(), m.isSynthetic());
+        }
+        for (Map.Entry<Constructor, ResolvedJavaMethod> e : constructors.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertEquals(e.getKey().isSynthetic(), m.isSynthetic());
+        }
+    }
+
+    @Test
     public void canBeStaticallyBoundTest() {
         for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
             ResolvedJavaMethod m = e.getValue();
@@ -252,7 +264,8 @@
         ResolvedJavaMethod method1 = runtime.lookupJavaMethod(getClass().getDeclaredMethod("methodWithAnnotatedParameters", HashMap.class, Class.class));
         ResolvedJavaMethod method2 = runtime.lookupJavaMethod(getClass().getDeclaredMethod("nullPointerExceptionOnFirstLine", Object.class, String.class));
         assertEquals(0, method1.getMaxStackSize());
-        assertEquals(3, method2.getMaxStackSize());
+        // some versions of javac produce bytecode with a stacksize of 2 for this method
+        assertTrue(3 == method2.getMaxStackSize() || 2 == method2.getMaxStackSize());
     }
 
     private Method findTestMethod(Method apiMethod) {
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AbstractJavaProfile.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AbstractJavaProfile.java	Tue Jun 18 10:12:27 2013 +0200
@@ -25,10 +25,14 @@
 import java.io.*;
 
 /**
- * This profile object represents a certain set of profiling information at a specific BCI. The
- * precision of the supplied values may vary, but a runtime that provides this information should be
- * aware that it will be used to guide performance-critical decisions like speculative inlining,
- * etc.
+ * This object holds probability information for a set of items that were profiled at a specific
+ * BCI. The precision of the supplied values may vary, but a runtime that provides this information
+ * should be aware that it will be used to guide performance-critical decisions like speculative
+ * inlining, etc.
+ * 
+ * @param <T> a subclass of AbstractProfiledItem
+ * @param <U> the class of the items that are profiled at the specific BCI and for which
+ *            probabilities are stored. E.g., a ResolvedJavaType or a ResolvedJavaMethod.
  */
 public abstract class AbstractJavaProfile<T extends AbstractProfiledItem<U>, U> implements Serializable {
 
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DefaultProfilingInfo.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DefaultProfilingInfo.java	Tue Jun 18 10:12:27 2013 +0200
@@ -87,6 +87,11 @@
     }
 
     @Override
+    public boolean isMature() {
+        return false;
+    }
+
+    @Override
     public String toString() {
         return "BaseProfilingInfo<" + MetaUtil.profileToString(this, null, "; ") + ">";
     }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java	Tue Jun 18 10:12:27 2013 +0200
@@ -62,7 +62,7 @@
 
     public JavaTypeProfile restrict(JavaTypeProfile otherProfile) {
         if (otherProfile.getNotRecordedProbability() > 0.0) {
-            // Not useful for restricting since there is an unknown set of types occuring.
+            // Not useful for restricting since there is an unknown set of types occurring.
             return this;
         }
 
@@ -155,7 +155,20 @@
 
         @Override
         public String toString() {
-            return "{" + item.getName() + ", " + probability + "}";
+            return String.format("%.6f#%s", probability, item);
         }
     }
+
+    @Override
+    public String toString() {
+        StringBuilder buf = new StringBuilder("JavaTypeProfile<nullSeen=").append(getNullSeen()).append(", types=[");
+        for (int j = 0; j < getTypes().length; j++) {
+            if (j != 0) {
+                buf.append(", ");
+            }
+            ProfiledType ptype = getTypes()[j];
+            buf.append(String.format("%.6f:%s", ptype.getProbability(), ptype.getType()));
+        }
+        return buf.append(String.format("], notRecorded:%.6f>", getNotRecordedProbability())).toString();
+    }
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java	Tue Jun 18 10:12:27 2013 +0200
@@ -112,4 +112,12 @@
      */
     int getDeoptimizationCount(DeoptimizationReason reason);
 
+    /**
+     * Returns true if the profiling information can be assumed as sufficiently accurate.
+     * 
+     * @return true if the profiling information was recorded often enough mature enough, false
+     *         otherwise.
+     */
+    boolean isMature();
+
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java	Tue Jun 18 10:12:27 2013 +0200
@@ -45,6 +45,11 @@
     boolean isInternal();
 
     /**
+     * Determines if this field is a synthetic field as defined by the Java Language Specification.
+     */
+    boolean isSynthetic();
+
+    /**
      * Gets the constant value of this field for a given object, if available.
      * 
      * @param receiver object from which this field's value is to be read. This value is ignored if
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Tue Jun 18 10:12:27 2013 +0200
@@ -80,6 +80,12 @@
     int getModifiers();
 
     /**
+     * Determines if this method is a synthetic method as defined by the Java Language
+     * Specification.
+     */
+    boolean isSynthetic();
+
+    /**
      * Checks whether this method is a class initializer.
      * 
      * @return {@code true} if the method is a class initializer
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Tue Jun 18 10:12:27 2013 +0200
@@ -90,6 +90,20 @@
         }
     }
 
+    public static class Fmt2e {
+        public Fmt2e(SPARCAssembler asm, int op, int c4lo, int cc2, int rs1, int d10lo, int regOrImmediate) {
+            assert op == 0;
+            assert (cc2 & 0xFFFFFFFE) == 0;
+            assert c4lo >= 0 && rs1 < 0x10;
+            assert rs1 >= 0 && rs1 < 0x20;
+            assert (regOrImmediate & 0x1F) < 0x20;
+            assert (regOrImmediate & 0xFFFFC000) == 0;
+            assert (d10lo & 0xFFFFFC00) == 0;
+
+            asm.emitInt(op << 30 | 1 << 28 | 3 << 22 | cc2 << 21 | (d10lo >> 8) << 19 | rs1 << 14 | (d10lo & 0xff) << 5 | regOrImmediate);
+        }
+    }
+
     public static class Fmt3a {
         public Fmt3a(SPARCAssembler masm, int op, int rd, int op3, int rs1, int rs2) {
             assert  op == 2 || op == 3;
@@ -158,6 +172,18 @@
         }
     }
 
+    public static class Fmt3n {
+        public Fmt3n(SPARCAssembler masm, int op, int op3, int opf, int rs2, int rd) {
+            assert  op == 2 || op == 3;
+            assert op3 >= 0 && op3 < 0x40;
+            assert opf >= 0 && opf < 0x200;
+            assert rs2 >= 0 && rs2 < 0x20;
+            assert  rd >= 0 &&  rd < 0x20;
+
+            masm.emitInt(op << 30 | rd << 25 | op3 << 19 | opf << 5 | rs2);
+        }
+    }
+
     public static class Fmt3p {
         public Fmt3p(SPARCAssembler masm, int op, int op3, int opf, int rs1, int rs2, int rd) {
             assert  op == 2 || op == 3;
@@ -171,18 +197,6 @@
         }
     }
 
-    public static class Fmt3n {
-        public Fmt3n(SPARCAssembler masm, int op, int op3, int opf, int rs2, int rd) {
-            assert  op == 2 || op == 3;
-            assert op3 >= 0 && op3 < 0x40;
-            assert opf >= 0 && opf < 0x200;
-            assert rs2 >= 0 && rs2 < 0x20;
-            assert  rd >= 0 &&  rd < 0x20;
-
-            masm.emitInt(op << 30 | rd << 25 | op3 << 19 | opf << 5 | rs2);
-        }
-    }
-
     public static class Fmt3q {
         public Fmt3q(SPARCAssembler masm, int op, int op3, int rs1, int rd) {
             assert  op == 2 || op == 3;
@@ -239,6 +253,20 @@
         }
     }
 
+    public static class Fmt5a {
+        public Fmt5a(SPARCAssembler masm, int op, int op3, int op5, int rs1, int rs2, int rs3, int rd) {
+            assert   op == 2;
+            assert  op3 >= 0 &&  op3 < 0x40;
+            assert  op5 >= 0 &&  op5 < 0x10;
+            assert  rs1 >= 0 &&  rs1 < 0x20;
+            assert  rs2 >= 0 &&  rs2 < 0x20;
+            assert  rs3 >= 0 &&  rs3 < 0x20;
+            assert  rd  >= 0 &&  rd  < 0x20;
+
+            masm.emitInt(op << 30 | rd << 25 | op3 << 19 | rs1 << 14 | rs3 << 9 | op5 << 5 | rs2);
+        }
+    }
+
     public static final int ImmedTrue = 0x00002000;
 
     public enum Ops {
@@ -389,6 +417,27 @@
         }
     }
 
+    public enum Op5s {
+        Fmadds(0x1),
+        Fmaddd(0x2),
+        Fmsubs(0x5),
+        Fmsubd(0x6),
+        Fnmsubs(0x9),
+        Fnmsubd(0xA),
+        Fnmadds(0xD),
+        Fnmaddd(0xE);
+
+        private final int value;
+
+        private Op5s(int value) {
+            this.value = value;
+        }
+
+        public int getValue() {
+            return value;
+        }
+    }
+
     public enum Opfs {
         Fmovs(0x01, "fmovs"),
         Fmovd(0x02, "fmovd"),
@@ -399,6 +448,62 @@
         Fabss(0x09, "fabss"),
         Fabsd(0x0A, "fabsd"),
         Fabsq(0x0B, "fabsq"),
+
+        // start VIS1
+        Edge8cc(0x0, "edge8cc"),
+        Edge8n(0x1, "edge8n"),
+        Edge8lcc(0x2, "edge8lcc"),
+        Edge8ln(0x3, "edge8ln"),
+        Edge16cc(0x4, "edge16cc"),
+        Edge16n(0x5, "edge16n"),
+        Edge16lcc(0x6, "edge16lcc"),
+        Edge16ln(0x7, "edge16ln"),
+        Edge32cc(0x8, "edge32cc"),
+        Edge32n(0x9, "edge32n"),
+        Edge32lcc(0xA, "edge32lcc"),
+        Edge32ln(0xB, "edge32ln"),
+        Array8(0x10, "array8"),
+        Array16(0x12, "array16"),
+        Array32(0x14, "array32"),
+        AlignAddress(0x18, "alignaddress"),
+        AlignAddressLittle(0x1A, "alignaddress_little"),
+        Fmul8x16(0x31, "fmul8x16"),
+        Fmul8x16au(0x33, "fmul8x16au"),
+        Fmul8x16al(0x35, "fmul8x16al"),
+        Fmul8sux16(0x36, "fmul8sux16"),
+        Fmul8ulx16(0x37, "fmul8ulx16"),
+        Fmuld8sux16(0x38, "fmuld8sux16"),
+        Fmuld8ulx16(0x39, "fmuld8ulx16"),
+        Faligndatag(0x48, "faligndata"),
+        Fnhadds(0x71, "fnhadds"),
+        Fnhaddd(0x72, "fnhaddd"),
+        // end VIS1
+
+        // start VIS2
+        Bmask(0x19, "bmask"),
+        Bshuffle(0x4c, "bshuffle"),
+        // end VIS2 only
+
+        // start VIS3
+        Addxc(0x11, "addxc"),
+        Addxccc(0x13, "addxccc"),
+        Cmask8(0x1B, "cmask8"),
+        Cmask16(0x1D, "cmask16"),
+        Cmask32(0x1F, "cmask32"),
+        Fmean16(0x40, "fmean16"),
+        Fnadds(0x51, "fnadds"),
+        Fnaddd(0x52, "fnaddd"),
+        // end VIS3
+
+        // start CAMMELLIA
+        CammelliaFl(0x13C, "cammelia_fl"),
+        CammelliaFli(0x13D, "cammellia_fli"),
+        // end CAMMELLIA
+
+        // start CRYPTO
+        Crc32c(0x147, "crc32c"),
+        // end CRYPTO
+
         Fadds(0x41, "fadds"),
         Faddd(0x42, "faddd"),
         Faddq(0x43, "faddq"),
@@ -663,6 +768,38 @@
         }
     }
 
+    public static class Addxc extends Fmt3p {
+        public Addxc(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS3 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Addxc.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Addxccc extends Fmt3p {
+        public Addxccc(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS3 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Addxccc.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Alignaddr extends Fmt3p {
+        public Alignaddr(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.AlignAddress.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Alignaddrl extends Fmt3p {
+        public Alignaddrl(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.AlignAddressLittle.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
     public static class And extends Fmt3b {
         public And(SPARCAssembler masm, Register src1, int simm13, Register dst) {
             super(masm, Ops.ArithOp.getValue(), Op3s.And.getValue(), src1.encoding(), simm13, dst.encoding());
@@ -699,6 +836,38 @@
         }
     }
 
+    public static class Array8 extends Fmt3p {
+        public Array8(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Array8.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Array16 extends Fmt3p {
+        public Array16(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Array16.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Array32 extends Fmt3p {
+        public Array32(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Array32.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Bmask extends Fmt3p {
+        public Bmask(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS2 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Bmask.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
     public static class Bpa extends Fmt2c {
         public Bpa(SPARCAssembler masm, int simmm19) {
             super(masm, Ops.BranchOp.getValue(), 0, ConditionFlag.Always.getValue(),
@@ -891,11 +1060,456 @@
         }
     }
 
+    public static class Bshuffle extends Fmt3p {
+        public Bshuffle(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS2 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Bshuffle.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class CammelliaFl extends Fmt3p {
+        public CammelliaFl(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* CAMELLIA only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.CammelliaFl.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class CammelliaFli extends Fmt3p {
+        public CammelliaFli(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* CAMELLIA only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.CammelliaFli.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
     private static int patchUnbound(SPARCAssembler masm, Label label) {
         label.addPatchAt(masm.codeBuffer.position());
         return 0;
     }
 
+    public static class Cmask8 extends Fmt3n {
+        public Cmask8(SPARCAssembler asm, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Cmask8.getValue(),
+                            src2.encoding(), 0);
+        }
+    }
+
+    public static class Cmask16 extends Fmt3n {
+        public Cmask16(SPARCAssembler asm, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Cmask16.getValue(),
+                            src2.encoding(), 0);
+        }
+    }
+
+    public static class Cmask32 extends Fmt3n {
+        public Cmask32(SPARCAssembler asm, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Cmask32.getValue(),
+                            src2.encoding(), 0);
+        }
+    }
+
+    public static class Crc32c extends Fmt3p {
+        public Crc32c(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* CRYPTO only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Crc32c.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Cwbcc extends Fmt2e {
+        public Cwbcc(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarryClear.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbcc(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Equal.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbcs extends Fmt2e {
+        public Cwbcs(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarrySet.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbcs(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarrySet.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbe extends Fmt2e {
+        public Cwbe(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarryClear.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbe(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Equal.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbg extends Fmt2e {
+        public Cwbg(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Greater.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbg(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Greater.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbge extends Fmt2e {
+        public Cwbge(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterEqual.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbge(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterEqual.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbgu extends Fmt2e {
+        public Cwbgu(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterUnsigned.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbgu(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterUnsigned.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbl extends Fmt2e {
+        public Cwbl(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Less.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbl(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Less.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwble extends Fmt2e {
+        public Cwble(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqual.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwble(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqual.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbleu extends Fmt2e {
+        public Cwbleu(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqualUnsigned.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbleu(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqualUnsigned.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbne extends Fmt2e {
+        public Cwbne(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.NotEqual.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbne(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.NotEqual.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbneg extends Fmt2e {
+        public Cwbneg(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Negative.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbneg(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Negative.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbpos extends Fmt2e {
+        public Cwbpos(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Positive.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbpos(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Positive.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbvc extends Fmt2e {
+        public Cwbvc(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowClear.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbvc(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowClear.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cwbvs extends Fmt2e {
+        public Cwbvs(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowSet.getValue(), 0,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cwbvs(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowSet.getValue(), 0,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbcc extends Fmt2e {
+        public Cxbcc(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarryClear.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbcc(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Equal.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbcs extends Fmt2e {
+        public Cxbcs(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarrySet.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbcs(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarrySet.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbe extends Fmt2e {
+        public Cxbe(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarryClear.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbe(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Equal.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbg extends Fmt2e {
+        public Cxbg(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Greater.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbg(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Greater.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbge extends Fmt2e {
+        public Cxbge(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterEqual.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbge(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterEqual.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbgu extends Fmt2e {
+        public Cxbgu(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterUnsigned.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbgu(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterUnsigned.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbl extends Fmt2e {
+        public Cxbl(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Less.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbl(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Less.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxble extends Fmt2e {
+        public Cxble(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqual.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxble(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqual.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbleu extends Fmt2e {
+        public Cxbleu(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqualUnsigned.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbleu(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqualUnsigned.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbne extends Fmt2e {
+        public Cxbne(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.NotEqual.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbne(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.NotEqual.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbneg extends Fmt2e {
+        public Cxbneg(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Negative.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbneg(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Negative.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbpos extends Fmt2e {
+        public Cxbpos(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Positive.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbpos(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Positive.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbvc extends Fmt2e {
+        public Cxbvc(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowClear.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbvc(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowClear.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Cxbvs extends Fmt2e {
+        public Cxbvs(SPARCAssembler asm, Register src1, Register src2, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowSet.getValue(), 1,
+                            src1.encoding(), simm10, src2.encoding());
+        }
+        public Cxbvs(SPARCAssembler asm, Register src1, int immed5, int simm10) {
+            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowSet.getValue(), 1,
+                            src1.encoding(), simm10, immed5 | ImmedTrue);
+        }
+    }
+
+    public static class Edge8cc extends Fmt3p {
+        public Edge8cc(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge8cc.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Edge8n extends Fmt3p {
+        public Edge8n(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge8n.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Edge8lcc extends Fmt3p {
+        public Edge8lcc(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge8lcc.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Edge8ln extends Fmt3p {
+        public Edge8ln(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge8ln.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Edge16cc extends Fmt3p {
+        public Edge16cc(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge16cc.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Edge16n extends Fmt3p {
+        public Edge16n(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge16n.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Edge16lcc extends Fmt3p {
+        public Edge16lcc(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge16lcc.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Edge16ln extends Fmt3p {
+        public Edge16ln(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge16ln.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Edge32cc extends Fmt3p {
+        public Edge32cc(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge32cc.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Edge32n extends Fmt3p {
+        public Edge32n(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge32n.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Edge32lcc extends Fmt3p {
+        public Edge32lcc(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge32lcc.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Edge32ln extends Fmt3p {
+        public Edge32ln(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Edge32ln.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
     public static class Fadds extends Fmt3p {
         public Fadds(SPARCAssembler masm, Register src1, Register src2, Register dst) {
             super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fadds.getValue(),
@@ -917,6 +1531,13 @@
         }
     }
 
+    public static class Faligndata extends Fmt3p {
+        public Faligndata(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Faligndatag.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
     public static class Fdivs extends Fmt3p {
         public Fdivs(SPARCAssembler masm, Register src1, Register src2, Register dst) {
             super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fdivs.getValue(),
@@ -931,6 +1552,86 @@
         }
     }
 
+    public static class Fmadds extends Fmt5a {
+        public Fmadds(SPARCAssembler asm, Register src1, Register src2, Register src3, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), Op5s.Fmadds.getValue(),
+                            src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fmaddd extends Fmt5a {
+        public Fmaddd(SPARCAssembler asm, Register src1, Register src2, Register src3, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), Op5s.Fmaddd.getValue(),
+                            src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fmean16 extends Fmt3p {
+        public Fmean16(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS3 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Fmean16.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fmsubs extends Fmt5a {
+        public Fmsubs(SPARCAssembler asm, Register src1, Register src2, Register src3, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), Op5s.Fmsubs.getValue(),
+                            src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fmsubd extends Fmt5a {
+        public Fmsubd(SPARCAssembler asm, Register src1, Register src2, Register src3, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), Op5s.Fmsubd.getValue(),
+                            src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fnadds extends Fmt3p {
+        public Fnadds(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS3 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fnadds.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fnaddd extends Fmt3p {
+        public Fnaddd(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS3 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fnaddd.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fnmadds extends Fmt5a {
+        public Fnmadds(SPARCAssembler asm, Register src1, Register src2, Register src3, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), Op5s.Fnmadds.getValue(),
+                            src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fnmaddd extends Fmt5a {
+        public Fnmaddd(SPARCAssembler asm, Register src1, Register src2, Register src3, Register dst) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), Op5s.Fnmaddd.getValue(),
+                            src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fnmsubs extends Fmt5a {
+        public Fnmsubs(SPARCAssembler masm, Register src1, Register src2, Register src3, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), Op5s.Fnmsubs.getValue(),
+                            src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fnmsubd extends Fmt5a {
+        public Fnmsubd(SPARCAssembler masm, Register src1, Register src2, Register src3, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), Op5s.Fnmsubd.getValue(),
+                            src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+        }
+    }
+
     public static class Fmuls extends Fmt3p {
         public Fmuls(SPARCAssembler masm, Register src1, Register src2, Register dst) {
             super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fmuls.getValue(),
@@ -945,6 +1646,62 @@
         }
     }
 
+    public static class Fmul8x16 extends Fmt3p {
+        public Fmul8x16(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Fmul8x16.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fmul8x16au extends Fmt3p {
+        public Fmul8x16au(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Fmul8x16.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fmul8x16al extends Fmt3p {
+        public Fmul8x16al(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Fmul8x16al.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fmul8sux16 extends Fmt3p {
+        public Fmul8sux16(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Fmul8sux16.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fmul8ulx16 extends Fmt3p {
+        public Fmul8ulx16(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Fmul8ulx16.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fmuld8sux16 extends Fmt3p {
+        public Fmuld8sux16(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Fmuld8sux16.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fmuld8ulx16 extends Fmt3p {
+        public Fmuld8ulx16(SPARCAssembler asm, Register src1, Register src2, Register dst) {
+            /* VIS1 only */
+            super(asm, Ops.ArithOp.getValue(), Op3s.Impdep1.getValue(), Opfs.Fmuld8ulx16.getValue(),
+                            src1.encoding(), src2.encoding(), dst.encoding());
+        }
+    }
+
     public static class Fnegs extends Fmt3n {
         public Fnegs(SPARCAssembler masm, Register src2, Register dst) {
             super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fnegs.getValue(),
@@ -1463,6 +2220,127 @@
         }
     }
 
+    public static class Tcc extends Fmt4a {
+        public Tcc(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.CarryClear.getValue());
+        }
+        public Tcc(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.CarryClear.getValue());
+        }
+    }
+
+    public static class Tcs extends Fmt4a {
+        public Tcs(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.CarrySet.getValue());
+        }
+        public Tcs(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.CarrySet.getValue());
+        }
+    }
+
+    public static class Te extends Fmt4a {
+        public Te(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.Equal.getValue());
+        }
+        public Te(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.Equal.getValue());
+        }
+    }
+
+    public static class Tg extends Fmt4a {
+        public Tg(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.Greater.getValue());
+        }
+        public Tg(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.Greater.getValue());
+        }
+    }
+
+    public static class Tge extends Fmt4a {
+        public Tge(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.GreaterEqual.getValue());
+        }
+        public Tge(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.GreaterEqual.getValue());
+        }
+    }
+
+    public static class Tle extends Fmt4a {
+        public Tle(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.LessEqual.getValue());
+        }
+        public Tle(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.LessEqual.getValue());
+        }
+    }
+
+    public static class Tleu extends Fmt4a {
+        public Tleu(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.LessEqualUnsigned.getValue());
+        }
+        public Tleu(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.LessEqualUnsigned.getValue());
+        }
+    }
+
+    public static class Tn extends Fmt4a {
+        public Tn(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.Never.getValue());
+        }
+        public Tn(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.Never.getValue());
+        }
+    }
+
+    public static class Tne extends Fmt4a {
+        public Tne(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.NotEqual.getValue());
+        }
+        public Tne(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.NotEqual.getValue());
+        }
+    }
+
+    public static class Tneg extends Fmt4a {
+        public Tneg(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.Negative.getValue());
+        }
+        public Tneg(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.Negative.getValue());
+        }
+    }
+
+    public static class Tpos extends Fmt4a {
+        public Tpos(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.Positive.getValue());
+        }
+        public Tpos(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.Positive.getValue());
+        }
+    }
+
     public static class Tsubcc extends Fmt3b {
         public Tsubcc(SPARCAssembler masm, Register src1, int simm13, Register dst) {
             super(masm, Ops.ArithOp.getValue(), Op3s.Tsubcc.getValue(), src1.encoding(), simm13, dst.encoding());
@@ -1484,6 +2362,28 @@
         }
     }
 
+    public static class Tvc extends Fmt4a {
+        public Tvc(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.OverflowClear.getValue());
+        }
+        public Tvc(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.OverflowClear.getValue());
+        }
+    }
+
+    public static class Tvs extends Fmt4a {
+        public Tvs(SPARCAssembler asm, CC cc, Register src1, int trap) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), trap, ConditionFlag.OverflowSet.getValue());
+        }
+        public Tvs(SPARCAssembler asm, CC cc, Register src1, Register src2) {
+            super(asm, Ops.ArithOp.getValue(), Op3s.Trap.getValue(), cc.getValue(),
+                  src1.encoding(), src2.encoding(), ConditionFlag.OverflowSet.getValue());
+        }
+    }
+
     @Deprecated
     public static class Udiv extends Fmt3b {
         @Deprecated
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Tue Jun 18 10:12:27 2013 +0200
@@ -212,6 +212,19 @@
     }
 
     @SuppressWarnings("unused")
+    public static class Mov {
+
+        public Mov(SPARCAssembler asm, Register src1, Register dst) {
+            assert src1.encoding() != dst.encoding();
+            new Or(asm, SPARC.g0, src1, dst);
+        }
+
+        public Mov(SPARCAssembler asm, int simm13, Register dst) {
+            new Or(asm, SPARC.g0, simm13, dst);
+        }
+    }
+
+    @SuppressWarnings("unused")
     public static class Not {
 
         public Not(SPARCAssembler asm, Register src1, Register dst) {
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Tue Jun 18 10:12:27 2013 +0200
@@ -59,18 +59,13 @@
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.SequentialSwitchOp;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.SwitchRangesOp;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.TableSwitchOp;
-import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp;
 import com.oracle.graal.lir.amd64.AMD64Move.LeaOp;
-import com.oracle.graal.lir.amd64.AMD64Move.LoadOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MembarOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp;
 import com.oracle.graal.lir.amd64.AMD64Move.StackLeaOp;
-import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp;
-import com.oracle.graal.lir.amd64.AMD64Move.StoreOp;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.util.*;
 
 /**
@@ -215,31 +210,6 @@
     }
 
     @Override
-    public Variable emitLoad(Kind kind, Value address, DeoptimizingNode deopting) {
-        AMD64AddressValue loadAddress = asAddressValue(address);
-        Variable result = newVariable(kind);
-        append(new LoadOp(kind, result, loadAddress, deopting != null ? state(deopting) : null));
-        return result;
-    }
-
-    @Override
-    public void emitStore(Kind kind, Value address, Value inputVal, DeoptimizingNode deopting) {
-        AMD64AddressValue storeAddress = asAddressValue(address);
-        LIRFrameState state = deopting != null ? state(deopting) : null;
-
-        if (isConstant(inputVal)) {
-            Constant c = asConstant(inputVal);
-            if (canStoreConstant(c)) {
-                append(new StoreConstantOp(kind, storeAddress, c, state));
-                return;
-            }
-        }
-
-        Variable input = load(inputVal);
-        append(new StoreOp(kind, storeAddress, input, state));
-    }
-
-    @Override
     public Variable emitAddress(StackSlot address) {
         Variable result = newVariable(target().wordKind);
         append(new StackLeaOp(result, address));
@@ -882,34 +852,6 @@
     }
 
     @Override
-    public void visitCompareAndSwap(CompareAndSwapNode node) {
-        Kind kind = node.newValue().kind();
-        assert kind == node.expected().kind();
-
-        Value expected = loadNonConst(operand(node.expected()));
-        Variable newValue = load(operand(node.newValue()));
-
-        AMD64AddressValue address;
-        int displacement = node.displacement();
-        Value index = operand(node.offset());
-        if (isConstant(index) && NumUtil.isInt(asConstant(index).asLong() + displacement)) {
-            assert !runtime.needsDataPatch(asConstant(index));
-            displacement += (int) asConstant(index).asLong();
-            address = new AMD64AddressValue(kind, load(operand(node.object())), displacement);
-        } else {
-            address = new AMD64AddressValue(kind, load(operand(node.object())), load(index), Scale.Times1, displacement);
-        }
-
-        RegisterValue rax = AMD64.rax.asValue(kind);
-        emitMove(rax, expected);
-        append(new CompareAndSwapOp(rax, address, rax, newValue));
-
-        Variable result = newVariable(node.kind());
-        append(new CondMoveOp(result, Condition.EQ, load(Constant.TRUE), Constant.FALSE));
-        setResult(node, result);
-    }
-
-    @Override
     public void visitBreakpointNode(BreakpointNode node) {
         JavaType[] sig = new JavaType[node.arguments().size()];
         for (int i = 0; i < sig.length; i++) {
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -39,6 +39,7 @@
 import com.oracle.graal.phases.OptimisticOptimizations;
 import com.oracle.graal.phases.PhasePlan;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.ptx.PTX;
 
 public abstract class PTXTestBase extends GraalCompilerTest {
@@ -57,8 +58,14 @@
         phasePlan.addPhase(PhasePosition.AFTER_PARSING, new PTXPhase());
         new PTXPhase().apply(graph);
         CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
+        /*
+         * Use Suites.createDefaultSuites() instead of GraalCompilerTest.suites. The
+         * GraalCompilerTest.suites variable contains the Suites for the HotSpotRuntime. This code
+         * will not run on hotspot, so it should use the plain Graal default suites, without hotspot
+         * specific phases.
+         */
         CompilationResult result = GraalCompiler.compileGraph(graph, cc, graph.method(), runtime, graalRuntime().getReplacements(), ptxBackend, target, null, phasePlan, OptimisticOptimizations.NONE,
-                        new SpeculationLog());
+                        new SpeculationLog(), Suites.createDefaultSuites());
         return result;
     }
 
--- a/graal/com.oracle.graal.compiler.sparc.test/src/com/oracle/graal/compiler/sparc/test/BasicSPARCTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.sparc.test/src/com/oracle/graal/compiler/sparc/test/BasicSPARCTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -26,7 +26,6 @@
 
 import org.junit.Test;
 
-
 public class BasicSPARCTest extends SPARCTestBase {
 
     @Test
--- a/graal/com.oracle.graal.compiler.sparc.test/src/com/oracle/graal/compiler/sparc/test/SPARCTestBase.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.sparc.test/src/com/oracle/graal/compiler/sparc/test/SPARCTestBase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -55,9 +55,8 @@
         GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.NONE);
         phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
         CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
-        CompilationResult result = GraalCompiler.compileGraph(graph, cc, graph.method(), runtime, graalRuntime().getReplacements(),
-                                                              sparcBackend, target, null, phasePlan, OptimisticOptimizations.NONE,
-                                                              new SpeculationLog());
+        CompilationResult result = GraalCompiler.compileGraph(graph, cc, graph.method(), runtime, graalRuntime().getReplacements(), sparcBackend, target, null, phasePlan,
+                        OptimisticOptimizations.NONE, new SpeculationLog(), suites);
         return result;
     }
 
@@ -66,4 +65,3 @@
     }
 
 }
-
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Tue Jun 18 10:12:27 2013 +0200
@@ -119,6 +119,13 @@
 
     @Override
     public void emitMove(AllocatableValue dst, Value src) {
+        // XXX SPARCAddress loads
+        /*
+         * if (src instanceof SPARCAddressValue) { public LoadOp(Kind kind, AllocatableValue result,
+         * SPARCAddressValue address, LIRFrameState state) {
+         * 
+         * return new LoadOp(result.getKind(), result, (SPARCAddressValue) src); }
+         */
         if (isRegister(src) || isStackSlot(dst)) {
             append(new MoveFromRegOp(dst, src));
         } else {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -309,8 +309,7 @@
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(runtime(), assumptions, replacements);
         new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-        new PartialEscapeAnalysisPhase(false, false).apply(graph, context);
-        new CullFrameStatesPhase().apply(graph);
+        new PartialEscapePhase(false, new CanonicalizerPhase(true)).apply(graph, context);
     }
 
     private void compareGraphs(final String snippet, final String referenceSnippet) {
@@ -326,22 +325,22 @@
 
                 Assumptions assumptions = new Assumptions(false);
                 HighTierContext context = new HighTierContext(runtime(), assumptions, replacements);
+                CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
                 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);
+                canonicalizer.apply(graph, context);
+                new PartialEscapePhase(false, canonicalizer).apply(graph, context);
 
-                new CullFrameStatesPhase().apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
-                new CanonicalizerPhase().apply(graph, context);
+                canonicalizer.apply(graph, context);
 
                 StructuredGraph referenceGraph = parse(referenceSnippet);
                 new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(referenceGraph);
                 new DeadCodeEliminationPhase().apply(referenceGraph);
-                new CanonicalizerPhase().apply(referenceGraph, context);
+                new CanonicalizerPhase(true).apply(referenceGraph, context);
 
                 assertEquals(referenceGraph, graph, excludeVirtual);
             }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -35,7 +35,7 @@
 
     private StructuredGraph getCanonicalizedGraph(String name) {
         StructuredGraph graph = parse(name);
-        new CanonicalizerPhase.Instance(runtime(), null).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
         return graph;
     }
 
@@ -53,7 +53,7 @@
             assertEquals(referenceGraph, graph);
         }
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(referenceGraph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).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	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Tue Jun 18 10:12:27 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.Instance(runtime(), new Assumptions(false)).apply(graph);
+                new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).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/EliminateNestedCheckCastsTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -115,7 +115,7 @@
                 StructuredGraph graph = parse(snippet);
                 Debug.dump(graph, "After parsing: " + snippet);
                 Assert.assertEquals(checkcasts, graph.getNodes().filter(CheckCastNode.class).count());
-                new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph);
+                new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph);
                 Assert.assertEquals(afterCanon, graph.getNodes(CheckCastNode.class).count());
                 return graph;
             }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -68,7 +68,7 @@
         GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault();
         new GraphBuilderPhase(runtime, conf, OptimisticOptimizations.ALL).apply(graph);
         new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
         return graph;
     }
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.compiler.test;
 
 import static com.oracle.graal.api.code.CodeUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -47,9 +48,9 @@
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.printer.*;
 import com.oracle.graal.test.*;
-import com.oracle.graal.hotspot.phases.WriteBarrierAdditionPhase;
 
 /**
  * Base class for Graal compiler unit tests.
@@ -75,11 +76,13 @@
     protected final GraalCodeCacheProvider runtime;
     protected final Replacements replacements;
     protected final Backend backend;
+    protected final Suites suites;
 
     public GraalCompilerTest() {
         this.replacements = Graal.getRequiredCapability(Replacements.class);
         this.runtime = Graal.getRequiredCapability(GraalCodeCacheProvider.class);
         this.backend = Graal.getRequiredCapability(Backend.class);
+        this.suites = Graal.getRequiredCapability(SuitesProvider.class).createSuites();
     }
 
     @BeforeClass
@@ -355,7 +358,7 @@
         test(method, expect, Collections.<DeoptimizationReason> emptySet(), receiver, args);
     }
 
-    protected void test(Method method, Result expect, Set<DeoptimizationReason> shouldNotDeopt, Object receiver, Object... args) {
+    protected Result executeActualCheckDeopt(Method method, Set<DeoptimizationReason> shouldNotDeopt, Object receiver, Object... args) {
         Map<DeoptimizationReason, Integer> deoptCounts = new EnumMap<>(DeoptimizationReason.class);
         ProfilingInfo profile = runtime.lookupJavaMethod(method).getProfilingInfo();
         for (DeoptimizationReason reason : shouldNotDeopt) {
@@ -365,7 +368,10 @@
         for (DeoptimizationReason reason : shouldNotDeopt) {
             Assert.assertEquals((int) deoptCounts.get(reason), profile.getDeoptimizationCount(reason));
         }
+        return actual;
+    }
 
+    protected void assertEquals(Result expect, Result actual) {
         if (expect.exception != null) {
             Assert.assertTrue("expected " + expect.exception, actual.exception != null);
             Assert.assertEquals(expect.exception.getClass(), actual.exception.getClass());
@@ -379,6 +385,11 @@
         }
     }
 
+    protected void test(Method method, Result expect, Set<DeoptimizationReason> shouldNotDeopt, Object receiver, Object... args) {
+        Result actual = executeActualCheckDeopt(method, shouldNotDeopt, receiver, args);
+        assertEquals(expect, actual);
+    }
+
     private Map<ResolvedJavaMethod, InstalledCode> cache = new HashMap<>();
 
     /**
@@ -420,20 +431,18 @@
         InstalledCode installedCode = Debug.scope("Compiling", new Object[]{runtime, new DebugDumpScope(String.valueOf(id), true)}, new Callable<InstalledCode>() {
 
             public InstalledCode call() throws Exception {
-                final boolean printCompilation = GraalOptions.PrintCompilation && !TTY.isSuppressed();
+                final boolean printCompilation = PrintCompilation.getValue() && !TTY.isSuppressed();
                 if (printCompilation) {
                     TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s ...", id, method.getDeclaringClass().getName(), method.getName(), method.getSignature()));
                 }
                 long start = System.currentTimeMillis();
                 PhasePlan phasePlan = new PhasePlan();
-                final 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);
                 CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
                 final CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, method, runtime, replacements, backend, runtime().getTarget(), null, phasePlan, OptimisticOptimizations.ALL,
-                                new SpeculationLog());
+                                new SpeculationLog(), suites);
                 if (printCompilation) {
                     TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize()));
                 }
@@ -441,7 +450,7 @@
 
                     @Override
                     public InstalledCode call() throws Exception {
-                        InstalledCode code = addMethod(method, compResult, graphCopy);
+                        InstalledCode code = addMethod(method, compResult);
                         if (Debug.isDumpEnabled()) {
                             Debug.dump(new Object[]{compResult, code}, "After code installation");
                         }
@@ -458,8 +467,8 @@
         return installedCode;
     }
 
-    protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult, final StructuredGraph graph) {
-        return runtime.addMethod(method, compResult, graph);
+    protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult) {
+        return runtime.addMethod(method, compResult);
     }
 
     /**
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -144,7 +144,7 @@
             n.replaceFirstInput(local, constant);
         }
         Debug.dump(graph, "Graph");
-        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph);
         StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
         assertEquals(referenceGraph, graph);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -60,7 +60,7 @@
         final StructuredGraph graph = parse(method);
         CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
         final CompilationResult cr = GraalCompiler.compileGraph(graph, cc, graph.method(), runtime, replacements, backend, runtime.getTarget(), null, getDefaultPhasePlan(),
-                        OptimisticOptimizations.ALL, new SpeculationLog());
+                        OptimisticOptimizations.ALL, new SpeculationLog(), suites);
         for (Infopoint sp : cr.getInfopoints()) {
             assertNotNull(sp.reason);
             if (sp instanceof Call) {
@@ -82,7 +82,7 @@
         assertTrue(graphLineSPs > 0);
         CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
         final CompilationResult cr = GraalCompiler.compileGraph(graph, cc, graph.method(), runtime, replacements, backend, runtime.getTarget(), null, getDefaultPhasePlan(true),
-                        OptimisticOptimizations.ALL, new SpeculationLog());
+                        OptimisticOptimizations.ALL, new SpeculationLog(), suites);
         int lineSPs = 0;
         for (Infopoint sp : cr.getInfopoints()) {
             assertNotNull(sp.reason);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java	Tue Jun 18 10:12:27 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.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java	Tue Jun 18 10:12:27 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.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).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	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -133,8 +133,8 @@
         }
 
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(referenceGraph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).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/MemoryScheduleTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -33,7 +33,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.Lowerable.*;
+import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
@@ -220,11 +220,11 @@
             public SchedulePhase call() throws Exception {
                 StructuredGraph graph = parse(snippet);
                 Assumptions assumptions = new Assumptions(false);
-                new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
+                HighTierContext context = new HighTierContext(runtime(), assumptions, replacements);
+                new CanonicalizerPhase(true).apply(graph, context);
                 if (mode == TestMode.INLINED_WITHOUT_FRAMESTATES) {
                     new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
                 }
-                HighTierContext context = new HighTierContext(runtime(), assumptions, replacements);
                 new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
                 if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) {
                     for (Node node : graph.getNodes()) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Tue Jun 18 10:12:27 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.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
         return graph;
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ProfilingInfoTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ProfilingInfoTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -128,7 +128,11 @@
     }
 
     public static Serializable checkCastSnippet(Object obj) {
-        return (Serializable) obj;
+        try {
+            return (Serializable) obj;
+        } catch (ClassCastException e) {
+            return null;
+        }
     }
 
     @Test
@@ -250,19 +254,30 @@
 
     @Test
     public void testNullSeen() {
-        ProfilingInfo info = profile("instanceOfSnippet", 1);
+        testNullSeen("instanceOfSnippet");
+        testNullSeen("checkCastSnippet");
+    }
+
+    private void testNullSeen(String snippet) {
+        ProfilingInfo info = profile(snippet, 1);
         Assert.assertEquals(TriState.FALSE, info.getNullSeen(1));
 
-        continueProfiling("instanceOfSnippet", "ABC");
+        continueProfiling(snippet, "ABC");
         Assert.assertEquals(TriState.FALSE, info.getNullSeen(1));
 
-        continueProfiling("instanceOfSnippet", (Object) null);
+        continueProfiling(snippet, new Object());
+        Assert.assertEquals(TriState.FALSE, info.getNullSeen(1));
+
+        continueProfiling(snippet, (Object) null);
         Assert.assertEquals(TriState.TRUE, info.getNullSeen(1));
 
-        continueProfiling("instanceOfSnippet", 0.0);
+        continueProfiling(snippet, 0.0);
         Assert.assertEquals(TriState.TRUE, info.getNullSeen(1));
 
-        resetProfile("instanceOfSnippet");
+        continueProfiling(snippet, new Object());
+        Assert.assertEquals(TriState.TRUE, info.getNullSeen(1));
+
+        resetProfile(snippet);
         Assert.assertEquals(TriState.FALSE, info.getNullSeen(1));
     }
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -93,10 +93,11 @@
     private StructuredGraph compileTestSnippet(final String snippet) {
         StructuredGraph graph = parse(snippet);
         HighTierContext context = new HighTierContext(runtime(), new Assumptions(false), replacements);
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
         new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
-        new CanonicalizerPhase().apply(graph, context);
+        canonicalizer.apply(graph, context);
         new PushThroughPiPhase().apply(graph);
-        new CanonicalizerPhase().apply(graph, context);
+        canonicalizer.apply(graph, context);
 
         return graph;
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -89,7 +89,7 @@
                 new FloatingReadPhase().apply(graph);
                 new EliminatePartiallyRedundantGuardsPhase(true, false).apply(graph);
                 new ReadEliminationPhase().apply(graph);
-                new CanonicalizerPhase().apply(graph, context);
+                new CanonicalizerPhase(true).apply(graph, context);
 
                 Debug.dump(graph, "After lowering");
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java	Tue Jun 18 10:12:27 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.Instance(runtime(), assumptions).apply(testGraph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(testGraph);
         StructuredGraph refGraph = parse(ref);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(refGraph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(refGraph);
         assertEquals(testGraph, refGraph);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -166,9 +166,9 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
         StructuredGraph referenceGraph = parse(referenceSnippet);
         assertEquals(referenceGraph, graph);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -96,9 +96,20 @@
         testZeroReturn("divStamp2");
     }
 
+    public static int distinctMask(int a, int b) {
+        int x = a & 0xaaaa;
+        int y = (b & 0x5555) | 0x1;
+        return x == y ? 1 : 0;
+    }
+
+    @Test
+    public void testDistinctMask() {
+        testZeroReturn("distinctMask");
+    }
+
     private void testZeroReturn(String methodName) {
         StructuredGraph graph = parse(methodName);
-        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
         assertConstantReturn(graph, 0);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Tue Jun 18 10:12:27 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.Instance(runtime(), new Assumptions(false)).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).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	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -186,13 +186,13 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
         // a second canonicalizer is needed to process nested MaterializeNodes
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
         StructuredGraph referenceGraph = parse(referenceSnippet);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(referenceGraph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(referenceGraph);
         assertEquals(referenceGraph, graph);
     }
 
@@ -242,9 +242,9 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), assumptions, true).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/WriteBarrierAdditionTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/WriteBarrierAdditionTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -27,10 +27,10 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.hotspot.phases.*;
+import com.oracle.graal.nodes.HeapAccess.WriteBarrierType;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType;
-import com.oracle.graal.nodes.spi.Lowerable.*;
+import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.compiler.test.backend;
 
 import static com.oracle.graal.api.code.CodeUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 import java.util.concurrent.*;
@@ -112,13 +113,13 @@
 
     private RegisterStats getRegisterStats(final StructuredGraph graph) {
         final PhasePlan phasePlan = getDefaultPhasePlan();
-        final Assumptions assumptions = new Assumptions(GraalOptions.OptAssumptions);
+        final Assumptions assumptions = new Assumptions(OptAssumptions.getValue());
 
         final LIR lir = Debug.scope("FrontEnd", new Callable<LIR>() {
 
             @Override
             public LIR call() {
-                return GraalCompiler.emitHIR(runtime, backend.target, graph, replacements, assumptions, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog());
+                return GraalCompiler.emitHIR(runtime, backend.target, graph, replacements, assumptions, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog(), suites);
             }
         });
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -55,7 +55,7 @@
     public void test1() {
         Method method = getMethod("testMethod");
         final StructuredGraph graph = parse(method);
-        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
 
         for (Node node : graph.getNodes()) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -222,7 +222,7 @@
                 HighTierContext context = new HighTierContext(runtime(), assumptions, replacements);
                 new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
-                new PartialEscapeAnalysisPhase(iterativeEscapeAnalysis, false).apply(graph, context);
+                new PartialEscapePhase(iterativeEscapeAnalysis, new CanonicalizerPhase(true)).apply(graph, context);
                 Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count());
                 ReturnNode returnNode = graph.getNodes(ReturnNode.class).first();
                 if (expectedConstantResult != null) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -33,6 +33,7 @@
 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.phases.ea.*;
 
@@ -79,19 +80,6 @@
         assertEquals(graph.getLocal(0), result);
     }
 
-    @SuppressWarnings("all")
-    public static int testSimpleReadSnippet(TestObject a, int b) throws Exception {
-        a.callable = new TestInt(b, 9);
-        return a.callable.call();
-    }
-
-    @Test
-    public void testSimpleRead() {
-        ValueNode result = getReturn("testSimpleReadSnippet").result();
-        assertTrue(graph.getNodes(LoadFieldNode.class).isEmpty());
-        assertEquals(graph.getLocal(1), result);
-    }
-
     final ReturnNode getReturn(String snippet) {
         processMethod(snippet);
         assertEquals(1, graph.getNodes(ReturnNode.class).count());
@@ -100,8 +88,7 @@
 
     private void processMethod(final String snippet) {
         graph = parse(snippet);
-        GraalOptions.OptEarlyReadElimination = true;
         HighTierContext context = new HighTierContext(runtime(), new Assumptions(false), replacements);
-        new IterativeInliningPhase(replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL, false).apply(graph, context);
+        new IterativeInliningPhase(null, getDefaultPhasePlan(), OptimisticOptimizations.ALL, new CanonicalizerPhase(true)).apply(graph, context);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,229 +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.compiler.test.ea;
-
-import static org.junit.Assert.*;
-
-import java.util.concurrent.*;
-
-import org.junit.*;
-
-import com.oracle.graal.api.code.*;
-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.*;
-import com.oracle.graal.phases.tiers.*;
-import com.oracle.graal.virtual.phases.ea.*;
-
-public class PEAReadEliminationTest extends GraalCompilerTest {
-
-    private StructuredGraph graph;
-
-    public static Object staticField;
-
-    public static class TestObject implements Callable<Integer> {
-
-        public int x;
-        public int y;
-
-        public TestObject(int x, int y) {
-            this.x = x;
-            this.y = y;
-        }
-
-        @Override
-        public Integer call() throws Exception {
-            return x;
-        }
-    }
-
-    public static class TestObject2 {
-
-        public Object x;
-        public Object y;
-
-        public TestObject2(Object x, Object y) {
-            this.x = x;
-            this.y = y;
-        }
-    }
-
-    @SuppressWarnings("all")
-    public static int testSimpleSnippet(TestObject a) {
-        a.x = 2;
-        staticField = a;
-        return a.x;
-    }
-
-    @Test
-    public void testSimple() {
-        ValueNode result = getReturn("testSimpleSnippet").result();
-        assertTrue(graph.getNodes(LoadFieldNode.class).isEmpty());
-        assertTrue(result.isConstant());
-        assertEquals(2, result.asConstant().asInt());
-    }
-
-    @SuppressWarnings("all")
-    public static int testSimpleConflictSnippet(TestObject a, TestObject b) {
-        a.x = 2;
-        b.x = 3;
-        staticField = a;
-        return a.x;
-    }
-
-    @Test
-    public void testSimpleConflict() {
-        ValueNode result = getReturn("testSimpleConflictSnippet").result();
-        assertFalse(result.isConstant());
-        assertTrue(result instanceof LoadFieldNode);
-    }
-
-    @SuppressWarnings("all")
-    public static int testParamSnippet(TestObject a, int b) {
-        a.x = b;
-        return a.x;
-    }
-
-    @Test
-    public void testParam() {
-        ValueNode result = getReturn("testParamSnippet").result();
-        assertTrue(graph.getNodes(LoadFieldNode.class).isEmpty());
-        assertEquals(graph.getLocal(1), result);
-    }
-
-    @SuppressWarnings("all")
-    public static int testMaterializedSnippet(int a) {
-        TestObject obj = new TestObject(a, 0);
-        staticField = obj;
-        return obj.x;
-    }
-
-    @Test
-    public void testMaterialized() {
-        ValueNode result = getReturn("testMaterializedSnippet").result();
-        assertTrue(graph.getNodes(LoadFieldNode.class).isEmpty());
-        assertEquals(graph.getLocal(0), result);
-    }
-
-    @SuppressWarnings("all")
-    public static int testSimpleLoopSnippet(TestObject obj, int a, int b) {
-        obj.x = a;
-        for (int i = 0; i < 10; i++) {
-            staticField = obj;
-        }
-        return obj.x;
-    }
-
-    @Test
-    public void testSimpleLoop() {
-        ValueNode result = getReturn("testSimpleLoopSnippet").result();
-        assertTrue(graph.getNodes(LoadFieldNode.class).isEmpty());
-        assertEquals(graph.getLocal(1), result);
-    }
-
-    @SuppressWarnings("all")
-    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;
-    }
-
-    @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);
-    }
-
-    @SuppressWarnings("all")
-    public static int testPhiSnippet(TestObject a, int b) {
-        if (b < 0) {
-            a.x = 1;
-        } else {
-            a.x = 2;
-        }
-        return a.x;
-    }
-
-    @Test
-    public void testPhi() {
-        ValueNode result = getReturn("testPhiSnippet").result();
-        assertTrue(graph.getNodes(LoadFieldNode.class).isEmpty());
-        assertTrue(result instanceof PhiNode);
-        PhiNode phi = (PhiNode) result;
-        assertTrue(phi.valueAt(0).isConstant());
-        assertTrue(phi.valueAt(1).isConstant());
-        assertEquals(1, phi.valueAt(0).asConstant().asInt());
-        assertEquals(2, phi.valueAt(1).asConstant().asInt());
-    }
-
-    @SuppressWarnings("all")
-    public static void testSimpleStoreSnippet(TestObject a, int b) {
-        a.x = b;
-        a.x = b;
-    }
-
-    @Test
-    public void testSimpleStore() {
-        processMethod("testSimpleStoreSnippet");
-        assertEquals(1, graph.getNodes().filter(StoreFieldNode.class).count());
-    }
-
-    final ReturnNode getReturn(String snippet) {
-        processMethod(snippet);
-        assertEquals(1, graph.getNodes(ReturnNode.class).count());
-        return graph.getNodes(ReturnNode.class).first();
-    }
-
-    private void processMethod(final String snippet) {
-        graph = parse(snippet);
-        Assumptions assumptions = new Assumptions(false);
-        HighTierContext context = new HighTierContext(runtime(), assumptions, replacements);
-        new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).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	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -164,12 +164,15 @@
                 HighTierContext context = new HighTierContext(runtime(), assumptions, replacements);
                 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);
+                CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
+                canonicalizer.apply(graph, context);
+                new PartialEscapePhase(false, canonicalizer).apply(graph, context);
 
-                new CullFrameStatesPhase().apply(graph);
+                for (MergeNode merge : graph.getNodes(MergeNode.class)) {
+                    merge.setStateAfter(null);
+                }
                 new DeadCodeEliminationPhase().apply(graph);
-                new CanonicalizerPhase().apply(graph, context);
+                canonicalizer.apply(graph, context);
                 return graph;
             }
         });
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -161,7 +161,7 @@
                 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 CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
                 return graph;
             }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.compiler;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.util.*;
 import java.util.concurrent.*;
 
@@ -56,6 +58,8 @@
     // @formatter:off
     @Option(help = "")
     public static final OptionValue<Boolean> VerifyUsageWithEquals = new OptionValue<>(true);
+    @Option(help = "Enable inlining")
+    public static final OptionValue<Boolean> Inline = new OptionValue<>(true);
     // @formatter:on
 
     /**
@@ -70,16 +74,16 @@
      */
     public static CompilationResult compileGraph(final StructuredGraph graph, final CallingConvention cc, final ResolvedJavaMethod installedCodeOwner, final GraalCodeCacheProvider runtime,
                     final Replacements replacements, final Backend backend, final TargetDescription target, final GraphCache cache, final PhasePlan plan, final OptimisticOptimizations optimisticOpts,
-                    final SpeculationLog speculationLog) {
+                    final SpeculationLog speculationLog, final Suites suites) {
         final CompilationResult compilationResult = new CompilationResult();
         Debug.scope("GraalCompiler", new Object[]{graph, runtime}, new Runnable() {
 
             public void run() {
-                final Assumptions assumptions = new Assumptions(GraalOptions.OptAssumptions);
+                final Assumptions assumptions = new Assumptions(OptAssumptions.getValue());
                 final LIR lir = Debug.scope("FrontEnd", new Callable<LIR>() {
 
                     public LIR call() {
-                        return emitHIR(runtime, target, graph, replacements, assumptions, cache, plan, optimisticOpts, speculationLog);
+                        return emitHIR(runtime, target, graph, replacements, assumptions, cache, plan, optimisticOpts, speculationLog, suites);
                     }
                 });
                 final LIRGenerator lirGen = Debug.scope("BackEnd", lir, new Callable<LIRGenerator>() {
@@ -119,7 +123,7 @@
      * @param target
      */
     public static LIR emitHIR(GraalCodeCacheProvider runtime, TargetDescription target, final StructuredGraph graph, Replacements replacements, Assumptions assumptions, GraphCache cache,
-                    PhasePlan plan, OptimisticOptimizations optimisticOpts, final SpeculationLog speculationLog) {
+                    PhasePlan plan, OptimisticOptimizations optimisticOpts, final SpeculationLog speculationLog, final Suites suites) {
 
         if (speculationLog != null) {
             speculationLog.snapshot();
@@ -136,21 +140,22 @@
             new VerifyUsageWithEquals(runtime, Register.class).apply(graph);
         }
 
-        if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!AOTCompilation.getValue());
+        HighTierContext highTierContext = new HighTierContext(runtime, assumptions, replacements);
+
+        if (OptCanonicalizer.getValue()) {
+            canonicalizer.apply(graph, highTierContext);
         }
 
-        HighTierContext highTierContext = new HighTierContext(runtime, assumptions, replacements);
-
-        if (GraalOptions.Inline && !plan.isPhaseDisabled(InliningPhase.class)) {
-            if (GraalOptions.IterativeInlining) {
-                new IterativeInliningPhase(replacements, cache, plan, optimisticOpts, GraalOptions.OptEarlyReadElimination).apply(graph, highTierContext);
+        if (Inline.getValue() && !plan.isPhaseDisabled(InliningPhase.class)) {
+            if (IterativeInlining.getValue()) {
+                new IterativeInliningPhase(cache, plan, optimisticOpts, canonicalizer).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.Instance(runtime, assumptions).apply(graph);
+                if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) {
+                    canonicalizer.apply(graph, highTierContext);
                     new IterativeConditionalEliminationPhase().apply(graph, highTierContext);
                 }
             }
@@ -158,16 +163,18 @@
         TypeProfileProxyNode.cleanFromGraph(graph);
 
         plan.runPhases(PhasePosition.HIGH_LEVEL, graph);
-        Suites.DEFAULT.getHighTier().apply(graph, highTierContext);
+        suites.getHighTier().apply(graph, highTierContext);
 
         MidTierContext midTierContext = new MidTierContext(runtime, assumptions, replacements, target, optimisticOpts);
-        Suites.DEFAULT.getMidTier().apply(graph, midTierContext);
-
-        plan.runPhases(PhasePosition.LOW_LEVEL, graph);
+        suites.getMidTier().apply(graph, midTierContext);
 
         LowTierContext lowTierContext = new LowTierContext(runtime, assumptions, replacements, target);
-        Suites.DEFAULT.getLowTier().apply(graph, lowTierContext);
-        InliningPhase.storeStatisticsAfterLowTier(graph);
+        suites.getLowTier().apply(graph, lowTierContext);
+
+        // we do not want to store statistics about OSR compilations because it may prevent inlining
+        if (!graph.isOSR()) {
+            InliningPhase.storeStatisticsAfterLowTier(graph);
+        }
 
         final SchedulePhase schedule = new SchedulePhase();
         schedule.apply(graph);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Tue Jun 18 10:12:27 2013 +0200
@@ -56,6 +56,16 @@
     public static final OptionValue<Boolean> SummarizePerPhase = new OptionValue<>(false);
     @Option(help = "Send Graal IR to dump handlers on error")
     public static final OptionValue<Boolean> DumpOnError = new OptionValue<>(false);
+    @Option(help = "Enable expensive assertions")
+    public static final OptionValue<Boolean> DetailedAsserts = new StableOptionValue<Boolean>() {
+        @Override
+        protected Boolean initialValue() {
+            boolean enabled = false;
+            // turn detailed assertions on when the general assertions are on (misusing the assert keyword for this)
+            assert (enabled = true) == true;
+            return enabled;
+        }
+    };
     // @formatter:on
 
     private final DebugFilter logFilter;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,10 @@
  */
 package com.oracle.graal.compiler.alloc;
 
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.compiler.GraalDebugConfig.*;
+import static com.oracle.graal.lir.LIRValueUtil.*;
+
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
@@ -29,12 +33,8 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.util.*;
 
-import static com.oracle.graal.api.code.ValueUtil.*;
-import static com.oracle.graal.lir.LIRValueUtil.*;
-
 /**
  * Represents an interval in the {@linkplain LinearScan linear scan register allocator}.
  */
@@ -922,7 +922,7 @@
 
         // do not add use positions for precolored intervals because they are never used
         if (registerPriority != RegisterPriority.None && isVariable(operand)) {
-            if (GraalOptions.DetailedAsserts) {
+            if (DetailedAsserts.getValue()) {
                 for (int i = 0; i < usePosList.size(); i++) {
                     assert pos <= usePosList.usePos(i) : "already added a use-position with lower position";
                     if (i > 0) {
@@ -1026,7 +1026,7 @@
         // split list of use positions
         result.usePosList = usePosList.splitAt(splitPos);
 
-        if (GraalOptions.DetailedAsserts) {
+        if (DetailedAsserts.getValue()) {
             for (int i = 0; i < usePosList.size(); i++) {
                 assert usePosList.usePos(i) < splitPos;
             }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/IntervalWalker.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/IntervalWalker.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,11 +22,12 @@
  */
 package com.oracle.graal.compiler.alloc;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.compiler.alloc.Interval.RegisterBinding;
 import com.oracle.graal.compiler.alloc.Interval.RegisterBindingLists;
 import com.oracle.graal.compiler.alloc.Interval.State;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.phases.*;
 
 /**
  */
@@ -208,7 +209,7 @@
             boolean isActive = currentInterval.from() <= toOpId;
             int opId = isActive ? currentInterval.from() : toOpId;
 
-            if (GraalOptions.TraceLinearScanLevel >= 2 && !TTY.isSuppressed()) {
+            if (TraceLinearScanLevel.getValue() >= 2 && !TTY.isSuppressed()) {
                 if (currentPosition < opId) {
                     TTY.println();
                     TTY.println("walkTo(%d) *", opId);
@@ -239,7 +240,7 @@
     private void intervalMoved(Interval interval, State from, State to) {
         // intervalMoved() is called whenever an interval moves from one interval list to another.
         // In the implementation of this method it is prohibited to move the interval to any list.
-        if (GraalOptions.TraceLinearScanLevel >= 4 && !TTY.isSuppressed()) {
+        if (TraceLinearScanLevel.getValue() >= 4 && !TTY.isSuppressed()) {
             TTY.print(from.toString() + " to " + to.toString());
             TTY.fillTo(23);
             TTY.out().println(interval.logString(allocator));
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Tue Jun 18 10:12:27 2013 +0200
@@ -24,7 +24,9 @@
 
 import static com.oracle.graal.api.code.CodeUtil.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.compiler.GraalDebugConfig.*;
 import static com.oracle.graal.lir.LIRValueUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 
@@ -44,7 +46,6 @@
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.nodes.cfg.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.util.*;
 
 /**
@@ -501,7 +502,7 @@
 
     // called once before assignment of register numbers
     void eliminateSpillMoves() {
-        if (GraalOptions.TraceLinearScanLevel >= 3) {
+        if (TraceLinearScanLevel.getValue() >= 3) {
             TTY.println(" Eliminating unnecessary spill moves");
         }
 
@@ -509,7 +510,7 @@
         // the list is sorted by Interval.spillDefinitionPos
         Interval interval;
         interval = createUnhandledLists(mustStoreAtDefinition, null).first;
-        if (GraalOptions.DetailedAsserts) {
+        if (DetailedAsserts.getValue()) {
             checkIntervals(interval);
         }
 
@@ -535,7 +536,7 @@
                     if (!isRegister(curInterval.location()) && curInterval.alwaysInMemory()) {
                         // move target is a stack slot that is always correct, so eliminate
                         // instruction
-                        if (GraalOptions.TraceLinearScanLevel >= 4) {
+                        if (TraceLinearScanLevel.getValue() >= 4) {
                             TTY.println("eliminating move from interval %d to %d", operandNumber(move.getInput()), operandNumber(move.getResult()));
                         }
                         instructions.set(j, null); // null-instructions are deleted by assignRegNum
@@ -561,7 +562,7 @@
 
                         insertionBuffer.append(j + 1, ir.spillMoveFactory.createMove(toLocation, fromLocation));
 
-                        if (GraalOptions.TraceLinearScanLevel >= 4) {
+                        if (TraceLinearScanLevel.getValue() >= 4) {
                             StackSlot slot = interval.spillSlot();
                             TTY.println("inserting move after definition of interval %d to stack slot %s at opId %d", interval.operandNumber, slot, opId);
                         }
@@ -593,7 +594,7 @@
             assert temp.spillDefinitionPos() >= temp.from() : "invalid order";
             assert temp.spillDefinitionPos() <= temp.from() + 2 : "only intervals defined once at their start-pos can be optimized";
 
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("interval %d (from %d to %d) must be stored at %d", temp.operandNumber, temp.from(), temp.to(), temp.spillDefinitionPos());
             }
 
@@ -658,7 +659,7 @@
         assert index == numInstructions : "must match";
         assert (index << 1) == opId : "must match: " + (index << 1);
 
-        if (GraalOptions.DetailedAsserts) {
+        if (DetailedAsserts.getValue()) {
             for (int i = 0; i < variables.size(); i++) {
                 assert variables.get(i) != null && variables.get(i).index == i;
             }
@@ -696,7 +697,7 @@
                             int operandNum = operandNumber(operand);
                             if (!liveKill.get(operandNum)) {
                                 liveGen.set(operandNum);
-                                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                                if (TraceLinearScanLevel.getValue() >= 4) {
                                     TTY.println("  Setting liveGen for operand %d at instruction %d", operandNum, op.id());
                                 }
                             }
@@ -705,7 +706,7 @@
                             }
                         }
 
-                        if (GraalOptions.DetailedAsserts) {
+                        if (DetailedAsserts.getValue()) {
                             verifyInput(block, liveKill, operand);
                         }
                         return operand;
@@ -718,7 +719,7 @@
                         int operandNum = operandNumber(operand);
                         if (!liveKill.get(operandNum)) {
                             liveGen.set(operandNum);
-                            if (GraalOptions.TraceLinearScanLevel >= 4) {
+                            if (TraceLinearScanLevel.getValue() >= 4) {
                                 TTY.println("  Setting liveGen for LIR opId %d, operand %d because of state for %s", op.id(), operandNum, op);
                             }
                         }
@@ -737,7 +738,7 @@
                             }
                         }
 
-                        if (GraalOptions.DetailedAsserts) {
+                        if (DetailedAsserts.getValue()) {
                             // fixed intervals are never live at block boundaries, so
                             // they need not be processed in live sets
                             // process them only in debug mode so that this can be checked
@@ -761,7 +762,7 @@
             blockData.get(block).liveIn = new BitSet(liveSize);
             blockData.get(block).liveOut = new BitSet(liveSize);
 
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("liveGen  B%d %s", block.getId(), blockData.get(block).liveGen);
                 TTY.println("liveKill B%d %s", block.getId(), blockData.get(block).liveKill);
             }
@@ -850,7 +851,7 @@
                     liveIn.or(blockData.get(block).liveGen);
                 }
 
-                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                if (TraceLinearScanLevel.getValue() >= 4) {
                     traceLiveness(changeOccurredInBlock, iterationCount, block);
                 }
             }
@@ -861,7 +862,7 @@
             }
         } while (changeOccurred);
 
-        if (GraalOptions.DetailedAsserts) {
+        if (DetailedAsserts.getValue()) {
             verifyLiveness();
         }
 
@@ -869,7 +870,7 @@
         Block startBlock = ir.cfg.getStartBlock();
         BitSet liveInArgs = new BitSet(blockData.get(startBlock).liveIn.size());
         if (!blockData.get(startBlock).liveIn.equals(liveInArgs)) {
-            if (GraalOptions.DetailedAsserts) {
+            if (DetailedAsserts.getValue()) {
                 reportFailure(numBlocks);
             }
 
@@ -970,7 +971,7 @@
         if (!isProcessed(operand)) {
             return;
         }
-        if (GraalOptions.TraceLinearScanLevel >= 2 && kind == null) {
+        if (TraceLinearScanLevel.getValue() >= 2 && kind == null) {
             TTY.println(" use %s from %d to %d (%s)", operand, from, to, registerPriority.name());
         }
 
@@ -989,7 +990,7 @@
         if (!isProcessed(operand)) {
             return;
         }
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println(" temp %s tempPos %d (%s)", operand, tempPos, RegisterPriority.MustHaveRegister.name());
         }
 
@@ -1010,7 +1011,7 @@
         if (!isProcessed(operand)) {
             return;
         }
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println(" def %s defPos %d (%s)", operand, defPos, registerPriority.name());
         }
 
@@ -1031,7 +1032,7 @@
             // also add register priority for dead intervals
             interval.addRange(defPos, defPos + 1);
             interval.addUsePos(defPos, registerPriority);
-            if (GraalOptions.TraceLinearScanLevel >= 2) {
+            if (TraceLinearScanLevel.getValue() >= 2) {
                 TTY.println("Warning: def of operand %s at %d occurs without use", operand, defPos);
             }
         }
@@ -1087,12 +1088,12 @@
             MoveOp move = (MoveOp) op;
             if (optimizeMethodArgument(move.getInput())) {
                 StackSlot slot = asStackSlot(move.getInput());
-                if (GraalOptions.DetailedAsserts) {
+                if (DetailedAsserts.getValue()) {
                     assert op.id() > 0 : "invalid id";
                     assert blockForId(op.id()).getPredecessorCount() == 0 : "move from stack must be in first block";
                     assert isVariable(move.getResult()) : "result of move must be a variable";
 
-                    if (GraalOptions.TraceLinearScanLevel >= 4) {
+                    if (TraceLinearScanLevel.getValue() >= 4) {
                         TTY.println("found move from stack slot %s to %s", slot, move.getResult());
                     }
                 }
@@ -1122,7 +1123,7 @@
                             from.setLocationHint(to);
                         }
 
-                        if (GraalOptions.TraceLinearScanLevel >= 4) {
+                        if (TraceLinearScanLevel.getValue() >= 4) {
                             TTY.println("operation at opId %d: added hint from interval %d to %d", op.id(), from.operandNumber, to.operandNumber);
                         }
                         return registerHint;
@@ -1155,7 +1156,7 @@
             for (int operandNum = live.nextSetBit(0); operandNum >= 0; operandNum = live.nextSetBit(operandNum + 1)) {
                 assert live.get(operandNum) : "should not stop here otherwise";
                 AllocatableValue operand = operandFor(operandNum);
-                if (GraalOptions.TraceLinearScanLevel >= 2) {
+                if (TraceLinearScanLevel.getValue() >= 2) {
                     TTY.println("live in %s to %d", operand, blockTo + 2);
                 }
 
@@ -1185,7 +1186,7 @@
                             addTemp(r.asValue(), opId, RegisterPriority.None, Kind.Illegal);
                         }
                     }
-                    if (GraalOptions.TraceLinearScanLevel >= 4) {
+                    if (TraceLinearScanLevel.getValue() >= 4) {
                         TTY.println("operation destroys all caller-save registers");
                     }
                 }
@@ -1436,7 +1437,7 @@
         Interval result = interval.getSplitChildAtOpId(opId, mode, this);
 
         if (result != null) {
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("Split child at pos " + opId + " of interval " + interval.toString() + " is " + result.toString());
             }
             return result;
@@ -1490,7 +1491,7 @@
 
     void resolveFindInsertPos(Block fromBlock, Block toBlock, MoveResolver moveResolver) {
         if (fromBlock.getSuccessorCount() <= 1) {
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("inserting moves at end of fromBlock B%d", fromBlock.getId());
             }
 
@@ -1504,11 +1505,11 @@
             }
 
         } else {
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("inserting moves at beginning of toBlock B%d", toBlock.getId());
             }
 
-            if (GraalOptions.DetailedAsserts) {
+            if (DetailedAsserts.getValue()) {
                 assert ir.lir(fromBlock).get(0) instanceof StandardOp.LabelOp : "block does not start with a label";
 
                 // because the number of predecessor edges matches the number of
@@ -1549,7 +1550,7 @@
 
                     // prevent optimization of two consecutive blocks
                     if (!blockCompleted.get(pred.getLinearScanNumber()) && !blockCompleted.get(sux.getLinearScanNumber())) {
-                        if (GraalOptions.TraceLinearScanLevel >= 3) {
+                        if (TraceLinearScanLevel.getValue() >= 3) {
                             TTY.println(" optimizing empty block B%d (pred: B%d, sux: B%d)", block.getId(), pred.getId(), sux.getId());
                         }
                         blockCompleted.set(block.getLinearScanNumber());
@@ -1576,7 +1577,7 @@
                     // check for duplicate edges between the same blocks (can happen with switch
                     // blocks)
                     if (!alreadyResolved.get(toBlock.getLinearScanNumber())) {
-                        if (GraalOptions.TraceLinearScanLevel >= 3) {
+                        if (TraceLinearScanLevel.getValue() >= 3) {
                             TTY.println(" processing edge between B%d and B%d", fromBlock.getId(), toBlock.getId());
                         }
                         alreadyResolved.set(toBlock.getLinearScanNumber());
@@ -1614,7 +1615,7 @@
         assert interval != null : "interval must exist";
 
         if (opId != -1) {
-            if (GraalOptions.DetailedAsserts) {
+            if (DetailedAsserts.getValue()) {
                 Block block = blockForId(opId);
                 if (block.getSuccessorCount() <= 1 && opId == getLastLirInstructionId(block)) {
                     // check if spill moves could have been appended at the end of this block, but
@@ -1655,7 +1656,7 @@
     }
 
     void computeOopMap(IntervalWalker iw, LIRInstruction op, BitSet registerRefMap, BitSet frameRefMap) {
-        if (GraalOptions.TraceLinearScanLevel >= 3) {
+        if (TraceLinearScanLevel.getValue() >= 3) {
             TTY.println("creating oop map at opId %d", op.id());
         }
 
@@ -1839,14 +1840,14 @@
 
                 sortIntervalsAfterAllocation();
 
-                if (GraalOptions.DetailedAsserts) {
+                if (DetailedAsserts.getValue()) {
                     verify();
                 }
 
                 eliminateSpillMoves();
                 assignLocations();
 
-                if (GraalOptions.DetailedAsserts) {
+                if (DetailedAsserts.getValue()) {
                     verifyIntervals();
                 }
             }
@@ -1864,7 +1865,7 @@
     }
 
     void printIntervals(String label) {
-        if (GraalOptions.TraceLinearScanLevel >= 1) {
+        if (TraceLinearScanLevel.getValue() >= 1) {
             int i;
             TTY.println();
             TTY.println(label);
@@ -1894,27 +1895,27 @@
 
     boolean verify() {
         // (check that all intervals have a correct register and that no registers are overwritten)
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println(" verifying intervals *");
         }
         verifyIntervals();
 
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println(" verifying that no oops are in fixed intervals *");
         }
         // verifyNoOopsInFixedIntervals();
 
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println(" verifying that unpinned constants are not alive across block boundaries");
         }
         verifyConstants();
 
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println(" verifying register allocation *");
         }
         verifyRegisters();
 
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println(" no errors found *");
         }
 
@@ -1986,7 +1987,7 @@
                 Value l1 = i1.location();
                 Value l2 = i2.location();
                 if (i1.intersects(i2) && (l1.equals(l2))) {
-                    if (GraalOptions.DetailedAsserts) {
+                    if (DetailedAsserts.getValue()) {
                         TTY.println("Intervals %d and %d overlap and have the same register assigned", i1.operandNumber, i2.operandNumber);
                         TTY.println(i1.logString(this));
                         TTY.println(i2.logString(this));
@@ -2066,7 +2067,7 @@
 
             // visit all operands where the liveAtEdge bit is set
             for (int operandNum = liveAtEdge.nextSetBit(0); operandNum >= 0; operandNum = liveAtEdge.nextSetBit(operandNum + 1)) {
-                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                if (TraceLinearScanLevel.getValue() >= 4) {
                     TTY.println("checking interval %d of block B%d", operandNum, block.getId());
                 }
                 Value operand = operandFor(operandNum);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Tue Jun 18 10:12:27 2013 +0200
@@ -25,6 +25,7 @@
 import static com.oracle.graal.api.code.CodeUtil.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.lir.LIRValueUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 
@@ -38,7 +39,6 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.nodes.cfg.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.util.*;
 
 /**
@@ -297,7 +297,7 @@
         int optimalSplitPos = -1;
         if (minSplitPos == maxSplitPos) {
             // trivial case, no optimization of split position possible
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("      min-pos and max-pos are equal, no optimization possible");
             }
             optimalSplitPos = minSplitPos;
@@ -321,7 +321,7 @@
             assert minBlock.getLinearScanNumber() <= maxBlock.getLinearScanNumber() : "invalid order";
             if (minBlock == maxBlock) {
                 // split position cannot be moved to block boundary : so split as late as possible
-                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                if (TraceLinearScanLevel.getValue() >= 4) {
                     TTY.println("      cannot move split pos to block boundary because minPos and maxPos are in same block");
                 }
                 optimalSplitPos = maxSplitPos;
@@ -333,14 +333,14 @@
                     // as mustHaveRegister) with a hole before each definition. When the register is
                     // needed
                     // for the second definition : an earlier reloading is unnecessary.
-                    if (GraalOptions.TraceLinearScanLevel >= 4) {
+                    if (TraceLinearScanLevel.getValue() >= 4) {
                         TTY.println("      interval has hole just before maxSplitPos, so splitting at maxSplitPos");
                     }
                     optimalSplitPos = maxSplitPos;
 
                 } else {
                     // seach optimal block boundary between minSplitPos and maxSplitPos
-                    if (GraalOptions.TraceLinearScanLevel >= 4) {
+                    if (TraceLinearScanLevel.getValue() >= 4) {
                         TTY.println("      moving split pos to optimal block boundary between block B%d and B%d", minBlock.getId(), maxBlock.getId());
                     }
 
@@ -349,7 +349,7 @@
                         // max-position :
                         // then split before this loop
                         int loopEndPos = interval.nextUsageExact(RegisterPriority.LiveAtLoopEnd, allocator.getLastLirInstructionId(minBlock) + 2);
-                        if (GraalOptions.TraceLinearScanLevel >= 4) {
+                        if (TraceLinearScanLevel.getValue() >= 4) {
                             TTY.println("      loop optimization: loop end found at pos %d", loopEndPos);
                         }
 
@@ -364,7 +364,7 @@
                             // of the interval (normally, only mustHaveRegister causes a reloading)
                             Block loopBlock = allocator.blockForId(loopEndPos);
 
-                            if (GraalOptions.TraceLinearScanLevel >= 4) {
+                            if (TraceLinearScanLevel.getValue() >= 4) {
                                 TTY.println("      interval is used in loop that ends in block B%d, so trying to move maxBlock back from B%d to B%d", loopBlock.getId(), maxBlock.getId(),
                                                 loopBlock.getId());
                             }
@@ -373,11 +373,11 @@
                             optimalSplitPos = findOptimalSplitPos(minBlock, loopBlock, allocator.getLastLirInstructionId(loopBlock) + 2);
                             if (optimalSplitPos == allocator.getLastLirInstructionId(loopBlock) + 2) {
                                 optimalSplitPos = -1;
-                                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                                if (TraceLinearScanLevel.getValue() >= 4) {
                                     TTY.println("      loop optimization not necessary");
                                 }
                             } else {
-                                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                                if (TraceLinearScanLevel.getValue() >= 4) {
                                     TTY.println("      loop optimization successful");
                                 }
                             }
@@ -391,7 +391,7 @@
                 }
             }
         }
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.println("      optimal split position: %d", optimalSplitPos);
         }
 
@@ -403,13 +403,13 @@
     // 1) the left part has already a location assigned
     // 2) the right part is sorted into to the unhandled-list
     void splitBeforeUsage(Interval interval, int minSplitPos, int maxSplitPos) {
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println("----- splitting interval: ");
         }
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.println(interval.logString(allocator));
         }
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println("      between %d and %d", minSplitPos, maxSplitPos);
         }
 
@@ -427,7 +427,7 @@
         if (optimalSplitPos == interval.to() && interval.nextUsage(RegisterPriority.MustHaveRegister, minSplitPos) == Integer.MAX_VALUE) {
             // the split position would be just before the end of the interval
             // . no split at all necessary
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("      no split necessary because optimal split position is at end of interval");
             }
             return;
@@ -442,7 +442,7 @@
             optimalSplitPos = (optimalSplitPos - 1) | 1;
         }
 
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.println("      splitting at position %d", optimalSplitPos);
         }
         assert allocator.isBlockBegin(optimalSplitPos) || (optimalSplitPos % 2 == 1) : "split pos must be odd when not on block boundary";
@@ -455,10 +455,10 @@
         assert splitPart.from() >= currentInterval.currentFrom() : "cannot append new interval before current walk position";
         unhandledLists.addToListSortedByStartAndUsePositions(RegisterBinding.Any, splitPart);
 
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println("      split interval in two parts (insertMoveWhenActivated: %b)", moveNecessary);
         }
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.print("      ");
             TTY.println(interval.logString(allocator));
             TTY.print("      ");
@@ -476,7 +476,7 @@
         int maxSplitPos = currentPosition;
         int minSplitPos = Math.max(interval.previousUsage(RegisterPriority.ShouldHaveRegister, maxSplitPos) + 1, interval.from());
 
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.print("----- splitting and spilling interval: ");
             TTY.println(interval.logString(allocator));
             TTY.println("      between %d and %d", minSplitPos, maxSplitPos);
@@ -490,7 +490,7 @@
 
         if (minSplitPos == interval.from()) {
             // the whole interval is never used, so spill it entirely to memory
-            if (GraalOptions.TraceLinearScanLevel >= 2) {
+            if (TraceLinearScanLevel.getValue() >= 2) {
                 TTY.println("      spilling entire interval because split pos is at beginning of interval");
                 TTY.println("      use positions: " + interval.usePosList().size());
             }
@@ -509,7 +509,7 @@
                 if (isRegister(parent.location())) {
                     if (parent.firstUsage(RegisterPriority.ShouldHaveRegister) == Integer.MAX_VALUE) {
                         // parent is never used, so kick it out of its assigned register
-                        if (GraalOptions.TraceLinearScanLevel >= 4) {
+                        if (TraceLinearScanLevel.getValue() >= 4) {
                             TTY.println("      kicking out interval %d out of its register because it is never used", parent.operandNumber);
                         }
                         allocator.assignSpillSlot(parent);
@@ -534,7 +534,7 @@
                 optimalSplitPos = (optimalSplitPos - 1) | 1;
             }
 
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("      splitting at position %d", optimalSplitPos);
             }
             assert allocator.isBlockBegin(optimalSplitPos) || (optimalSplitPos % 2 == 1) : "split pos must be odd when not on block boundary";
@@ -545,7 +545,7 @@
             allocator.changeSpillState(spilledPart, optimalSplitPos);
 
             if (!allocator.isBlockBegin(optimalSplitPos)) {
-                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                if (TraceLinearScanLevel.getValue() >= 4) {
                     TTY.println("      inserting move from interval %d to %d", interval.operandNumber, spilledPart.operandNumber);
                 }
                 insertMove(optimalSplitPos, interval, spilledPart);
@@ -555,7 +555,7 @@
             assert spilledPart.currentSplitChild() == interval : "overwriting wrong currentSplitChild";
             spilledPart.makeCurrentSplitChild();
 
-            if (GraalOptions.TraceLinearScanLevel >= 2) {
+            if (TraceLinearScanLevel.getValue() >= 2) {
                 TTY.println("      split interval in two parts");
                 TTY.print("      ");
                 TTY.println(interval.logString(allocator));
@@ -604,7 +604,7 @@
     }
 
     boolean allocFreeRegister(Interval interval) {
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println("trying to find free register for " + interval.logString(allocator));
         }
 
@@ -620,7 +620,7 @@
         // (either as a fixed register or a normal allocated register in the past)
         // only intervals overlapping with cur are processed, non-overlapping invervals can be
         // ignored safely
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.println("      state of registers:");
             for (Register register : availableRegs) {
                 int i = register.number;
@@ -632,7 +632,7 @@
         Interval locationHint = interval.locationHint(true);
         if (locationHint != null && locationHint.location() != null && isRegister(locationHint.location())) {
             hint = asRegister(locationHint.location());
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("      hint register %d from interval %s", hint.number, locationHint.logString(allocator));
             }
         }
@@ -676,7 +676,7 @@
 
         splitPos = usePos[reg.number];
         interval.assignLocation(reg.asValue(interval.kind()));
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println("selected register %d", reg.number);
         }
 
@@ -702,7 +702,7 @@
 
     // Split an Interval and spill it to memory so that cur can be placed in a register
     void allocLockedRegister(Interval interval) {
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println("need to split and spill to get register for " + interval.logString(allocator));
         }
 
@@ -715,7 +715,7 @@
         spillCollectActiveAny();
         spillCollectInactiveAny(interval);
 
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.println("      state of registers:");
             for (Register reg : availableRegs) {
                 int i = reg.number;
@@ -748,7 +748,7 @@
 
         if (reg == null || usePos[reg.number] <= firstUsage) {
             // the first use of cur is later than the spilling position -> spill cur
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("able to spill current interval. firstUsage(register): %d, usePos: %d", firstUsage, reg == null ? 0 : usePos[reg.number]);
             }
 
@@ -767,7 +767,7 @@
 
         int splitPos = blockPos[reg.number];
 
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.println("decided to use register %d", reg.number);
         }
         assert splitPos > 0 : "invalid splitPos";
@@ -796,7 +796,7 @@
             if (isOdd(pos)) {
                 // the current instruction is a call that blocks all registers
                 if (pos < allocator.maxOpId() && allocator.hasCall(pos + 1) && interval.to() > pos + 1) {
-                    if (GraalOptions.TraceLinearScanLevel >= 4) {
+                    if (TraceLinearScanLevel.getValue() >= 4) {
                         TTY.println("      free register cannot be available because all registers blocked by following call");
                     }
 
@@ -888,11 +888,11 @@
         Interval interval = currentInterval;
         boolean result = true;
 
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println("+++++ activating interval " + interval.logString(allocator));
         }
 
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.println("      splitParent: %s, insertMoveWhenActivated: %b", interval.splitParent().operandNumber, interval.insertMoveWhenActivated());
         }
 
@@ -901,7 +901,7 @@
             // activating an interval that has a stack slot assigned . split it at first use
             // position
             // used for method parameters
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("      interval has spill slot assigned (method parameter) . split it before first use");
             }
             splitStackInterval(interval);
@@ -911,7 +911,7 @@
             if (interval.location() == null) {
                 // interval has not assigned register . normal allocation
                 // (this is the normal case for most intervals)
-                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                if (TraceLinearScanLevel.getValue() >= 4) {
                     TTY.println("      normal allocation of register");
                 }
 
@@ -937,7 +937,7 @@
             assert interval.isSplitChild();
             assert interval.currentSplitChild() != null;
             assert !interval.currentSplitChild().operand.equals(operand) : "cannot insert move between same interval";
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println("Inserting move from interval %d to %d because insertMoveWhenActivated is set", interval.currentSplitChild().operandNumber, interval.operandNumber);
             }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/MoveResolver.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/MoveResolver.java	Tue Jun 18 10:12:27 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.compiler.alloc;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 
@@ -30,7 +31,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.phases.*;
 
 /**
  */
@@ -201,7 +201,7 @@
 
         insertionBuffer.append(insertIdx, allocator.ir.spillMoveFactory.createMove(toOpr, fromOpr));
 
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.println("MoveResolver: inserted move from %d (%s) to %d (%s)", fromInterval.operandNumber, fromInterval.location(), toInterval.operandNumber, toInterval.location());
         }
     }
@@ -213,7 +213,7 @@
         AllocatableValue toOpr = toInterval.operand;
         insertionBuffer.append(insertIdx, allocator.ir.spillMoveFactory.createMove(toOpr, fromOpr));
 
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.print("MoveResolver: inserted move from constant %s to %d (%s)", fromOpr, toInterval.operandNumber, toInterval.location());
         }
     }
@@ -285,7 +285,7 @@
                 }
                 spillInterval.assignLocation(spillSlot);
 
-                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                if (TraceLinearScanLevel.getValue() >= 4) {
                     TTY.println("created new Interval %s for spilling", spillInterval.operand);
                 }
 
@@ -327,7 +327,7 @@
     }
 
     void addMapping(Interval fromInterval, Interval toInterval) {
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.println("MoveResolver: adding mapping from interval %d (%s) to interval %d (%s)", fromInterval.operandNumber, fromInterval.location(), toInterval.operandNumber, toInterval.location());
         }
 
@@ -339,7 +339,7 @@
     }
 
     void addMapping(Value fromOpr, Interval toInterval) {
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.println("MoveResolver: adding mapping from %s to %d (%s)", fromOpr, toInterval.operandNumber, toInterval.location());
         }
         assert isConstant(fromOpr) : "only for constants";
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java	Tue Jun 18 10:12:27 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.compiler.alloc;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 
@@ -33,7 +34,6 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.LIRInstruction.*;
 import com.oracle.graal.nodes.cfg.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.util.*;
 
 /**
@@ -92,7 +92,7 @@
     }
 
     private void processBlock(Block block) {
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
+        if (TraceLinearScanLevel.getValue() >= 2) {
             TTY.println();
             TTY.println("processBlock B%d", block.getId());
         }
@@ -100,7 +100,7 @@
         // must copy state because it is modified
         Interval[] inputState = copy(stateForBlock(block));
 
-        if (GraalOptions.TraceLinearScanLevel >= 4) {
+        if (TraceLinearScanLevel.getValue() >= 4) {
             TTY.println("Input-State of intervals:");
             TTY.print("    ");
             for (int i = 0; i < stateSize(); i++) {
@@ -142,7 +142,7 @@
                         savedStateCorrect = false;
                         savedState[i] = null;
 
-                        if (GraalOptions.TraceLinearScanLevel >= 4) {
+                        if (TraceLinearScanLevel.getValue() >= 4) {
                             TTY.println("processSuccessor B%d: invalidating slot %d", block.getId(), i);
                         }
                     }
@@ -151,12 +151,12 @@
 
             if (savedStateCorrect) {
                 // already processed block with correct inputState
-                if (GraalOptions.TraceLinearScanLevel >= 2) {
+                if (TraceLinearScanLevel.getValue() >= 2) {
                     TTY.println("processSuccessor B%d: previous visit already correct", block.getId());
                 }
             } else {
                 // must re-visit this block
-                if (GraalOptions.TraceLinearScanLevel >= 2) {
+                if (TraceLinearScanLevel.getValue() >= 2) {
                     TTY.println("processSuccessor B%d: must re-visit because input state changed", block.getId());
                 }
                 addToWorkList(block);
@@ -164,7 +164,7 @@
 
         } else {
             // block was not processed before, so set initial inputState
-            if (GraalOptions.TraceLinearScanLevel >= 2) {
+            if (TraceLinearScanLevel.getValue() >= 2) {
                 TTY.println("processSuccessor B%d: initial visit", block.getId());
             }
 
@@ -182,11 +182,11 @@
             Register reg = asRegister(location);
             int regNum = reg.number;
             if (interval != null) {
-                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                if (TraceLinearScanLevel.getValue() >= 4) {
                     TTY.println("        %s = %s", reg, interval.operand);
                 }
             } else if (inputState[regNum] != null) {
-                if (GraalOptions.TraceLinearScanLevel >= 4) {
+                if (TraceLinearScanLevel.getValue() >= 4) {
                     TTY.println("        %s = null", reg);
                 }
             }
@@ -209,7 +209,7 @@
         for (int i = 0; i < ops.size(); i++) {
             final LIRInstruction op = ops.get(i);
 
-            if (GraalOptions.TraceLinearScanLevel >= 4) {
+            if (TraceLinearScanLevel.getValue() >= 4) {
                 TTY.println(op.toStringWithIdPrefix());
             }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Tue Jun 18 10:12:27 2013 +0200
@@ -26,6 +26,7 @@
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.api.meta.Value.*;
 import static com.oracle.graal.lir.LIRValueUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 import java.util.Map.Entry;
@@ -46,7 +47,6 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.virtual.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.util.*;
 
 /**
@@ -68,12 +68,6 @@
     protected Block currentBlock;
     private ValueNode currentInstruction;
     private ValueNode lastInstructionPrinted; // Debugging only
-    private FrameState lastState;
-
-    /**
-     * Mapping from blocks to the last encountered frame state at the end of the block.
-     */
-    private final BlockMap<FrameState> blockLastState;
 
     /**
      * Checks whether the supplied constant can be used without loading it into a register for store
@@ -100,7 +94,6 @@
         this.nodeOperands = graph.createNodeMap();
         this.lir = lir;
         this.debugInfoBuilder = createDebugInfoBuilder(nodeOperands);
-        this.blockLastState = new BlockMap<>(lir.cfg);
     }
 
     @SuppressWarnings("hiding")
@@ -259,7 +252,7 @@
     }
 
     public void append(LIRInstruction op) {
-        if (GraalOptions.PrintIRWithLIR && !TTY.isSuppressed()) {
+        if (PrintIRWithLIR.getValue() && !TTY.isSuppressed()) {
             if (currentInstruction != null && lastInstructionPrinted != currentInstruction) {
                 lastInstructionPrinted = currentInstruction;
                 InstructionPrinter ip = new InstructionPrinter(TTY.out());
@@ -273,7 +266,7 @@
     }
 
     public void doBlock(Block block) {
-        if (GraalOptions.PrintIRWithLIR) {
+        if (PrintIRWithLIR.getValue()) {
             TTY.print(block.toString());
         }
 
@@ -284,60 +277,23 @@
 
         append(new LabelOp(new Label(), block.isAligned()));
 
-        if (GraalOptions.TraceLIRGeneratorLevel >= 1) {
+        if (TraceLIRGeneratorLevel.getValue() >= 1) {
             TTY.println("BEGIN Generating LIR for block B" + block.getId());
         }
 
         if (block == lir.cfg.getStartBlock()) {
             assert block.getPredecessorCount() == 0;
             emitPrologue();
-
         } else {
             assert block.getPredecessorCount() > 0;
-            FrameState fs = null;
-
-            for (Block pred : block.getPredecessors()) {
-                if (fs == null) {
-                    fs = blockLastState.get(pred);
-                } else {
-                    if (blockLastState.get(pred) == null) {
-                        // Only a back edge can have a null state for its enclosing block.
-                        assert pred.getEndNode() instanceof LoopEndNode;
-
-                        if (block.getBeginNode().stateAfter() == null) {
-                            // We'll assert later that the begin and end of a framestate-less loop
-                            // share the frame state that flowed into the loop
-                            blockLastState.put(pred, fs);
-                        }
-                    } else if (fs != blockLastState.get(pred)) {
-                        fs = null;
-                        break;
-                    }
-                }
-            }
-            if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
-                if (fs == null) {
-                    TTY.println("STATE RESET");
-                } else {
-                    TTY.println("STATE CHANGE (singlePred)");
-                    if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
-                        TTY.println(fs.toString(Node.Verbosity.Debugger));
-                    }
-                }
-            }
-            lastState = fs;
         }
 
         List<ScheduledNode> nodes = lir.nodesFor(block);
         for (int i = 0; i < nodes.size(); i++) {
             Node instr = nodes.get(i);
-            if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
+            if (TraceLIRGeneratorLevel.getValue() >= 3) {
                 TTY.println("LIRGen for " + instr);
             }
-            FrameState stateAfter = null;
-            if (instr instanceof StateSplit && !(instr instanceof InfopointNode)) {
-                stateAfter = ((StateSplit) instr).stateAfter();
-            }
             if (instr instanceof ValueNode) {
                 ValueNode valueNode = (ValueNode) instr;
                 if (operand(valueNode) == null) {
@@ -355,16 +311,6 @@
                     // before by other instructions.
                 }
             }
-            if (stateAfter != null) {
-                lastState = stateAfter;
-                assert checkStateReady(lastState);
-                if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
-                    TTY.println("STATE CHANGE");
-                    if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
-                        TTY.println(stateAfter.toString(Node.Verbosity.Debugger));
-                    }
-                }
-            }
         }
         if (block.getSuccessorCount() >= 1 && !endsWithJump(block)) {
             NodeClassIterable successors = block.getEndNode().successors();
@@ -373,37 +319,19 @@
             emitJump(getLIRBlock((FixedNode) successors.first()));
         }
 
-        if (GraalOptions.TraceLIRGeneratorLevel >= 1) {
+        if (TraceLIRGeneratorLevel.getValue() >= 1) {
             TTY.println("END Generating LIR for block B" + block.getId());
         }
 
-        // Check that the begin and end of a framestate-less loop
-        // share the frame state that flowed into the loop
-        assert blockLastState.get(block) == null || blockLastState.get(block) == lastState;
-
-        blockLastState.put(block, lastState);
         currentBlock = null;
 
-        if (GraalOptions.PrintIRWithLIR) {
+        if (PrintIRWithLIR.getValue()) {
             TTY.println();
         }
     }
 
     protected abstract boolean peephole(ValueNode valueNode);
 
-    private boolean checkStateReady(FrameState state) {
-        FrameState fs = state;
-        while (fs != null) {
-            for (ValueNode v : fs.values()) {
-                if (v != null && !(v instanceof VirtualObjectNode)) {
-                    assert operand(v) != null : "Value " + v + " in " + fs + " is not ready!";
-                }
-            }
-            fs = fs.outerFrameState();
-        }
-        return true;
-    }
-
     private boolean endsWithJump(Block block) {
         List<LIRInstruction> instructions = lir.lir(block);
         if (instructions.size() == 0) {
@@ -414,7 +342,7 @@
     }
 
     private void doRoot(ValueNode instr) {
-        if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
+        if (TraceLIRGeneratorLevel.getValue() >= 2) {
             TTY.println("Emitting LIR for instruction " + instr);
         }
         currentInstruction = instr;
@@ -484,7 +412,7 @@
     }
 
     private void moveToPhi(MergeNode merge, AbstractEndNode pred) {
-        if (GraalOptions.TraceLIRGeneratorLevel >= 1) {
+        if (TraceLIRGeneratorLevel.getValue() >= 1) {
             TTY.println("MOVE TO PHI from " + pred + " to " + merge);
         }
         PhiResolver resolver = new PhiResolver(this);
@@ -660,7 +588,7 @@
 
     @Override
     public Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args) {
-        LIRFrameState state = info != null ? state(info) : null;
+        LIRFrameState state = !linkage.canDeoptimize() ? null : stateFor(info.getDeoptimizationState(), info.getDeoptimizationReason());
 
         // move the arguments into the correct location
         CallingConvention linkageCc = linkage.getCallingConvention();
@@ -707,7 +635,7 @@
                 int switchRangeCount = switchRangeCount(x);
                 if (switchRangeCount == 0) {
                     emitJump(getLIRBlock(x.defaultSuccessor()));
-                } else if (switchRangeCount >= GraalOptions.MinimumJumpTableSize && keyCount / (double) valueRange >= GraalOptions.MinTableSwitchDensity) {
+                } else if (switchRangeCount >= MinimumJumpTableSize.getValue() && keyCount / (double) valueRange >= MinTableSwitchDensity.getValue()) {
                     int minValue = x.keyAt(0).asInt();
                     assert valueRange < Integer.MAX_VALUE;
                     LabelRef[] targets = new LabelRef[(int) valueRange];
@@ -718,7 +646,7 @@
                         targets[x.keyAt(i).asInt() - minValue] = getLIRBlock(x.keySuccessor(i));
                     }
                     emitTableSwitch(minValue, defaultTarget, targets, value);
-                } else if (keyCount / switchRangeCount >= GraalOptions.RangeTestsSwitchDensity) {
+                } else if (keyCount / switchRangeCount >= RangeTestsSwitchDensity.getValue()) {
                     emitSwitchRanges(x, switchRangeCount, value, defaultTarget);
                 } else {
                     emitSequentialSwitch(x, value, defaultTarget);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.compiler.phases;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.phases.*;
@@ -32,39 +34,36 @@
 public class HighTier extends PhaseSuite<HighTierContext> {
 
     public HighTier() {
-        if (GraalOptions.FullUnroll) {
-            addPhase(new LoopFullUnrollPhase());
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!AOTCompilation.getValue());
+
+        if (FullUnroll.getValue()) {
+            appendPhase(new LoopFullUnrollPhase(!AOTCompilation.getValue()));
         }
 
-        if (GraalOptions.OptTailDuplication) {
-            addPhase(new TailDuplicationPhase());
+        if (OptTailDuplication.getValue()) {
+            appendPhase(new TailDuplicationPhase());
         }
 
-        if (GraalOptions.PartialEscapeAnalysis) {
-            addPhase(new PartialEscapeAnalysisPhase(true, GraalOptions.OptEarlyReadElimination));
-        }
-
-        if (GraalOptions.OptConvertDeoptsToGuards) {
-            addPhase(new ConvertDeoptimizeToGuardPhase());
+        if (PartialEscapeAnalysis.getValue()) {
+            appendPhase(new PartialEscapePhase(true, canonicalizer));
         }
 
-        addPhase(new LockEliminationPhase());
-
-        if (GraalOptions.OptLoopTransform) {
-            addPhase(new LoopTransformHighPhase());
-            addPhase(new LoopTransformLowPhase());
-        }
-        addPhase(new RemoveValueProxyPhase());
-
-        if (GraalOptions.CullFrameStates) {
-            addPhase(new CullFrameStatesPhase());
+        if (OptConvertDeoptsToGuards.getValue()) {
+            appendPhase(new ConvertDeoptimizeToGuardPhase());
         }
 
-        if (GraalOptions.OptCanonicalizer) {
-            addPhase(new CanonicalizerPhase());
+        appendPhase(new LockEliminationPhase());
+
+        if (OptLoopTransform.getValue()) {
+            appendPhase(new LoopTransformHighPhase());
+            appendPhase(new LoopTransformLowPhase());
+        }
+        appendPhase(new RemoveValueProxyPhase());
+
+        if (OptCanonicalizer.getValue()) {
+            appendPhase(canonicalizer);
         }
 
-        addPhase(new LoweringPhase(LoweringType.BEFORE_GUARDS));
+        appendPhase(new LoweringPhase(LoweringType.BEFORE_GUARDS));
     }
-
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Tue Jun 18 10:12:27 2013 +0200
@@ -30,12 +30,12 @@
 public class LowTier extends PhaseSuite<LowTierContext> {
 
     public LowTier() {
-        addPhase(new LoweringPhase(LoweringType.AFTER_GUARDS));
+        appendPhase(new LoweringPhase(LoweringType.AFTER_GUARDS));
 
-        addPhase(new FrameStateAssignmentPhase());
+        appendPhase(new FrameStateAssignmentPhase());
 
-        addPhase(new ExpandLogicPhase());
+        appendPhase(new ExpandLogicPhase());
 
-        addPhase(new DeadCodeEliminationPhase());
+        appendPhase(new DeadCodeEliminationPhase());
     }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.compiler.phases;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
@@ -30,51 +32,53 @@
 public class MidTier extends PhaseSuite<MidTierContext> {
 
     public MidTier() {
-        if (GraalOptions.OptPushThroughPi) {
-            addPhase(new PushThroughPiPhase());
-            if (GraalOptions.OptCanonicalizer) {
-                addPhase(new CanonicalizerPhase());
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!AOTCompilation.getValue());
+
+        if (OptPushThroughPi.getValue()) {
+            appendPhase(new PushThroughPiPhase());
+            if (OptCanonicalizer.getValue()) {
+                appendPhase(canonicalizer);
             }
         }
 
-        if (GraalOptions.OptFloatingReads) {
-            IncrementalCanonicalizerPhase<MidTierContext> canonicalizer = new IncrementalCanonicalizerPhase<>();
-            canonicalizer.addPhase(new FloatingReadPhase());
-            addPhase(canonicalizer);
-            if (GraalOptions.OptReadElimination) {
-                addPhase(new ReadEliminationPhase());
+        if (OptFloatingReads.getValue()) {
+            IncrementalCanonicalizerPhase<MidTierContext> incCanonicalizer = new IncrementalCanonicalizerPhase<>();
+            incCanonicalizer.appendPhase(new FloatingReadPhase());
+            appendPhase(incCanonicalizer);
+            if (OptReadElimination.getValue()) {
+                appendPhase(new ReadEliminationPhase());
             }
         }
-        addPhase(new RemoveValueProxyPhase());
+        appendPhase(new RemoveValueProxyPhase());
 
-        if (GraalOptions.OptCanonicalizer) {
-            addPhase(new CanonicalizerPhase());
+        if (OptCanonicalizer.getValue()) {
+            appendPhase(canonicalizer);
         }
 
-        if (GraalOptions.OptEliminatePartiallyRedundantGuards) {
-            addPhase(new EliminatePartiallyRedundantGuardsPhase(false, true));
+        if (OptEliminatePartiallyRedundantGuards.getValue()) {
+            appendPhase(new EliminatePartiallyRedundantGuardsPhase(false, true));
         }
 
-        if (GraalOptions.ConditionalElimination && GraalOptions.OptCanonicalizer) {
-            addPhase(new IterativeConditionalEliminationPhase());
+        if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) {
+            appendPhase(new IterativeConditionalEliminationPhase());
         }
 
-        if (GraalOptions.OptEliminatePartiallyRedundantGuards) {
-            addPhase(new EliminatePartiallyRedundantGuardsPhase(true, true));
+        if (OptEliminatePartiallyRedundantGuards.getValue()) {
+            appendPhase(new EliminatePartiallyRedundantGuardsPhase(true, true));
         }
 
-        if (GraalOptions.OptCanonicalizer) {
-            addPhase(new CanonicalizerPhase());
+        if (OptCanonicalizer.getValue()) {
+            appendPhase(canonicalizer);
         }
 
-        addPhase(new LoopSafepointEliminationPhase());
+        appendPhase(new LoopSafepointEliminationPhase());
 
-        addPhase(new SafepointInsertionPhase());
+        appendPhase(new SafepointInsertionPhase());
 
-        addPhase(new GuardLoweringPhase());
+        appendPhase(new GuardLoweringPhase());
 
-        if (GraalOptions.OptCanonicalizer) {
-            addPhase(new CanonicalizerPhase());
+        if (OptCanonicalizer.getValue()) {
+            appendPhase(canonicalizer);
         }
     }
 }
--- a/graal/com.oracle.graal.graph/.checkstyle_checks.xml	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.graph/.checkstyle_checks.xml	Tue Jun 18 10:12:27 2013 +0200
@@ -203,6 +203,12 @@
     <property name="checkFormat" value="RegexpSingleline"/>
     <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable System.(out|err).print checks"/>
   </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: stop header check"/>
+    <property name="onCommentFormat" value="CheckStyle: resume header check"/>
+    <property name="checkFormat" value=".*Header"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable header checks"/>
+  </module>
   <module name="RegexpSingleline">
     <property name="format" value="System\.(out|err)\.print"/>
     <property name="fileExtensions" value="java"/>
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeFlood.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeFlood.java	Tue Jun 18 10:12:27 2013 +0200
@@ -43,7 +43,7 @@
         }
     }
 
-    public void addAll(Iterable<Node> nodes) {
+    public void addAll(Iterable<? extends Node> nodes) {
         for (Node node : nodes) {
             this.add(node);
         }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Tue Jun 18 10:12:27 2013 +0200
@@ -50,7 +50,6 @@
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
-import com.oracle.graal.phases.*;
 
 /**
  * HotSpot AMD64 specific backend.
@@ -75,7 +74,7 @@
      *            the current frame
      */
     protected static void emitStackOverflowCheck(TargetMethodAssembler tasm, boolean afterFrameInit) {
-        if (GraalOptions.StackShadowPages > 0) {
+        if (StackShadowPages.getValue() > 0) {
 
             AMD64MacroAssembler asm = (AMD64MacroAssembler) tasm.asm;
             int frameSize = tasm.frameMap.frameSize();
@@ -83,7 +82,7 @@
                 int lastFramePage = frameSize / unsafe.pageSize();
                 // emit multiple stack bangs for methods with frames larger than a page
                 for (int i = 0; i <= lastFramePage; i++) {
-                    int disp = (i + GraalOptions.StackShadowPages) * unsafe.pageSize();
+                    int disp = (i + StackShadowPages.getValue()) * unsafe.pageSize();
                     if (afterFrameInit) {
                         disp -= frameSize;
                     }
@@ -112,7 +111,7 @@
                 emitStackOverflowCheck(tasm, false);
             }
             asm.decrementq(rsp, frameSize);
-            if (GraalOptions.ZapStackOnMethodEntry) {
+            if (ZapStackOnMethodEntry.getValue()) {
                 final int intSize = 4;
                 for (int i = 0; i < frameSize / intSize; ++i) {
                     asm.movl(new AMD64Address(rsp, i * intSize), 0xC1C1C1C1);
@@ -158,7 +157,7 @@
         AMD64HotSpotLIRGenerator gen = (AMD64HotSpotLIRGenerator) lirGen;
         FrameMap frameMap = gen.frameMap;
         LIR lir = gen.lir;
-        boolean omitFrame = CanOmitFrame && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame();
+        boolean omitFrame = CanOmitFrame.getValue() && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame();
 
         Stub stub = gen.getStub();
         AbstractAssembler masm = createAssembler(frameMap);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallEpilogueOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallEpilogueOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -27,7 +27,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallPrologueOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallPrologueOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -27,11 +27,11 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
-@Opcode("CRUNTIME_CALL_PROLOGUE")
+@Opcode
 final class AMD64HotSpotCRuntimeCallPrologueOp extends AMD64LIRInstruction {
 
     @Override
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -29,7 +29,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -31,7 +31,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 /**
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Tue Jun 18 10:12:27 2013 +0200
@@ -45,9 +45,18 @@
 import com.oracle.graal.lir.StandardOp.ParametersOp;
 import com.oracle.graal.lir.StandardOp.PlaceholderOp;
 import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp;
+import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapCompressedOp;
 import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp;
+import com.oracle.graal.lir.amd64.AMD64Move.LoadCompressedPointer;
+import com.oracle.graal.lir.amd64.AMD64Move.LoadOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp;
+import com.oracle.graal.lir.amd64.AMD64Move.StoreCompressedPointer;
+import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp;
+import com.oracle.graal.lir.amd64.AMD64Move.StoreOp;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 
 /**
@@ -211,8 +220,7 @@
     @Override
     public Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args) {
         Stub stub = getStub();
-        HotSpotForeignCallLinkage hsLinkage = (HotSpotForeignCallLinkage) linkage;
-        boolean destroysRegisters = hsLinkage.destroysRegisters();
+        boolean destroysRegisters = linkage.destroysRegisters();
 
         AMD64SaveRegistersOp save = null;
         StackSlot[] savedRegisterLocations = null;
@@ -234,7 +242,7 @@
 
         Variable result;
 
-        if (!hsLinkage.isLeaf()) {
+        if (linkage.canDeoptimize()) {
             assert info != null;
             append(new AMD64HotSpotCRuntimeCallPrologueOp());
             result = super.emitForeignCall(linkage, info, args);
@@ -391,4 +399,75 @@
             op.savedRbp = savedRbp;
         }
     }
+
+    private static boolean isCompressCandidate(DeoptimizingNode access) {
+        return access != null && ((HeapAccess) access).compress();
+    }
+
+    @Override
+    public Variable emitLoad(Kind kind, Value address, DeoptimizingNode access) {
+        AMD64AddressValue loadAddress = asAddressValue(address);
+        Variable result = newVariable(kind);
+        assert access == null || access instanceof HeapAccess;
+        if (runtime().config.useCompressedOops && isCompressCandidate(access)) {
+            Variable scratch = newVariable(Kind.Long);
+            append(new LoadCompressedPointer(kind, result, scratch, loadAddress, access != null ? state(access) : null, runtime().config.narrowOopBase, runtime().config.narrowOopShift,
+                            runtime().config.logMinObjAlignment));
+        } else {
+            append(new LoadOp(kind, result, loadAddress, access != null ? state(access) : null));
+        }
+        return result;
+    }
+
+    @Override
+    public void emitStore(Kind kind, Value address, Value inputVal, DeoptimizingNode access) {
+        AMD64AddressValue storeAddress = asAddressValue(address);
+        LIRFrameState state = access != null ? state(access) : null;
+        if (isConstant(inputVal)) {
+            Constant c = asConstant(inputVal);
+            if (canStoreConstant(c)) {
+                append(new StoreConstantOp(kind, storeAddress, c, state, runtime().config.useCompressedOops && isCompressCandidate(access)));
+                return;
+            }
+        }
+        Variable input = load(inputVal);
+        if (runtime().config.useCompressedOops && isCompressCandidate(access)) {
+            Variable scratch = newVariable(Kind.Long);
+            append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, runtime().config.narrowOopBase, runtime().config.narrowOopShift, runtime().config.logMinObjAlignment));
+        } else {
+            append(new StoreOp(kind, storeAddress, input, state));
+        }
+    }
+
+    @Override
+    public void visitCompareAndSwap(CompareAndSwapNode node) {
+        Kind kind = node.newValue().kind();
+        assert kind == node.expected().kind();
+
+        Value expected = loadNonConst(operand(node.expected()));
+        Variable newValue = load(operand(node.newValue()));
+
+        AMD64AddressValue address;
+        int displacement = node.displacement();
+        Value index = operand(node.offset());
+        if (isConstant(index) && NumUtil.isInt(asConstant(index).asLong() + displacement)) {
+            assert !runtime.needsDataPatch(asConstant(index));
+            displacement += (int) asConstant(index).asLong();
+            address = new AMD64AddressValue(kind, load(operand(node.object())), displacement);
+        } else {
+            address = new AMD64AddressValue(kind, load(operand(node.object())), load(index), Scale.Times1, displacement);
+        }
+
+        RegisterValue raxRes = AMD64.rax.asValue(kind);
+        emitMove(raxRes, expected);
+        if (runtime().config.useCompressedOops && node.compress()) {
+            Variable scratch = newVariable(Kind.Long);
+            append(new CompareAndSwapCompressedOp(raxRes, address, raxRes, newValue, scratch, runtime().config.narrowOopBase, runtime().config.narrowOopShift, runtime().config.logMinObjAlignment));
+        } else {
+            append(new CompareAndSwapOp(raxRes, address, raxRes, newValue));
+        }
+        Variable result = newVariable(node.kind());
+        append(new CondMoveOp(result, Condition.EQ, load(Constant.TRUE), Constant.FALSE));
+        setResult(node, result);
+    }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotPatchReturnAddressOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotPatchReturnAddressOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -28,7 +28,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Tue Jun 18 10:12:27 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot.amd64;
 
 import static com.oracle.graal.amd64.AMD64.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 
@@ -32,13 +33,12 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.phases.*;
 
 public class AMD64HotSpotRegisterConfig implements RegisterConfig {
 
     private final Architecture architecture;
 
-    private final Register[] allocatable = initAllocatable();
+    private final Register[] allocatable;
 
     private final HashMap<PlatformKind, Register[]> categorized = new HashMap<>();
 
@@ -86,25 +86,34 @@
         throw new IllegalArgumentException("register " + name + " is not allocatable");
     }
 
-    private static Register[] initAllocatable() {
+    private static Register[] initAllocatable(boolean reserveForHeapBase) {
+        Register[] registers = null;
         // @formatter:off
-        Register[] allocatable = {
+        if (reserveForHeapBase) {
+            registers = new Register[] {
+                        rax, rbx, rcx, rdx, /*rsp,*/ rbp, rsi, rdi, r8, r9,  r10, r11, /*r12,*/ r13, r14, /*r15, */
+                        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
+                        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
+                      };
+        } else {
+            registers = new Register[] {
                         rax, rbx, rcx, rdx, /*rsp,*/ rbp, rsi, rdi, r8, r9,  r10, r11, r12, r13, r14, /*r15, */
                         xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
                         xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
-                    };
-        // @formatter:on
+                      };
+        }
+       // @formatter:on
 
-        if (GraalOptions.RegisterPressure != null) {
-            String[] names = GraalOptions.RegisterPressure.split(",");
+        if (RegisterPressure.getValue() != null) {
+            String[] names = RegisterPressure.getValue().split(",");
             Register[] regs = new Register[names.length];
             for (int i = 0; i < names.length; i++) {
-                regs[i] = findRegister(names[i], allocatable);
+                regs[i] = findRegister(names[i], registers);
             }
             return regs;
         }
 
-        return allocatable;
+        return registers;
     }
 
     public AMD64HotSpotRegisterConfig(Architecture architecture, HotSpotVMConfig config) {
@@ -119,6 +128,7 @@
         }
 
         csl = null;
+        allocatable = initAllocatable(config.useCompressedOops);
         attributesMap = RegisterAttributes.createMap(this, AMD64.allRegisters);
     }
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 /**
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -31,7 +31,7 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.stubs.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -27,7 +27,6 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp;
 import com.oracle.graal.lir.asm.*;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -29,7 +29,6 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp;
 import com.oracle.graal.lir.asm.*;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -31,7 +31,6 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.amd64.AMD64Call.IndirectCallOp;
 import com.oracle.graal.lir.asm.*;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -32,7 +32,6 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.spi.*;
@@ -59,7 +58,7 @@
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler asm) {
         int pos = asm.codeBuffer.position();
-        int offset = SafepointPollOffset % unsafe.pageSize();
+        int offset = SafepointPollOffset.getValue() % unsafe.pageSize();
         RegisterValue scratch = (RegisterValue) temp;
         if (config.isPollingPageFar) {
             asm.movq(scratch.getRegister(), config.safepointPollingAddress + offset);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64TailcallOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64TailcallOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -27,7 +27,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.lir.LIRInstruction.*;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Tue Jun 18 10:12:27 2013 +0200
@@ -77,7 +77,7 @@
         SPARCHotSpotLIRGenerator gen = (SPARCHotSpotLIRGenerator) lirGen;
         FrameMap frameMap = gen.frameMap;
         LIR lir = gen.lir;
-        boolean omitFrame = CanOmitFrame && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame();
+        boolean omitFrame = CanOmitFrame.getValue() && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame();
 
         Stub stub = gen.getStub();
         AbstractAssembler masm = createAssembler(frameMap);
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime.java	Tue Jun 18 10:12:27 2013 +0200
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.sparc.*;
 
 /**
  * SPARC specific implementation of {@link HotSpotGraalRuntime}.
@@ -44,10 +45,15 @@
         return graalRuntime();
     }
 
+    protected static Architecture createArchitecture() {
+        return new SPARC();
+    }
+
     @Override
     protected TargetDescription createTarget() {
-        // SPARC: Create target description.
-        throw new InternalError("NYI");
+        final int stackFrameAlignment = 16;
+        final int implicitNullCheckLimit = 4096;
+        return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, true);
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -0,0 +1,216 @@
+/*
+ * 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 static com.oracle.graal.api.code.CodeUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CallingConvention.Type;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.java.*;
+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.tiers.*;
+
+/**
+ * use
+ * 
+ * <pre>
+ * mx unittest AheadOfTimeCompilationTest @-XX:CompileCommand='print,*AheadOfTimeCompilationTest.*'
+ * </pre>
+ * 
+ * to print disassembly.
+ */
+public class AheadOfTimeCompilationTest extends GraalCompilerTest {
+
+    public static final Object STATICFINALOBJECT = new Object();
+    public static final String STATICFINALSTRING = "test string";
+
+    public static Object getStaticFinalObject() {
+        return AheadOfTimeCompilationTest.STATICFINALOBJECT;
+    }
+
+    @Test
+    public void testStaticFinalObjectAOT() {
+        StructuredGraph result = compile("getStaticFinalObject", true);
+        assertEquals(1, result.getNodes().filter(ConstantNode.class).count());
+        assertEquals(runtime.getTarget().wordKind, result.getNodes().filter(ConstantNode.class).first().kind());
+        assertEquals(2, result.getNodes(FloatingReadNode.class).count());
+        assertEquals(0, result.getNodes(ReadNode.class).count());
+    }
+
+    @Test
+    public void testStaticFinalObject() {
+        StructuredGraph result = compile("getStaticFinalObject", false);
+        assertEquals(1, result.getNodes().filter(ConstantNode.class).count());
+        assertEquals(Kind.Object, result.getNodes().filter(ConstantNode.class).first().kind());
+        assertEquals(0, result.getNodes(FloatingReadNode.class).count());
+        assertEquals(0, result.getNodes(ReadNode.class).count());
+    }
+
+    public static Class getClassObject() {
+        return AheadOfTimeCompilationTest.class;
+    }
+
+    @Test
+    public void testClassObjectAOT() {
+        StructuredGraph result = compile("getClassObject", true);
+
+        NodeIterable<ConstantNode> filter = result.getNodes().filter(ConstantNode.class);
+        assertEquals(1, filter.count());
+        HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) runtime.lookupJavaType(AheadOfTimeCompilationTest.class);
+        assertEquals(type.klass(), filter.first().asConstant());
+
+        assertEquals(1, result.getNodes(FloatingReadNode.class).count());
+        assertEquals(0, result.getNodes(ReadNode.class).count());
+    }
+
+    @Test
+    public void testClassObject() {
+        StructuredGraph result = compile("getClassObject", false);
+
+        NodeIterable<ConstantNode> filter = result.getNodes().filter(ConstantNode.class);
+        assertEquals(1, filter.count());
+        Object mirror = filter.first().asConstant().asObject();
+        assertEquals(Class.class, mirror.getClass());
+        assertEquals(AheadOfTimeCompilationTest.class, mirror);
+
+        assertEquals(0, result.getNodes(FloatingReadNode.class).count());
+        assertEquals(0, result.getNodes(ReadNode.class).count());
+    }
+
+    public static Class getPrimitiveClassObject() {
+        return int.class;
+    }
+
+    @Test
+    public void testPrimitiveClassObjectAOT() {
+        StructuredGraph result = compile("getPrimitiveClassObject", true);
+        NodeIterable<ConstantNode> filter = result.getNodes().filter(ConstantNode.class);
+        assertEquals(1, filter.count());
+        assertEquals(runtime.getTarget().wordKind, filter.first().kind());
+
+        assertEquals(2, result.getNodes(FloatingReadNode.class).count());
+        assertEquals(0, result.getNodes(ReadNode.class).count());
+    }
+
+    @Test
+    public void testPrimitiveClassObject() {
+        StructuredGraph result = compile("getPrimitiveClassObject", false);
+        NodeIterable<ConstantNode> filter = result.getNodes().filter(ConstantNode.class);
+        assertEquals(1, filter.count());
+        Object mirror = filter.first().asConstant().asObject();
+        assertEquals(Class.class, mirror.getClass());
+        assertEquals(Integer.TYPE, mirror);
+
+        assertEquals(0, result.getNodes(FloatingReadNode.class).count());
+        assertEquals(0, result.getNodes(ReadNode.class).count());
+    }
+
+    public static String getStringObject() {
+        return AheadOfTimeCompilationTest.STATICFINALSTRING;
+    }
+
+    @Test
+    public void testStringObjectAOT() {
+        // embedded strings are fine
+        testStringObjectCommon(true);
+    }
+
+    @Test
+    public void testStringObject() {
+        testStringObjectCommon(false);
+    }
+
+    private void testStringObjectCommon(boolean compileAOT) {
+        StructuredGraph result = compile("getStringObject", compileAOT);
+
+        NodeIterable<ConstantNode> filter = result.getNodes().filter(ConstantNode.class);
+        assertEquals(1, filter.count());
+        Object mirror = filter.first().asConstant().asObject();
+        assertEquals(String.class, mirror.getClass());
+        assertEquals("test string", mirror);
+
+        assertEquals(0, result.getNodes(FloatingReadNode.class).count());
+        assertEquals(0, result.getNodes(ReadNode.class).count());
+    }
+
+    public static Boolean getBoxedBoolean() {
+        return Boolean.valueOf(true);
+    }
+
+    @Test
+    public void testBoxedBooleanAOT() {
+        StructuredGraph result = compile("getBoxedBoolean", true);
+
+        assertEquals(2, result.getNodes(FloatingReadNode.class).count());
+        assertEquals(1, result.getNodes(UnsafeCastNode.class).count());
+        assertEquals(1, result.getNodes().filter(ConstantNode.class).count());
+        ConstantNode constant = result.getNodes().filter(ConstantNode.class).first();
+        assertEquals(Kind.Long, constant.kind());
+        assertEquals(((HotSpotResolvedObjectType) runtime.lookupJavaType(Boolean.class)).klass(), constant.asConstant());
+    }
+
+    @Test
+    public void testBoxedBoolean() {
+        StructuredGraph result = compile("getBoxedBoolean", false);
+        assertEquals(0, result.getNodes(FloatingReadNode.class).count());
+        assertEquals(0, result.getNodes(UnsafeCastNode.class).count());
+        assertEquals(1, result.getNodes().filter(ConstantNode.class).count());
+        ConstantNode constant = result.getNodes().filter(ConstantNode.class).first();
+        assertEquals(Kind.Object, constant.kind());
+        assertEquals(Boolean.TRUE, constant.asConstant().asObject());
+    }
+
+    private StructuredGraph compile(String test, boolean compileAOT) {
+        StructuredGraph graph = parse(test);
+        ResolvedJavaMethod method = graph.method();
+
+        boolean originalSetting = AOTCompilation.getValue();
+        AOTCompilation.setValue(compileAOT);
+        PhasePlan phasePlan = new PhasePlan();
+        GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
+        phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
+        editPhasePlan(method, graph, phasePlan);
+        CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
+        // create suites everytime, as we modify options for the compiler
+        final Suites suitesLocal = Graal.getRequiredCapability(SuitesProvider.class).createSuites();
+        final CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, method, runtime, replacements, backend, runtime().getTarget(), null, phasePlan, OptimisticOptimizations.ALL,
+                        new SpeculationLog(), suitesLocal);
+        addMethod(method, compResult);
+
+        AOTCompilation.setValue(originalSetting);
+
+        return graph;
+    }
+}
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.test;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import org.junit.*;
 
 import com.oracle.graal.compiler.test.*;
@@ -34,9 +36,11 @@
 
     @Test
     public void testRtJar() throws Throwable {
+        boolean originalSetting = ExitVMOnException.getValue();
         // Compile a couple classes in rt.jar
         String file = System.getProperty("java.home") + "/lib/rt.jar";
         new CompileTheWorld(file, 1, 5).compile();
+        ExitVMOnException.setValue(originalSetting);
     }
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -0,0 +1,356 @@
+/*
+ * 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 java.lang.reflect.*;
+import java.util.*;
+import java.util.concurrent.atomic.*;
+
+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.*;
+
+/**
+ * The following tests perform object/array equality and assignments in various ways. The selected
+ * cases have been the problematic ones while implementing the Compressed Oops support.
+ */
+public class CompressedOopTest extends GraalCompilerTest {
+
+    private final MetaAccessProvider metaAccessProvider;
+
+    public CompressedOopTest() {
+        this.metaAccessProvider = Graal.getRequiredCapability(MetaAccessProvider.class);
+    }
+
+    private HotSpotInstalledCode getInstalledCode(String name) throws Exception {
+        final Method method = CompressedOopTest.class.getMethod(name, Object.class, Object.class, Object.class);
+        final HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccessProvider.lookupJavaMethod(method);
+        final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(javaMethod, parse(method));
+        return installedBenchmarkCode;
+    }
+
+    @Test
+    public void test() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("fieldTest");
+        Container c1 = new Container();
+        Assert.assertEquals(c1.b, installedBenchmarkCode.executeVarargs(c1, c1, c1));
+    }
+
+    public static Object fieldTest(Object c1, @SuppressWarnings("unused") Object c2, @SuppressWarnings("unused") Object c3) {
+        ((Container) c1).a = ((Container) c1).b;
+        return ((Container) c1).a;
+    }
+
+    @Test
+    public void test1() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("arrayTest");
+        ArrayContainer ac = new ArrayContainer();
+        Assert.assertEquals(ac.a[9], installedBenchmarkCode.executeVarargs(ac.a, 0, 9));
+        Assert.assertEquals(ac.a[8], installedBenchmarkCode.executeVarargs(ac.a, 1, 8));
+        Assert.assertEquals(ac.a[7], installedBenchmarkCode.executeVarargs(ac.a, 2, 7));
+        Assert.assertEquals(ac.a[6], installedBenchmarkCode.executeVarargs(ac.a, 3, 6));
+        Assert.assertEquals(ac.a[5], installedBenchmarkCode.executeVarargs(ac.a, 4, 5));
+        Assert.assertEquals(ac.a[4], installedBenchmarkCode.executeVarargs(ac.a, 5, 4));
+        Assert.assertEquals(ac.a[3], installedBenchmarkCode.executeVarargs(ac.a, 6, 3));
+        Assert.assertEquals(ac.a[2], installedBenchmarkCode.executeVarargs(ac.a, 7, 2));
+        Assert.assertEquals(ac.a[1], installedBenchmarkCode.executeVarargs(ac.a, 8, 1));
+        Assert.assertEquals(ac.a[0], installedBenchmarkCode.executeVarargs(ac.a, 9, 0));
+    }
+
+    public static Object arrayTest(Object c1, Object c2, Object c3) {
+        Object[] array = (Object[]) c1;
+        int initialIndex = ((Integer) c2).intValue();
+        int replacingIndex = ((Integer) c3).intValue();
+        array[initialIndex] = array[replacingIndex];
+        return array[initialIndex];
+    }
+
+    @Test
+    public void test2() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("arrayCopyTest");
+        ArrayContainer source = new ArrayContainer();
+        ArrayContainer destination = new ArrayContainer();
+        Assert.assertEquals(source.a.length, destination.a.length);
+        Assert.assertFalse(Arrays.equals(source.a, destination.a));
+        installedBenchmarkCode.execute(source.a, destination.a, source.a);
+        Assert.assertArrayEquals(source.a, destination.a);
+    }
+
+    public static void arrayCopyTest(Object c1, Object c2, @SuppressWarnings("unused") Object c3) {
+        Object[] source = (Object[]) c1;
+        Object[] destination = (Object[]) c2;
+        System.arraycopy(source, 0, destination, 0, source.length);
+    }
+
+    @Test
+    public void test3() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("compareAndSwapTest");
+        Object initial = new Object();
+        Object replacement = new Object();
+        AtomicReference<Object> cas = new AtomicReference<>();
+        Assert.assertEquals(cas.get(), null);
+        installedBenchmarkCode.execute(cas, null, initial);
+        Assert.assertEquals(cas.get(), initial);
+        installedBenchmarkCode.execute(cas, initial, replacement);
+        Assert.assertEquals(cas.get(), replacement);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static void compareAndSwapTest(Object c1, Object c2, Object c3) throws ClassCastException {
+        AtomicReference<Object> cas = (AtomicReference<Object>) c1;
+        cas.compareAndSet(c2, c3);
+    }
+
+    @Test
+    public void test4() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("charArrayCopyTest");
+        StringContainer1 source1 = new StringContainer1();
+        StringContainer2 source2 = new StringContainer2();
+        char[] result = new char[source1.value.length + source2.value.length];
+        installedBenchmarkCode.execute(source1.value, source2.value, result);
+        Assert.assertArrayEquals(new char[]{'T', 'e', 's', 't', ' ', 'S', 't', 'r', 'i', 'n', 'g'}, result);
+    }
+
+    public static char[] charArrayCopyTest(Object c1, Object c2, Object c3) {
+        char[] source1 = (char[]) c1;
+        char[] source2 = (char[]) c2;
+        char[] result = (char[]) c3;
+        for (int i = 0; i < source1.length; i++) {
+            result[i] = source1[i];
+        }
+
+        for (int i = 0; i < source2.length; i++) {
+            result[source1.length + i] = source2[i];
+        }
+        return result;
+    }
+
+    @Test
+    public void test5() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("charContainerArrayCopyTest");
+        StringContainer1 source1 = new StringContainer1();
+        StringContainer2 source2 = new StringContainer2();
+        char[] result = new char[source1.value.length + source2.value.length];
+        installedBenchmarkCode.execute(source1, source2, result);
+        Assert.assertArrayEquals(new char[]{'T', 'e', 's', 't', ' ', 'S', 't', 'r', 'i', 'n', 'g'}, result);
+    }
+
+    public static char[] charContainerArrayCopyTest(Object c1, Object c2, Object c3) {
+        char[] source1 = ((StringContainer1) c1).value;
+        char[] source2 = ((StringContainer2) c2).value;
+        char[] result = (char[]) c3;
+        for (int i = 0; i < source1.length; i++) {
+            result[i] = source1[i];
+        }
+        for (int i = 0; i < source2.length; i++) {
+            result[source1.length + i] = source2[i];
+        }
+        return result;
+    }
+
+    @Test
+    public void test6() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringCopyTest");
+        String a = new String("Test ");
+        String b = new String("String");
+        String c = (String) installedBenchmarkCode.execute(a, b, null);
+        Assert.assertTrue(c.equals("Test String"));
+    }
+
+    public static String stringCopyTest(Object c1, Object c2, @SuppressWarnings("unused") Object c3) {
+        String source = (String) c1;
+        String destination = (String) c2;
+        return source + destination;
+    }
+
+    @Test
+    public void test7() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("queueTest");
+        ArrayDeque<Object> q = new ArrayDeque<>();
+        Object[] objects = new Object[512];
+        for (int i = 0; i < objects.length; i++) {
+            objects[i] = new Object();
+        }
+        int j = 0;
+        while (j < objects.length) {
+            installedBenchmarkCode.execute(q, objects[j], null);
+            j++;
+        }
+
+        System.gc();
+        Assert.assertTrue(q.size() == objects.length);
+        Assert.assertTrue(!q.isEmpty());
+        j = 0;
+        while (j < objects.length) {
+            Assert.assertTrue(objects[j] == q.remove());
+            j++;
+        }
+
+        Assert.assertTrue(q.size() == 0);
+        Assert.assertTrue(q.isEmpty());
+    }
+
+    @SuppressWarnings("unchecked")
+    public static void queueTest(Object c1, Object c2, @SuppressWarnings("unused") Object c3) {
+        ArrayDeque<Object> queue = (ArrayDeque<Object>) c1;
+        queue.add(c2);
+    }
+
+    @Test
+    public void test8() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("unmodListTest");
+        List<Object> list = new ArrayList<>();
+        for (int i = 0; i < 512; i++) {
+            list.add(new Object());
+        }
+        Object[] array = (Object[]) installedBenchmarkCode.execute(list, null, null);
+        Assert.assertTrue(list.size() == array.length);
+        int i = 0;
+        for (Object obj : list) {
+            Assert.assertTrue(obj == array[i]);
+            i++;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public static Object[] unmodListTest(Object c1, @SuppressWarnings("unused") Object c2, @SuppressWarnings("unused") Object c3) {
+        List<Object> queue = (ArrayList<Object>) c1;
+        Object[] result = Collections.unmodifiableCollection(queue).toArray(new Object[queue.size()]);
+        return result;
+    }
+
+    @Test
+    public void test9() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("unmodListTest");
+        List<Object> list = new ArrayList<>();
+        Object[] array = (Object[]) installedBenchmarkCode.execute(list, null, null);
+        Assert.assertTrue(list.size() == array.length);
+    }
+
+    public void test10() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("constantTest");
+        Container c = new Container();
+        Assert.assertFalse((boolean) installedBenchmarkCode.execute(c, null, null));
+    }
+
+    public static Boolean constantTest(Object c1, @SuppressWarnings("unused") Object c2, @SuppressWarnings("unused") Object c3) {
+        ConstantContainer container = (ConstantContainer) c1;
+        return container.a.equals(container.b);
+    }
+
+    @Test
+    public void test11() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringEqualsTest");
+        String s1 = new String("Test");
+        String s2 = new String("Test");
+        boolean result = ((Boolean) (installedBenchmarkCode.execute(s1, s2, null))).booleanValue();
+        Assert.assertTrue(result);
+    }
+
+    public static Boolean stringEqualsTest(Object c1, Object c2, @SuppressWarnings("unused") Object c3) {
+        return ((String) c1).equals(c2);
+    }
+
+    @Test
+    public void test12() throws Exception {
+        HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringConstantEqualsTest");
+        String s1 = new String("Test");
+        boolean result = ((Boolean) (installedBenchmarkCode.execute(s1, null, null))).booleanValue();
+        Assert.assertTrue(result);
+    }
+
+    public static Boolean stringConstantEqualsTest(Object c1, @SuppressWarnings("unused") Object c2, @SuppressWarnings("unused") Object c3) {
+        return "Test".equals(c1);
+    }
+
+    static class Container {
+
+        public Object a = new Object();
+        public Object b = new Object();
+    }
+
+    static class ArrayContainer {
+
+        public Object[] a = new Object[10];
+
+        public ArrayContainer() {
+            for (int i = 0; i < 10; i++) {
+                a[i] = new Object();
+            }
+        }
+    }
+
+    static class HashMapContainer {
+
+        public HashMap<Object, Object> a = new HashMap<>();
+
+        public HashMapContainer() {
+            for (int i = 0; i < 10; i++) {
+                a.put(new Object(), new Object());
+            }
+        }
+    }
+
+    static class StringContainer1 {
+
+        public char[] value = new char[5];
+
+        public StringContainer1() {
+            value[0] = 'T';
+            value[1] = 'e';
+            value[2] = 's';
+            value[3] = 't';
+            value[4] = ' ';
+
+        }
+    }
+
+    static class StringContainer2 {
+
+        public char[] value = new char[6];
+
+        public StringContainer2() {
+            value[0] = 'S';
+            value[1] = 't';
+            value[2] = 'r';
+            value[3] = 'i';
+            value[4] = 'n';
+            value[5] = 'g';
+        }
+    }
+
+    static class ConstantContainer {
+
+        public final Object a = new Object();
+        public final Object b = new Object();
+
+        public ConstantContainer() {
+
+        }
+    }
+
+}
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -46,9 +46,9 @@
 public class HotSpotCryptoSubstitutionTest extends GraalCompilerTest {
 
     @Override
-    protected InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, StructuredGraph graph) {
+    protected InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) {
         HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method;
-        HotSpotNmethod installedCode = new HotSpotNmethod(hsMethod, graph, true);
+        HotSpotNmethod installedCode = new HotSpotNmethod(hsMethod, true, null);
         HotSpotCompiledNmethod compiledNmethod = new HotSpotCompiledNmethod(hsMethod, StructuredGraph.INVOCATION_ENTRY_BCI, compResult);
         CodeInstallResult result = graalRuntime().getCompilerToVM().installCode(compiledNmethod, installedCode, null);
         Assert.assertEquals("Error installing method " + method + ": " + result, result, CodeInstallResult.OK);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Tue Jun 18 10:12:27 2013 +0200
@@ -24,9 +24,11 @@
 
 import static com.oracle.graal.api.code.CodeUtil.*;
 import static com.oracle.graal.nodes.StructuredGraph.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.lang.reflect.*;
 import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.CallingConvention.Type;
@@ -34,20 +36,16 @@
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
+import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 public final class CompilationTask implements Runnable, Comparable<CompilationTask> {
 
-    //@formatter:off
-    @Option(help = "")
-    public static final OptionValue<Integer> SlowQueueCutoff = new OptionValue<>(100000);
-    //@formatter:on
-
     public static final ThreadLocal<Boolean> withinEnqueue = new ThreadLocal<Boolean>() {
 
         @Override
@@ -56,16 +54,19 @@
         }
     };
 
-    private volatile boolean cancelled;
-    private volatile boolean inProgress;
+    private enum CompilationStatus {
+        Queued, Running, Canceled
+    }
 
     private final HotSpotGraalRuntime graalRuntime;
     private final PhasePlan plan;
+    private final SuitesProvider suitesProvider;
     private final OptimisticOptimizations optimisticOpts;
     private final HotSpotResolvedJavaMethod method;
     private final int entryBCI;
     private final int id;
     private final int priority;
+    private final AtomicReference<CompilationStatus> status;
 
     private StructuredGraph graph;
 
@@ -76,11 +77,13 @@
     private CompilationTask(HotSpotGraalRuntime graalRuntime, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int entryBCI, int id, int priority) {
         this.graalRuntime = graalRuntime;
         this.plan = plan;
+        this.suitesProvider = graalRuntime.getCapability(SuitesProvider.class);
         this.method = method;
         this.optimisticOpts = optimisticOpts;
         this.entryBCI = entryBCI;
         this.id = id;
         this.priority = priority;
+        this.status = new AtomicReference<>();
     }
 
     public ResolvedJavaMethod getMethod() {
@@ -91,16 +94,8 @@
         return priority;
     }
 
-    public void cancel() {
-        cancelled = true;
-    }
-
-    public boolean isInProgress() {
-        return inProgress;
-    }
-
-    public boolean isCancelled() {
-        return cancelled;
+    public boolean tryToCancel() {
+        return tryToChangeStatus(CompilationStatus.Queued, CompilationStatus.Canceled);
     }
 
     public int getEntryBCI() {
@@ -110,12 +105,11 @@
     public void run() {
         withinEnqueue.set(Boolean.FALSE);
         try {
-            if (cancelled) {
+            if (!tryToChangeStatus(CompilationStatus.Queued, CompilationStatus.Running)) {
                 return;
             }
-            inProgress = true;
-            if (GraalOptions.DynamicCompilePriority) {
-                int threadPriority = priority < SlowQueueCutoff.getValue() ? Thread.NORM_PRIORITY : Thread.MIN_PRIORITY;
+            if (DynamicCompilePriority.getValue()) {
+                int threadPriority = priority < VMToCompilerImpl.SlowQueueCutoff.getValue() ? Thread.NORM_PRIORITY : Thread.MIN_PRIORITY;
                 if (Thread.currentThread().getPriority() != threadPriority) {
                     Thread.currentThread().setPriority(threadPriority);
                 }
@@ -125,8 +119,6 @@
             if (method.currentTask() == this) {
                 method.setCurrentTask(null);
             }
-            graalRuntime.getCompilerToVM().clearQueuedForCompilation(method);
-            inProgress = false;
             withinEnqueue.set(Boolean.TRUE);
         }
     }
@@ -139,17 +131,17 @@
     public void runCompilation() {
         CompilationStatistics stats = CompilationStatistics.create(method, entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI);
         try (TimerCloseable a = CompilationTime.start()) {
-            final boolean printCompilation = GraalOptions.PrintCompilation && !TTY.isSuppressed();
+            final boolean printCompilation = PrintCompilation.getValue() && !TTY.isSuppressed();
             if (printCompilation) {
                 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) {
+            if (HotSpotPrintCompilation.getValue()) {
                 printCompilation();
             }
 
             CompilationResult result = null;
-            TTY.Filter filter = new TTY.Filter(GraalOptions.PrintFilter, method);
+            TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method);
             long start = System.currentTimeMillis();
             try {
                 result = Debug.scope("Compiling", new DebugDumpScope(String.valueOf(id), true), new Callable<CompilationResult>() {
@@ -169,7 +161,7 @@
                         HotSpotRuntime runtime = graalRuntime.getRuntime();
                         CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
                         return GraalCompiler.compileGraph(graph, cc, method, runtime, replacements, graalRuntime.getBackend(), graalRuntime.getTarget(), graalRuntime.getCache(), plan, optimisticOpts,
-                                        method.getSpeculationLog());
+                                        method.getSpeculationLog(), suitesProvider.getDefaultSuites());
                     }
                 });
             } finally {
@@ -182,21 +174,24 @@
             installMethod(result);
         } catch (BailoutException bailout) {
             Debug.metric("Bailouts").increment();
-            if (GraalOptions.ExitVMOnBailout) {
+            if (ExitVMOnBailout.getValue()) {
                 TTY.cachedOut.println(MetaUtil.format("Bailout in %H.%n(%p)", method));
                 bailout.printStackTrace(TTY.cachedOut);
                 System.exit(-1);
-            } else if (GraalOptions.PrintBailout) {
+            } else if (PrintBailout.getValue()) {
                 TTY.cachedOut.println(MetaUtil.format("Bailout in %H.%n(%p)", method));
                 bailout.printStackTrace(TTY.cachedOut);
             }
         } catch (Throwable t) {
-            if (GraalOptions.PrintStackTraceOnException || GraalOptions.ExitVMOnException) {
+            if (PrintStackTraceOnException.getValue() || ExitVMOnException.getValue()) {
                 t.printStackTrace(TTY.cachedOut);
             }
-            if (GraalOptions.ExitVMOnException) {
+            if (ExitVMOnException.getValue()) {
                 System.exit(-1);
             }
+        } finally {
+            assert method.isQueuedForCompilation();
+            method.clearQueuedForCompilation();
         }
         stats.finish(method);
     }
@@ -216,7 +211,7 @@
 
             @Override
             public void run() {
-                HotSpotInstalledCode installedCode = graalRuntime.getRuntime().installMethod(method, graph, entryBCI, compResult);
+                HotSpotInstalledCode installedCode = graalRuntime.getRuntime().installMethod(method, entryBCI, compResult);
                 if (Debug.isDumpEnabled()) {
                     Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
                 }
@@ -228,6 +223,10 @@
         });
     }
 
+    private boolean tryToChangeStatus(CompilationStatus from, CompilationStatus to) {
+        return status.compareAndSet(from, to);
+    }
+
     @Override
     public int compareTo(CompilationTask o) {
         if (priority < o.priority) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Tue Jun 18 10:12:27 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot;
 
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.io.File;
 import java.lang.reflect.Constructor;
@@ -75,7 +76,7 @@
      * {@link GraalOptions#CompileTheWorldStopAt}.
      */
     public CompileTheWorld() {
-        this(GraalOptions.CompileTheWorld, GraalOptions.CompileTheWorldStartAt, GraalOptions.CompileTheWorldStopAt);
+        this(CompileTheWorld.getValue(), CompileTheWorldStartAt.getValue(), CompileTheWorldStopAt.getValue());
     }
 
     /**
@@ -91,7 +92,7 @@
         this.stopAt = stopAt;
 
         // We don't want the VM to exit when a method fails to compile.
-        GraalOptions.ExitVMOnException = false;
+        ExitVMOnException.setValue(false);
     }
 
     /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotForeignCallLinkage.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotForeignCallLinkage.java	Tue Jun 18 10:12:27 2013 +0200
@@ -107,7 +107,7 @@
      * @param effect specifies if the call destroys or preserves all registers (apart from
      *            temporaries which are always destroyed)
      * @param ccType calling convention type
-     * @param transition specifies if this is a {@linkplain #isLeaf() leaf} call
+     * @param transition specifies if this is a {@linkplain #canDeoptimize() leaf} call
      * @param reexecutable specifies if the call can be re-executed without (meaningful) side
      *            effects. Deoptimization will not return to a point before a call that cannot be
      *            re-executed.
@@ -235,11 +235,8 @@
         return effect == DESTROYS_REGISTERS;
     }
 
-    /**
-     * Determines if this is call to a function that does not lock, GC or throw exceptions. That is,
-     * the thread's execution state during the call is never inspected by another thread.
-     */
-    public boolean isLeaf() {
-        return transition == Transition.LEAF;
+    @Override
+    public boolean canDeoptimize() {
+        return transition != Transition.LEAF;
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Tue Jun 18 10:12:27 2013 +0200
@@ -31,11 +31,16 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.logging.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.tiers.*;
+
+//import static com.oracle.graal.phases.GraalOptions.*;
 
 /**
  * Singleton class holding the instance of the {@link GraalRuntime}.
@@ -84,12 +89,24 @@
         runtime.compilerToVm = toVM;
     }
 
+    private static final String DEFAULT_GRAAL_RUNTIME = "basic";
+
+    // @formatter:off
+    @Option(help = "The runtime configuration to use")
+    private static final OptionValue<String> GraalRuntime = new OptionValue<>(DEFAULT_GRAAL_RUNTIME);
+    // @formatter:on
+
     protected static HotSpotGraalRuntimeFactory findFactory(String architecture) {
         for (HotSpotGraalRuntimeFactory factory : ServiceLoader.loadInstalled(HotSpotGraalRuntimeFactory.class)) {
-            if (factory.getArchitecture().equals(architecture) && factory.getName().equals(GraalOptions.GraalRuntime)) {
+            if (factory.getArchitecture().equals(architecture) && factory.getName().equals(GraalRuntime.getValue())) {
                 return factory;
             }
         }
+        if (!DEFAULT_GRAAL_RUNTIME.equals(GraalRuntime.getValue())) {
+            // Fail fast if a non-default value for GraalRuntime was specified
+            // and the corresponding factory is not available
+            throw new GraalInternalError("Specified runtime \"%s\" not available for the %s architecture", GraalRuntime.getValue(), architecture);
+        }
         return null;
     }
 
@@ -123,9 +140,9 @@
         return unsafe.getInt(object, offset);
     }
 
-    protected/* final */CompilerToVM  compilerToVm;
+    protected/* final */CompilerToVM compilerToVm;
     protected/* final */CompilerToGPU compilerToGpu;
-    protected/* final */VMToCompiler  vmToCompiler;
+    protected/* final */VMToCompiler vmToCompiler;
 
     protected final HotSpotRuntime runtime;
     protected final TargetDescription target;
@@ -138,13 +155,13 @@
     private final HotSpotBackend backend;
 
     protected HotSpotGraalRuntime() {
-        CompilerToVM  toVM  = new CompilerToVMImpl();
+        CompilerToVM toVM = new CompilerToVMImpl();
         CompilerToGPU toGPU = new CompilerToGPUImpl();
 
         // initialize VmToCompiler
         VMToCompiler toCompiler = new VMToCompilerImpl(this);
 
-        compilerToVm  = toVM;
+        compilerToVm = toVM;
         compilerToGpu = toGPU;
         vmToCompiler = toCompiler;
         config = new HotSpotVMConfig();
@@ -153,16 +170,16 @@
 
         // Set some global options:
         if (config.compileTheWorld) {
-            GraalOptions.CompileTheWorld = CompileTheWorld.SUN_BOOT_CLASS_PATH;
+            GraalOptions.CompileTheWorld.setValue(CompileTheWorld.SUN_BOOT_CLASS_PATH);
         }
         if (config.compileTheWorldStartAt != 1) {
-            GraalOptions.CompileTheWorldStartAt = config.compileTheWorldStartAt;
+            GraalOptions.CompileTheWorldStartAt.setValue(config.compileTheWorldStartAt);
         }
         if (config.compileTheWorldStopAt != Integer.MAX_VALUE) {
-            GraalOptions.CompileTheWorldStopAt = config.compileTheWorldStopAt;
+            GraalOptions.CompileTheWorldStopAt.setValue(config.compileTheWorldStopAt);
         }
-        GraalOptions.HotSpotPrintCompilation = config.printCompilation;
-        GraalOptions.HotSpotPrintInlining = config.printInlining;
+        GraalOptions.HotSpotPrintCompilation.setValue(config.printCompilation);
+        GraalOptions.HotSpotPrintInlining.setValue(config.printInlining);
 
         if (Boolean.valueOf(System.getProperty("graal.printconfig"))) {
             printConfig(config);
@@ -180,8 +197,8 @@
         replacements = new HotSpotReplacementsImpl(runtime, assumptions, runtime.getGraalRuntime().getTarget());
 
         backend = createBackend();
-        GraalOptions.StackShadowPages = config.stackShadowPages;
-        if (GraalOptions.CacheGraphs) {
+        GraalOptions.StackShadowPages.setValue(config.stackShadowPages);
+        if (GraalOptions.CacheGraphs.getValue()) {
             cache = new HotSpotGraphCache();
         }
     }
@@ -302,7 +319,7 @@
         if (clazz == GraalCodeCacheProvider.class || clazz == CodeCacheProvider.class || clazz == MetaAccessProvider.class) {
             return (T) getRuntime();
         }
-        if (clazz == DisassemblerProvider.class || clazz == BytecodeDisassemblerProvider.class) {
+        if (clazz == DisassemblerProvider.class || clazz == BytecodeDisassemblerProvider.class || clazz == SuitesProvider.class) {
             return (T) getRuntime();
         }
         if (clazz == HotSpotRuntime.class) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Tue Jun 18 10:12:27 2013 +0200
@@ -23,23 +23,77 @@
 
 package com.oracle.graal.hotspot;
 
-import java.lang.reflect.*;
+import static java.nio.file.Files.*;
+
+import java.io.*;
+import java.nio.charset.*;
+import java.nio.file.*;
 import java.util.*;
 
 import com.oracle.graal.hotspot.logging.*;
 import com.oracle.graal.options.*;
-import com.oracle.graal.phases.*;
 
+/**
+ * Called from {@code graalCompiler.cpp} to parse any Graal specific options. Such options are
+ * (currently) distinguished by a {@code "-G:"} prefix.
+ */
 public class HotSpotOptions {
 
-    private static final Map<String, OptionProvider> options = new HashMap<>();
+    private static final Map<String, OptionDescriptor> options = new HashMap<>();
+
+    /**
+     * Initializes {@link #options} from {@link Options} services.
+     */
+    private static void initializeOptions() {
+        ServiceLoader<Options> sl = ServiceLoader.loadInstalled(Options.class);
+        for (Options opts : sl) {
+            for (OptionDescriptor desc : opts) {
+                if (isHotSpotOption(desc)) {
+                    String name = desc.getName();
+                    OptionDescriptor existing = options.put(name, desc);
+                    assert existing == null : "Option named \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + desc.getLocation();
+                }
+            }
+        }
+    }
+
+    /**
+     * Determines if a given option is a HotSpot command line option.
+     */
+    public static boolean isHotSpotOption(OptionDescriptor desc) {
+        return desc.getClass().getName().startsWith("com.oracle.graal");
+    }
+
+    /**
+     * Loads default option value overrides from a {@code graal.options} file if it exists. Each
+     * line in this file starts with {@code "#"} and is ignored or must have the format of a Graal
+     * command line option without the leading {@code "-G:"} prefix. These option value are set
+     * prior to processing of any Graal options present on the command line.
+     */
+    private static void loadOptionOverrides() throws InternalError {
+        String javaHome = System.getProperty("java.home");
+        Path graalDotOptions = Paths.get(javaHome, "lib", "graal.options");
+        if (!exists(graalDotOptions)) {
+            graalDotOptions = Paths.get(javaHome, "jre", "lib", "graal.options");
+        }
+        if (exists(graalDotOptions)) {
+            try {
+                for (String line : Files.readAllLines(graalDotOptions, Charset.defaultCharset())) {
+                    if (!line.startsWith("#")) {
+                        if (!setOption(line)) {
+                            throw new InternalError("Invalid option \"" + line + "\" specified in " + graalDotOptions);
+                        }
+                    }
+                }
+            } catch (IOException e) {
+                throw (InternalError) new InternalError().initCause(e);
+            }
+        }
+    }
 
     static {
-        ServiceLoader<OptionProvider> sl = ServiceLoader.loadInstalled(OptionProvider.class);
-        for (OptionProvider provider : sl) {
-            String name = provider.getName();
-            options.put(name, provider);
-        }
+        initializeOptions();
+        loadOptionOverrides();
     }
 
     // Called from VM code
@@ -49,7 +103,7 @@
         }
 
         Object value = null;
-        String fieldName = null;
+        String optionName = null;
         String valueString = null;
 
         if (option.equals("+PrintFlags")) {
@@ -59,34 +113,35 @@
 
         char first = option.charAt(0);
         if (first == '+' || first == '-') {
-            fieldName = option.substring(1);
+            optionName = option.substring(1);
             value = (first == '+');
         } else {
             int index = option.indexOf('=');
             if (index == -1) {
-                fieldName = option;
+                optionName = option;
                 valueString = null;
             } else {
-                fieldName = option.substring(0, index);
+                optionName = option.substring(0, index);
                 valueString = option.substring(index + 1);
             }
         }
 
-        OptionProvider optionProvider = options.get(fieldName);
-        if (optionProvider == null) {
-            return setOptionLegacy(option, fieldName, value, valueString);
+        OptionDescriptor desc = options.get(optionName);
+        if (desc == null) {
+            Logger.info("Could not find option " + optionName + " (use -G:+PrintFlags to see Graal options)");
+            return false;
         }
 
-        Class<?> optionType = optionProvider.getType();
+        Class<?> optionType = desc.getType();
 
         if (value == null) {
             if (optionType == Boolean.TYPE || optionType == Boolean.class) {
-                Logger.info("Value for boolean option '" + fieldName + "' must use '-G:+" + fieldName + "' or '-G:-" + fieldName + "' format");
+                Logger.info("Value for boolean option '" + optionName + "' must use '-G:+" + optionName + "' or '-G:-" + optionName + "' format");
                 return false;
             }
 
             if (valueString == null) {
-                Logger.info("Value for option '" + fieldName + "' must use '-G:" + fieldName + "=<value>' format");
+                Logger.info("Value for option '" + optionName + "' must use '-G:" + optionName + "=<value>' format");
                 return false;
             }
 
@@ -101,114 +156,33 @@
             }
         } else {
             if (optionType != Boolean.class) {
-                Logger.info("Value for option '" + fieldName + "' must use '-G:" + fieldName + "=<value>' format");
+                Logger.info("Value for option '" + optionName + "' must use '-G:" + optionName + "=<value>' format");
                 return false;
             }
         }
 
         if (value != null) {
-            optionProvider.getOptionValue().setValue(value);
+            OptionValue<?> optionValue = desc.getOptionValue();
+            optionValue.setValue(value);
             // Logger.info("Set option " + fieldName + " to " + value);
         } else {
-            Logger.info("Wrong value \"" + valueString + "\" for option " + fieldName);
+            Logger.info("Wrong value \"" + valueString + "\" for option " + optionName);
             return false;
         }
 
         return true;
     }
 
-    private static boolean setOptionLegacy(String option, String fieldName, Object v, String valueString) {
-        Object value = v;
-        Field f;
-        try {
-            f = GraalOptions.class.getDeclaredField(fieldName);
-            Class<?> fType = f.getType();
-
-            if (value == null) {
-                if (fType == Boolean.TYPE) {
-                    Logger.info("Value for boolean option '" + fieldName + "' must use '-G:+" + fieldName + "' or '-G:-" + fieldName + "' format");
-                    return false;
-                }
-
-                if (valueString == null) {
-                    Logger.info("Value for option '" + fieldName + "' must use '-G:" + fieldName + "=<value>' format");
-                    return false;
-                }
-
-                if (fType == Float.TYPE) {
-                    value = Float.parseFloat(valueString);
-                } else if (fType == Double.TYPE) {
-                    value = Double.parseDouble(valueString);
-                } else if (fType == Integer.TYPE) {
-                    value = Integer.parseInt(valueString);
-                } else if (fType == String.class) {
-                    value = valueString;
-                }
-            } else {
-                if (fType != Boolean.TYPE) {
-                    Logger.info("Value for option '" + fieldName + "' must use '-G:" + fieldName + "=<value>' format");
-                    return false;
-                }
-            }
-
-            if (value != null) {
-                f.setAccessible(true);
-                f.set(null, value);
-                // Logger.info("Set option " + fieldName + " to " + value);
-            } else {
-                Logger.info("Wrong value \"" + valueString + "\" for option " + fieldName);
-                return false;
-            }
-        } catch (SecurityException e) {
-            Logger.info("Security exception when setting option " + option);
-            return false;
-        } catch (NoSuchFieldException e) {
-            Logger.info("Could not find option " + fieldName + " (use -G:+PrintFlags to see Graal options)");
-            return false;
-        } catch (IllegalArgumentException e) {
-            Logger.info("Illegal value for option " + option);
-            return false;
-        } catch (IllegalAccessException e) {
-            Logger.info("Illegal access exception when setting option " + option);
-            return false;
-        }
-
-        return true;
-
-    }
-
     private static void printFlags() {
         Logger.info("[Graal flags]");
-        SortedMap<String, OptionProvider> sortedOptions = new TreeMap<>(options);
-        for (Map.Entry<String, OptionProvider> e : sortedOptions.entrySet()) {
+        SortedMap<String, OptionDescriptor> sortedOptions = new TreeMap<>(options);
+        for (Map.Entry<String, OptionDescriptor> e : sortedOptions.entrySet()) {
             e.getKey();
-            OptionProvider opt = e.getValue();
-            Object value = opt.getOptionValue().getValue();
-            Logger.info(String.format("%9s %-40s = %-14s %s", opt.getType().getSimpleName(), e.getKey(), value, opt.getHelp()));
+            OptionDescriptor desc = e.getValue();
+            Object value = desc.getOptionValue().getValue();
+            Logger.info(String.format("%9s %-40s = %-14s %s", desc.getType().getSimpleName(), e.getKey(), value, desc.getHelp()));
         }
 
-        printFlagsLegacy();
-
         System.exit(0);
     }
-
-    protected static void printFlagsLegacy() {
-        Field[] flags = GraalOptions.class.getDeclaredFields();
-        Arrays.sort(flags, new Comparator<Field>() {
-
-            public int compare(Field o1, Field o2) {
-                return o1.getName().compareTo(o2.getName());
-            }
-        });
-        for (Field f : flags) {
-            if (Modifier.isPublic(f.getModifiers()) && Modifier.isStatic(f.getModifiers())) {
-                f.setAccessible(true);
-                try {
-                    Object value = f.get(null);
-                    Logger.info(String.format("%9s %-40s = %s", f.getType().getSimpleName(), f.getName(), value));
-                } catch (Exception e) {
-                }
-            }
-        }
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Tue Jun 18 10:12:27 2013 +0200
@@ -38,6 +38,7 @@
     public int codeEntryAlignment;
     public boolean verifyOops;
     public boolean ciTime;
+    public int compileThreshold;
     public boolean compileTheWorld;
     public int compileTheWorldStartAt;
     public int compileTheWorldStopAt;
@@ -50,6 +51,13 @@
     public boolean useAESIntrinsics;
     public boolean useG1GC;
 
+    // Compressed Oops related values.
+    public boolean useCompressedOops;
+    public boolean useCompressedKlassPointers;
+    public long narrowOopBase;
+    public int narrowOopShift;
+    public int logMinObjAlignment;
+
     // CPU capabilities
     public int useSSE;
     public int useAVX;
@@ -206,6 +214,12 @@
     public int methodAccessFlagsOffset;
 
     /**
+     * JVM_ACC_QUEUED defined in accessFlags.hpp and used for marking a Method object as queued for
+     * compilation.
+     */
+    public int methodQueuedForCompilationBit;
+
+    /**
      * Offset of _intrinsic_id in a metaspace Method object.
      */
     public int methodIntrinsicIdOffset;
@@ -322,6 +336,11 @@
     public int klassOffset;
 
     /**
+     * The offset of the injected array klass field in a {@link Class}.
+     */
+    public int arrayKlassOffset;
+
+    /**
      * The offset of the injected graal_mirror field in a {@link Class}.
      */
     public int graalMirrorInClassOffset;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Tue Jun 18 10:12:27 2013 +0200
@@ -168,6 +168,8 @@
 
     HotSpotResolvedJavaField[] getInstanceFields(HotSpotResolvedObjectType klass);
 
+    HotSpotResolvedJavaMethod[] getMethods(HotSpotResolvedObjectType klass);
+
     boolean hasFinalizableSubclass(HotSpotResolvedObjectType klass);
 
     /**
@@ -220,8 +222,6 @@
 
     String getFileName(HotSpotResolvedJavaType method);
 
-    void clearQueuedForCompilation(HotSpotResolvedJavaMethod method);
-
     /**
      * Invalidates the profiling information and restarts profiling upon the next invocation.
      * 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Tue Jun 18 10:12:27 2013 +0200
@@ -124,6 +124,9 @@
     public native HotSpotResolvedJavaField[] getInstanceFields(HotSpotResolvedObjectType klass);
 
     @Override
+    public native HotSpotResolvedJavaMethod[] getMethods(HotSpotResolvedObjectType klass);
+
+    @Override
     public native int getCompiledCodeSize(long metaspaceMethod);
 
     @Override
@@ -161,9 +164,6 @@
     public native String getFileName(HotSpotResolvedJavaType method);
 
     @Override
-    public native void clearQueuedForCompilation(HotSpotResolvedJavaMethod method);
-
-    @Override
     public native void reprofile(long metaspaceMethod);
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Tue Jun 18 10:12:27 2013 +0200
@@ -37,19 +37,13 @@
     /**
      * 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;
+    void 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 compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, boolean blocking, int priority) throws Throwable;
 
     void shutdownCompiler() throws Throwable;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Tue Jun 18 10:12:27 2013 +0200
@@ -28,6 +28,7 @@
 import static com.oracle.graal.hotspot.CompilationTask.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.java.GraphBuilderPhase.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.io.*;
 import java.lang.reflect.*;
@@ -51,6 +52,7 @@
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.printer.*;
 import com.oracle.graal.replacements.*;
 
 /**
@@ -71,11 +73,14 @@
     @Option(help = "Print compilation queue activity periodically")
     private static final OptionValue<Boolean> PrintQueue = new OptionValue<>(false);
 
+    @Option(help = "")
+    public static final OptionValue<Integer> SlowQueueCutoff = new OptionValue<>(100000);
+
     @Option(help = "Time limit in milliseconds for bootstrap (-1 for no limit)")
     private static final OptionValue<Integer> TimedBootstrap = new OptionValue<>(-1);
 
     @Option(help = "Number of compilation threads to use")
-    private static final OptionValue<Integer> Threads = new OptionValue<Integer>(1) {
+    private static final StableOptionValue<Integer> Threads = new StableOptionValue<Integer>() {
 
         @Override
         public Integer initialValue() {
@@ -175,13 +180,15 @@
         }
 
         if (DebugEnabled.getValue()) {
-            Debug.enable();
+            DebugEnvironment.initialize(log);
         }
 
+        assert VerifyHotSpotOptionsPhase.checkOptions();
+
         // Install intrinsics.
         final HotSpotRuntime runtime = graalRuntime.getCapability(HotSpotRuntime.class);
         final Replacements replacements = graalRuntime.getCapability(Replacements.class);
-        if (GraalOptions.Intrinsify) {
+        if (Intrinsify.getValue()) {
             Debug.scope("RegisterReplacements", new Object[]{new DebugDumpScope("RegisterReplacements")}, new Runnable() {
 
                 @Override
@@ -191,7 +198,7 @@
                         provider.registerReplacements(runtime, replacements, runtime.getTarget());
                     }
                     runtime.registerReplacements(replacements);
-                    if (GraalOptions.BootstrapReplacements) {
+                    if (BootstrapReplacements.getValue()) {
                         for (ResolvedJavaMethod method : replacements.getAllReplacements()) {
                             replacements.getMacroSubstitution(method);
                             replacements.getMethodSubstitution(method);
@@ -421,7 +428,7 @@
         System.gc();
         phaseTransition("bootstrap2");
 
-        if (GraalOptions.CompileTheWorld != null) {
+        if (CompileTheWorld.getValue() != null) {
             new CompileTheWorld().compile();
             System.exit(0);
         }
@@ -569,24 +576,20 @@
     }
 
     @Override
-    public boolean compileMethod(long metaspaceMethod, final HotSpotResolvedObjectType holder, final int entryBCI, boolean blocking, int priority) throws Throwable {
+    public void compileMethod(long metaspaceMethod, final HotSpotResolvedObjectType holder, final int entryBCI, boolean blocking, int priority) throws Throwable {
         HotSpotResolvedJavaMethod method = holder.createMethod(metaspaceMethod);
-        return compileMethod(method, entryBCI, blocking, priority);
+        compileMethod(method, entryBCI, blocking, priority);
     }
 
     /**
      * 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)
      */
-    public boolean compileMethod(final HotSpotResolvedJavaMethod method, final int entryBCI, boolean blocking, int priority) throws Throwable {
-        CompilationTask current = method.currentTask();
+    public void compileMethod(final HotSpotResolvedJavaMethod method, final int entryBCI, boolean blocking, int priority) throws Throwable {
         boolean osrCompilation = entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI;
         if (osrCompilation && bootstrapRunning) {
             // no OSR compilations during bootstrap - the compiler is just too slow at this point,
             // and we know that there are no endless loops
-            return current != null && (current.isInProgress() || !current.isCancelled());
+            return;
         }
 
         if (CompilationTask.withinEnqueue.get()) {
@@ -594,39 +597,32 @@
             // java.util.concurrent.BlockingQueue is used to implement the compilation worker
             // queues. If a compiler thread triggers a compilation, then it may be blocked trying
             // to add something to its own queue.
-            return current != null && (current.isInProgress() || !current.isCancelled());
+            return;
         }
-        CompilationTask.withinEnqueue.set(Boolean.TRUE);
 
         try {
-            if (!blocking && current != null) {
-                if (current.isInProgress()) {
-                    if (current.getEntryBCI() == entryBCI) {
-                        // a compilation with the correct bci is already in progress, so just return
-                        // true
-                        return true;
-                    }
-                } else {
-                    if (PriorityCompileQueue.getValue()) {
-                        // normally compilation tasks will only be re-queued when they get a
-                        // priority boost, so cancel the old task and add a new one
-                        current.cancel();
-                    } else if (!current.isCancelled()) {
-                        // without a prioritizing compile queue it makes no sense to re-queue the
-                        // compilation task
-                        return true;
-                    }
+            CompilationTask.withinEnqueue.set(Boolean.TRUE);
+            if (!method.tryToQueueForCompilation()) {
+                // method is already queued
+                CompilationTask current = method.currentTask();
+                if (!PriorityCompileQueue.getValue() || current == null || !current.tryToCancel()) {
+                    // normally compilation tasks will only be re-queued when they get a
+                    // priority boost, so cancel the old task and add a new one
+                    // without a prioritizing compile queue it makes no sense to re-queue the
+                    // compilation task
+                    return;
                 }
             }
+            assert method.isQueuedForCompilation();
 
             final OptimisticOptimizations optimisticOpts = new OptimisticOptimizations(method);
             int id = compileTaskIds.incrementAndGet();
             // OSR compilations need to be finished quickly, so they get max priority
             int queuePriority = osrCompilation ? -1 : priority;
             CompilationTask task = CompilationTask.create(graalRuntime, createPhasePlan(optimisticOpts, osrCompilation), optimisticOpts, method, entryBCI, id, queuePriority);
+
             if (blocking) {
                 task.runCompilation();
-                return false;
             } else {
                 try {
                     method.setCurrentTask(task);
@@ -635,10 +631,8 @@
                     } else {
                         compileQueue.execute(task);
                     }
-                    return true;
                 } catch (RejectedExecutionException e) {
                     // The compile queue was already shut down.
-                    return false;
                 }
             }
         } finally {
@@ -767,11 +761,6 @@
         if (onStackReplacement) {
             phasePlan.addPhase(PhasePosition.AFTER_PARSING, new OnStackReplacementPhase());
         }
-        phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierAdditionPhase());
-        if (GraalOptions.VerifyPhases) {
-            phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierVerificationPhase());
-
-        }
         return phasePlan;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.meta;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.io.*;
 import java.lang.ref.*;
 import java.util.*;
@@ -30,7 +32,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.phases.*;
 
 /**
  * This class implements the graph caching system for the HotSpot platform.
@@ -73,12 +74,12 @@
         private static final long serialVersionUID = -3973307040793397840L;
 
         public LRUCache() {
-            super(GraalOptions.GraphCacheSize * 2, 0.75f, false);
+            super(GraphCacheSize.getValue() * 2, 0.75f, false);
         }
 
         @Override
         protected boolean removeEldestEntry(Entry<Long, WeakReference<ResolvedJavaMethod>> eldest) {
-            if (size() > GraalOptions.GraphCacheSize) {
+            if (size() > GraphCacheSize.getValue()) {
                 ResolvedJavaMethod method = eldest.getValue().get();
                 if (method != null) {
                     StructuredGraph cachedGraph = (StructuredGraph) method.getCompilerStorage().get(HotSpotGraphCache.this);
@@ -96,7 +97,7 @@
     private final Map<Long, WeakReference<ResolvedJavaMethod>> cachedGraphIds = Collections.synchronizedMap(new LRUCache());
 
     public HotSpotGraphCache() {
-        if (GraalOptions.PrintGraphCache) {
+        if (PrintGraphCache.getValue()) {
             Runtime.getRuntime().addShutdownHook(new Thread() {
 
                 @Override
@@ -115,7 +116,7 @@
     public StructuredGraph get(ResolvedJavaMethod method) {
         StructuredGraph result = (StructuredGraph) method.getCompilerStorage().get(this);
 
-        if (GraalOptions.PrintGraphCache) {
+        if (PrintGraphCache.getValue()) {
             if (result == null) {
                 missCounter++;
             } else {
@@ -126,13 +127,15 @@
     }
 
     @Override
-    public void put(StructuredGraph graph) {
+    public void put(StructuredGraph graph, boolean hasMatureProfilingInfo) {
         assert graph.method() != null;
-        cachedGraphIds.put(graph.graphId(), new WeakReference<>(graph.method()));
-        graph.method().getCompilerStorage().put(this, graph);
+        if (hasMatureProfilingInfo) {
+            cachedGraphIds.put(graph.graphId(), new WeakReference<>(graph.method()));
+            graph.method().getCompilerStorage().put(this, graph);
 
-        if (GraalOptions.PrintGraphCache) {
-            putCounter++;
+            if (PrintGraphCache.getValue()) {
+                putCounter++;
+            }
         }
     }
 
@@ -161,12 +164,12 @@
                 StructuredGraph cachedGraph = (StructuredGraph) method.getCompilerStorage().get(this);
                 if (cachedGraph != null && cachedGraph.graphId() == graphId) {
                     method.getCompilerStorage().remove(this);
-                    if (GraalOptions.PrintGraphCache) {
+                    if (PrintGraphCache.getValue()) {
                         removeHitCounter++;
                     }
                 }
             }
-            if (GraalOptions.PrintGraphCache) {
+            if (PrintGraphCache.getValue()) {
                 removeCounter++;
             }
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethod.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethod.java	Tue Jun 18 10:12:27 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.*;
 import com.oracle.graal.hotspot.*;
 
@@ -30,8 +32,22 @@
     private static final long serialVersionUID = 7167491397941960839L;
     protected String name;
 
+    /**
+     * Controls whether {@link #toString()} includes the qualified or simple name of the class in
+     * which the method is declared.
+     */
+    public static final boolean FULLY_QUALIFIED_METHOD_NAME = false;
+
     @Override
     public final String getName() {
         return name;
     }
+
+    @Override
+    public final String toString() {
+        char h = FULLY_QUALIFIED_METHOD_NAME ? 'H' : 'h';
+        String suffix = this instanceof ResolvedJavaMethod ? "" : ", unresolved";
+        String fmt = String.format("HotSpotMethod<%%%c.%%n(%%p)%s>", h, suffix);
+        return format(fmt, this);
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Tue Jun 18 10:12:27 2013 +0200
@@ -32,7 +32,6 @@
 import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.phases.*;
 
 /**
  * Access to a HotSpot MethodData structure (defined in methodData.hpp).
@@ -376,7 +375,7 @@
         protected abstract long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position);
 
         private static JavaTypeProfile createTypeProfile(TriState nullSeen, ResolvedJavaType[] types, long[] counts, long totalCount, int entries) {
-            if (entries <= 0 || totalCount < GraalOptions.MatureExecutionsTypeProfile) {
+            if (entries <= 0 || totalCount <= 0) {
                 return null;
             }
 
@@ -484,7 +483,7 @@
         }
 
         private static JavaMethodProfile createMethodProfile(ResolvedJavaMethod[] methods, long[] counts, long totalCount, int entries) {
-            if (entries <= 0 || totalCount < GraalOptions.MatureExecutionsTypeProfile) {
+            if (entries <= 0 || totalCount <= 0) {
                 return null;
             }
 
@@ -540,11 +539,7 @@
             long notTakenCount = data.readUnsignedInt(position, NOT_TAKEN_COUNT_OFFSET);
             long total = takenCount + notTakenCount;
 
-            if (total < GraalOptions.MatureExecutionsBranch) {
-                return -1;
-            } else {
-                return takenCount / (double) total;
-            }
+            return total <= 0 ? -1 : takenCount / (double) total;
         }
 
         @Override
@@ -607,7 +602,7 @@
                 result[i - 1] = count;
             }
 
-            if (totalCount < GraalOptions.MatureExecutionsPerSwitchCase * length) {
+            if (totalCount <= 0) {
                 return null;
             } else {
                 for (int i = 0; i < length; i++) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodUnresolved.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodUnresolved.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.api.meta.MetaUtil.*;
-
 import com.oracle.graal.api.meta.*;
 
 /**
@@ -50,9 +48,4 @@
     public JavaType getDeclaringClass() {
         return holder;
     }
-
-    @Override
-    public String toString() {
-        return format("HotSpotMethod<%H.%n(%p), unresolved>", this);
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java	Tue Jun 18 10:12:27 2013 +0200
@@ -47,10 +47,10 @@
     private final boolean isDefault;
     private final Graph graph;
 
-    public HotSpotNmethod(HotSpotResolvedJavaMethod method, Graph graph, boolean isDefault) {
+    public HotSpotNmethod(HotSpotResolvedJavaMethod method, boolean isDefault, Graph graph) {
         this.method = method;
+        this.isDefault = isDefault;
         this.graph = graph;
-        this.isDefault = isDefault;
     }
 
     public boolean isDefault() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProfilingInfo.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProfilingInfo.java	Tue Jun 18 10:12:27 2013 +0200
@@ -31,23 +31,24 @@
     private static final long serialVersionUID = -8307682725047864875L;
     private static final DebugMetric metricInsufficentSpace = Debug.metric("InsufficientSpaceForProfilingData");
 
+    private final HotSpotMethodData methodData;
+    private final HotSpotResolvedJavaMethod method;
+
     private int position;
     private int hintPosition;
     private int hintBCI;
     private HotSpotMethodDataAccessor dataAccessor;
-    private HotSpotMethodData methodData;
-    private final int codeSize;
 
-    public HotSpotProfilingInfo(HotSpotMethodData methodData, int codeSize) {
+    public HotSpotProfilingInfo(HotSpotMethodData methodData, HotSpotResolvedJavaMethod method) {
         this.methodData = methodData;
-        this.codeSize = codeSize;
+        this.method = method;
         hintPosition = 0;
         hintBCI = -1;
     }
 
     @Override
     public int getCodeSize() {
-        return codeSize;
+        return method.getCodeSize();
     }
 
     @Override
@@ -158,6 +159,11 @@
     }
 
     @Override
+    public boolean isMature() {
+        return true;
+    }
+
+    @Override
     public String toString() {
         return "HotSpotProfilingInfo<" + MetaUtil.profileToString(this, null, "; ") + ">";
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Tue Jun 18 10:12:27 2013 +0200
@@ -25,14 +25,19 @@
 
 import static com.oracle.graal.api.meta.MetaUtil.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
+import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.phases.*;
+import com.oracle.graal.options.*;
 import com.oracle.graal.replacements.*;
+import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
 
 /**
  * Represents a field in a HotSpot type.
@@ -75,15 +80,93 @@
         return (flags & FIELD_INTERNAL_FLAG) != 0;
     }
 
+    /**
+     * If the compiler is configured for AOT mode, {@link #readConstantValue(Constant)} should be
+     * only called for snippets or replacements.
+     */
+    private static boolean isCalledForSnippets() {
+        HotSpotRuntime runtime = graalRuntime().getRuntime();
+
+        ResolvedJavaMethod makeGraphMethod = null;
+        ResolvedJavaMethod initMethod = null;
+        try {
+            Class<?> rjm = ResolvedJavaMethod.class;
+            makeGraphMethod = runtime.lookupJavaMethod(ReplacementsImpl.class.getDeclaredMethod("makeGraph", rjm, rjm, SnippetInliningPolicy.class));
+            initMethod = runtime.lookupJavaMethod(SnippetTemplate.AbstractTemplates.class.getDeclaredMethod("template", Arguments.class));
+        } catch (NoSuchMethodException | SecurityException e) {
+            throw new GraalInternalError(e);
+        }
+        StackTraceElement makeGraphSTE = makeGraphMethod.asStackTraceElement(1);
+        StackTraceElement initSTE = initMethod.asStackTraceElement(30);
+
+        for (StackTraceElement element : new Exception().getStackTrace()) {
+            if (makeGraphSTE.equals(element) || initSTE.equals(element)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static final Set<ResolvedJavaField> notEmbeddable = new HashSet<>();
+
+    private static void addResolvedToSet(Field field) {
+        HotSpotRuntime runtime = graalRuntime().getRuntime();
+        notEmbeddable.add(runtime.lookupJavaField(field));
+    }
+
+    static {
+        try {
+            addResolvedToSet(Boolean.class.getDeclaredField("TRUE"));
+            addResolvedToSet(Boolean.class.getDeclaredField("FALSE"));
+
+            Class<?> characterCacheClass = Character.class.getDeclaredClasses()[0];
+            assert "java.lang.Character$CharacterCache".equals(characterCacheClass.getName());
+            addResolvedToSet(characterCacheClass.getDeclaredField("cache"));
+
+            Class<?> byteCacheClass = Byte.class.getDeclaredClasses()[0];
+            assert "java.lang.Byte$ByteCache".equals(byteCacheClass.getName());
+            addResolvedToSet(byteCacheClass.getDeclaredField("cache"));
+
+            Class<?> shortCacheClass = Short.class.getDeclaredClasses()[0];
+            assert "java.lang.Short$ShortCache".equals(shortCacheClass.getName());
+            addResolvedToSet(shortCacheClass.getDeclaredField("cache"));
+
+            Class<?> integerCacheClass = Integer.class.getDeclaredClasses()[0];
+            assert "java.lang.Integer$IntegerCache".equals(integerCacheClass.getName());
+            addResolvedToSet(integerCacheClass.getDeclaredField("cache"));
+
+            Class<?> longCacheClass = Long.class.getDeclaredClasses()[0];
+            assert "java.lang.Long$LongCache".equals(longCacheClass.getName());
+            addResolvedToSet(longCacheClass.getDeclaredField("cache"));
+
+            addResolvedToSet(Throwable.class.getDeclaredField("UNASSIGNED_STACK"));
+            addResolvedToSet(Throwable.class.getDeclaredField("SUPPRESSED_SENTINEL"));
+        } catch (SecurityException | NoSuchFieldException e) {
+            throw new GraalInternalError(e);
+        }
+    }
+
+    /**
+     * in AOT mode, some fields should never be embedded even for snippets/replacements.
+     */
+    private boolean isEmbeddable() {
+        if (AOTCompilation.getValue() && notEmbeddable.contains(this)) {
+            return false;
+        }
+        return true;
+    }
+
     private static final String SystemClassName = MetaUtil.toInternalName(System.class.getName());
 
     @Override
     public Constant readConstantValue(Constant receiver) {
+        assert !AOTCompilation.getValue() || isCalledForSnippets();
+
         if (receiver == null) {
             assert Modifier.isStatic(flags);
             if (constant == null) {
-                if (holder.isInitialized() && !holder.getName().equals(SystemClassName)) {
-                    if (Modifier.isFinal(getModifiers()) || assumeStaticFieldsFinal(holder.mirror())) {
+                if (holder.isInitialized() && !holder.getName().equals(SystemClassName) && isEmbeddable()) {
+                    if (Modifier.isFinal(getModifiers())) {
                         constant = readValue(receiver);
                     }
                 }
@@ -95,11 +178,18 @@
              * have a non-default value.
              */
             assert !Modifier.isStatic(flags);
+            Object object = receiver.asObject();
             if (Modifier.isFinal(getModifiers())) {
                 Constant value = readValue(receiver);
-                if (assumeNonStaticFinalFieldsAsFinal(receiver.asObject().getClass()) || !value.isDefaultForKind()) {
+                if (assumeNonStaticFinalFieldsAsFinal(object.getClass()) || !value.isDefaultForKind()) {
                     return value;
                 }
+            } else {
+                Class<?> clazz = object.getClass();
+                if (StableOptionValue.class.isAssignableFrom(clazz)) {
+                    StableOptionValue<?> option = (StableOptionValue<?>) object;
+                    return Constant.forObject(option.getValue());
+                }
             }
         }
         return null;
@@ -119,10 +209,6 @@
         }
     }
 
-    private static boolean assumeStaticFieldsFinal(Class<?> clazz) {
-        return clazz == GraalOptions.class;
-    }
-
     private static boolean assumeNonStaticFinalFieldsAsFinal(Class<?> clazz) {
         return clazz == SnippetCounter.class;
     }
@@ -157,6 +243,15 @@
     }
 
     @Override
+    public boolean isSynthetic() {
+        Field javaField = toJava();
+        if (javaField != null) {
+            return javaField.isSynthetic();
+        }
+        return false;
+    }
+
+    @Override
     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
         Field javaField = toJava();
         if (javaField != null) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.api.meta.MetaUtil.*;
 import static com.oracle.graal.graph.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
@@ -37,7 +37,6 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.debug.*;
-import com.oracle.graal.phases.*;
 
 /**
  * Implementation of {@link JavaMethod} for resolved HotSpot methods.
@@ -259,11 +258,6 @@
         return signature;
     }
 
-    @Override
-    public String toString() {
-        return format("HotSpotMethod<%H.%n(%p)>", this);
-    }
-
     public int getCompiledCodeSize() {
         return graalRuntime().getCompilerToVM().getCompiledCodeSize(metaspaceMethod);
     }
@@ -276,7 +270,7 @@
     public ProfilingInfo getProfilingInfo() {
         ProfilingInfo info;
 
-        if (GraalOptions.UseProfilingInformation && methodData == null) {
+        if (UseProfilingInformation.getValue() && methodData == null) {
             long metaspaceMethodData = unsafeReadWord(metaspaceMethod + graalRuntime().getConfig().methodDataOffset);
             if (metaspaceMethodData != 0) {
                 methodData = new HotSpotMethodData(metaspaceMethodData);
@@ -288,7 +282,7 @@
             // case of a deoptimization.
             info = DefaultProfilingInfo.get(TriState.FALSE);
         } else {
-            info = new HotSpotProfilingInfo(methodData, codeSize);
+            info = new HotSpotProfilingInfo(methodData, this);
         }
         return info;
     }
@@ -332,6 +326,29 @@
     }
 
     @Override
+    public boolean isSynthetic() {
+        if (isConstructor()) {
+            Constructor<?> javaConstructor = toJavaConstructor();
+            return javaConstructor == null ? false : javaConstructor.isSynthetic();
+        }
+
+        // Cannot use toJava() as it ignores the return type
+        HotSpotSignature sig = getSignature();
+        JavaType[] sigTypes = MetaUtil.signatureToTypes(sig, null);
+        HotSpotRuntime runtime = graalRuntime().getRuntime();
+        for (Method method : holder.mirror().getDeclaredMethods()) {
+            if (method.getName().equals(name)) {
+                if (runtime.lookupJavaType(method.getReturnType()).equals(sig.getReturnType(holder))) {
+                    if (matches(runtime, sigTypes, method.getParameterTypes())) {
+                        return method.isSynthetic();
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    @Override
     public Type[] getGenericParameterTypes() {
         if (isConstructor()) {
             Constructor javaConstructor = toJavaConstructor();
@@ -351,6 +368,18 @@
         return result;
     }
 
+    private static boolean matches(HotSpotRuntime runtime, JavaType[] sigTypes, Class<?>[] parameterTypes) {
+        if (parameterTypes.length == sigTypes.length) {
+            for (int i = 0; i < parameterTypes.length; i++) {
+                if (!runtime.lookupJavaType(parameterTypes[i]).equals(sigTypes[i])) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
     private Method toJava() {
         try {
             return holder.mirror().getDeclaredMethod(name, signatureToTypes());
@@ -475,4 +504,43 @@
             throw new IllegalArgumentException(ex);
         }
     }
+
+    public boolean tryToQueueForCompilation() {
+        // other threads may update certain bits of the access flags field concurrently. So, the
+        // loop ensures that this method only returns false when another thread has set the
+        // queuedForCompilation bit.
+        do {
+            long address = getAccessFlagsAddress();
+            int actualValue = unsafe.getInt(address);
+            int expectedValue = actualValue & ~graalRuntime().getConfig().methodQueuedForCompilationBit;
+            if (actualValue != expectedValue) {
+                return false;
+            } else {
+                int newValue = expectedValue | graalRuntime().getConfig().methodQueuedForCompilationBit;
+                boolean success = unsafe.compareAndSwapInt(null, address, expectedValue, newValue);
+                if (success) {
+                    return true;
+                }
+            }
+        } while (true);
+    }
+
+    public void clearQueuedForCompilation() {
+        long address = getAccessFlagsAddress();
+        boolean success;
+        do {
+            int actualValue = unsafe.getInt(address);
+            int newValue = actualValue & ~graalRuntime().getConfig().methodQueuedForCompilationBit;
+            assert isQueuedForCompilation() : "queued for compilation must be set";
+            success = unsafe.compareAndSwapInt(null, address, actualValue, newValue);
+        } while (!success);
+    }
+
+    public boolean isQueuedForCompilation() {
+        return (unsafe.getInt(getAccessFlagsAddress()) & graalRuntime().getConfig().methodQueuedForCompilationBit) != 0;
+    }
+
+    private long getAccessFlagsAddress() {
+        return metaspaceMethod + graalRuntime().getConfig().methodAccessFlagsOffset;
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Tue Jun 18 10:12:27 2013 +0200
@@ -541,6 +541,15 @@
         return result;
     }
 
+    /**
+     * Gets all methods and constructors declared by this class, including the {@code <clinit>}
+     * method if there is one. The latter is not made accessible via standard Java reflection.
+     */
+    public ResolvedJavaMethod[] getMethods() {
+        HotSpotResolvedJavaMethod[] methods = graalRuntime().getCompilerToVM().getMethods(this);
+        return methods;
+    }
+
     @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	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Tue Jun 18 10:12:27 2013 +0200
@@ -37,8 +37,6 @@
 import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*;
 import static com.oracle.graal.hotspot.nodes.NewMultiArrayStubCall.*;
 import static com.oracle.graal.hotspot.nodes.VMErrorNode.*;
-import static com.oracle.graal.hotspot.nodes.WriteBarrierPostStubCall.*;
-import static com.oracle.graal.hotspot.nodes.WriteBarrierPreStubCall.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.MonitorSnippets.*;
 import static com.oracle.graal.hotspot.replacements.SystemSubstitutions.*;
@@ -50,6 +48,7 @@
 import static com.oracle.graal.hotspot.stubs.UnwindExceptionToCallerStub.*;
 import static com.oracle.graal.java.GraphBuilderPhase.RuntimeCalls.*;
 import static com.oracle.graal.nodes.java.RegisterFinalizerNode.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.Log.*;
 import static com.oracle.graal.replacements.MathSubstitutionsX86.*;
 
@@ -72,19 +71,21 @@
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.bridge.CompilerToVM.CodeInstallResult;
 import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.hotspot.phases.*;
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.HeapAccess.WriteBarrierType;
 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.*;
+import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
-import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.printer.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.word.*;
@@ -92,7 +93,7 @@
 /**
  * HotSpot implementation of {@link GraalCodeCacheProvider}.
  */
-public abstract class HotSpotRuntime implements GraalCodeCacheProvider, DisassemblerProvider, BytecodeDisassemblerProvider {
+public abstract class HotSpotRuntime implements GraalCodeCacheProvider, DisassemblerProvider, BytecodeDisassemblerProvider, SuitesProvider {
 
     public static final ForeignCallDescriptor OSR_MIGRATION_END = new ForeignCallDescriptor("OSR_migration_end", void.class, long.class);
     public static final ForeignCallDescriptor IDENTITY_HASHCODE = new ForeignCallDescriptor("identity_hashcode", int.class, Object.class);
@@ -103,6 +104,7 @@
 
     protected final RegisterConfig regConfig;
     protected final HotSpotGraalRuntime graalRuntime;
+    private final Suites defaultSuites;
 
     private CheckCastSnippets.Templates checkcastSnippets;
     private InstanceOfSnippets.Templates instanceofSnippets;
@@ -178,6 +180,7 @@
         this.config = c;
         this.graalRuntime = graalRuntime;
         regConfig = createRegisterConfig();
+        defaultSuites = createSuites();
     }
 
     protected abstract RegisterConfig createRegisterConfig();
@@ -284,8 +287,6 @@
         linkForeignCall(r, CREATE_OUT_OF_BOUNDS_EXCEPTION, c.createOutOfBoundsExceptionAddress, PREPEND_THREAD, REEXECUTABLE, ANY_LOCATION);
         linkForeignCall(r, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
         linkForeignCall(r, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
-        linkForeignCall(r, WRITE_BARRIER_PRE, c.writeBarrierPreAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
-        linkForeignCall(r, WRITE_BARRIER_POST, c.writeBarrierPostAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
         linkForeignCall(r, NEW_MULTI_ARRAY, c.newMultiArrayAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
         linkForeignCall(r, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
         linkForeignCall(r, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
@@ -294,26 +295,26 @@
         linkForeignCall(r, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
         linkForeignCall(r, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, NOT_REEXECUTABLE, NO_LOCATIONS);
 
-        if (GraalOptions.IntrinsifyObjectMethods) {
+        if (IntrinsifyObjectMethods.getValue()) {
             r.registerSubstitutions(ObjectSubstitutions.class);
         }
-        if (GraalOptions.IntrinsifySystemMethods) {
+        if (IntrinsifySystemMethods.getValue()) {
             r.registerSubstitutions(SystemSubstitutions.class);
         }
-        if (GraalOptions.IntrinsifyThreadMethods) {
+        if (IntrinsifyThreadMethods.getValue()) {
             r.registerSubstitutions(ThreadSubstitutions.class);
         }
-        if (GraalOptions.IntrinsifyUnsafeMethods) {
+        if (IntrinsifyUnsafeMethods.getValue()) {
             r.registerSubstitutions(UnsafeSubstitutions.class);
         }
-        if (GraalOptions.IntrinsifyClassMethods) {
+        if (IntrinsifyClassMethods.getValue()) {
             r.registerSubstitutions(ClassSubstitutions.class);
         }
-        if (GraalOptions.IntrinsifyAESMethods) {
+        if (IntrinsifyAESMethods.getValue()) {
             r.registerSubstitutions(AESCryptSubstitutions.class);
             r.registerSubstitutions(CipherBlockChainingSubstitutions.class);
         }
-        if (GraalOptions.IntrinsifyReflectionMethods) {
+        if (IntrinsifyReflectionMethods.getValue()) {
             r.registerSubstitutions(ReflectionSubstitutions.class);
         }
 
@@ -476,7 +477,8 @@
         if (n instanceof ArrayLengthNode) {
             ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n;
             ValueNode array = arrayLengthNode.array();
-            ReadNode arrayLengthRead = graph.add(new ReadNode(array, ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, config.arrayLengthOffset, graph), StampFactory.positiveInt()));
+            ReadNode arrayLengthRead = graph.add(new ReadNode(array, ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, config.arrayLengthOffset, graph), StampFactory.positiveInt(),
+                            WriteBarrierType.NONE, false));
             tool.createNullCheckGuard(arrayLengthRead, array);
             graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead);
         } else if (n instanceof Invoke) {
@@ -491,7 +493,7 @@
                 JavaType[] signature = MetaUtil.signatureToTypes(callTarget.targetMethod().getSignature(), callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass());
 
                 LoweredCallTargetNode loweredCallTarget = null;
-                if (callTarget.invokeKind() == InvokeKind.Virtual && GraalOptions.InlineVTableStubs && (GraalOptions.AlwaysInlineVTableStubs || invoke.isPolymorphic())) {
+                if (callTarget.invokeKind() == InvokeKind.Virtual && InlineVTableStubs.getValue() && (AlwaysInlineVTableStubs.getValue() || invoke.isPolymorphic())) {
 
                     HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod();
                     if (!hsMethod.getDeclaringClass().isInterface()) {
@@ -504,7 +506,7 @@
                             // compiled code entry as HotSpot does not guarantee they are final
                             // values.
                             ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, ConstantLocationNode.create(ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph),
-                                            StampFactory.forKind(wordKind())));
+                                            StampFactory.forKind(wordKind()), WriteBarrierType.NONE, false));
 
                             loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(),
                                             CallingConvention.Type.JavaCall));
@@ -527,7 +529,7 @@
             HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) loadField.field();
             ValueNode object = loadField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), this, graph) : loadField.object();
             assert loadField.kind() != Kind.Illegal;
-            ReadNode memoryRead = graph.add(new ReadNode(object, createFieldLocation(graph, field), loadField.stamp()));
+            ReadNode memoryRead = graph.add(new ReadNode(object, createFieldLocation(graph, field), loadField.stamp(), WriteBarrierType.NONE, (loadField.kind() == Kind.Object)));
             tool.createNullCheckGuard(memoryRead, object);
 
             graph.replaceFixedWithFixed(loadField, memoryRead);
@@ -543,7 +545,7 @@
             HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field();
             ValueNode object = storeField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), this, graph) : storeField.object();
             WriteBarrierType barrierType = getFieldStoreBarrierType(storeField);
-            WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), createFieldLocation(graph, field), barrierType));
+            WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), createFieldLocation(graph, field), barrierType, storeField.field().getKind() == Kind.Object));
             tool.createNullCheckGuard(memoryWrite, object);
             memoryWrite.setStateAfter(storeField.stateAfter());
             graph.replaceFixedWithFixed(storeField, memoryWrite);
@@ -562,12 +564,15 @@
             LocationNode location = IndexedLocationNode.create(ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, 1);
             cas.setLocation(location);
             cas.setWriteBarrierType(getCompareAndSwapBarrier(cas));
+            if (cas.expected().kind() == Kind.Object) {
+                cas.setCompress();
+            }
         } else if (n instanceof LoadIndexedNode) {
             LoadIndexedNode loadIndexed = (LoadIndexedNode) n;
             GuardingNode boundsCheck = createBoundsCheck(loadIndexed, tool);
             Kind elementKind = loadIndexed.elementKind();
             LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index());
-            ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadIndexed.stamp()));
+            ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadIndexed.stamp(), WriteBarrierType.NONE, elementKind == Kind.Object));
             memoryRead.setGuard(boundsCheck);
             graph.replaceFixedWithFixed(loadIndexed, memoryRead);
         } else if (n instanceof StoreIndexedNode) {
@@ -598,7 +603,7 @@
                 }
             }
             WriteBarrierType barrierType = getArrayStoreBarrierType(storeIndexed);
-            WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation, barrierType));
+            WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation, barrierType, elementKind == Kind.Object));
             memoryWrite.setGuard(boundsCheck);
             memoryWrite.setStateAfter(storeIndexed.stateAfter());
             graph.replaceFixedWithFixed(storeIndexed, memoryWrite);
@@ -607,7 +612,10 @@
             UnsafeLoadNode load = (UnsafeLoadNode) n;
             assert load.kind() != Kind.Illegal;
             IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, load.accessKind(), load.displacement(), load.offset(), graph, 1);
-            ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp()));
+            // Unsafe Accesses to the metaspace or to any
+            // absolute address do not perform uncompression.
+            boolean compress = (!load.object().isNullConstant() && load.accessKind() == Kind.Object);
+            ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), WriteBarrierType.NONE, compress));
             // An unsafe read must not floating outside its block as may float above an explicit
             // null check on its object.
             memoryRead.setGuard(AbstractBeginNode.prevBegin(load));
@@ -617,7 +625,7 @@
             IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, store.accessKind(), store.displacement(), store.offset(), graph, 1);
             ValueNode object = store.object();
             WriteBarrierType barrierType = getUnsafeStoreBarrierType(store);
-            WriteNode write = graph.add(new WriteNode(object, store.value(), location, barrierType));
+            WriteNode write = graph.add(new WriteNode(object, store.value(), location, barrierType, store.value().kind() == Kind.Object));
             write.setStateAfter(store.stateAfter());
             graph.replaceFixedWithFixed(store, write);
         } else if (n instanceof LoadHubNode) {
@@ -633,103 +641,115 @@
             graph.replaceFixed(loadMethodNode, metaspaceMethod);
         } else if (n instanceof FixedGuardNode) {
             FixedGuardNode node = (FixedGuardNode) n;
-            ValueAnchorNode newAnchor = graph.add(new ValueAnchorNode(tool.createGuard(node.condition(), node.getReason(), node.getAction(), node.isNegated()).asNode()));
+            GuardingNode guard = tool.createGuard(node.condition(), node.getReason(), node.getAction(), node.isNegated());
+            ValueAnchorNode newAnchor = graph.add(new ValueAnchorNode(guard.asNode()));
+            node.replaceAtUsages(guard.asNode());
             graph.replaceFixedWithFixed(node, newAnchor);
         } else if (n instanceof CommitAllocationNode) {
-            CommitAllocationNode commit = (CommitAllocationNode) n;
+            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+                CommitAllocationNode commit = (CommitAllocationNode) n;
 
-            ValueNode[] allocations = new ValueNode[commit.getVirtualObjects().size()];
-            for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
-                VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex);
-                int entryCount = virtual.entryCount();
+                ValueNode[] allocations = new ValueNode[commit.getVirtualObjects().size()];
+                for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
+                    VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex);
+                    int entryCount = virtual.entryCount();
 
-                FixedWithNextNode newObject;
-                if (virtual instanceof VirtualInstanceNode) {
-                    newObject = graph.add(new NewInstanceNode(virtual.type(), true));
-                } else {
-                    ResolvedJavaType element = ((VirtualArrayNode) virtual).componentType();
-                    newObject = graph.add(new NewArrayNode(element, ConstantNode.forInt(entryCount, graph), true));
+                    FixedWithNextNode newObject;
+                    if (virtual instanceof VirtualInstanceNode) {
+                        newObject = graph.add(new NewInstanceNode(virtual.type(), true));
+                    } else {
+                        ResolvedJavaType element = ((VirtualArrayNode) virtual).componentType();
+                        newObject = graph.add(new NewArrayNode(element, ConstantNode.forInt(entryCount, graph), true));
+                    }
+                    graph.addBeforeFixed(commit, newObject);
+                    allocations[objIndex] = newObject;
                 }
-                graph.addBeforeFixed(commit, newObject);
-                allocations[objIndex] = newObject;
-            }
-            int valuePos = 0;
-            for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
-                VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex);
-                int entryCount = virtual.entryCount();
+                int valuePos = 0;
+                for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
+                    VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex);
+                    int entryCount = virtual.entryCount();
 
-                ValueNode newObject = allocations[objIndex];
-                if (virtual instanceof VirtualInstanceNode) {
-                    VirtualInstanceNode instance = (VirtualInstanceNode) virtual;
-                    for (int i = 0; i < entryCount; i++) {
-                        ValueNode value = commit.getValues().get(valuePos++);
-                        if (value instanceof VirtualObjectNode) {
-                            value = allocations[commit.getVirtualObjects().indexOf(value)];
-                        }
-                        if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
-                            graph.addBeforeFixed(commit, graph.add(new WriteNode(newObject, value, createFieldLocation(graph, (HotSpotResolvedJavaField) instance.field(i)), WriteBarrierType.NONE)));
+                    ValueNode newObject = allocations[objIndex];
+                    if (virtual instanceof VirtualInstanceNode) {
+                        VirtualInstanceNode instance = (VirtualInstanceNode) virtual;
+                        for (int i = 0; i < entryCount; i++) {
+                            ValueNode value = commit.getValues().get(valuePos++);
+                            if (value instanceof VirtualObjectNode) {
+                                value = allocations[commit.getVirtualObjects().indexOf(value)];
+                            }
+                            if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
+                                WriteNode write = new WriteNode(newObject, value, createFieldLocation(graph, (HotSpotResolvedJavaField) instance.field(i)), WriteBarrierType.NONE,
+                                                instance.field(i).getKind() == Kind.Object);
+
+                                graph.addBeforeFixed(commit, graph.add(write));
+                            }
                         }
-                    }
-                } else {
-                    VirtualArrayNode array = (VirtualArrayNode) virtual;
-                    ResolvedJavaType element = array.componentType();
-                    for (int i = 0; i < entryCount; i++) {
-                        ValueNode value = commit.getValues().get(valuePos++);
-                        if (value instanceof VirtualObjectNode) {
-                            int indexOf = commit.getVirtualObjects().indexOf(value);
-                            assert indexOf != -1 : commit + " " + value;
-                            value = allocations[indexOf];
-                        }
-                        if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
-                            graph.addBeforeFixed(commit,
-                                            graph.add(new WriteNode(newObject, value, createArrayLocation(graph, element.getKind(), ConstantNode.forInt(i, graph)), WriteBarrierType.NONE)));
+
+                    } else {
+                        VirtualArrayNode array = (VirtualArrayNode) virtual;
+                        ResolvedJavaType element = array.componentType();
+                        for (int i = 0; i < entryCount; i++) {
+                            ValueNode value = commit.getValues().get(valuePos++);
+                            if (value instanceof VirtualObjectNode) {
+                                int indexOf = commit.getVirtualObjects().indexOf(value);
+                                assert indexOf != -1 : commit + " " + value;
+                                value = allocations[indexOf];
+                            }
+                            if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
+                                WriteNode write = new WriteNode(newObject, value, createArrayLocation(graph, element.getKind(), ConstantNode.forInt(i, graph)), WriteBarrierType.NONE,
+                                                value.kind() == Kind.Object);
+                                graph.addBeforeFixed(commit, graph.add(write));
+                            }
                         }
                     }
                 }
-            }
-            for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
-                FixedValueAnchorNode anchor = graph.add(new FixedValueAnchorNode(allocations[objIndex]));
-                allocations[objIndex] = anchor;
-                graph.addBeforeFixed(commit, anchor);
+                for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
+                    FixedValueAnchorNode anchor = graph.add(new FixedValueAnchorNode(allocations[objIndex]));
+                    allocations[objIndex] = anchor;
+                    graph.addBeforeFixed(commit, anchor);
+                }
+                for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
+                    for (int lockDepth : commit.getLocks().get(objIndex)) {
+                        MonitorEnterNode enter = graph.add(new MonitorEnterNode(allocations[objIndex], lockDepth));
+                        graph.addBeforeFixed(commit, enter);
+                    }
+                }
+                for (Node usage : commit.usages().snapshot()) {
+                    AllocatedObjectNode addObject = (AllocatedObjectNode) usage;
+                    int index = commit.getVirtualObjects().indexOf(addObject.getVirtualObject());
+                    graph.replaceFloating(addObject, allocations[index]);
+                }
+                graph.removeFixed(commit);
             }
-            for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
-                for (int lockDepth : commit.getLocks().get(objIndex)) {
-                    MonitorEnterNode enter = graph.add(new MonitorEnterNode(allocations[objIndex], lockDepth));
-                    graph.addBeforeFixed(commit, enter);
-                }
-            }
-            for (Node usage : commit.usages().snapshot()) {
-                AllocatedObjectNode addObject = (AllocatedObjectNode) usage;
-                int index = commit.getVirtualObjects().indexOf(addObject.getVirtualObject());
-                graph.replaceFloating(addObject, allocations[index]);
-            }
-            graph.removeFixed(commit);
         } else if (n instanceof CheckCastNode) {
             checkcastSnippets.lower((CheckCastNode) n, tool);
         } else if (n instanceof OSRStartNode) {
-            OSRStartNode osrStart = (OSRStartNode) n;
-            StartNode newStart = graph.add(new StartNode());
-            LocalNode buffer = graph.unique(new LocalNode(0, StampFactory.forKind(wordKind())));
-            ForeignCallNode migrationEnd = graph.add(new ForeignCallNode(this, OSR_MIGRATION_END, buffer));
-            migrationEnd.setStateAfter(osrStart.stateAfter());
+            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+                OSRStartNode osrStart = (OSRStartNode) n;
+                StartNode newStart = graph.add(new StartNode());
+                LocalNode buffer = graph.unique(new LocalNode(0, StampFactory.forKind(wordKind())));
+                ForeignCallNode migrationEnd = graph.add(new ForeignCallNode(this, OSR_MIGRATION_END, buffer));
+                migrationEnd.setStateAfter(osrStart.stateAfter());
 
-            newStart.setNext(migrationEnd);
-            FixedNode next = osrStart.next();
-            osrStart.setNext(null);
-            migrationEnd.setNext(next);
-            graph.setStart(newStart);
+                newStart.setNext(migrationEnd);
+                FixedNode next = osrStart.next();
+                osrStart.setNext(null);
+                migrationEnd.setNext(next);
+                graph.setStart(newStart);
 
-            // mirroring the calculations in c1_GraphBuilder.cpp (setup_osr_entry_block)
-            int localsOffset = (graph.method().getMaxLocals() - 1) * 8;
-            for (OSRLocalNode osrLocal : graph.getNodes(OSRLocalNode.class)) {
-                int size = FrameStateBuilder.stackSlots(osrLocal.kind());
-                int offset = localsOffset - (osrLocal.index() + size - 1) * 8;
-                UnsafeLoadNode load = graph.add(new UnsafeLoadNode(buffer, offset, ConstantNode.forInt(0, graph), osrLocal.kind()));
-                osrLocal.replaceAndDelete(load);
-                graph.addBeforeFixed(migrationEnd, load);
+                // mirroring the calculations in c1_GraphBuilder.cpp (setup_osr_entry_block)
+                int localsOffset = (graph.method().getMaxLocals() - 1) * 8;
+                for (OSRLocalNode osrLocal : graph.getNodes(OSRLocalNode.class)) {
+                    int size = FrameStateBuilder.stackSlots(osrLocal.kind());
+                    int offset = localsOffset - (osrLocal.index() + size - 1) * 8;
+                    IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, osrLocal.kind(), offset, ConstantNode.forLong(0, graph), graph, 1);
+                    ReadNode load = graph.add(new ReadNode(buffer, location, osrLocal.stamp(), WriteBarrierType.NONE, false));
+                    osrLocal.replaceAndDelete(load);
+                    graph.addBeforeFixed(migrationEnd, load);
+                }
+                osrStart.replaceAtUsages(newStart);
+                osrStart.safeDelete();
             }
-            osrStart.replaceAtUsages(newStart);
-            osrStart.safeDelete();
         } else if (n instanceof CheckCastDynamicNode) {
             checkcastSnippets.lower((CheckCastDynamicNode) n);
         } else if (n instanceof InstanceOfNode) {
@@ -737,19 +757,33 @@
         } else if (n instanceof InstanceOfDynamicNode) {
             instanceofSnippets.lower((InstanceOfDynamicNode) n, tool);
         } else if (n instanceof NewInstanceNode) {
-            newObjectSnippets.lower((NewInstanceNode) n);
+            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+                newObjectSnippets.lower((NewInstanceNode) n);
+            }
         } else if (n instanceof NewArrayNode) {
-            newObjectSnippets.lower((NewArrayNode) n);
+            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+                newObjectSnippets.lower((NewArrayNode) n);
+            }
+        } else if (n instanceof DynamicNewArrayNode) {
+            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+                newObjectSnippets.lower((DynamicNewArrayNode) n);
+            }
         } else if (n instanceof MonitorEnterNode) {
-            monitorSnippets.lower((MonitorEnterNode) n, tool);
+            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+                monitorSnippets.lower((MonitorEnterNode) n, tool);
+            }
         } else if (n instanceof MonitorExitNode) {
-            monitorSnippets.lower((MonitorExitNode) n, tool);
+            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+                monitorSnippets.lower((MonitorExitNode) 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 NewMultiArrayNode) {
-            newObjectSnippets.lower((NewMultiArrayNode) n);
+            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+                newObjectSnippets.lower((NewMultiArrayNode) n);
+            }
         } else if (n instanceof LoadExceptionObjectNode) {
             exceptionObjectSnippets.lower((LoadExceptionObjectNode) n);
         } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) {
@@ -776,14 +810,15 @@
         assert vtableEntryOffset > 0;
         // We use LocationNode.ANY_LOCATION for the reads that access the vtable
         // entry as HotSpot does not guarantee that this is a final value.
-        ReadNode metaspaceMethod = graph.add(new ReadNode(hub, ConstantLocationNode.create(ANY_LOCATION, wordKind, vtableEntryOffset, graph), StampFactory.forKind(wordKind())));
+        ReadNode metaspaceMethod = graph.add(new ReadNode(hub, ConstantLocationNode.create(ANY_LOCATION, wordKind, vtableEntryOffset, graph), StampFactory.forKind(wordKind()), WriteBarrierType.NONE,
+                        false));
         return metaspaceMethod;
     }
 
     private ReadNode createReadHub(LoweringTool tool, StructuredGraph graph, Kind wordKind, ValueNode object) {
         LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.hubOffset, graph);
         assert !object.isConstant() || object.asConstant().isNull();
-        ReadNode hub = graph.add(new ReadNode(object, location, StampFactory.forKind(wordKind())));
+        ReadNode hub = graph.add(new ReadNode(object, location, StampFactory.forKind(wordKind()), WriteBarrierType.NONE, false));
         tool.createNullCheckGuard(hub, object);
         return hub;
     }
@@ -834,8 +869,16 @@
         return ConstantLocationNode.create(field, field.getKind(), field.offset(), graph);
     }
 
+    public int getScalingFactor(Kind kind) {
+        if (config.useCompressedOops && kind == Kind.Object) {
+            return this.graalRuntime.getTarget().arch.getSizeInBytes(Kind.Int);
+        } else {
+            return this.graalRuntime.getTarget().arch.getSizeInBytes(kind);
+        }
+    }
+
     protected IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index) {
-        int scale = this.graalRuntime.getTarget().arch.getSizeInBytes(elementKind);
+        int scale = getScalingFactor(elementKind);
         return IndexedLocationNode.create(NamedLocationIdentity.getArrayLocation(elementKind), elementKind, getArrayBaseOffset(elementKind), index, graph, scale);
     }
 
@@ -879,8 +922,8 @@
         return graalRuntime.getCompilerToVM().getJavaField(reflectionField);
     }
 
-    public HotSpotInstalledCode installMethod(HotSpotResolvedJavaMethod method, Graph graph, int entryBCI, CompilationResult compResult) {
-        HotSpotInstalledCode installedCode = new HotSpotNmethod(method, graph, true);
+    public HotSpotInstalledCode installMethod(HotSpotResolvedJavaMethod method, int entryBCI, CompilationResult compResult) {
+        HotSpotInstalledCode installedCode = new HotSpotNmethod(method, true, null);
         graalRuntime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(method, entryBCI, compResult), installedCode, method.getSpeculationLog());
         return installedCode;
     }
@@ -893,7 +936,7 @@
     @Override
     public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, Graph graph) {
         HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method;
-        HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, graph, false);
+        HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, false, graph);
         CodeInstallResult result = graalRuntime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(hotspotMethod, -1, compResult), code, null);
         if (result != CodeInstallResult.OK) {
             return null;
@@ -999,7 +1042,7 @@
     }
 
     public boolean canDeoptimize(ForeignCallDescriptor descriptor) {
-        return !foreignCalls.get(descriptor).isLeaf();
+        return foreignCalls.get(descriptor).canDeoptimize();
     }
 
     public LocationIdentity[] getKilledLocations(ForeignCallDescriptor descriptor) {
@@ -1022,4 +1065,27 @@
     public String disassemble(ResolvedJavaMethod method) {
         return new BytecodeDisassembler().disassemble(method);
     }
+
+    public Suites getDefaultSuites() {
+        return defaultSuites;
+    }
+
+    public Suites createSuites() {
+        Suites ret = Suites.createDefaultSuites();
+
+        if (AOTCompilation.getValue()) {
+            // lowering introduces class constants, therefore it must be after lowering
+            ret.getHighTier().appendPhase(new LoadJavaMirrorWithKlassPhase());
+            if (VerifyPhases.getValue()) {
+                ret.getHighTier().appendPhase(new AheadOfTimeVerifcationPhase());
+            }
+        }
+
+        ret.getMidTier().appendPhase(new WriteBarrierAdditionPhase());
+        if (VerifyPhases.getValue()) {
+            ret.getMidTier().appendPhase(new WriteBarrierVerificationPhase());
+        }
+
+        return ret;
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotNmethodExecuteNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotNmethodExecuteNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -58,7 +58,7 @@
             InvokeNode invoke = replaceWithInvoke(tool.getRuntime());
             StructuredGraph graph = (StructuredGraph) nmethod.getGraph();
             if (graph != null) {
-                InliningUtil.inline(invoke, (StructuredGraph) nmethod.getGraph(), false);
+                InliningUtil.inline(invoke, graph, false);
             }
         } else {
             replaceWithInvoke(tool.getRuntime());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java	Tue Jun 18 10:12:27 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.hotspot.nodes;
+
+import com.oracle.graal.api.code.*;
+
+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.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Node for a {@linkplain ForeignCallDescriptor foreign} call from within a stub.
+ */
+@NodeInfo(nameTemplate = "StubForeignCall#{p#descriptor/s}")
+public class StubForeignCallNode extends FixedWithNextNode implements DeoptimizingNode, LIRLowerable, MemoryCheckpoint {
+
+    @Input private final NodeInputList<ValueNode> arguments;
+    private final MetaAccessProvider runtime;
+    @Input private FrameState deoptState;
+
+    private final ForeignCallDescriptor descriptor;
+
+    public StubForeignCallNode(MetaAccessProvider runtime, ForeignCallDescriptor descriptor, ValueNode... arguments) {
+        super(StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType())));
+        this.arguments = new NodeInputList<>(this, arguments);
+        this.descriptor = descriptor;
+        this.runtime = runtime;
+    }
+
+    public ForeignCallDescriptor getDescriptor() {
+        return descriptor;
+    }
+
+    @Override
+    public LocationIdentity[] getLocationIdentities() {
+        return runtime.getKilledLocations(descriptor);
+    }
+
+    protected Value[] operands(LIRGeneratorTool gen) {
+        Value[] operands = new Value[arguments.size()];
+        for (int i = 0; i < operands.length; i++) {
+            operands[i] = gen.operand(arguments.get(i));
+        }
+        return operands;
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool gen) {
+        assert graph().start() instanceof StubStartNode;
+        ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(descriptor);
+        Value[] operands = operands(gen);
+        Value result = gen.emitForeignCall(linkage, this, operands);
+        if (result != null) {
+            gen.setResult(this, result);
+        }
+    }
+
+    @Override
+    public String toString(Verbosity verbosity) {
+        if (verbosity == Verbosity.Name) {
+            return super.toString(verbosity) + "#" + descriptor;
+        }
+        return super.toString(verbosity);
+    }
+
+    @Override
+    public boolean canDeoptimize() {
+        return false;
+    }
+
+    @Override
+    public FrameState getDeoptimizationState() {
+        return null;
+    }
+
+    @Override
+    public void setDeoptimizationState(FrameState state) {
+    }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return null;
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPost.java	Tue Jun 18 10:11:28 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +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 WriteBarrierPost extends FixedWithNextNode implements Lowerable {
-
-    @Input private ValueNode object;
-    @Input private ValueNode value;
-    @Input private LocationNode location;
-    private final boolean precise;
-
-    public ValueNode getObject() {
-        return object;
-    }
-
-    public ValueNode getValue() {
-        return value;
-    }
-
-    public LocationNode getLocation() {
-        return location;
-    }
-
-    public boolean usePrecise() {
-        return precise;
-    }
-
-    public WriteBarrierPost(ValueNode object, ValueNode value, LocationNode location, boolean precise) {
-        super(StampFactory.forVoid());
-        this.object = object;
-        this.value = value;
-        this.location = location;
-        this.precise = precise;
-    }
-
-    public void lower(LoweringTool generator, LoweringType loweringType) {
-        generator.getRuntime().lower(this, generator);
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPostStubCall.java	Tue Jun 18 10:11:28 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +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.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.word.*;
-
-/**
- * A call to {@code GraalRuntime::write_barrier_post}.
- */
-public class WriteBarrierPostStubCall extends FixedWithNextNode implements LIRGenLowerable {
-
-    @Input private ValueNode object;
-    @Input private ValueNode card;
-    public static final ForeignCallDescriptor WRITE_BARRIER_POST = new ForeignCallDescriptor("writeBarrierPost", void.class, Object.class, Word.class);
-
-    public WriteBarrierPostStubCall(ValueNode object, ValueNode card) {
-        super(StampFactory.forVoid());
-        this.object = object;
-        this.card = card;
-    }
-
-    @Override
-    public void generate(LIRGenerator gen) {
-        ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(WriteBarrierPostStubCall.WRITE_BARRIER_POST);
-        gen.emitForeignCall(linkage, null, gen.operand(object), gen.operand(card));
-    }
-
-    @NodeIntrinsic
-    public static native void call(Object hub, Word card);
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPre.java	Tue Jun 18 10:11:28 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +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 WriteBarrierPre extends FixedWithNextNode implements Lowerable {
-
-    @Input private ValueNode object;
-    @Input private LocationNode location;
-    @Input private ValueNode expectedObject;
-    private final boolean doLoad;
-
-    public ValueNode getObject() {
-        return object;
-    }
-
-    public ValueNode getExpectedObject() {
-        return expectedObject;
-    }
-
-    public boolean doLoad() {
-        return doLoad;
-    }
-
-    public LocationNode getLocation() {
-        return location;
-    }
-
-    public WriteBarrierPre(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad) {
-        super(StampFactory.forVoid());
-        this.object = object;
-        this.doLoad = doLoad;
-        this.location = location;
-        this.expectedObject = expectedObject;
-    }
-
-    public void lower(LoweringTool generator, LoweringType loweringType) {
-        generator.getRuntime().lower(this, generator);
-    }
-
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPreStubCall.java	Tue Jun 18 10:11:28 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +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.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
-
-/**
- * A call to {@code GraalRuntime::write_barrier_pre}.
- */
-public class WriteBarrierPreStubCall extends FixedWithNextNode implements LIRGenLowerable {
-
-    @Input private ValueNode object;
-    public static final ForeignCallDescriptor WRITE_BARRIER_PRE = new ForeignCallDescriptor("writeBarrierPre", void.class, Object.class);
-
-    public WriteBarrierPreStubCall(ValueNode object) {
-        super(StampFactory.forVoid());
-        this.object = object;
-    }
-
-    @Override
-    public void generate(LIRGenerator gen) {
-        ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(WriteBarrierPreStubCall.WRITE_BARRIER_PRE);
-        gen.emitForeignCall(linkage, null, gen.operand(object));
-    }
-
-    @NodeIntrinsic
-    public static native void call(Object hub);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerifcationPhase.java	Tue Jun 18 10:12:27 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.hotspot.phases;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+
+/**
+ * Checking for embedded oops in the graph. (Interned) Strings are an exception as they live in CDS
+ * space.
+ * 
+ * @see LoadJavaMirrorWithKlassPhase
+ */
+public class AheadOfTimeVerifcationPhase extends VerifyPhase {
+
+    @Override
+    protected boolean verify(StructuredGraph graph) {
+        for (ConstantNode node : graph.getNodes().filter(ConstantNode.class)) {
+            assert !isOop(node) || isNullReference(node) || isString(node) : "embedded oop: " + node;
+        }
+        return true;
+    }
+
+    private static boolean isOop(ConstantNode node) {
+        return node.kind() == Kind.Object;
+    }
+
+    private static boolean isNullReference(ConstantNode node) {
+        return isOop(node) && node.asConstant().asObject() == null;
+    }
+
+    private static boolean isString(ConstantNode node) {
+        return isOop(node) && node.asConstant().asObject() instanceof String;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -0,0 +1,67 @@
+/*
+ * 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.phases;
+
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.tiers.*;
+
+/**
+ * For AOT compilation we aren't allowed to use a class reference (javaMirror) directly. Instead the
+ * class reference should be obtained from the klass object. The reason for this is, that in CDS a
+ * klass object is mapped to a fixed address in memory, but the javaMirror is not (which lives in
+ * the java heap).
+ * 
+ * Lowering can introduce new ConstantNodes containing a class reference, thus this phase must be
+ * applied after lowering.
+ */
+public class LoadJavaMirrorWithKlassPhase extends BasePhase<PhaseContext> {
+
+    @Override
+    protected void run(StructuredGraph graph, PhaseContext context) {
+        for (ConstantNode node : graph.getNodes().filter(ConstantNode.class)) {
+            Constant constant = node.asConstant();
+            if (constant.getKind() == Kind.Object && constant.asObject() instanceof Class<?>) {
+                ResolvedJavaType type = context.getRuntime().lookupJavaType((Class<?>) constant.asObject());
+                assert type instanceof HotSpotResolvedObjectType;
+
+                HotSpotRuntime runtime = (HotSpotRuntime) context.getRuntime();
+
+                Constant klass = ((HotSpotResolvedObjectType) type).klass();
+                ConstantNode klassNode = ConstantNode.forConstant(klass, runtime, graph);
+
+                Stamp stamp = StampFactory.exactNonNull(runtime.lookupJavaType(Class.class));
+                LocationNode location = graph.unique(ConstantLocationNode.create(FINAL_LOCATION, stamp.kind(), runtime.config.classMirrorOffset, graph));
+                FloatingReadNode freadNode = graph.add(new FloatingReadNode(klassNode, location, null, stamp));
+
+                graph.replaceFloating(node, freadNode);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/VerifyHotSpotOptionsPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -0,0 +1,142 @@
+/*
+ * 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.phases;
+
+import static com.oracle.graal.api.meta.MetaUtil.*;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static java.lang.reflect.Modifier.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.java.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.options.*;
+import com.oracle.graal.phases.*;
+
+/**
+ * Verifies that a class that declares one or more HotSpot {@linkplain OptionValue options} has a
+ * class initializer that only initializes the option(s). This sanity check prevents an option being
+ * read to initialize some global state before it is parsed on the command line. The latter occurs
+ * if an option declaring class has a class initializer that reads options or triggers other class
+ * initializers that read options.
+ */
+public class VerifyHotSpotOptionsPhase extends Phase {
+
+    public static boolean checkOptions() {
+        HotSpotRuntime runtime = graalRuntime().getRuntime();
+        ServiceLoader<Options> sl = ServiceLoader.loadInstalled(Options.class);
+        Set<HotSpotResolvedObjectType> checked = new HashSet<>();
+        for (Options opts : sl) {
+            for (OptionDescriptor desc : opts) {
+                if (HotSpotOptions.isHotSpotOption(desc)) {
+                    HotSpotResolvedObjectType holder = (HotSpotResolvedObjectType) runtime.lookupJavaType(desc.getDeclaringClass());
+                    if (!checked.contains(holder)) {
+                        checked.add(holder);
+                        for (ResolvedJavaMethod method : holder.getMethods()) {
+                            if (method.isClassInitializer()) {
+                                StructuredGraph graph = new StructuredGraph(method);
+                                new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
+                                new VerifyHotSpotOptionsPhase(holder, runtime).apply(graph);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return true;
+    }
+
+    private final HotSpotRuntime runtime;
+    private final ResolvedJavaType declaringClass;
+    private final ResolvedJavaType optionValueType;
+    private final Set<ResolvedJavaType> boxingTypes;
+
+    public VerifyHotSpotOptionsPhase(ResolvedJavaType declaringClass, HotSpotRuntime runtime) {
+        this.runtime = runtime;
+        this.declaringClass = declaringClass;
+        this.optionValueType = runtime.lookupJavaType(OptionValue.class);
+        this.boxingTypes = new HashSet<>();
+        for (Class c : new Class[]{Boolean.class, Byte.class, Short.class, Character.class, Integer.class, Float.class, Long.class, Double.class}) {
+            this.boxingTypes.add(runtime.lookupJavaType(c));
+        }
+    }
+
+    /**
+     * Checks whether a given method is allowed to be called.
+     */
+    private boolean checkInvokeTarget(ResolvedJavaMethod method) {
+        ResolvedJavaType holder = method.getDeclaringClass();
+        if (method.isConstructor()) {
+            if (optionValueType.isAssignableFrom(holder)) {
+                return true;
+            }
+        } else if (boxingTypes.contains(holder)) {
+            return method.getName().equals("valueOf");
+        } else if (method.getDeclaringClass() == runtime.lookupJavaType(Class.class)) {
+            return method.getName().equals("desiredAssertionStatus");
+        } else if (method.getDeclaringClass().equals(declaringClass)) {
+            return (method.getName().equals("$jacocoInit"));
+        }
+        return false;
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (ValueNode node : graph.getNodes().filter(ValueNode.class)) {
+            if (node instanceof StoreFieldNode) {
+                HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) ((StoreFieldNode) node).field();
+                verify(field.getDeclaringClass() == declaringClass, node, "store to field " + format("%H.%n", field));
+                verify(isStatic(field.getModifiers()), node, "store to field " + format("%H.%n", field));
+                if (optionValueType.isAssignableFrom((ResolvedJavaType) field.getType())) {
+                    verify(isFinal(field.getModifiers()), node, "option field " + format("%H.%n", field) + " not final");
+                } else {
+                    verify((field.isSynthetic()), node, "store to non-synthetic field " + format("%H.%n", field));
+                }
+            } else if (node instanceof Invoke) {
+                Invoke invoke = (Invoke) node;
+                MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget();
+                ResolvedJavaMethod targetMethod = callTarget.targetMethod();
+                verify(checkInvokeTarget(targetMethod), node, "invocation of " + format("%H.%n(%p)", targetMethod));
+            }
+        }
+    }
+
+    private void verify(boolean condition, Node node, String message) {
+        if (!condition) {
+            error(node, message);
+        }
+    }
+
+    private void error(Node node, String message) {
+        String loc = GraphUtil.approxSourceLocation(node);
+        throw new GraalInternalError(String.format("HotSpot option declarer %s contains code pattern implying action other than initialization of an option:%n    %s%n    %s",
+                        toJavaName(declaringClass), loc, message));
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -23,8 +23,8 @@
 package com.oracle.graal.hotspot.phases;
 
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.HeapAccess.WriteBarrierType;
 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.*;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -27,8 +27,8 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.HeapAccess.WriteBarrierType;
 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.*;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import sun.misc.*;
 
@@ -67,7 +66,8 @@
     }
 
     private static void crypt(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset, boolean encrypt) {
-        Word kAddr = Word.fromObject(rcvr).readWord(Word.unsigned(kOffset), ANY_LOCATION).add(arrayBaseOffset(Kind.Byte));
+        Object kObject = UnsafeLoadNode.load(rcvr, 0, kOffset, Kind.Object);
+        Word kAddr = (Word) Word.fromObject(kObject).add(arrayBaseOffset(Kind.Byte));
         Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset);
         Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset);
         if (encrypt) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.Node.IterableNodeType;
@@ -29,7 +31,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 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.*;
@@ -83,14 +84,14 @@
         // the canonicalization before loop unrolling is needed to propagate the length into
         // additions, etc.
         HighTierContext context = new HighTierContext(tool.getRuntime(), tool.assumptions(), tool.getReplacements());
-        new CanonicalizerPhase().apply(snippetGraph, context);
-        new LoopFullUnrollPhase().apply(snippetGraph, context);
-        new CanonicalizerPhase().apply(snippetGraph, context);
+        new CanonicalizerPhase(true).apply(snippetGraph, context);
+        new LoopFullUnrollPhase(true).apply(snippetGraph, context);
+        new CanonicalizerPhase(true).apply(snippetGraph, context);
     }
 
     @Override
     protected StructuredGraph getSnippetGraph(LoweringTool tool) {
-        if (!GraalOptions.IntrinsifyArrayCopy) {
+        if (!IntrinsifyArrayCopy.getValue()) {
             return null;
         }
 
@@ -115,10 +116,22 @@
         return position >= 0 && position + length <= virtualObject.entryCount();
     }
 
-    private static boolean checkEntryTypes(int srcPos, int length, State srcState, ResolvedJavaType destComponentType) {
+    private static boolean checkEntryTypes(int srcPos, int length, State srcState, ResolvedJavaType destComponentType, VirtualizerTool tool) {
         if (destComponentType.getKind() == Kind.Object) {
             for (int i = 0; i < length; i++) {
-                if (!destComponentType.isAssignableFrom(srcState.getEntry(srcPos + i).objectStamp().type())) {
+                ValueNode entry = srcState.getEntry(srcPos + i);
+                State state = tool.getObjectState(entry);
+                ResolvedJavaType type;
+                if (state != null) {
+                    if (state.getState() == EscapeState.Virtual) {
+                        type = state.getVirtualObject().type();
+                    } else {
+                        type = state.getMaterializedValue().objectStamp().type();
+                    }
+                } else {
+                    type = entry.objectStamp().type();
+                }
+                if (type == null || !destComponentType.isAssignableFrom(type)) {
                     return false;
                 }
             }
@@ -138,10 +151,16 @@
             if (srcState != null && srcState.getState() == EscapeState.Virtual && destState != null && destState.getState() == EscapeState.Virtual) {
                 VirtualObjectNode srcVirtual = srcState.getVirtualObject();
                 VirtualObjectNode destVirtual = destState.getVirtualObject();
+                if (!(srcVirtual instanceof VirtualArrayNode) || !(destVirtual instanceof VirtualArrayNode)) {
+                    return;
+                }
+                if (((VirtualArrayNode) srcVirtual).componentType().getKind() != Kind.Object || ((VirtualArrayNode) destVirtual).componentType().getKind() != Kind.Object) {
+                    return;
+                }
                 if (length < 0 || !checkBounds(srcPos, length, srcVirtual) || !checkBounds(destPos, length, destVirtual)) {
                     return;
                 }
-                if (!checkEntryTypes(srcPos, length, srcState, destVirtual.type().getComponentType())) {
+                if (!checkEntryTypes(srcPos, length, srcState, destVirtual.type().getComponentType(), tool)) {
                     return;
                 }
                 for (int i = 0; i < length; i++) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Tue Jun 18 10:12:27 2013 +0200
@@ -24,6 +24,7 @@
 
 import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
 import java.lang.reflect.*;
@@ -314,12 +315,12 @@
         }
     }
 
-    private static final SnippetCounter.Group checkCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("System.arraycopy checkInputs") : null;
+    private static final SnippetCounter.Group checkCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("System.arraycopy checkInputs") : null;
     private static final SnippetCounter checkSuccessCounter = new SnippetCounter(checkCounters, "checkSuccess", "checkSuccess");
     private static final SnippetCounter checkNPECounter = new SnippetCounter(checkCounters, "checkNPE", "checkNPE");
     private static final SnippetCounter checkAIOOBECounter = new SnippetCounter(checkCounters, "checkAIOOBE", "checkAIOOBE");
 
-    private static final SnippetCounter.Group counters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("System.arraycopy") : null;
+    private static final SnippetCounter.Group counters = SnippetCounters.getValue() ? new SnippetCounter.Group("System.arraycopy") : null;
     private static final SnippetCounter byteCounter = new SnippetCounter(counters, "byte[]", "arraycopy for byte[] arrays");
     private static final SnippetCounter charCounter = new SnippetCounter(counters, "char[]", "arraycopy for char[] arrays");
     private static final SnippetCounter shortCounter = new SnippetCounter(counters, "short[]", "arraycopy for short[] arrays");
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.lang.invoke.*;
 
 import com.oracle.graal.api.code.*;
@@ -29,14 +31,13 @@
 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(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) {
-        if (GraalOptions.IntrinsifyCallSiteTarget) {
+        if (IntrinsifyCallSiteTarget.getValue()) {
             replacements.registerSubstitutions(ConstantCallSiteSubstitutions.class);
             replacements.registerSubstitutions(MutableCallSiteSubstitutions.class);
             replacements.registerSubstitutions(VolatileCallSiteSubstitutions.class);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java	Tue Jun 18 10:12:27 2013 +0200
@@ -27,6 +27,7 @@
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*;
 import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
@@ -39,7 +40,6 @@
 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.ConstantParameter;
 import com.oracle.graal.replacements.Snippet.VarargsParameter;
@@ -168,16 +168,14 @@
             StructuredGraph graph = checkcast.graph();
             ValueNode object = checkcast.object();
             HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) checkcast.type();
-            TypeCheckHints hintInfo = new TypeCheckHints(checkcast.type(), checkcast.profile(), tool.assumptions(), GraalOptions.CheckcastMinHintHitProbability, GraalOptions.CheckcastMaxHints);
+            TypeCheckHints hintInfo = new TypeCheckHints(checkcast.type(), checkcast.profile(), tool.assumptions(), CheckcastMinHintHitProbability.getValue(), CheckcastMaxHints.getValue());
             ValueNode hub = ConstantNode.forConstant(type.klass(), runtime, checkcast.graph());
 
             Arguments args;
-            if (hintInfo.exact) {
-                ConstantNode[] hints = createHints(hintInfo, runtime, true, graph).hubs;
-                assert hints.length == 1;
+            if (hintInfo.exact != null) {
                 args = new Arguments(exact);
                 args.add("object", object);
-                args.add("exactHub", hints[0]);
+                args.add("exactHub", ConstantNode.forConstant(((HotSpotResolvedObjectType) hintInfo.exact).klass(), runtime, graph));
             } else if (type.isPrimaryType()) {
                 args = new Arguments(primary);
                 args.add("hub", hub);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import sun.misc.*;
 
@@ -63,7 +62,7 @@
 
     @MethodSubstitution(isStatic = false)
     static void encrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
-        Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset), ANY_LOCATION);
+        Object embeddedCipher = UnsafeLoadNode.load(rcvr, 0, embeddedCipherOffset, Kind.Object);
         if (getAESCryptClass().isInstance(embeddedCipher)) {
             crypt(rcvr, in, inOffset, inLength, out, outOffset, embeddedCipher, true);
         } else {
@@ -73,7 +72,7 @@
 
     @MethodSubstitution(isStatic = false)
     static void decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
-        Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset), ANY_LOCATION);
+        Object embeddedCipher = UnsafeLoadNode.load(rcvr, 0, embeddedCipherOffset, Kind.Object);
         if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
             crypt(rcvr, in, inOffset, inLength, out, outOffset, embeddedCipher, false);
         } else {
@@ -82,8 +81,10 @@
     }
 
     private static void crypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset, Object embeddedCipher, boolean encrypt) {
-        Word kAddr = Word.fromObject(embeddedCipher).readWord(Word.unsigned(AESCryptSubstitutions.kOffset), ANY_LOCATION).add(arrayBaseOffset(Kind.Byte));
-        Word rAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(rOffset), ANY_LOCATION).add(arrayBaseOffset(Kind.Byte));
+        Object kObject = UnsafeLoadNode.load(embeddedCipher, 0, AESCryptSubstitutions.kOffset, Kind.Object);
+        Object rObject = UnsafeLoadNode.load(rcvr, 0, rOffset, Kind.Object);
+        Word kAddr = (Word) Word.fromObject(kObject).add(arrayBaseOffset(Kind.Byte));
+        Word rAddr = (Word) Word.fromObject(rObject).add(arrayBaseOffset(Kind.Byte));
         Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset);
         Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset);
         if (encrypt) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNmethodIntrinsics.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNmethodIntrinsics.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,18 +22,19 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.phases.*;
 
 @ServiceProvider(ReplacementsProvider.class)
 public class HotSpotNmethodIntrinsics implements ReplacementsProvider {
 
     @Override
     public void registerReplacements(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) {
-        if (GraalOptions.IntrinsifyInstalledCodeMethods) {
+        if (IntrinsifyInstalledCodeMethods.getValue()) {
             replacements.registerSubstitutions(HotSpotNmethodSubstitutions.class);
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Tue Jun 18 10:12:27 2013 +0200
@@ -443,6 +443,13 @@
         return loadHubIntrinsic(object, getWordKind());
     }
 
+    /**
+     * Loads the hub from a object.
+     */
+    public static Word loadHubNoNullcheck(Object object) {
+        return loadWordFromObject(object, hubOffset());
+    }
+
     public static Object verifyOop(Object object) {
         if (verifyOops()) {
             verifyOopStub(VERIFY_OOP, object);
@@ -514,6 +521,11 @@
     }
 
     @Fold
+    public static int arrayKlassOffset() {
+        return config().arrayKlassOffset;
+    }
+
+    @Fold
     public static int classMirrorOffset() {
         return config().classMirrorOffset;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,12 +22,17 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.api.code.DeoptimizationAction.*;
+import static com.oracle.graal.api.meta.DeoptimizationReason.*;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.Hints;
 import com.oracle.graal.nodes.*;
@@ -54,6 +59,54 @@
 public class InstanceOfSnippets implements Snippets {
 
     /**
+     * Gets the minimum required probability of a profiled instanceof hitting one the profiled types
+     * for use of the {@linkplain #instanceofWithProfile deoptimizing} snippet. The value is
+     * computed to be an order of magnitude greater than the configured compilation threshold. For
+     * example, if a method is compiled after being interpreted 10000 times, the deoptimizing
+     * snippet will only be used for an instanceof if its profile indicates that less than 1 in
+     * 100000 executions are for an object whose type is not one of the top N profiled types (where
+     * {@code N == } {@link GraalOptions#InstanceOfMaxHints}).
+     */
+    public static double hintHitProbabilityThresholdForDeoptimizingSnippet() {
+        return 1.0D - (1.0D / (graalRuntime().getConfig().compileThreshold * 10));
+    }
+
+    /**
+     * A test against a set of hints derived from a profile with very close to 100% precise coverage
+     * of seen types. This snippet deoptimizes on hint miss paths.
+     * 
+     * @see #hintHitProbabilityThresholdForDeoptimizingSnippet()
+     */
+    @Snippet
+    public static Object instanceofWithProfile(Object object, @VarargsParameter Word[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue,
+                    @ConstantParameter boolean checkNull, @ConstantParameter boolean nullSeen) {
+        if (probability(NOT_FREQUENT_PROBABILITY, checkNull && object == null)) {
+            isNull.inc();
+            if (!nullSeen) {
+                // In this case, the execution is contradicting the profile
+                // so invalidating and re-profiling is justified.
+                DeoptimizeNode.deopt(InvalidateReprofile, OptimizedTypeCheckViolated);
+            }
+            return falseValue;
+        }
+        Word objectHub = loadHub(object);
+        // if we get an exact match: succeed immediately
+        ExplodeLoopNode.explodeLoop();
+        for (int i = 0; i < hints.length; i++) {
+            Word hintHub = hints[i];
+            boolean positive = hintIsPositive[i];
+            if (probability(NOT_FREQUENT_PROBABILITY, hintHub.equal(objectHub))) {
+                hintsHit.inc();
+                return positive ? trueValue : falseValue;
+            }
+        }
+        // Don't throw away the code as we assume this is a rare event
+        // that will periodically occur.
+        DeoptimizeNode.deopt(DeoptimizationAction.None, OptimizedTypeCheckViolated);
+        return falseValue;
+    }
+
+    /**
      * A test against a final type.
      */
     @Snippet
@@ -136,6 +189,7 @@
 
     public static class Templates extends InstanceOfSnippetsTemplates {
 
+        private final SnippetInfo instanceofWithProfile = snippet(InstanceOfSnippets.class, "instanceofWithProfile");
         private final SnippetInfo instanceofExact = snippet(InstanceOfSnippets.class, "instanceofExact");
         private final SnippetInfo instanceofPrimary = snippet(InstanceOfSnippets.class, "instanceofPrimary");
         private final SnippetInfo instanceofSecondary = snippet(InstanceOfSnippets.class, "instanceofSecondary");
@@ -150,17 +204,22 @@
             if (replacer.instanceOf instanceof InstanceOfNode) {
                 InstanceOfNode instanceOf = (InstanceOfNode) replacer.instanceOf;
                 ValueNode object = instanceOf.object();
-                TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), instanceOf.profile(), tool.assumptions(), GraalOptions.InstanceOfMinHintHitProbability, GraalOptions.InstanceOfMaxHints);
+                TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), instanceOf.profile(), tool.assumptions(), InstanceOfMinHintHitProbability.getValue(), InstanceOfMaxHints.getValue());
                 final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) instanceOf.type();
                 ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, instanceOf.graph());
 
                 Arguments args;
-                if (hintInfo.exact) {
-                    ConstantNode[] hints = createHints(hintInfo, runtime, true, hub.graph()).hubs;
-                    assert hints.length == 1;
+
+                if (hintInfo.hintHitProbability >= hintHitProbabilityThresholdForDeoptimizingSnippet()) {
+                    Hints hints = createHints(hintInfo, runtime, false, hub.graph());
+                    args = new Arguments(instanceofWithProfile);
+                    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);
+                } else if (hintInfo.exact != null) {
                     args = new Arguments(instanceofExact);
                     args.add("object", object);
-                    args.add("exactHub", hints[0]);
+                    args.add("exactHub", ConstantNode.forConstant(((HotSpotResolvedObjectType) hintInfo.exact).klass(), runtime, hub.graph()));
                 } else if (type.isPrimaryType()) {
                     args = new Arguments(instanceofPrimary);
                     args.add("hub", hub);
@@ -177,6 +236,9 @@
                 args.add("trueValue", replacer.trueValue);
                 args.add("falseValue", replacer.falseValue);
                 args.addConst("checkNull", !object.stamp().nonNull());
+                if (hintInfo.hintHitProbability >= hintHitProbabilityThresholdForDeoptimizingSnippet()) {
+                    args.addConst("nullSeen", hintInfo.profile.getNullSeen() != TriState.FALSE);
+                }
                 return args;
 
             } else {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Tue Jun 18 10:12:27 2013 +0200
@@ -107,7 +107,7 @@
             } else {
                 // The bias pattern is present in the object's mark word. Need to check
                 // whether the bias owner and the epoch are both still current.
-                Word hub = loadHub(object);
+                Word hub = loadHubNoNullcheck(object);
                 final Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION);
                 final Word thread = thread();
                 final Word tmp = prototypeMarkWord.or(thread).xor(mark).and(~ageMaskInPlace());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Tue Jun 18 10:12:27 2013 +0200
@@ -27,6 +27,7 @@
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.nodes.extended.UnsafeArrayCastNode.*;
 import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 import static com.oracle.graal.replacements.nodes.ExplodeLoopNode.*;
@@ -40,7 +41,6 @@
 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.ConstantParameter;
 import com.oracle.graal.replacements.Snippet.VarargsParameter;
@@ -121,6 +121,33 @@
         return unsafeArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic(), anchorNode);
     }
 
+    @Snippet
+    public static Object allocateArrayDynamic(Class<?> elementType, int length, @ConstantParameter boolean fillContents) {
+        Word hub = loadWordFromObject(elementType, arrayKlassOffset());
+        if (hub.equal(Word.zero())) {
+            // the array class is not yet loaded
+            DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.Unresolved);
+        }
+
+        int layoutHelper = readLayoutHelper(hub);
+        //@formatter:off
+        // For arrays, layout helper is a negative number, containing four
+        // distinct bytes, as follows:
+        //    MSB:[tag, hsz, ebt, log2(esz)]:LSB
+        // where:
+        //    tag is 0x80 if the elements are oops, 0xC0 if non-oops
+        //    hsz is array header size in bytes (i.e., offset of first element)
+        //    ebt is the BasicType of the elements
+        //    esz is the element size in bytes
+        //@formatter:on
+
+        int headerSize = (layoutHelper >> 16) & 0xFF;
+        int log2ElementSize = layoutHelper & 0xFF;
+        Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION);
+
+        return allocateArray(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents);
+    }
+
     /**
      * 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
@@ -201,6 +228,7 @@
 
         private final SnippetInfo allocateInstance = snippet(NewObjectSnippets.class, "allocateInstance");
         private final SnippetInfo allocateArray = snippet(NewObjectSnippets.class, "allocateArray");
+        private final SnippetInfo allocateArrayDynamic = snippet(NewObjectSnippets.class, "allocateArrayDynamic");
         private final SnippetInfo newmultiarray = snippet(NewObjectSnippets.class, "newmultiarray");
 
         public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) {
@@ -238,7 +266,7 @@
             Kind elementKind = elementType.getKind();
             ConstantNode hub = ConstantNode.forConstant(arrayType.klass(), runtime, graph);
             final int headerSize = HotSpotRuntime.getArrayBaseOffset(elementKind);
-            int log2ElementSize = CodeUtil.log2(target.arch.getSizeInBytes(elementKind));
+            int log2ElementSize = CodeUtil.log2(((HotSpotRuntime) runtime).getScalingFactor(elementKind));
 
             Arguments args = new Arguments(allocateArray);
             args.add("hub", hub);
@@ -253,6 +281,16 @@
             template.instantiate(runtime, newArrayNode, DEFAULT_REPLACER, args);
         }
 
+        public void lower(DynamicNewArrayNode newArrayNode) {
+            Arguments args = new Arguments(allocateArrayDynamic);
+            args.add("elementType", newArrayNode.getElementType());
+            args.add("length", newArrayNode.length());
+            args.addConst("fillContents", newArrayNode.fillContents());
+
+            SnippetTemplate template = template(args);
+            template.instantiate(runtime, newArrayNode, DEFAULT_REPLACER, args);
+        }
+
         public void lower(NewMultiArrayNode newmultiarrayNode) {
             StructuredGraph graph = newmultiarrayNode.graph();
             int rank = newmultiarrayNode.dimensionCount();
@@ -278,12 +316,12 @@
         }
     }
 
-    private static final SnippetCounter.Group countersNew = GraalOptions.SnippetCounters ? new SnippetCounter.Group("NewInstance") : null;
+    private static final SnippetCounter.Group countersNew = SnippetCounters.getValue() ? new SnippetCounter.Group("NewInstance") : null;
     private static final SnippetCounter new_seqInit = new SnippetCounter(countersNew, "tlabSeqInit", "TLAB alloc with unrolled zeroing");
     private static final SnippetCounter new_loopInit = new SnippetCounter(countersNew, "tlabLoopInit", "TLAB alloc with zeroing in a loop");
     private static final SnippetCounter new_stub = new SnippetCounter(countersNew, "stub", "alloc and zeroing via stub");
 
-    private static final SnippetCounter.Group countersNewArray = GraalOptions.SnippetCounters ? new SnippetCounter.Group("NewArray") : null;
+    private static final SnippetCounter.Group countersNewArray = SnippetCounters.getValue() ? new SnippetCounter.Group("NewArray") : null;
     private static final SnippetCounter newarray_loopInit = new SnippetCounter(countersNewArray, "tlabLoopInit", "TLAB alloc with zeroing in a loop");
     private static final SnippetCounter newarray_stub = new SnippetCounter(countersNewArray, "stub", "alloc and zeroing via stub");
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.lang.reflect.*;
 
 import com.oracle.graal.api.code.*;
@@ -31,7 +33,6 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.nodes.*;
 
 public class ObjectCloneNode extends MacroNode implements VirtualizableAllocation, ArrayLengthProvider {
@@ -51,7 +52,7 @@
 
     @Override
     protected StructuredGraph getSnippetGraph(LoweringTool tool) {
-        if (!GraalOptions.IntrinsifyObjectClone) {
+        if (!IntrinsifyObjectClone.getValue()) {
             return null;
         }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java	Tue Jun 18 10:12:27 2013 +0200
@@ -24,6 +24,7 @@
 
 import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
 import java.lang.reflect.*;
@@ -33,7 +34,6 @@
 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.replacements.*;
 import com.oracle.graal.word.*;
 
@@ -117,12 +117,12 @@
         }
     }
 
-    private static final SnippetCounter.Group cloneCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Object.clone") : null;
+    private static final SnippetCounter.Group cloneCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("Object.clone") : null;
     private static final SnippetCounter instanceCloneCounter = new SnippetCounter(cloneCounters, "instanceClone", "clone snippet for instances");
     private static final SnippetCounter arrayCloneCounter = new SnippetCounter(cloneCounters, "arrayClone", "clone snippet for arrays");
     private static final SnippetCounter genericCloneCounter = new SnippetCounter(cloneCounters, "genericClone", "clone snippet for arrays and instances");
 
-    private static final SnippetCounter.Group genericCloneCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Object.clone generic snippet") : null;
+    private static final SnippetCounter.Group genericCloneCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("Object.clone generic snippet") : null;
     private static final SnippetCounter genericInstanceCloneCounter = new SnippetCounter(genericCloneCounters, "genericInstanceClone", "generic clone implementation took instance path");
     private static final SnippetCounter genericArrayCloneCounter = new SnippetCounter(genericCloneCounters, "genericArrayClone", "generic clone implementation took array path");
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,12 +22,13 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.nodes.*;
 
 public class ReflectionGetCallerClassNode extends MacroNode implements Canonicalizable, Lowerable {
@@ -64,7 +65,7 @@
      * @return ConstantNode of the caller class, or null
      */
     private ConstantNode getCallerClassNode(MetaAccessProvider runtime) {
-        if (!GraalOptions.IntrinsifyReflectionMethods) {
+        if (!IntrinsifyReflectionMethods.getValue()) {
             return null;
         }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Tue Jun 18 10:12:27 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot.replacements;
 
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
 import java.util.*;
@@ -32,7 +33,6 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.word.*;
 
@@ -145,7 +145,7 @@
         return metaspaceArray.readWord(metaspaceArrayBaseOffset() + index * wordSize(), LocationIdentity.FINAL_LOCATION);
     }
 
-    private static final SnippetCounter.Group counters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("TypeCheck") : null;
+    private static final SnippetCounter.Group counters = SnippetCounters.getValue() ? new SnippetCounter.Group("TypeCheck") : null;
     static final SnippetCounter hintsHit = new SnippetCounter(counters, "hintsHit", "hit a hint type");
     static final SnippetCounter exactHit = new SnippetCounter(counters, "exactHit", "exact type test succeeded");
     static final SnippetCounter exactMiss = new SnippetCounter(counters, "exactMiss", "exact type test failed");
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java	Tue Jun 18 10:12:27 2013 +0200
@@ -34,7 +34,7 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.Fold;
@@ -127,6 +127,6 @@
 
     public static final ForeignCallDescriptor EXCEPTION_HANDLER_FOR_PC = descriptorFor(ExceptionHandlerStub.class, "exceptionHandlerForPc");
 
-    @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true)
+    @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true)
     public static native Word exceptionHandlerForPc(@ConstantNodeParameter ForeignCallDescriptor exceptionHandlerForPc, Word thread);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Tue Jun 18 10:12:27 2013 +0200
@@ -24,9 +24,9 @@
 
 import static com.oracle.graal.api.code.CallingConvention.Type.*;
 import static com.oracle.graal.api.meta.MetaUtil.*;
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition.*;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
 import java.lang.reflect.*;
 
@@ -40,7 +40,6 @@
 import com.oracle.graal.hotspot.replacements.*;
 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.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
@@ -283,14 +282,14 @@
         return invoke;
     }
 
-    private ForeignCallNode createTargetCall(GraphBuilder builder, LocalNode[] locals, ReadRegisterNode thread) {
+    private StubForeignCallNode createTargetCall(GraphBuilder builder, LocalNode[] locals, ReadRegisterNode thread) {
         if (prependThread) {
             ValueNode[] targetArguments = new ValueNode[1 + locals.length];
             targetArguments[0] = thread;
             System.arraycopy(locals, 0, targetArguments, 1, locals.length);
-            return builder.append(new ForeignCallNode(runtime, target.getDescriptor(), targetArguments));
+            return builder.append(new StubForeignCallNode(runtime, target.getDescriptor(), targetArguments));
         } else {
-            return builder.append(new ForeignCallNode(runtime, target.getDescriptor(), locals));
+            return builder.append(new StubForeignCallNode(runtime, target.getDescriptor(), locals));
         }
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Tue Jun 18 10:12:27 2013 +0200
@@ -36,7 +36,6 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.replacements.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
@@ -122,6 +121,6 @@
 
     public static final ForeignCallDescriptor NEW_ARRAY_C = descriptorFor(NewArrayStub.class, "newArrayC");
 
-    @NodeIntrinsic(ForeignCallNode.class)
+    @NodeIntrinsic(StubForeignCallNode.class)
     public static native void newArrayC(@ConstantNodeParameter ForeignCallDescriptor newArrayC, Word thread, Word hub, int length);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Tue Jun 18 10:12:27 2013 +0200
@@ -37,7 +37,6 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.replacements.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
@@ -242,6 +241,6 @@
 
     public static final ForeignCallDescriptor NEW_INSTANCE_C = descriptorFor(NewInstanceStub.class, "newInstanceC");
 
-    @NodeIntrinsic(ForeignCallNode.class)
+    @NodeIntrinsic(StubForeignCallNode.class)
     public static native void newInstanceC(@ConstantNodeParameter ForeignCallDescriptor newInstanceC, Word thread, Word hub);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Tue Jun 18 10:12:27 2013 +0200
@@ -156,7 +156,7 @@
                     phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
                     CallingConvention cc = linkage.getCallingConvention();
                     final CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, getInstalledCodeOwner(), runtime, replacements, backend, runtime.getTarget(), null, phasePlan,
-                                    OptimisticOptimizations.ALL, new SpeculationLog());
+                                    OptimisticOptimizations.ALL, new SpeculationLog(), runtime.getDefaultSuites());
 
                     assert destroyedRegisters != null;
                     code = Debug.scope("CodeInstall", new Callable<InstalledCode>() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java	Tue Jun 18 10:12:27 2013 +0200
@@ -35,7 +35,6 @@
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.nodes.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.Fold;
 import com.oracle.graal.word.*;
@@ -50,15 +49,15 @@
     public static final ForeignCallDescriptor VM_MESSAGE_C = descriptorFor(StubUtil.class, "vmMessageC");
 
     /**
-     * Looks for a {@link ForeignCallNode} node intrinsic named {@code name} in {@code stubClass}
-     * and returns a {@link ForeignCallDescriptor} based on its signature and the value of
-     * {@code hasSideEffect}.
+     * Looks for a {@link StubForeignCallNode} node intrinsic named {@code name} in
+     * {@code stubClass} and returns a {@link ForeignCallDescriptor} based on its signature and the
+     * value of {@code hasSideEffect}.
      */
     public static ForeignCallDescriptor descriptorFor(Class<?> stubClass, String name) {
         Method found = null;
         for (Method method : stubClass.getDeclaredMethods()) {
             if (Modifier.isStatic(method.getModifiers()) && method.getAnnotation(NodeIntrinsic.class) != null && method.getName().equals(name)) {
-                if (method.getAnnotation(NodeIntrinsic.class).value() == ForeignCallNode.class) {
+                if (method.getAnnotation(NodeIntrinsic.class).value() == StubForeignCallNode.class) {
                     assert found == null : "found more than one foreign call named " + name + " in " + stubClass;
                     assert method.getParameterTypes().length != 0 && method.getParameterTypes()[0] == ForeignCallDescriptor.class : "first parameter of foreign call '" + name + "' in " + stubClass +
                                     " must be of type " + ForeignCallDescriptor.class.getSimpleName();
@@ -81,7 +80,7 @@
         }
     }
 
-    @NodeIntrinsic(ForeignCallNode.class)
+    @NodeIntrinsic(StubForeignCallNode.class)
     private static native void vmMessageC(@ConstantNodeParameter ForeignCallDescriptor stubPrintfC, boolean vmError, Word format, long v1, long v2, long v3);
 
     /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UnwindExceptionToCallerStub.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UnwindExceptionToCallerStub.java	Tue Jun 18 10:12:27 2013 +0200
@@ -34,8 +34,8 @@
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
+import 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.replacements.*;
 import com.oracle.graal.replacements.Snippet.Fold;
@@ -99,6 +99,6 @@
 
     public static final ForeignCallDescriptor EXCEPTION_HANDLER_FOR_RETURN_ADDRESS = descriptorFor(UnwindExceptionToCallerStub.class, "exceptionHandlerForReturnAddress");
 
-    @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true)
+    @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true)
     public static native Word exceptionHandlerForReturnAddress(@ConstantNodeParameter ForeignCallDescriptor exceptionHandlerForReturnAddress, Word thread, Word returnAddress);
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Tue Jun 18 10:12:27 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.java;
 
 import static com.oracle.graal.bytecode.Bytecodes.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 
@@ -31,7 +32,6 @@
 import com.oracle.graal.bytecode.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.*;
 
 /**
  * Builds a mapping between bytecodes and basic blocks and builds a conservative control flow graph
@@ -187,7 +187,7 @@
         makeExceptionEntries();
         iterateOverBytecodes();
         if (hasJsrBytecodes) {
-            if (!GraalOptions.SupportJsrBytecodes) {
+            if (!SupportJsrBytecodes.getValue()) {
                 throw new JsrNotSupportedBailout("jsr/ret parsing disabled");
             }
             createJsrAlternatives(blockMap[0]);
@@ -209,7 +209,7 @@
         if (Debug.isLogEnabled()) {
             this.log("Before LivenessAnalysis");
         }
-        if (GraalOptions.OptLivenessAnalysis) {
+        if (OptLivenessAnalysis.getValue()) {
             Debug.scope("LivenessAnalysis", new Runnable() {
 
                 @Override
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Tue Jun 18 10:12:27 2013 +0200
@@ -49,6 +49,10 @@
     private ValueNode[] locks;
 
     private int stackSize;
+
+    /**
+     * @see BytecodeFrame#rethrowException
+     */
     private boolean rethrowException;
 
     public FrameStateBuilder(ResolvedJavaMethod method, StructuredGraph graph, boolean eagerResolve) {
@@ -308,10 +312,16 @@
         }
     }
 
+    /**
+     * @see BytecodeFrame#rethrowException
+     */
     public boolean rethrowException() {
         return rethrowException;
     }
 
+    /**
+     * @see BytecodeFrame#rethrowException
+     */
     public void setRethrowException(boolean b) {
         rethrowException = b;
     }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -27,6 +27,7 @@
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.bytecode.Bytecodes.*;
 import static com.oracle.graal.java.GraphBuilderPhase.RuntimeCalls.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 import static java.lang.reflect.Modifier.*;
 
 import java.lang.reflect.*;
@@ -158,7 +159,7 @@
         methodSynchronizedObject = null;
         this.currentGraph = graph;
         this.frameState = new FrameStateBuilder(method, graph, graphBuilderConfig.eagerResolving());
-        TTY.Filter filter = new TTY.Filter(GraalOptions.PrintFilter, method);
+        TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method);
         try {
             build();
         } finally {
@@ -182,7 +183,7 @@
     }
 
     private void build() {
-        if (GraalOptions.PrintProfilingInformation) {
+        if (PrintProfilingInformation.getValue()) {
             TTY.println("Profiling info for " + method);
             TTY.println(MetaUtil.indent(MetaUtil.profileToString(profilingInfo, method, CodeUtil.NEW_LINE), "  "));
         }
@@ -918,10 +919,10 @@
         }
         BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode());
         BlockPlaceholderNode falseSucc = currentGraph.add(new BlockPlaceholderNode());
-        append(new IfNode(currentGraph.unique(new IsNullNode(receiver)), trueSucc, falseSucc, 0.1));
+        append(new IfNode(currentGraph.unique(new IsNullNode(receiver)), trueSucc, falseSucc, 0.01));
         lastInstr = falseSucc;
 
-        if (GraalOptions.OmitHotExceptionStacktrace) {
+        if (OmitHotExceptionStacktrace.getValue()) {
             ValueNode exception = ConstantNode.forObject(cachedNullPointerException, runtime, currentGraph);
             trueSucc.setNext(handleException(exception, bci()));
         } else {
@@ -942,10 +943,10 @@
     private void emitBoundsCheck(ValueNode index, ValueNode length) {
         BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode());
         BlockPlaceholderNode falseSucc = currentGraph.add(new BlockPlaceholderNode());
-        append(new IfNode(currentGraph.unique(new IntegerBelowThanNode(index, length)), trueSucc, falseSucc, 0.9));
+        append(new IfNode(currentGraph.unique(new IntegerBelowThanNode(index, length)), trueSucc, falseSucc, 0.99));
         lastInstr = trueSucc;
 
-        if (GraalOptions.OmitHotExceptionStacktrace) {
+        if (OmitHotExceptionStacktrace.getValue()) {
             ValueNode exception = ConstantNode.forObject(cachedArrayIndexOutOfBoundsException, runtime, currentGraph);
             falseSucc.setNext(handleException(exception, bci()));
         } else {
@@ -1023,7 +1024,7 @@
         if (target instanceof ResolvedJavaMethod) {
             ResolvedJavaMethod resolvedTarget = (ResolvedJavaMethod) target;
             ResolvedJavaType holder = resolvedTarget.getDeclaringClass();
-            if (!holder.isInitialized() && GraalOptions.ResolveClassBeforeStaticInvoke) {
+            if (!holder.isInitialized() && ResolveClassBeforeStaticInvoke.getValue()) {
                 handleUnresolvedInvoke(target, InvokeKind.Static);
             } else {
                 ValueNode[] args = frameState.popArguments(resolvedTarget.getSignature().getParameterSlots(false), resolvedTarget.getSignature().getParameterCount(false));
@@ -1123,7 +1124,7 @@
 
     private void appendInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args) {
         Kind resultType = targetMethod.getSignature().getReturnKind();
-        if (GraalOptions.DeoptALot) {
+        if (DeoptALot.getValue()) {
             append(new DeoptimizeNode(DeoptimizationAction.None, RuntimeConstraint));
             frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, currentGraph));
             return;
@@ -1766,7 +1767,7 @@
     }
 
     private void traceState() {
-        if (GraalOptions.TraceBytecodeParserLevel >= TRACELEVEL_STATE && Debug.isLogEnabled()) {
+        if (TraceBytecodeParserLevel.getValue() >= TRACELEVEL_STATE && Debug.isLogEnabled()) {
             Debug.log(String.format("|   state [nr locals = %d, stack depth = %d, method = %s]", frameState.localsSize(), frameState.stackSize(), method));
             for (int i = 0; i < frameState.localsSize(); ++i) {
                 ValueNode value = frameState.localAt(i);
@@ -1996,7 +1997,7 @@
     }
 
     private void traceInstruction(int bci, int opcode, boolean blockStart) {
-        if (GraalOptions.TraceBytecodeParserLevel >= TRACELEVEL_INSTRUCTIONS && Debug.isLogEnabled()) {
+        if (TraceBytecodeParserLevel.getValue() >= TRACELEVEL_INSTRUCTIONS && Debug.isLogEnabled()) {
             StringBuilder sb = new StringBuilder(40);
             sb.append(blockStart ? '+' : '|');
             if (bci < 10) {
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 public class AMD64BitManipulationOp extends AMD64LIRInstruction {
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BreakpointOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BreakpointOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 /**
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ByteSwapOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ByteSwapOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -25,7 +25,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 @Opcode("BSWAP")
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java	Tue Jun 18 10:12:27 2013 +0200
@@ -29,7 +29,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.spi.*;
 
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java	Tue Jun 18 10:12:27 2013 +0200
@@ -28,6 +28,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 // @formatter:off
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Tue Jun 18 10:12:27 2013 +0200
@@ -35,7 +35,6 @@
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.StandardOp.FallThroughOp;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.calc.*;
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64MathIntrinsicOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64MathIntrinsicOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -27,6 +27,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 // @formatter:off
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Tue Jun 18 10:12:27 2013 +0200
@@ -33,9 +33,9 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.lir.asm.*;
 
@@ -118,6 +118,31 @@
         }
     }
 
+    public static class LoadCompressedPointer extends LoadOp {
+
+        private long narrowOopBase;
+        private int narrowOopShift;
+        private int logMinObjAlignment;
+        @Temp({REG}) private AllocatableValue scratch;
+
+        public LoadCompressedPointer(Kind kind, AllocatableValue result, AllocatableValue scratch, AMD64AddressValue address, LIRFrameState state, long narrowOopBase, int narrowOopShift,
+                        int logMinObjAlignment) {
+            super(kind, result, address, state);
+            this.narrowOopBase = narrowOopBase;
+            this.narrowOopShift = narrowOopShift;
+            this.logMinObjAlignment = logMinObjAlignment;
+            this.scratch = scratch;
+            assert kind == Kind.Object;
+        }
+
+        @Override
+        public void emitMemAccess(AMD64MacroAssembler masm) {
+            Register resRegister = asRegister(result);
+            masm.movl(resRegister, address.toAddress());
+            decodePointer(masm, resRegister, narrowOopBase, narrowOopShift, logMinObjAlignment);
+        }
+    }
+
     public static class LoadOp extends MemOp {
 
         @Def({REG}) protected AllocatableValue result;
@@ -161,6 +186,41 @@
         }
     }
 
+    public static class StoreCompressedPointer extends AMD64LIRInstruction {
+
+        protected final Kind kind;
+        private long narrowOopBase;
+        private int narrowOopShift;
+        private int logMinObjAlignment;
+        @Temp({REG}) private AllocatableValue scratch;
+        @Alive({REG}) protected AllocatableValue input;
+        @Alive({COMPOSITE}) protected AMD64AddressValue address;
+        @State protected LIRFrameState state;
+
+        public StoreCompressedPointer(Kind kind, AMD64AddressValue address, AllocatableValue input, AllocatableValue scratch, LIRFrameState state, long narrowOopBase, int narrowOopShift,
+                        int logMinObjAlignment) {
+            this.narrowOopBase = narrowOopBase;
+            this.narrowOopShift = narrowOopShift;
+            this.logMinObjAlignment = logMinObjAlignment;
+            this.scratch = scratch;
+            this.kind = kind;
+            this.address = address;
+            this.state = state;
+            this.input = input;
+            assert kind == Kind.Object;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            masm.movq(asRegister(scratch), asRegister(input));
+            encodePointer(masm, asRegister(scratch), narrowOopBase, narrowOopShift, logMinObjAlignment);
+            if (state != null) {
+                tasm.recordImplicitException(masm.codeBuffer.position(), state);
+            }
+            masm.movl(address.toAddress(), asRegister(scratch));
+        }
+    }
+
     public static class StoreOp extends MemOp {
 
         @Use({REG}) protected AllocatableValue input;
@@ -206,10 +266,12 @@
     public static class StoreConstantOp extends MemOp {
 
         protected final Constant input;
+        private final boolean compress;
 
-        public StoreConstantOp(Kind kind, AMD64AddressValue address, Constant input, LIRFrameState state) {
+        public StoreConstantOp(Kind kind, AMD64AddressValue address, Constant input, LIRFrameState state, boolean compress) {
             super(kind, address, state);
             this.input = input;
+            this.compress = compress;
         }
 
         @Override
@@ -240,7 +302,11 @@
                     throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
                 case Object:
                     if (input.isNull()) {
-                        masm.movptr(address.toAddress(), 0);
+                        if (compress) {
+                            masm.movl(address.toAddress(), 0);
+                        } else {
+                            masm.movptr(address.toAddress(), 0);
+                        }
                     } else {
                         throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
                     }
@@ -335,6 +401,38 @@
         }
     }
 
+    @Opcode("CAS")
+    public static class CompareAndSwapCompressedOp extends AMD64LIRInstruction {
+
+        @Def protected AllocatableValue result;
+        @Alive({COMPOSITE}) protected AMD64AddressValue address;
+        @Alive protected AllocatableValue cmpValue;
+        @Alive protected AllocatableValue newValue;
+        @Temp({REG}) protected AllocatableValue scratch;
+
+        private long narrowOopBase;
+        private int narrowOopShift;
+        private int logMinObjAlignment;
+
+        public CompareAndSwapCompressedOp(AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue, AllocatableValue scratch, long narrowOopBase,
+                        int narrowOopShift, int logMinObjAlignment) {
+            this.narrowOopBase = narrowOopBase;
+            this.narrowOopShift = narrowOopShift;
+            this.logMinObjAlignment = logMinObjAlignment;
+            this.scratch = scratch;
+            this.result = result;
+            this.address = address;
+            this.cmpValue = cmpValue;
+            this.newValue = newValue;
+            assert cmpValue.getKind() == Kind.Object;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            compareAndSwapCompressed(tasm, masm, result, address, cmpValue, newValue, scratch, narrowOopBase, narrowOopShift, logMinObjAlignment);
+        }
+    }
+
     public static void move(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Value input) {
         if (isRegister(input)) {
             if (isRegister(result)) {
@@ -543,4 +641,56 @@
                 throw GraalInternalError.shouldNotReachHere();
         }
     }
+
+    protected static void compareAndSwapCompressed(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue,
+                    AllocatableValue newValue, AllocatableValue scratch, long narrowOopBase, int narrowOopShift, int logMinObjAlignment) {
+        assert asRegister(cmpValue) == AMD64.rax && asRegister(result) == AMD64.rax;
+        final Register scratchRegister = asRegister(scratch);
+        final Register cmpRegister = asRegister(cmpValue);
+        final Register newRegister = asRegister(newValue);
+        encodePointer(masm, cmpRegister, narrowOopBase, narrowOopShift, logMinObjAlignment);
+        masm.movq(scratchRegister, newRegister);
+        encodePointer(masm, scratchRegister, narrowOopBase, narrowOopShift, logMinObjAlignment);
+        if (tasm.target.isMP) {
+            masm.lock();
+        }
+        masm.cmpxchgl(scratchRegister, address.toAddress());
+    }
+
+    private static void encodePointer(AMD64MacroAssembler masm, Register scratchRegister, long narrowOopBase, int narrowOopShift, int logMinObjAlignment) {
+        // If the narrowOopBase is zero, the uncompressed address has to be shifted right
+        // in order to be compressed.
+        if (narrowOopBase == 0) {
+            if (narrowOopShift != 0) {
+                assert logMinObjAlignment == narrowOopShift : "Encode algorithm is wrong";
+                masm.shrq(scratchRegister, logMinObjAlignment);
+            }
+        } else {
+            // Otherwise the narrow heap base, which resides always in register 12, is subtracted
+            // followed by right shift.
+            masm.testq(scratchRegister, scratchRegister);
+            masm.cmovq(ConditionFlag.Equal, scratchRegister, AMD64.r12);
+            masm.subq(scratchRegister, AMD64.r12);
+            masm.shrq(scratchRegister, logMinObjAlignment);
+        }
+    }
+
+    private static void decodePointer(AMD64MacroAssembler masm, Register resRegister, long narrowOopBase, int narrowOopShift, int logMinObjAlignment) {
+        // If the narrowOopBase is zero, the compressed address has to be shifted left
+        // in order to be uncompressed.
+        if (narrowOopBase == 0) {
+            if (narrowOopShift != 0) {
+                assert logMinObjAlignment == narrowOopShift : "Decode algorithm is wrong";
+                masm.shlq(resRegister, logMinObjAlignment);
+            }
+        } else {
+            Label done = new Label();
+            masm.shlq(resRegister, logMinObjAlignment);
+            masm.jccb(ConditionFlag.Equal, done);
+            // Otherwise the narrow heap base is added to the shifted address.
+            masm.addq(resRegister, AMD64.r12);
+            masm.bind(done);
+        }
+    }
+
 }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RestoreRegistersOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RestoreRegistersOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 /**
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -29,7 +29,6 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.asm.*;
 
 /**
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ZapRegistersOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ZapRegistersOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -30,7 +30,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.asm.*;
 
 /**
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java	Tue Jun 18 10:12:27 2013 +0200
@@ -373,6 +373,12 @@
             }
         } else {
             switch (opcode) {
+            // case A:  new Add(Int, dst, src1, src2);
+            // case S:  new Sub(Int, dst, src1, src2);
+            // case U:  new Shl(UnsignedInt, dst, src1, src2);
+            // case L:  new Shl(UnsignedLong, dst, src1, src2);
+            // case F:  new Add(Float, dst, src1, src2);
+            // case D:  new Mul(Double, dst, src1, src2);
             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;
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXBitManipulationOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXBitManipulationOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -26,6 +26,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.ptx.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 public class PTXBitManipulationOp extends PTXLIRInstruction {
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java	Tue Jun 18 10:12:27 2013 +0200
@@ -29,6 +29,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.ptx.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.calc.*;
 
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java	Tue Jun 18 10:12:27 2013 +0200
@@ -30,7 +30,6 @@
 import com.oracle.graal.asm.ptx.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Tue Jun 18 10:12:27 2013 +0200
@@ -56,7 +56,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.SPARCAssembler;
 import com.oracle.graal.graph.GraalInternalError;
-import com.oracle.graal.lir.LIRFrameState;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.TargetMethodAssembler;
 
 //@formatter:off
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,14 +22,22 @@
  */
 package com.oracle.graal.lir.sparc;
 
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Andn;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Ldsw;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Ldx;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Or;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.Popc;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.Srl;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Srlx;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Sub;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.isSimm13;
+import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.sparc.SPARC;
 
@@ -53,6 +61,7 @@
     @SuppressWarnings("unused")
     public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
         Register dst = ValueUtil.asIntReg(result);
+        Register tmp = null;  // ??
         if (ValueUtil.isRegister(input)) {
             Register src = ValueUtil.asRegister(input);
             switch (opcode) {
@@ -64,9 +73,64 @@
                 case LPOPCNT:
                     new Popc(masm, src, dst);
                     break;
-                case BSF:  // masm.bsfq(dst, src);
-                case IBSR:  // masm.bsrl(dst, src);
-                case LBSR:  // masm.bsrq(dst, src);
+                case BSF:
+                    // countTrailingZerosI - bsfl
+                    // countTrailingZerosL - masm.bsfq(dst, src);
+                    Kind tkind = input.getKind();
+                    if (tkind == Kind.Int) {
+                        new Sub(masm, src, 1, dst);
+                        new Andn(masm, dst, src, dst);
+                        new Srl(masm, dst, SPARC.g0, dst);
+                        new Popc(masm, dst, dst);
+                    } else if (tkind == Kind.Long) {
+                        new Sub(masm, src, 1, dst);
+                        new Andn(masm, dst, src, dst);
+                        new Popc(masm, dst, dst);
+                    } else {
+                        throw GraalInternalError.shouldNotReachHere("missing: " + tkind);
+                    }
+                    break;
+                case IBSR:
+                    // countLeadingZerosI_bsr masm.bsrq(dst, src);
+                    // masm.bsrl(dst, src);
+                    Kind ikind = input.getKind();
+                    assert ikind == Kind.Int;
+                    new Srl(masm, src, 1, tmp);
+                    new Srl(masm, src, 0, dst);
+                    new Or(masm, src, tmp, dst);
+                    new Srl(masm, dst, 2, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Srl(masm, dst, 4, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Srl(masm, dst, 8, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Srl(masm, dst, 16, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Popc(masm, dst, dst);
+                    new Mov(masm, ikind.getBitCount(), tmp);
+                    new Sub(masm, tmp, dst, dst);
+                    break;
+                case LBSR:
+                    // countLeadingZerosL_bsr masm.bsrq(dst, src);
+                    // masm.bsrq(dst, src);
+                    Kind lkind = input.getKind();
+                    assert lkind == Kind.Int;
+                    new Srlx(masm, src, 1, tmp);
+                    new Or(masm, src, tmp, dst);
+                    new Srlx(masm, dst, 2, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Srlx(masm, dst, 4, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Srlx(masm, dst, 8, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Srlx(masm, dst, 16, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Srlx(masm, dst, 32, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Popc(masm, dst, dst);
+                    new Mov(masm, lkind.getBitCount(), tmp);
+                    new Sub(masm, tmp, dst, dst);
+                    break;
                 default:
                     throw GraalInternalError.shouldNotReachHere("missing: " + opcode);
 
@@ -86,20 +150,41 @@
             SPARCAddress src = (SPARCAddress) tasm.asAddress(input);
             switch (opcode) {
                 case IPOPCNT:
-                    // masm.popcntl(dst, src);
+                    new Ldsw(masm, src, tmp);
+                    // clear upper word for 64 bit POPC
+                    new Srl(masm, tmp, SPARC.g0, dst);
+                    new Popc(masm, tmp, dst);
                     break;
                 case LPOPCNT:
-                    // masm.popcntq(dst, src);
+                    new Ldx(masm, src, tmp);
+                    new Popc(masm, tmp, dst);
                     break;
                 case BSF:
-                    // masm.bsfq(dst, src);
+                    assert input.getKind() == Kind.Int;
+                    new Ldsw(masm, src, tmp);
+                    new Srl(masm, tmp, 1, tmp);
+                    new Srl(masm, tmp, 0, dst);
+                    new Or(masm, tmp, tmp, dst);
+                    new Srl(masm, dst, 2, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Srl(masm, dst, 4, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Srl(masm, dst, 8, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Srl(masm, dst, 16, tmp);
+                    new Or(masm, dst, tmp, dst);
+                    new Popc(masm, dst, dst);
+                    new Mov(masm, Kind.Int.getBitCount(), tmp);
+                    new Sub(masm, tmp, dst, dst);
                     break;
                 case IBSR:
                     // masm.bsrl(dst, src);
-                    break;
+                    // countLeadingZerosI_bsr masm.bsrq(dst, src);
+                    // masm.bsrl(dst, src);
                 case LBSR:
                     // masm.bsrq(dst, src);
-                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere("missing: " + opcode);
             }
         }
     }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBreakpointOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBreakpointOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -25,9 +25,9 @@
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.asm.sparc.SPARCAssembler;
+import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Trap;
-import com.oracle.graal.lir.LIRInstruction.*;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 /**
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -24,7 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 @Opcode("BSWAP")
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java	Tue Jun 18 10:12:27 2013 +0200
@@ -30,6 +30,7 @@
 import com.oracle.graal.asm.sparc.SPARCAssembler;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Cmp;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 //@formatter:off
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Tue Jun 18 10:12:27 2013 +0200
@@ -25,22 +25,21 @@
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
+import com.oracle.graal.api.code.CompilationResult.JumpTable;
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.CompilationResult.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Bpe;
 import com.oracle.graal.asm.sparc.SPARCAssembler.CC;
 import com.oracle.graal.asm.sparc.SPARCAssembler.ConditionFlag;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Bpe;
 import com.oracle.graal.asm.sparc.SPARCAssembler.Subcc;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.*;
-import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.StandardOp.FallThroughOp;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.calc.Condition;
-import com.oracle.graal.sparc.SPARC;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.sparc.*;
 
 public class SPARCControlFlow {
 
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -28,6 +28,7 @@
 import com.oracle.graal.asm.sparc.SPARCAssembler;
 import com.oracle.graal.asm.sparc.SPARCAssembler.Fsqrtd;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 public class SPARCMathIntrinsicOp extends SPARCLIRInstruction {
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Tue Jun 18 10:12:27 2013 +0200
@@ -27,8 +27,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.asm.sparc.SPARCAddress;
-import com.oracle.graal.asm.sparc.SPARCAssembler;
+import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.asm.sparc.SPARCAssembler.Lddf;
 import com.oracle.graal.asm.sparc.SPARCAssembler.Ldf;
 import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsb;
@@ -37,20 +36,19 @@
 import com.oracle.graal.asm.sparc.SPARCAssembler.Lduw;
 import com.oracle.graal.asm.sparc.SPARCAssembler.Ldx;
 import com.oracle.graal.asm.sparc.SPARCAssembler.Membar;
+import com.oracle.graal.asm.sparc.SPARCAssembler.NullCheck;
 import com.oracle.graal.asm.sparc.SPARCAssembler.Or;
 import com.oracle.graal.asm.sparc.SPARCAssembler.Stb;
 import com.oracle.graal.asm.sparc.SPARCAssembler.Sth;
 import com.oracle.graal.asm.sparc.SPARCAssembler.Stw;
 import com.oracle.graal.asm.sparc.SPARCAssembler.Stx;
-import com.oracle.graal.asm.sparc.SPARCAssembler.NullCheck;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setuw;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
-import com.oracle.graal.graph.GraalInternalError;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.*;
 import com.oracle.graal.lir.StandardOp.MoveOp;
-import com.oracle.graal.lir.asm.TargetMethodAssembler;
-import com.oracle.graal.sparc.SPARC;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.sparc.*;
 
 public class SPARCMove {
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InfopointOp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InfopointOp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,8 +22,6 @@
  */
 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.*;
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Tue Jun 18 10:12:27 2013 +0200
@@ -144,13 +144,6 @@
     public static @interface State {
     }
 
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target({ElementType.TYPE, ElementType.FIELD})
-    public static @interface Opcode {
-
-        String value() default "";
-    }
-
     /**
      * Flags for an operand.
      */
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Tue Jun 18 10:12:27 2013 +0200
@@ -174,8 +174,8 @@
 
         @Override
         protected void scan(Class<?> clazz) {
-            if (clazz.getAnnotation(LIRInstruction.Opcode.class) != null) {
-                opcodeConstant = clazz.getAnnotation(LIRInstruction.Opcode.class).value();
+            if (clazz.getAnnotation(Opcode.class) != null) {
+                opcodeConstant = clazz.getAnnotation(Opcode.class).value();
             }
             opcodeOffset = -1;
 
@@ -199,7 +199,7 @@
                 super.scanField(field, type, offset);
             }
 
-            if (field.getAnnotation(LIRInstruction.Opcode.class) != null) {
+            if (field.getAnnotation(Opcode.class) != null) {
                 assert opcodeConstant == null && opcodeOffset == -1 : "Can have only one Opcode definition: " + field.getType();
                 opcodeOffset = offset;
             }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/Opcode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -0,0 +1,40 @@
+/*
+ * 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 java.lang.annotation.*;
+
+/**
+ * Denotes an opcode name for an annotated {@link LIRInstruction}.
+ * <p>
+ * Note: Unlike the other LIR related annotations declared as inner classes of
+ * {@link LIRInstruction}, this annotation is in a top level file to work around a <a
+ * href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=409824">bug</a> in Eclipse causing spurious
+ * warnings about unused imports.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.FIELD})
+public @interface Opcode {
+
+    String value() default "";
+}
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,12 +22,13 @@
  */
 package com.oracle.graal.loop;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.phases.*;
 
 public abstract class LoopPolicies {
 
@@ -39,7 +40,7 @@
     public static boolean shouldPeel(LoopEx loop, NodesToDoubles probabilities) {
         LoopBeginNode loopBegin = loop.loopBegin();
         double entryProbability = probabilities.get(loopBegin.forwardEnd());
-        return entryProbability > GraalOptions.MinimumPeelProbability && loop.size() + loopBegin.graph().getNodeCount() < GraalOptions.MaximumDesiredSize;
+        return entryProbability > MinimumPeelProbability.getValue() && loop.size() + loopBegin.graph().getNodeCount() < MaximumDesiredSize.getValue();
     }
 
     public static boolean shouldFullUnroll(LoopEx loop) {
@@ -48,14 +49,14 @@
         }
         CountedLoopInfo counted = loop.counted();
         long exactTrips = counted.constantMaxTripCount();
-        int maxNodes = (counted.isExactTripCount() && counted.isConstantExactTripCount()) ? GraalOptions.ExactFullUnrollMaxNodes : GraalOptions.FullUnrollMaxNodes;
-        maxNodes = Math.min(maxNodes, GraalOptions.MaximumDesiredSize - loop.loopBegin().graph().getNodeCount());
+        int maxNodes = (counted.isExactTripCount() && counted.isConstantExactTripCount()) ? ExactFullUnrollMaxNodes.getValue() : FullUnrollMaxNodes.getValue();
+        maxNodes = Math.min(maxNodes, MaximumDesiredSize.getValue() - loop.loopBegin().graph().getNodeCount());
         int size = Math.max(1, loop.size() - 1 - loop.loopBegin().phis().count());
         return size * exactTrips <= maxNodes;
     }
 
     public static boolean shouldTryUnswitch(LoopEx loop) {
-        return loop.loopBegin().unswitches() <= GraalOptions.LoopMaxUnswitch;
+        return loop.loopBegin().unswitches() <= LoopMaxUnswitch.getValue();
     }
 
     public static boolean shouldUnswitch(LoopEx loop, ControlSplitNode controlSplit) {
@@ -77,7 +78,7 @@
         }
         int netDiff = loopTotal - (inBranchTotal);
         double uncertainty = 1 - maxProbability;
-        int maxDiff = GraalOptions.LoopUnswitchMaxIncrease + (int) (GraalOptions.LoopUnswitchUncertaintyBoost * loop.loopBegin().loopFrequency() * uncertainty);
+        int maxDiff = LoopUnswitchMaxIncrease.getValue() + (int) (LoopUnswitchUncertaintyBoost.getValue() * loop.loopBegin().loopFrequency() * uncertainty);
         Debug.log("shouldUnswitch(%s, %s) : delta=%d, max=%d, %.2f%% inside of branches", loop, controlSplit, netDiff, maxDiff, (double) (inBranchTotal) / loopTotal * 100);
         return netDiff <= maxDiff;
     }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.loop;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
@@ -29,12 +31,11 @@
 import com.oracle.graal.graph.NodeClass.Position;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 
 public abstract class LoopTransformations {
 
-    private static final int UNROLL_LIMIT = GraalOptions.FullUnrollMaxNodes * 2;
+    private static final int UNROLL_LIMIT = FullUnrollMaxNodes.getValue() * 2;
 
     private LoopTransformations() {
         // does not need to be instantiated
@@ -52,7 +53,7 @@
         loop.inside().duplicate().insertBefore(loop);
     }
 
-    public static void fullUnroll(LoopEx loop, MetaAccessProvider runtime, Assumptions assumptions) {
+    public static void fullUnroll(LoopEx loop, MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads) {
         // assert loop.isCounted(); //TODO (gd) strenghten : counted with known trip count
         int iterations = 0;
         LoopBeginNode loopBegin = loop.loopBegin();
@@ -60,8 +61,8 @@
         while (!loopBegin.isDeleted()) {
             int mark = graph.getMark();
             peel(loop);
-            new CanonicalizerPhase.Instance(runtime, assumptions, mark, null).apply(graph);
-            if (iterations++ > UNROLL_LIMIT || graph.getNodeCount() > GraalOptions.MaximumDesiredSize * 3) {
+            new CanonicalizerPhase.Instance(runtime, assumptions, canonicalizeReads, mark, null).apply(graph);
+            if (iterations++ > UNROLL_LIMIT || graph.getNodeCount() > MaximumDesiredSize.getValue() * 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	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -31,8 +31,10 @@
 public class LoopFullUnrollPhase extends BasePhase<HighTierContext> {
 
     private static final DebugMetric FULLY_UNROLLED_LOOPS = Debug.metric("FullUnrolls");
+    private final boolean canonicalizeReads;
 
-    public LoopFullUnrollPhase() {
+    public LoopFullUnrollPhase(boolean canonicalizeReads) {
+        this.canonicalizeReads = canonicalizeReads;
     }
 
     @Override
@@ -46,7 +48,7 @@
                 for (LoopEx loop : dataCounted.countedLoops()) {
                     if (LoopPolicies.shouldFullUnroll(loop)) {
                         Debug.log("FullUnroll %s", loop);
-                        LoopTransformations.fullUnroll(loop, context.getRuntime(), context.getAssumptions());
+                        LoopTransformations.fullUnroll(loop, context.getRuntime(), context.getAssumptions(), canonicalizeReads);
                         FULLY_UNROLLED_LOOPS.increment();
                         Debug.dump(graph, "After fullUnroll %s", loop);
                         peeled = true;
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopSafepointEliminationPhase.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopSafepointEliminationPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -39,9 +39,15 @@
             loops.detectedCountedLoops();
             for (LoopEx loop : loops.countedLoops()) {
                 if (loop.lirLoop().children.isEmpty() && loop.counted().getKind() == Kind.Int) {
-                    loop.counted().createOverFlowGuard();
+                    boolean hasSafepoint = false;
                     for (LoopEndNode loopEnd : loop.loopBegin().loopEnds()) {
-                        loopEnd.disableSafepoint();
+                        hasSafepoint |= loopEnd.canSafepoint();
+                    }
+                    if (hasSafepoint) {
+                        loop.counted().createOverFlowGuard();
+                        for (LoopEndNode loopEnd : loop.loopBegin().loopEnds()) {
+                            loopEnd.disableSafepoint();
+                        }
                     }
                 }
             }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.loop.phases;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.debug.*;
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
@@ -34,7 +36,7 @@
     @Override
     protected void run(StructuredGraph graph) {
         if (graph.hasLoops()) {
-            if (GraalOptions.LoopPeeling) {
+            if (LoopPeeling.getValue()) {
                 NodesToDoubles probabilities = new ComputeProbabilityClosure(graph).apply();
                 LoopsData data = new LoopsData(graph);
                 for (LoopEx loop : data.outterFirst()) {
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.loop.phases;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.loop.*;
@@ -35,7 +37,7 @@
     @Override
     protected void run(StructuredGraph graph) {
         if (graph.hasLoops()) {
-            if (GraalOptions.ReassociateInvariants) {
+            if (ReassociateInvariants.getValue()) {
                 final LoopsData dataReassociate = new LoopsData(graph);
                 Debug.scope("ReassociateInvariants", new Runnable() {
 
@@ -47,7 +49,7 @@
                     }
                 });
             }
-            if (GraalOptions.LoopUnswitch) {
+            if (LoopUnswitch.getValue()) {
                 boolean unswitched;
                 do {
                     unswitched = false;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -35,4 +35,6 @@
     }
 
     public abstract double probability(AbstractBeginNode successor);
+
+    public abstract void setProbability(AbstractBeginNode successor, double value);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -25,12 +25,13 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(nameTemplate = "FixedGuard(!={p#negated}) {p#reason/s}")
-public final class FixedGuardNode extends FixedWithNextNode implements Simplifiable, Lowerable, Node.IterableNodeType, Negatable {
+public final class FixedGuardNode extends FixedWithNextNode implements Simplifiable, Lowerable, Node.IterableNodeType, Negatable, GuardingNode {
 
     @Input private LogicNode condition;
     private final DeoptimizationReason reason;
@@ -51,7 +52,7 @@
     }
 
     public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) {
-        super(StampFactory.forVoid());
+        super(StampFactory.dependency());
         this.action = action;
         this.negated = negated;
         this.condition = condition;
@@ -84,6 +85,7 @@
         if (condition instanceof LogicConstantNode) {
             LogicConstantNode c = (LogicConstantNode) condition;
             if (c.getValue() != negated) {
+                this.replaceAtUsages(BeginNode.prevBegin(this));
                 graph().removeFixed(this);
             } else {
                 FixedNode next = this.next();
@@ -121,4 +123,9 @@
         negated = !negated;
         return this;
     }
+
+    @Override
+    public FixedGuardNode asNode() {
+        return this;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Tue Jun 18 10:12:27 2013 +0200
@@ -41,6 +41,9 @@
 
     protected final int stackSize;
 
+    /**
+     * @see BytecodeFrame#rethrowException
+     */
     private boolean rethrowException;
 
     private boolean duringCall;
@@ -160,6 +163,9 @@
         this.outerFrameState = x;
     }
 
+    /**
+     * @see BytecodeFrame#rethrowException
+     */
     public boolean rethrowException() {
         return rethrowException;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -95,7 +95,7 @@
         if (condition() instanceof LogicConstantNode) {
             LogicConstantNode c = (LogicConstantNode) condition();
             if (c.getValue() != negated) {
-                return getGuard().asNode();
+                return graph().start();
             }
         }
         return this;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/HeapAccess.java	Tue Jun 18 10:12:27 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;
+
+/**
+ * A HeapAccess is a node that access the heap and therefore may be subjected to certain rules of
+ * the underlying runtime.
+ */
+public interface HeapAccess {
+
+    /*
+     * 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
+    }
+
+    /**
+     * Gets the write barrier type for that particular access.
+     */
+    WriteBarrierType getWriteBarrierType();
+
+    /**
+     * Returns whether or not the heap access is a compressed pointer candidate.
+     */
+    boolean compress();
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -132,6 +132,12 @@
     }
 
     @Override
+    public void setProbability(AbstractBeginNode successor, double value) {
+        assert successor == trueSuccessor || successor == falseSuccessor;
+        setTrueSuccessorProbability(successor == trueSuccessor ? value : 1 - value);
+    }
+
+    @Override
     public void generate(LIRGeneratorTool gen) {
         gen.emitIf(this);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InlineableElement.java	Tue Jun 18 10:11:28 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes;
-
-public interface InlineableElement {
-
-    int getNodeCount();
-
-    Iterable<Invoke> getInvokes();
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -36,6 +36,8 @@
 @NodeInfo(nameTemplate = "Invoke!#{p#targetMethod/s}")
 public class InvokeWithExceptionNode extends ControlSplitNode implements Node.IterableNodeType, Invoke, MemoryCheckpoint, LIRLowerable {
 
+    private static final double EXCEPTION_PROBA = 1e-5;
+
     @Successor private AbstractBeginNode next;
     @Successor private DispatchBeginNode exceptionEdge;
     @Input private CallTargetNode callTarget;
@@ -45,6 +47,7 @@
     private final int bci;
     private boolean polymorphic;
     private boolean useForInlining;
+    private double exceptionProbability;
 
     public InvokeWithExceptionNode(CallTargetNode callTarget, DispatchBeginNode exceptionEdge, int bci) {
         super(callTarget.returnStamp());
@@ -53,6 +56,7 @@
         this.callTarget = callTarget;
         this.polymorphic = false;
         this.useForInlining = true;
+        this.exceptionProbability = EXCEPTION_PROBA;
     }
 
     public DispatchBeginNode exceptionEdge() {
@@ -205,11 +209,15 @@
         }
     }
 
-    private static final double EXCEPTION_PROBA = 1e-5;
+    @Override
+    public double probability(AbstractBeginNode successor) {
+        return successor == next ? 1 - exceptionProbability : exceptionProbability;
+    }
 
     @Override
-    public double probability(AbstractBeginNode successor) {
-        return successor == next ? 1 - EXCEPTION_PROBA : EXCEPTION_PROBA;
+    public void setProbability(AbstractBeginNode successor, double value) {
+        assert successor == next || successor == exceptionEdge;
+        this.exceptionProbability = successor == next ? 1 - value : value;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -32,10 +32,9 @@
  * A node that changes the type of its input, usually narrowing it. For example, a PI node refines
  * the type of a receiver during type-guarded inlining to be the type tested by the guard.
  */
-public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, Node.IterableNodeType, GuardingNode {
+public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, Node.IterableNodeType, GuardingNode, Canonicalizable {
 
     @Input private ValueNode object;
-    @Input private FixedNode anchor;
 
     public ValueNode object() {
         return object;
@@ -46,10 +45,9 @@
         this.object = object;
     }
 
-    public PiNode(ValueNode object, Stamp stamp, FixedNode anchor) {
-        super(stamp);
+    public PiNode(ValueNode object, Stamp stamp, GuardingNode anchor) {
+        super(stamp, anchor);
         this.object = object;
-        this.anchor = anchor;
     }
 
     @Override
@@ -71,4 +69,15 @@
             tool.replaceWithVirtual(state.getVirtualObject());
         }
     }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        if (getGuard() == graph().start()) {
+            inferStamp();
+            if (stamp().equals(object().stamp())) {
+                return object();
+            }
+        }
+        return this;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Tue Jun 18 10:12:27 2013 +0200
@@ -35,7 +35,7 @@
  * A graph that contains at least one distinguished node : the {@link #start() start} node. This
  * node is the start of the control flow of the graph.
  */
-public class StructuredGraph extends Graph implements InlineableElement {
+public class StructuredGraph extends Graph {
 
     public static final int INVOCATION_ENTRY_BCI = -1;
     public static final long INVALID_GRAPH_ID = -1;
@@ -119,6 +119,10 @@
         return entryBCI;
     }
 
+    public boolean isOSR() {
+        return entryBCI != INVOCATION_ENTRY_BCI;
+    }
+
     public long graphId() {
         return graphId;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -30,7 +30,7 @@
 import com.oracle.graal.nodes.type.*;
 
 /**
- * A node that attached a type profile to a proxied input node.
+ * A node that attaches a type profile to a proxied input node.
  */
 public final class TypeProfileProxyNode extends FloatingNode implements Canonicalizable, Node.IterableNodeType {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -29,7 +29,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "*")
-public final class IntegerMulNode extends IntegerArithmeticNode implements Canonicalizable, LIRLowerable {
+public class IntegerMulNode extends IntegerArithmeticNode implements Canonicalizable, LIRLowerable {
 
     public IntegerMulNode(Kind kind, ValueNode x, ValueNode y) {
         super(kind, x, y);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -29,7 +29,7 @@
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "-")
-public final class IntegerSubNode extends IntegerArithmeticNode implements Canonicalizable, LIRLowerable {
+public class IntegerSubNode extends IntegerArithmeticNode implements Canonicalizable, LIRLowerable {
 
     public IntegerSubNode(Kind kind, ValueNode x, ValueNode y) {
         super(kind, x, y);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java	Tue Jun 18 10:12:27 2013 +0200
@@ -24,7 +24,7 @@
 
 import com.oracle.graal.nodes.*;
 
-public interface Access extends DeoptimizingNode, GuardedNode {
+public interface Access extends DeoptimizingNode, GuardedNode, HeapAccess {
 
     ValueNode object();
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -37,6 +37,8 @@
     @Input private ValueNode object;
     @Input private ValueNode location;
     private boolean nullCheck;
+    private WriteBarrierType barrierType;
+    private boolean compress;
 
     public ValueNode object() {
         return object;
@@ -59,14 +61,20 @@
     }
 
     public AccessNode(ValueNode object, ValueNode location, Stamp stamp) {
-        this(object, location, stamp, null);
+        this(object, location, stamp, null, WriteBarrierType.NONE, false);
     }
 
-    public AccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard) {
+    public AccessNode(ValueNode object, ValueNode location, Stamp stamp, WriteBarrierType barrierType, boolean compress) {
+        this(object, location, stamp, null, barrierType, compress);
+    }
+
+    public AccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, WriteBarrierType barrierType, boolean compress) {
         super(stamp);
         this.object = object;
         this.location = location;
         this.guard = guard;
+        this.barrierType = barrierType;
+        this.compress = compress;
     }
 
     @Override
@@ -94,4 +102,14 @@
         updateUsages(this.guard == null ? null : this.guard.asNode(), guard == null ? null : guard.asNode());
         this.guard = guard;
     }
+
+    @Override
+    public WriteBarrierType getWriteBarrierType() {
+        return barrierType;
+    }
+
+    @Override
+    public boolean compress() {
+        return compress;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -34,8 +34,12 @@
         super(object, location, stamp);
     }
 
-    public FloatableAccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard) {
-        super(object, location, stamp, guard);
+    public FloatableAccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, WriteBarrierType barrierType, boolean compress) {
+        super(object, location, stamp, guard, barrierType, compress);
+    }
+
+    public FloatableAccessNode(ValueNode object, ValueNode location, Stamp stamp, WriteBarrierType barrierType, boolean compress) {
+        super(object, location, stamp, barrierType, compress);
     }
 
     public abstract FloatingAccessNode asFloatingNode(ValueNode lastLocationAccess);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -32,6 +32,8 @@
     @Input private LocationNode location;
     @Input private FrameState deoptState;
     private boolean nullCheck;
+    private WriteBarrierType barrierType;
+    private boolean compress;
 
     public ValueNode object() {
         return object;
@@ -59,10 +61,12 @@
         this.location = location;
     }
 
-    public FloatingAccessNode(ValueNode object, LocationNode location, Stamp stamp, GuardingNode guard) {
+    public FloatingAccessNode(ValueNode object, LocationNode location, Stamp stamp, GuardingNode guard, WriteBarrierType barrierType, boolean compress) {
         super(stamp, guard);
         this.object = object;
         this.location = location;
+        this.barrierType = barrierType;
+        this.compress = compress;
     }
 
     @Override
@@ -91,5 +95,15 @@
         deoptState = f;
     }
 
+    @Override
+    public WriteBarrierType getWriteBarrierType() {
+        return barrierType;
+    }
+
+    @Override
+    public boolean compress() {
+        return compress;
+    }
+
     public abstract Access asFixedNode();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -37,11 +37,11 @@
     @Input private Node lastLocationAccess;
 
     public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp) {
-        this(object, location, lastLocationAccess, stamp, null);
+        this(object, location, lastLocationAccess, stamp, null, WriteBarrierType.NONE, false);
     }
 
-    public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp, GuardingNode guard) {
-        super(object, location, stamp, guard);
+    public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp, GuardingNode guard, WriteBarrierType barrierType, boolean compress) {
+        super(object, location, stamp, guard, barrierType, compress);
         this.lastLocationAccess = lastLocationAccess;
     }
 
@@ -62,6 +62,6 @@
 
     @Override
     public Access asFixedNode() {
-        return graph().add(new ReadNode(object(), nullCheckLocation(), stamp(), getGuard()));
+        return graph().add(new ReadNode(object(), nullCheckLocation(), stamp(), getGuard(), getWriteBarrierType(), compress()));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -91,7 +91,7 @@
     public FrameState getDeoptimizationState() {
         if (deoptState != null) {
             return deoptState;
-        } else if (stateAfter() != null) {
+        } else if (stateAfter() != null && canDeoptimize()) {
             FrameState stateDuring = stateAfter();
             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());
@@ -105,10 +105,15 @@
     @Override
     public void setDeoptimizationState(FrameState f) {
         updateUsages(deoptState, f);
-        if (deoptState != null) {
-            throw new IllegalStateException(toString(Verbosity.Debugger));
+        assert deoptState == null && canDeoptimize() : "shouldn't assign deoptState to " + this;
+        deoptState = f;
+    }
+
+    @Override
+    public void setStateAfter(FrameState x) {
+        if (hasSideEffect() || canDeoptimize()) {
+            super.setStateAfter(x);
         }
-        deoptState = f;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -64,7 +64,7 @@
         return graph.unique(new IndexedLocationNode(identity, kind, displacement, index, indexScaling));
     }
 
-    private IndexedLocationNode(LocationIdentity identity, Kind kind, long displacement, ValueNode index, int indexScaling) {
+    public IndexedLocationNode(LocationIdentity identity, Kind kind, long displacement, ValueNode index, int indexScaling) {
         super(StampFactory.extension());
         assert kind != Kind.Illegal && kind != Kind.Void;
         this.valueKind = kind;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRStartNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRStartNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -30,9 +30,7 @@
 
     @Override
     public void lower(LoweringTool tool, LoweringType loweringType) {
-        if (loweringType == LoweringType.AFTER_GUARDS) {
-            tool.getRuntime().lower(this, tool);
-        }
+        tool.getRuntime().lower(this, tool);
     }
 
     public NodeIterable<OSRLocalNode> getOSRLocals() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -27,18 +27,19 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.virtual.*;
 
 /**
  * Reads an {@linkplain AccessNode accessed} value.
  */
-public final class ReadNode extends FloatableAccessNode implements Node.IterableNodeType, LIRLowerable, Canonicalizable, PiPushable {
+public final class ReadNode extends FloatableAccessNode implements Node.IterableNodeType, LIRLowerable, Canonicalizable, PiPushable, Virtualizable {
 
-    public ReadNode(ValueNode object, ValueNode location, Stamp stamp) {
-        super(object, location, stamp);
+    public ReadNode(ValueNode object, ValueNode location, Stamp stamp, WriteBarrierType barrierType, boolean compress) {
+        super(object, location, stamp, barrierType, compress);
     }
 
-    public ReadNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard) {
-        super(object, location, stamp, guard);
+    public ReadNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, WriteBarrierType barrierType, boolean compress) {
+        super(object, location, stamp, guard, barrierType, compress);
     }
 
     private ReadNode(ValueNode object, int displacement, LocationIdentity locationIdentity, Kind kind) {
@@ -50,7 +51,7 @@
          * Used by node intrinsics. Since the initial value for location is a parameter, i.e., a
          * LocalNode, the constructor cannot use the declared type LocationNode.
          */
-        super(object, location, StampFactory.forNodeIntrinsic(), (GuardingNode) guard);
+        super(object, location, StampFactory.forNodeIntrinsic(), (GuardingNode) guard, WriteBarrierType.NONE, false);
     }
 
     @Override
@@ -66,7 +67,7 @@
 
     @Override
     public FloatingAccessNode asFloatingNode(ValueNode lastLocationAccess) {
-        return graph().unique(new FloatingReadNode(object(), location(), lastLocationAccess, stamp(), getGuard()));
+        return graph().unique(new FloatingReadNode(object(), location(), lastLocationAccess, stamp(), getGuard(), getWriteBarrierType(), compress()));
     }
 
     public static ValueNode canonicalizeRead(ValueNode read, LocationNode location, ValueNode object, CanonicalizerTool tool) {
@@ -75,7 +76,7 @@
             // Read without usages can be savely removed.
             return null;
         }
-        if (runtime != null && object != null && object.isConstant()) {
+        if (tool.canonicalizeReads() && runtime != null && object != null && object.isConstant()) {
             if (location.getLocationIdentity() == LocationIdentity.FINAL_LOCATION && location instanceof ConstantLocationNode) {
                 long displacement = ((ConstantLocationNode) location).getDisplacement();
                 Kind kind = location.getValueKind();
@@ -128,6 +129,21 @@
         return false;
     }
 
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        if (location() instanceof ConstantLocationNode) {
+            ConstantLocationNode constantLocation = (ConstantLocationNode) location();
+            State state = tool.getObjectState(object());
+            if (state != null && state.getState() == EscapeState.Virtual) {
+                VirtualObjectNode virtual = state.getVirtualObject();
+                int entryIndex = virtual.entryIndexForOffset(constantLocation.getDisplacement());
+                if (entryIndex != -1 && virtual.entryKind(entryIndex) == constantLocation.getValueKind()) {
+                    tool.replaceWith(state.getEntry(entryIndex));
+                }
+            }
+        }
+    }
+
     /**
      * Reads a value from memory.
      * 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -56,9 +56,12 @@
     }
 
     private boolean assertProbabilities() {
+        double total = 0;
         for (double d : keyProbabilities) {
+            total += d;
             assert d >= 0.0 : "Cannot have negative probabilities in switch node: " + d;
         }
+        assert total > 0.999 && total < 1.001;
         return true;
     }
 
@@ -73,6 +76,33 @@
         return sum;
     }
 
+    @Override
+    public void setProbability(AbstractBeginNode successor, double value) {
+        double changeInProbability = 0;
+        int nonZeroProbabilityCases = 0;
+        for (int i = 0; i < keySuccessors.length; i++) {
+            if (successors.get(keySuccessors[i]) == successor) {
+                changeInProbability += keyProbabilities[i] - value;
+                keyProbabilities[i] = value;
+            } else if (keyProbabilities[i] > 0) {
+                nonZeroProbabilityCases++;
+            }
+        }
+
+        if (nonZeroProbabilityCases > 0) {
+            double changePerEntry = changeInProbability / nonZeroProbabilityCases;
+            if (changePerEntry != 0) {
+                for (int i = 0; i < keyProbabilities.length; i++) {
+                    if (keyProbabilities[i] > 0) {
+                        keyProbabilities[i] = keyProbabilities[i] + changePerEntry;
+                    }
+                }
+            }
+        }
+
+        assertProbabilities();
+    }
+
     public ValueNode value() {
         return value;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -42,11 +42,15 @@
         this.length = length;
     }
 
-    public UnsafeArrayCastNode(ValueNode object, ValueNode length, Stamp stamp, ValueNode anchor) {
+    public UnsafeArrayCastNode(ValueNode object, ValueNode length, Stamp stamp, GuardingNode anchor) {
         super(object, stamp, anchor);
         this.length = length;
     }
 
+    private UnsafeArrayCastNode(ValueNode object, ValueNode length, Stamp stamp, ValueNode anchor) {
+        this(object, length, stamp, (GuardingNode) anchor);
+    }
+
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (!(object() instanceof ArrayLengthProvider) || length() != ((ArrayLengthProvider) object()).length()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -36,8 +36,12 @@
         super(object, stamp);
     }
 
+    public UnsafeCastNode(ValueNode object, Stamp stamp, GuardingNode anchor) {
+        super(object, stamp, anchor);
+    }
+
     public UnsafeCastNode(ValueNode object, Stamp stamp, ValueNode anchor) {
-        super(object, stamp, (FixedNode) anchor);
+        this(object, stamp, (GuardingNode) anchor);
     }
 
     public UnsafeCastNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) {
@@ -100,7 +104,7 @@
     public static native <T> T unsafeCast(Object object, @ConstantNodeParameter Stamp stamp);
 
     @NodeIntrinsic
-    public static native <T> T unsafeCast(Object object, @ConstantNodeParameter Stamp stamp, ValueNode anchor);
+    public static native <T> T unsafeCast(Object object, @ConstantNodeParameter Stamp stamp, GuardingNode anchor);
 
     @SuppressWarnings("unused")
     @NodeIntrinsic
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -83,8 +83,8 @@
                                                                   // UnsafeAccess only have an
                                                                   // object base
                 ObjectStamp receiverStamp = object().objectStamp();
-                if (receiverStamp.nonNull()) {
-                    ResolvedJavaType receiverType = receiverStamp.type();
+                ResolvedJavaType receiverType = receiverStamp.type();
+                if (receiverStamp.nonNull() && receiverType != null) {
                     ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(displacement());
                     if (field != null) {
                         return this.graph().add(new LoadFieldNode(object(), field));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -61,6 +61,10 @@
         }
     }
 
+    public void removeAnchoredNode(ValueNode value) {
+        this.anchored.remove(value);
+    }
+
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (permanent) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -28,33 +28,15 @@
 import com.oracle.graal.nodes.extended.LocationNode.Location;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.virtual.*;
 
 /**
  * Writes a given {@linkplain #value() value} a {@linkplain AccessNode memory location}.
  */
-public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint, Node.IterableNodeType {
+public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint, Node.IterableNodeType, Virtualizable {
 
     @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;
@@ -74,14 +56,9 @@
         return value;
     }
 
-    public WriteBarrierType getWriteBarrierType() {
-        return barrierType;
-    }
-
-    public WriteNode(ValueNode object, ValueNode value, ValueNode location, WriteBarrierType barrierType) {
-        super(object, location, StampFactory.forVoid());
+    public WriteNode(ValueNode object, ValueNode value, ValueNode location, WriteBarrierType barrierType, boolean compress) {
+        super(object, location, StampFactory.forVoid(), barrierType, compress);
         this.value = value;
-        this.barrierType = barrierType;
     }
 
     @Override
@@ -91,10 +68,26 @@
     }
 
     @NodeIntrinsic
-    public static native void writeMemory(Object object, Object value, Location location, @ConstantNodeParameter WriteBarrierType barrierType);
+    public static native void writeMemory(Object object, Object value, Location location, @ConstantNodeParameter WriteBarrierType barrierType, @ConstantNodeParameter boolean compress);
 
     @Override
     public LocationIdentity[] getLocationIdentities() {
         return new LocationIdentity[]{location().getLocationIdentity()};
     }
+
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        if (location() instanceof ConstantLocationNode) {
+            ConstantLocationNode constantLocation = (ConstantLocationNode) location();
+            State state = tool.getObjectState(object());
+            if (state != null && state.getState() == EscapeState.Virtual) {
+                VirtualObjectNode virtual = state.getVirtualObject();
+                int entryIndex = virtual.entryIndexForOffset(constantLocation.getDisplacement());
+                if (entryIndex != -1 && virtual.entryKind(entryIndex) == constantLocation.getValueKind()) {
+                    tool.setVirtualEntry(state, entryIndex, value());
+                    tool.delete();
+                }
+            }
+        }
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -29,7 +29,6 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -37,7 +36,7 @@
  * 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, Node.IterableNodeType {
+public class CompareAndSwapNode extends AbstractStateSplit implements StateSplit, LIRLowerable, Lowerable, MemoryCheckpoint, Node.IterableNodeType, HeapAccess {
 
     @Input private ValueNode object;
     @Input private ValueNode offset;
@@ -46,6 +45,7 @@
     @Input private LocationNode location;
     private final int displacement;
     private WriteBarrierType barrierType;
+    private boolean compress;
 
     public ValueNode object() {
         return object;
@@ -76,6 +76,7 @@
         this.location = location;
     }
 
+    @Override
     public WriteBarrierType getWriteBarrierType() {
         return barrierType;
     }
@@ -84,6 +85,15 @@
         this.barrierType = type;
     }
 
+    @Override
+    public boolean compress() {
+        return compress;
+    }
+
+    public void setCompress() {
+        this.compress = true;
+    }
+
     public CompareAndSwapNode(ValueNode object, int displacement, ValueNode offset, ValueNode expected, ValueNode newValue) {
         super(StampFactory.forKind(Kind.Boolean.getStackKind()));
         assert expected.kind() == newValue.kind();
@@ -93,6 +103,7 @@
         this.newValue = newValue;
         this.displacement = displacement;
         this.barrierType = WriteBarrierType.NONE;
+        this.compress = false;
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -0,0 +1,87 @@
+/*
+ * 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.java;
+
+import java.lang.reflect.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * The {@code DynamicNewArrayNode} is used for allocation of arrays when the type is not a
+ * compile-time constant.
+ */
+public class DynamicNewArrayNode extends FixedWithNextNode implements Canonicalizable, Lowerable, ArrayLengthProvider {
+
+    @Input private ValueNode elementType;
+    @Input private ValueNode length;
+    private final boolean fillContents;
+
+    public DynamicNewArrayNode(ValueNode elementType, ValueNode length) {
+        this(elementType, length, true);
+    }
+
+    public DynamicNewArrayNode(ValueNode elementType, ValueNode length, boolean fillContents) {
+        super(StampFactory.objectNonNull());
+        this.length = length;
+        this.elementType = elementType;
+        this.fillContents = fillContents;
+    }
+
+    public ValueNode getElementType() {
+        return elementType;
+    }
+
+    @Override
+    public ValueNode length() {
+        return length;
+    }
+
+    public boolean fillContents() {
+        return fillContents;
+    }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        if (elementType.isConstant()) {
+            Class<?> elementClass = (Class<?>) elementType.asConstant().asObject();
+            if (elementClass != null && !(elementClass.equals(void.class))) {
+                ResolvedJavaType javaType = tool.runtime().lookupJavaType(elementClass);
+                return graph().add(new NewArrayNode(javaType, length, fillContents));
+            }
+        }
+        return this;
+    }
+
+    @Override
+    public void lower(LoweringTool tool, LoweringType loweringType) {
+        tool.getRuntime().lower(this, tool);
+    }
+
+    @NodeIntrinsic
+    public static Object newArray(Class<?> componentType, int length) {
+        return Array.newInstance(componentType, length);
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -24,6 +24,7 @@
 
 import static com.oracle.graal.api.meta.LocationIdentity.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
@@ -54,6 +55,13 @@
         return (stamp() == StampFactory.forVoid());
     }
 
+    /**
+     * The frame state upon entry to an exception handler is such that it is a
+     * {@link BytecodeFrame#rethrowException rethrow exception} state and the stack contains exactly
+     * the exception object (per the JVM spec) to rethrow. This means that the code creating this
+     * state (i.e. the {@link LoadExceptionObjectNode}) cannot cause a deoptimization as the
+     * runtime/interpreter would not have a valid location for the exception object to be rethrown.
+     */
     @Override
     public void lower(LoweringTool tool, LoweringType loweringType) {
         if (isLowered()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.java;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -29,6 +30,12 @@
 /**
  * Loads an exception object passed by the runtime from a callee to an exception handler in a
  * caller. The node is only produced when lowering an {@link ExceptionObjectNode}.
+ * <p>
+ * The frame state upon entry to an exception handler is such that it is a
+ * {@link BytecodeFrame#rethrowException rethrow exception} state and the stack contains exactly the
+ * exception object (per the JVM spec) to rethrow. This means that the code generated for this node
+ * must not cause a deoptimization as the runtime/interpreter would not have a valid location to
+ * find the exception object to be rethrown.
  */
 public class LoadExceptionObjectNode extends AbstractStateSplit implements Lowerable {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -57,7 +57,7 @@
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         MetaAccessProvider runtime = tool.runtime();
-        if (runtime != null) {
+        if (tool.canonicalizeReads() && runtime != null) {
             Constant constant = null;
             if (isStatic()) {
                 constant = field().readConstantValue(null);
@@ -79,13 +79,6 @@
             if (fieldIndex != -1) {
                 tool.replaceWith(state.getEntry(fieldIndex));
             }
-        } else {
-            ValueNode cachedValue = tool.getReadCache(object(), field());
-            if (cachedValue != null) {
-                tool.replaceWithValue(cachedValue);
-            } else {
-                tool.addReadCache(object(), field(), this);
-            }
         }
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -100,9 +100,7 @@
 
     @Override
     public void lower(LoweringTool tool, LoweringType loweringType) {
-        if (loweringType == LoweringType.AFTER_GUARDS) {
-            tool.getRuntime().lower(this, tool);
-        }
+        tool.getRuntime().lower(this, tool);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -78,9 +78,7 @@
 
     @Override
     public void lower(LoweringTool tool, LoweringType loweringType) {
-        if (loweringType == LoweringType.AFTER_GUARDS) {
-            tool.getRuntime().lower(this, tool);
-        }
+        tool.getRuntime().lower(this, tool);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -63,9 +63,7 @@
 
     @Override
     public void lower(LoweringTool tool, LoweringType loweringType) {
-        if (loweringType == LoweringType.AFTER_GUARDS) {
-            tool.getRuntime().lower(this, tool);
-        }
+        tool.getRuntime().lower(this, tool);
     }
 
     public ResolvedJavaType type() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -77,12 +77,6 @@
                 tool.setVirtualEntry(state, fieldIndex, value());
                 tool.delete();
             }
-        } else {
-            if (value() == tool.getReadCache(object(), field())) {
-                tool.delete();
-            }
-            tool.killReadCache(field());
-            tool.addReadCache(object(), field(), value());
         }
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/CanonicalizerTool.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/CanonicalizerTool.java	Tue Jun 18 10:12:27 2013 +0200
@@ -32,5 +32,7 @@
 
     MetaAccessProvider runtime();
 
+    boolean canonicalizeReads();
+
     void removeIfUnused(Node node);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraphCache.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraphCache.java	Tue Jun 18 10:12:27 2013 +0200
@@ -27,7 +27,7 @@
 
 public interface GraphCache {
 
-    void put(StructuredGraph graph);
+    void put(StructuredGraph graph, boolean hasMatureProfilingInfo);
 
     StructuredGraph get(ResolvedJavaMethod method);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java	Tue Jun 18 10:12:27 2013 +0200
@@ -28,11 +28,14 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 
 public interface LoweringTool {
 
     GraalCodeCacheProvider getRuntime();
 
+    LoweringType getLoweringType();
+
     Replacements getReplacements();
 
     GuardingNode createNullCheckGuard(GuardedNode guardedNode, ValueNode object);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Virtualizable.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Virtualizable.java	Tue Jun 18 10:12:27 2013 +0200
@@ -43,8 +43,6 @@
 
         public abstract VirtualObjectNode getVirtualObject();
 
-        public abstract void setEntry(int index, ValueNode value);
-
         public abstract ValueNode getEntry(int index);
 
         public abstract void addLock(int depth);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java	Tue Jun 18 10:12:27 2013 +0200
@@ -153,10 +153,4 @@
      */
     void replaceWith(ValueNode value);
 
-    void addReadCache(ValueNode object, ResolvedJavaField identity, ValueNode value);
-
-    ValueNode getReadCache(ValueNode object, ResolvedJavaField identity);
-
-    void killReadCache(ResolvedJavaField identity);
-
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Tue Jun 18 10:12:27 2013 +0200
@@ -129,7 +129,15 @@
     @Override
     public boolean alwaysDistinct(Stamp otherStamp) {
         IntegerStamp other = (IntegerStamp) otherStamp;
-        return lowerBound > other.upperBound || upperBound < other.lowerBound;
+        if (lowerBound > other.upperBound || upperBound < other.lowerBound) {
+            return true;
+        } else {
+            if ((mask & other.mask) == 0) {
+                // zero is the only common value if the masks don't overlap => check for non-zero
+                return lowerBound > 0 || upperBound < 0 || other.lowerBound > 0 || other.upperBound < 0;
+            }
+            return false;
+        }
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java	Tue Jun 18 10:12:27 2013 +0200
@@ -101,6 +101,10 @@
     private static final long LONG_SIGN_BIT = 0x8000000000000000L;
 
     private static Stamp stampForMask(Kind kind, long mask) {
+        return stampForMask(kind, mask, 0);
+    }
+
+    private static Stamp stampForMask(Kind kind, long mask, long alwaysSetBits) {
         long lowerBound;
         long upperBound;
         if (kind == Kind.Int && (mask & INTEGER_SIGN_BIT) != 0) {
@@ -112,7 +116,7 @@
             lowerBound = Long.MIN_VALUE;
             upperBound = mask ^ LONG_SIGN_BIT;
         } else {
-            lowerBound = 0;
+            lowerBound = alwaysSetBits;
             upperBound = mask;
         }
         return StampFactory.forInteger(kind, lowerBound, upperBound, mask);
@@ -127,7 +131,11 @@
     public static Stamp or(IntegerStamp stamp1, IntegerStamp stamp2) {
         Kind kind = stamp1.kind();
         long mask = stamp1.mask() | stamp2.mask();
-        return stampForMask(kind, mask);
+        if (stamp1.lowerBound() >= 0 && stamp2.lowerBound() >= 0) {
+            return stampForMask(kind, mask, stamp1.lowerBound() | stamp2.lowerBound());
+        } else {
+            return stampForMask(kind, mask);
+        }
     }
 
     public static Stamp xor(IntegerStamp stamp1, IntegerStamp stamp2) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -66,9 +66,7 @@
 
     @Override
     public void lower(LoweringTool tool, LoweringType loweringType) {
-        if (loweringType == LoweringType.AFTER_GUARDS) {
-            tool.getRuntime().lower(this, tool);
-        }
+        tool.getRuntime().lower(this, tool);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -37,6 +37,11 @@
         this.fields = type.getInstanceFields(true);
     }
 
+    public VirtualInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields) {
+        this.type = type;
+        this.fields = fields;
+    }
+
     @Override
     public ResolvedJavaType type() {
         return type;
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/Option.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/Option.java	Tue Jun 18 10:12:27 2013 +0200
@@ -27,6 +27,9 @@
 /**
  * Describes the attributes of an option whose {@link OptionValue value} is in a static field
  * annotated by this annotation type.
+ * 
+ * @see OptionProcessor
+ * @see OptionDescriptor
  */
 @Retention(RetentionPolicy.CLASS)
 @Target(ElementType.FIELD)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionDescriptor.java	Tue Jun 18 10:12:27 2013 +0200
@@ -0,0 +1,90 @@
+/*
+ * 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.options;
+
+/**
+ * Describes the attributes of a static field {@linkplain Option option} and provides access to its
+ * {@linkplain OptionValue value}.
+ */
+public class OptionDescriptor {
+
+    protected final String name;
+    protected final Class type;
+    protected final String help;
+    protected final OptionValue<?> option;
+    protected final Class<?> declaringClass;
+    protected final String fieldName;
+
+    public OptionDescriptor(String name, Class type, String help, Class<?> declaringClass, String fieldName, OptionValue<?> option) {
+        this.name = name;
+        this.type = type;
+        this.help = help;
+        this.option = option;
+        this.declaringClass = declaringClass;
+        this.fieldName = fieldName;
+    }
+
+    /**
+     * Gets the type of values stored in the option.
+     */
+    public Class getType() {
+        return type;
+    }
+
+    /**
+     * Gets a descriptive help message for the option.
+     */
+    public String getHelp() {
+        return help;
+    }
+
+    /**
+     * Gets the name of the option. It's up to the client of this object how to use the name to get
+     * a user specified value for the option from the environment.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Gets the boxed option value.
+     */
+    public OptionValue<?> getOptionValue() {
+        return option;
+    }
+
+    public Class<?> getDeclaringClass() {
+        return declaringClass;
+    }
+
+    public String getFieldName() {
+        return fieldName;
+    }
+
+    /**
+     * Gets a description of the location where this option is stored.
+     */
+    public String getLocation() {
+        return getDeclaringClass().getName() + "." + getFieldName();
+    }
+}
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java	Tue Jun 18 10:12:27 2013 +0200
@@ -23,26 +23,25 @@
 package com.oracle.graal.options;
 
 import java.io.*;
-import java.lang.reflect.*;
 import java.util.*;
 
 import javax.annotation.processing.*;
 import javax.lang.model.*;
 import javax.lang.model.element.*;
-import javax.lang.model.element.Modifier;
 import javax.lang.model.type.*;
 import javax.lang.model.util.*;
 import javax.tools.Diagnostic.Kind;
 import javax.tools.*;
 
 /**
- * Processes static fields annotated with {@link Option}. An {@link OptionProvider} is generated for
- * each such field that can be accessed as a {@linkplain ServiceLoader service} as follows:
+ * Processes static fields annotated with {@link Option}. An {@link Options} service is generated
+ * for each top level class containing at least one such field. These service objects can be
+ * retrieved as follows:
  * 
  * <pre>
- * ServiceLoader&lt;OptionProvider&gt; sl = ServiceLoader.loadInstalled(OptionProvider.class);
- * for (OptionProvider provider : sl) {
- *     // use provider
+ * ServiceLoader&lt;Options&gt; sl = ServiceLoader.loadInstalled(Options.class);
+ * for (OptionDescriptor desc : sl) {
+ *     // use desc
  * }
  * </pre>
  */
@@ -52,11 +51,7 @@
 
     private final Set<Element> processed = new HashSet<>();
 
-    private void processElement(Element element) {
-        if (processed.contains(element)) {
-            return;
-        }
-        processed.add(element);
+    private void processElement(Element element, OptionsInfo info) {
 
         if (!element.getModifiers().contains(Modifier.STATIC)) {
             processingEnv.getMessager().printMessage(Kind.ERROR, "Option field must be static", element);
@@ -102,10 +97,11 @@
             optionType = optionType.substring("java.lang.".length());
         }
 
-        String pkg = null;
         Element enclosing = element.getEnclosingElement();
         String declaringClass = "";
         String separator = "";
+        Set<Element> originatingElementsList = info.originatingElements;
+        originatingElementsList.add(field);
         while (enclosing != null) {
             if (enclosing.getKind() == ElementKind.CLASS || enclosing.getKind() == ElementKind.INTERFACE) {
                 if (enclosing.getModifiers().contains(Modifier.PRIVATE)) {
@@ -113,96 +109,97 @@
                     processingEnv.getMessager().printMessage(Kind.ERROR, msg, element);
                     return;
                 }
+                originatingElementsList.add(enclosing);
                 declaringClass = enclosing.getSimpleName() + separator + declaringClass;
                 separator = ".";
             } else {
                 assert enclosing.getKind() == ElementKind.PACKAGE;
-                pkg = ((PackageElement) enclosing).getQualifiedName().toString();
             }
             enclosing = enclosing.getEnclosingElement();
         }
 
-        String providerClassName = declaringClass.replace('.', '_') + "_" + fieldName;
+        info.options.add(new OptionInfo(optionName, annotation.help(), optionType, declaringClass, field));
+    }
+
+    private void createFiles(OptionsInfo info) {
+        String pkg = ((PackageElement) info.topDeclaringType.getEnclosingElement()).getQualifiedName().toString();
+        Name topDeclaringClass = info.topDeclaringType.getSimpleName();
+
+        String optionsClassName = topDeclaringClass + "_" + Options.class.getSimpleName();
+        Element[] originatingElements = info.originatingElements.toArray(new Element[info.originatingElements.size()]);
 
         Filer filer = processingEnv.getFiler();
-        try (PrintWriter out = createSourceFile(element, pkg, providerClassName, filer)) {
+        try (PrintWriter out = createSourceFile(pkg, optionsClassName, filer, originatingElements)) {
 
-            out.println("/*");
-            out.println(" * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.");
-            out.println(" * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.");
-            out.println(" *");
-            out.println(" * This code is free software; you can redistribute it and/or modify it");
-            out.println(" * under the terms of the GNU General Public License version 2 only, as");
-            out.println(" * published by the Free Software Foundation.");
-            out.println(" *");
-            out.println(" * This code is distributed in the hope that it will be useful, but WITHOUT");
-            out.println(" * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or");
-            out.println(" * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License");
-            out.println(" * version 2 for more details (a copy is included in the LICENSE file that");
-            out.println(" * accompanied this code).");
-            out.println(" *");
-            out.println(" * You should have received a copy of the GNU General Public License version");
-            out.println(" * 2 along with this work; if not, write to the Free Software Foundation,");
-            out.println(" * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.");
-            out.println(" *");
-            out.println(" * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA");
-            out.println(" * or visit www.oracle.com if you need additional information or have any");
-            out.println(" * questions.");
-            out.println(" */");
-
+            out.println("// CheckStyle: stop header check");
+            out.println("// GENERATED CONTENT - DO NOT EDIT");
+            out.println("// Source: " + topDeclaringClass + ".java");
             out.println("package " + pkg + ";");
             out.println("");
-            if (element.getModifiers().contains(Modifier.PRIVATE)) {
-                out.println("import " + Field.class.getName() + ";");
+            out.println("import java.util.*;");
+            out.println("import " + Options.class.getPackage().getName() + ".*;");
+            out.println("");
+            out.println("public class " + optionsClassName + " implements " + Options.class.getSimpleName() + " {");
+            out.println("    @Override");
+            String desc = OptionDescriptor.class.getSimpleName();
+            out.println("    public Iterator<" + desc + "> iterator() {");
+            out.println("        List<" + desc + "> options = Arrays.asList(");
+
+            boolean needPrivateFieldAccessor = false;
+            int i = 0;
+            for (OptionInfo option : info.options) {
+                String optionValue;
+                if (option.field.getModifiers().contains(Modifier.PRIVATE)) {
+                    needPrivateFieldAccessor = true;
+                    optionValue = "field(" + option.declaringClass + ".class, \"" + option.field.getSimpleName() + "\")";
+                } else {
+                    optionValue = option.declaringClass + "." + option.field.getSimpleName();
+                }
+                String name = option.name;
+                String type = option.type;
+                String help = option.help;
+                String declaringClass = option.declaringClass;
+                Name fieldName = option.field.getSimpleName();
+                String comma = i == info.options.size() - 1 ? "" : ",";
+                out.printf("            new %s(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s)%s\n", desc, name, type, help, declaringClass, fieldName, optionValue, comma);
+                i++;
             }
-            out.println("import " + OptionValue.class.getName() + ";");
-            out.println("import " + OptionProvider.class.getName() + ";");
-            out.println("");
-            out.println("public class " + providerClassName + " implements " + OptionProvider.class.getSimpleName() + " {");
-            out.println("    public String getHelp() {");
-            out.println("        return \"" + annotation.help() + "\";");
+            out.println("        );");
+            out.println("        return options.iterator();");
             out.println("    }");
-            out.println("    public String getName() {");
-            out.println("        return \"" + optionName + "\";");
-            out.println("    }");
-            out.println("    public Class getType() {");
-            out.println("        return " + optionType + ".class;");
-            out.println("    }");
-            out.println("    public " + OptionValue.class.getSimpleName() + "<?> getOptionValue() {");
-            if (!element.getModifiers().contains(Modifier.PRIVATE)) {
-                out.println("        return " + declaringClass + "." + fieldName + ";");
-            } else {
+            if (needPrivateFieldAccessor) {
+                out.println("    private static " + OptionValue.class.getSimpleName() + " field(Class<?> declaringClass, String fieldName) {");
                 out.println("        try {");
-                out.println("            Field field = " + declaringClass + ".class.getDeclaredField(\"" + fieldName + "\");");
+                out.println("            java.lang.reflect.Field field = declaringClass.getDeclaredField(fieldName);");
                 out.println("            field.setAccessible(true);");
                 out.println("            return (" + OptionValue.class.getSimpleName() + ") field.get(null);");
                 out.println("        } catch (Exception e) {");
                 out.println("            throw (InternalError) new InternalError().initCause(e);");
                 out.println("        }");
+                out.println("    }");
             }
-            out.println("    }");
             out.println("}");
         }
 
         try {
-            createProviderFile(field, pkg, providerClassName);
+            createProviderFile(pkg, optionsClassName, originatingElements);
         } catch (IOException e) {
-            processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), field);
+            processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), info.topDeclaringType);
         }
     }
 
-    private void createProviderFile(Element field, String pkg, String providerClassName) throws IOException {
+    private void createProviderFile(String pkg, String providerClassName, Element... originatingElements) throws IOException {
         String filename = "META-INF/providers/" + pkg + "." + providerClassName;
-        FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, field);
+        FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, originatingElements);
         PrintWriter writer = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8"));
-        writer.println(OptionProvider.class.getName());
+        writer.println(Options.class.getName());
         writer.close();
     }
 
-    protected PrintWriter createSourceFile(Element element, String pkg, String relativeName, Filer filer) {
+    protected PrintWriter createSourceFile(String pkg, String relativeName, Filer filer, Element... originatingElements) {
         try {
             // Ensure Unix line endings to comply with Graal code style guide checked by Checkstyle
-            JavaFileObject sourceFile = filer.createSourceFile(pkg + "." + relativeName, element);
+            JavaFileObject sourceFile = filer.createSourceFile(pkg + "." + relativeName, originatingElements);
             return new PrintWriter(sourceFile.openWriter()) {
 
                 @Override
@@ -215,14 +212,84 @@
         }
     }
 
+    static class OptionInfo {
+
+        final String name;
+        final String help;
+        final String type;
+        final String declaringClass;
+        final VariableElement field;
+
+        public OptionInfo(String name, String help, String type, String declaringClass, VariableElement field) {
+            this.name = name;
+            this.help = help;
+            this.type = type;
+            this.declaringClass = declaringClass;
+            this.field = field;
+        }
+
+        @Override
+        public String toString() {
+            return declaringClass + "." + field;
+        }
+    }
+
+    static class OptionsInfo {
+
+        final Element topDeclaringType;
+        final List<OptionInfo> options = new ArrayList<>();
+        final Set<Element> originatingElements = new HashSet<>();
+
+        public OptionsInfo(Element topDeclaringType) {
+            this.topDeclaringType = topDeclaringType;
+        }
+    }
+
+    private static Element topDeclaringType(Element element) {
+        Element enclosing = element.getEnclosingElement();
+        if (element == null || enclosing.getKind() == ElementKind.PACKAGE) {
+            assert element.getKind() == ElementKind.CLASS || element.getKind() == ElementKind.INTERFACE;
+            return element;
+        }
+        return topDeclaringType(enclosing);
+    }
+
     @Override
     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
         if (roundEnv.processingOver()) {
             return true;
         }
 
+        Map<Element, OptionsInfo> map = new HashMap<>();
         for (Element element : roundEnv.getElementsAnnotatedWith(Option.class)) {
-            processElement(element);
+            if (!processed.contains(element)) {
+                processed.add(element);
+                Element topDeclaringType = topDeclaringType(element);
+                OptionsInfo options = map.get(topDeclaringType);
+                if (options == null) {
+                    options = new OptionsInfo(topDeclaringType);
+                    map.put(topDeclaringType, options);
+                }
+                processElement(element, options);
+            }
+        }
+
+        boolean ok = true;
+        Map<String, OptionInfo> uniqueness = new HashMap<>();
+        for (OptionsInfo info : map.values()) {
+            for (OptionInfo option : info.options) {
+                OptionInfo conflict = uniqueness.put(option.name, option);
+                if (conflict != null) {
+                    processingEnv.getMessager().printMessage(Kind.ERROR, "Duplicate option names for " + option + " and " + conflict, option.field);
+                    ok = false;
+                }
+            }
+        }
+
+        if (ok) {
+            for (OptionsInfo info : map.values()) {
+                createFiles(info);
+            }
         }
 
         return true;
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProvider.java	Tue Jun 18 10:11:28 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +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.options;
-
-import java.util.*;
-
-/**
- * Describes the attributes of an {@linkplain Option option} and provides access to its
- * {@linkplain OptionValue value}. The {@link OptionProcessor} auto-generates instances of this
- * interface that are accessible as a {@linkplain ServiceLoader service}.
- */
-public interface OptionProvider {
-
-    /**
-     * Gets the type of values stored in the option.
-     */
-    Class getType();
-
-    /**
-     * Gets a descriptive help message for the option.
-     */
-    String getHelp();
-
-    /**
-     * Gets the name of the option. It's up to the client of this object how to use the name to get
-     * a user specified value for the option from the environment.
-     */
-    String getName();
-
-    /**
-     * Gets the boxed option value.
-     */
-    OptionValue<?> getOptionValue();
-}
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,14 +22,8 @@
  */
 package com.oracle.graal.options;
 
-import java.util.*;
-
 /**
- * A settable option value.
- * <p>
- * To access {@link OptionProvider} instances via a {@link ServiceLoader} for working with options,
- * instances of this class should be assigned to static final fields that are annotated with
- * {@link Option}.
+ * An option value.
  */
 public class OptionValue<T> {
 
@@ -38,32 +32,34 @@
      */
     protected T value;
 
-    /**
-     * Guards whether {@link #initialValue()} should be called to give a subclass an opportunity to
-     * provide a context-sensitive initial value for this option.
-     */
-    protected boolean initialValueCalled;
-
-    /**
-     * Create an option.
-     * 
-     * @param value the initial/default value of the option
-     */
     public OptionValue(T value) {
         this.value = value;
     }
 
+    private static final Object UNINITIALIZED = "UNINITIALIZED";
+
+    /**
+     * Creates an uninitialized option value for a subclass that initializes itself
+     * {@link #initialValue() lazily}.
+     */
+    @SuppressWarnings("unchecked")
+    protected OptionValue() {
+        this.value = (T) UNINITIALIZED;
+    }
+
+    /**
+     * Lazy initialization of value.
+     */
     protected T initialValue() {
-        return value;
+        throw new InternalError("Uninitialized option value must override initialValue()");
     }
 
     /**
      * Gets the value of this option.
      */
-    public final T getValue() {
-        if (!initialValueCalled) {
+    public T getValue() {
+        if (value == UNINITIALIZED) {
             value = initialValue();
-            initialValueCalled = true;
         }
         return value;
     }
@@ -72,8 +68,7 @@
      * Sets the value of this option.
      */
     @SuppressWarnings("unchecked")
-    public final void setValue(Object v) {
+    public void setValue(Object v) {
         this.value = (T) v;
-        this.initialValueCalled = true;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/Options.java	Tue Jun 18 10:12:27 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.options;
+
+import java.util.*;
+
+/**
+ * A {@linkplain ServiceLoader service} for accessing a set of {@link OptionDescriptor}s.
+ */
+public interface Options extends Iterable<OptionDescriptor> {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/StableOptionValue.java	Tue Jun 18 10:12:27 2013 +0200
@@ -0,0 +1,75 @@
+/*
+ * 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.options;
+
+/**
+ * An option that always returns the same {@linkplain #getValue() value}.
+ */
+public class StableOptionValue<T> extends OptionValue<T> {
+
+    /**
+     * Creates a stable option value.
+     */
+    public StableOptionValue(T value) {
+        super(value);
+    }
+
+    /**
+     * Used to assert the invariant for stability. Without using locks, this check is not safe
+     * against races and so it's only an assertion.
+     */
+    private boolean getValueCalled;
+
+    /**
+     * Creates an uninitialized stable option value for a subclass that initializes itself
+     * {@link #initialValue() lazily}.
+     */
+    public StableOptionValue() {
+    }
+
+    /**
+     * Gets the value of this option.
+     */
+    @Override
+    public final T getValue() {
+        T result = super.getValue();
+        assert initGetValueCalled();
+        return result;
+    }
+
+    private boolean initGetValueCalled() {
+        getValueCalled = true;
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     * <p>
+     * This must only be called if {@link #getValue()} has never been called.
+     */
+    @Override
+    public final void setValue(Object v) {
+        assert !getValueCalled;
+        super.setValue(v);
+    }
+}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -47,30 +47,20 @@
     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 CustomCanonicalizer customCanonicalizer;
-    private final Iterable<Node> workingSet;
+    private final boolean canonicalizeReads;
 
     public interface CustomCanonicalizer {
 
         ValueNode canonicalize(ValueNode node);
     }
 
-    public CanonicalizerPhase() {
-        this(null);
-    }
-
-    public CanonicalizerPhase(CustomCanonicalizer customCanonicalizer) {
-        this(customCanonicalizer, null);
-    }
-
-    public CanonicalizerPhase(CustomCanonicalizer customCanonicalizer, Iterable<Node> workingSet) {
-        this.customCanonicalizer = customCanonicalizer;
-        this.workingSet = workingSet;
+    public CanonicalizerPhase(boolean canonicalizeReads) {
+        this.canonicalizeReads = canonicalizeReads;
     }
 
     @Override
     protected void run(StructuredGraph graph, PhaseContext context) {
-        new Instance(context.getRuntime(), context.getAssumptions(), workingSet, customCanonicalizer).run(graph);
+        new Instance(context.getRuntime(), context.getAssumptions(), canonicalizeReads).run(graph);
     }
 
     public static class Instance extends Phase {
@@ -80,12 +70,13 @@
         private final MetaAccessProvider runtime;
         private final CustomCanonicalizer customCanonicalizer;
         private final Iterable<Node> initWorkingSet;
+        private final boolean canonicalizeReads;
 
         private NodeWorkList workList;
         private Tool tool;
 
-        public Instance(MetaAccessProvider runtime, Assumptions assumptions) {
-            this(runtime, assumptions, null, 0, null);
+        public Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads) {
+            this(runtime, assumptions, canonicalizeReads, null, 0, null);
         }
 
         /**
@@ -95,23 +86,24 @@
          *            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);
+        public Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads, Iterable<Node> workingSet, CustomCanonicalizer customCanonicalizer) {
+            this(runtime, assumptions, canonicalizeReads, 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 Instance(MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
-            this(runtime, assumptions, null, newNodesMark, customCanonicalizer);
+        public Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
+            this(runtime, assumptions, canonicalizeReads, null, newNodesMark, customCanonicalizer);
         }
 
-        public Instance(MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
+        public Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads, Iterable<Node> workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
             super("Canonicalizer");
             this.newNodesMark = newNodesMark;
             this.assumptions = assumptions;
             this.runtime = runtime;
+            this.canonicalizeReads = canonicalizeReads;
             this.customCanonicalizer = customCanonicalizer;
             this.initWorkingSet = workingSet;
         }
@@ -127,7 +119,7 @@
             if (newNodesMark > 0) {
                 workList.addAll(graph.getNewNodes(newNodesMark));
             }
-            tool = new Tool(workList, runtime, assumptions);
+            tool = new Tool();
             processWorkSet(graph);
         }
 
@@ -211,21 +203,6 @@
 
                     public Boolean call() {
                         ValueNode canonical = ((Canonicalizable) node).canonical(tool);
-// @formatter:off
-//     cases:                                           original node:
-//                                         |Floating|Fixed-unconnected|Fixed-connected|
-//                                         --------------------------------------------
-//                                     null|   1    |        X        |       3       |
-//                                         --------------------------------------------
-//                                 Floating|   2    |        X        |       4       |
-//       canonical node:                   --------------------------------------------
-//                        Fixed-unconnected|   X    |        X        |       5       |
-//                                         --------------------------------------------
-//                          Fixed-connected|   2    |        X        |       6       |
-//                                         --------------------------------------------
-//       X: must not happen (checked with assertions)
-// @formatter:on
-
                         return performReplacement(node, graph, canonical);
                     }
                 });
@@ -242,6 +219,20 @@
             return node.isDeleted();
         }
 
+// @formatter:off
+//     cases:                                           original node:
+//                                         |Floating|Fixed-unconnected|Fixed-connected|
+//                                         --------------------------------------------
+//                                     null|   1    |        X        |       3       |
+//                                         --------------------------------------------
+//                                 Floating|   2    |        X        |       4       |
+//       canonical node:                   --------------------------------------------
+//                        Fixed-unconnected|   X    |        X        |       5       |
+//                                         --------------------------------------------
+//                          Fixed-connected|   2    |        X        |       6       |
+//                                         --------------------------------------------
+//       X: must not happen (checked with assertions)
+// @formatter:on
         private boolean performReplacement(final Node node, final StructuredGraph graph, ValueNode canonical) {
             if (canonical == node) {
                 Debug.log("Canonicalizer: work on %s", node);
@@ -318,17 +309,7 @@
             }
         }
 
-        private static final class Tool implements SimplifierTool {
-
-            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;
-            }
+        private final class Tool implements SimplifierTool {
 
             @Override
             public void deleteBranch(FixedNode branch) {
@@ -352,13 +333,18 @@
 
             @Override
             public void addToWorkList(Node node) {
-                nodeWorkSet.addAgain(node);
+                workList.addAgain(node);
             }
 
             @Override
             public void removeIfUnused(Node node) {
                 tryKillUnused(node);
             }
+
+            @Override
+            public boolean canonicalizeReads() {
+                return canonicalizeReads;
+            }
         }
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CullFrameStatesPhase.java	Tue Jun 18 10:11:28 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +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.phases.common;
-
-import java.util.*;
-
-import com.oracle.graal.debug.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.graph.*;
-
-/**
- * This phase culls unused FrameStates from the graph. It does a post order iteration over the
- * graph, and
- */
-public class CullFrameStatesPhase extends Phase {
-
-    private static final DebugMetric metricFrameStatesCulled = Debug.metric("FrameStatesCulled");
-    private static final DebugMetric metricNodesRemoved = Debug.metric("NodesRemoved");
-    private static final DebugMetric metricMergesTraversed = Debug.metric("MergesTraversed");
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        int initialNodes = graph.getNodeCount();
-        new CullFrameStates(graph.start(), new State(null)).apply();
-        metricNodesRemoved.add(initialNodes - graph.getNodeCount());
-    }
-
-    public static class State implements MergeableState<State> {
-
-        private FrameState lastFrameState;
-
-        public State(FrameState lastFrameState) {
-            this.lastFrameState = lastFrameState;
-        }
-
-        @Override
-        public boolean merge(MergeNode merge, List<State> withStates) {
-            FrameState stateAfter = merge.stateAfter();
-            if (merge instanceof LoopBeginNode) {
-                if (stateAfter != null) {
-                    lastFrameState = stateAfter;
-                }
-                return true;
-            }
-            metricMergesTraversed.increment();
-            if (stateAfter != null) {
-                for (State other : withStates) {
-                    if (other.lastFrameState != lastFrameState) {
-                        lastFrameState = stateAfter;
-                        return true;
-                    }
-                }
-                metricFrameStatesCulled.increment();
-                merge.setStateAfter(null);
-                if (stateAfter.usages().isEmpty()) {
-                    GraphUtil.killWithUnusedFloatingInputs(stateAfter);
-                }
-            }
-            return true;
-        }
-
-        @Override
-        public void loopBegin(LoopBeginNode loopBegin) {
-        }
-
-        @Override
-        public void loopEnds(LoopBeginNode loopBegin, List<State> loopEndStates) {
-        }
-
-        @Override
-        public void afterSplit(AbstractBeginNode node) {
-        }
-
-        @Override
-        public State clone() {
-            return new State(lastFrameState);
-        }
-    }
-
-    public static class CullFrameStates extends PostOrderNodeIterator<State> {
-
-        public CullFrameStates(FixedNode start, State initialState) {
-            super(start, initialState);
-        }
-
-        @Override
-        protected void node(FixedNode node) {
-            if (node instanceof StateSplit) {
-                FrameState stateAfter = ((StateSplit) node).stateAfter();
-                if (stateAfter != null) {
-                    state.lastFrameState = stateAfter;
-                }
-            }
-        }
-    }
-
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -41,6 +41,7 @@
             if (node instanceof DeoptimizingNode) {
                 DeoptimizingNode deopt = (DeoptimizingNode) node;
                 if (deopt.canDeoptimize() && deopt.getDeoptimizationState() == null) {
+                    GraalInternalError.guarantee(currentState != null, "no FrameState at DeoptimizingNode %s", deopt);
                     deopt.setDeoptimizationState(currentState);
                 }
             }
@@ -58,10 +59,7 @@
 
         @Override
         protected FrameState merge(MergeNode merge, List<FrameState> states) {
-            if (merge.stateAfter() != null) {
-                return merge.stateAfter();
-            }
-            return singleFrameState(merge, states);
+            return merge.stateAfter() != null ? merge.stateAfter() : singleFrameState(merge, states);
         }
 
         @Override
@@ -73,7 +71,6 @@
         protected Map<LoopExitNode, FrameState> processLoop(LoopBeginNode loop, FrameState initialState) {
             return ReentrantNodeIterator.processLoop(this, loop, initialState).exitStates;
         }
-
     }
 
     @Override
@@ -93,33 +90,12 @@
     }
 
     private static FrameState singleFrameState(@SuppressWarnings("unused") MergeNode merge, List<FrameState> states) {
-        if (states.size() == 0) {
-            return null;
-        }
-        FrameState firstState = states.get(0);
-        FrameState singleState = firstState;
-        if (singleState == null) {
-            return null;
-        }
-        int singleBci = singleState.bci;
+        FrameState singleState = states.get(0);
         for (int i = 1; i < states.size(); ++i) {
-            FrameState cur = states.get(i);
-            if (cur == null) {
+            if (states.get(i) != singleState) {
                 return null;
             }
-
-            if (cur != singleState) {
-                singleState = null;
-            }
-
-            if (cur.bci != singleBci) {
-                singleBci = FrameState.INVALID_FRAMESTATE_BCI;
-            }
-
         }
-        if (singleState != null) {
-            return singleState;
-        }
-        return null;
+        return singleState;
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.phases.common;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.util.*;
 import java.util.Map.Entry;
 
@@ -220,7 +222,7 @@
 
     private static void processBlock(Block block, SchedulePhase schedule, int implicitNullCheckLimit) {
         List<ScheduledNode> nodes = schedule.nodesFor(block);
-        if (GraalOptions.OptImplicitNullChecks && implicitNullCheckLimit > 0) {
+        if (OptImplicitNullChecks.getValue() && implicitNullCheckLimit > 0) {
             new UseImplicitNullChecks(implicitNullCheckLimit).processNodes(nodes, block.getBeginNode());
         }
         new LowerGuards(block).processNodes(nodes, block.getBeginNode());
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.phases.common;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer;
@@ -43,6 +45,6 @@
     protected void run(StructuredGraph graph, C context) {
         int mark = graph.getMark();
         super.run(graph, context);
-        new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), mark, customCanonicalizer).apply(graph);
+        new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), !AOTCompilation.getValue(), mark, customCanonicalizer).apply(graph);
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,9 @@
  */
 package com.oracle.graal.phases.common;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.phases.common.InliningPhase.Options.*;
+
 import java.util.*;
 import java.util.concurrent.*;
 
@@ -33,16 +36,27 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer;
 import com.oracle.graal.phases.common.InliningUtil.InlineInfo;
+import com.oracle.graal.phases.common.InliningUtil.Inlineable;
 import com.oracle.graal.phases.common.InliningUtil.InlineableMacroNode;
+import com.oracle.graal.phases.common.InliningUtil.InlineableGraph;
 import com.oracle.graal.phases.common.InliningUtil.InliningPolicy;
 import com.oracle.graal.phases.graph.*;
 
 public class InliningPhase extends Phase {
 
+    static class Options {
+
+        // @formatter:off
+        @Option(help = "Unconditionally inline intrinsics")
+        public static final OptionValue<Boolean> AlwaysInlineIntrinsics = new OptionValue<>(false);
+        // @formatter:on
+    }
+
     private final PhasePlan plan;
     private final MetaAccessProvider runtime;
     private final Assumptions compilationAssumptions;
@@ -77,6 +91,16 @@
         this.optimisticOpts = optimisticOpts;
     }
 
+    public InliningPhase(MetaAccessProvider runtime, Replacements replacements, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts, InliningPolicy policy) {
+        this.runtime = runtime;
+        this.replacements = replacements;
+        this.compilationAssumptions = assumptions;
+        this.cache = cache;
+        this.plan = plan;
+        this.inliningPolicy = policy;
+        this.optimisticOpts = optimisticOpts;
+    }
+
     public void setCustomCanonicalizer(CustomCanonicalizer customCanonicalizer) {
         this.customCanonicalizer = customCanonicalizer;
     }
@@ -141,19 +165,16 @@
         if (info != null) {
             double invokeProbability = graphInfo.invokeProbability(invoke);
             double invokeRelevance = graphInfo.invokeRelevance(invoke);
-
-            if (inliningPolicy.isWorthInlining(info, data.inliningDepth(), invokeProbability, invokeRelevance, false)) {
-                MethodInvocation calleeInvocation = data.pushInvocation(info, parentAssumptions, invokeProbability, invokeRelevance);
+            MethodInvocation calleeInvocation = data.pushInvocation(info, parentAssumptions, invokeProbability, invokeRelevance);
 
-                for (int i = 0; i < info.numberOfMethods(); i++) {
-                    InlineableElement elem = getInlineableElement(info.methodAt(i), info.invoke(), calleeInvocation.assumptions());
-                    info.setInlinableElement(i, elem);
-                    if (elem instanceof StructuredGraph) {
-                        data.pushGraph((StructuredGraph) elem, invokeProbability * info.probabilityAt(i), invokeRelevance * info.relevanceAt(i));
-                    } else {
-                        assert elem instanceof InlineableMacroNode;
-                        data.pushDummyGraph();
-                    }
+            for (int i = 0; i < info.numberOfMethods(); i++) {
+                Inlineable elem = getInlineableElement(info.methodAt(i), info.invoke(), calleeInvocation.assumptions());
+                info.setInlinableElement(i, elem);
+                if (elem instanceof InlineableGraph) {
+                    data.pushGraph(((InlineableGraph) elem).getGraph(), invokeProbability * info.probabilityAt(i), invokeRelevance * info.relevanceAt(i));
+                } else {
+                    assert elem instanceof InlineableMacroNode;
+                    data.pushDummyGraph();
                 }
             }
         }
@@ -182,9 +203,9 @@
             metricInliningRuns.increment();
             Debug.dump(callerGraph, "after %s", callee);
 
-            if (GraalOptions.OptCanonicalizer) {
+            if (OptCanonicalizer.getValue()) {
                 int markBeforeCanonicalization = callerGraph.getMark();
-                new CanonicalizerPhase.Instance(runtime, callerAssumptions, invokeUsages, markBeforeInlining, customCanonicalizer).apply(callerGraph);
+                new CanonicalizerPhase.Instance(runtime, callerAssumptions, !AOTCompilation.getValue(), invokeUsages, markBeforeInlining, customCanonicalizer).apply(callerGraph);
 
                 // process invokes that are possibly created during canonicalization
                 for (Node newNode : callerGraph.getNewNodes(markBeforeCanonicalization)) {
@@ -207,12 +228,12 @@
         }
     }
 
-    private InlineableElement getInlineableElement(final ResolvedJavaMethod method, Invoke invoke, Assumptions assumptions) {
+    private Inlineable getInlineableElement(final ResolvedJavaMethod method, Invoke invoke, Assumptions assumptions) {
         Class<? extends FixedWithNextNode> macroNodeClass = InliningUtil.getMacroNodeClass(replacements, method);
         if (macroNodeClass != null) {
             return new InlineableMacroNode(macroNodeClass);
         } else {
-            return buildGraph(method, invoke, assumptions);
+            return new InlineableGraph(buildGraph(method, invoke, assumptions));
         }
     }
 
@@ -268,8 +289,8 @@
                     // probability to check the inlining
                 }
 
-                if (GraalOptions.OptCanonicalizer) {
-                    new CanonicalizerPhase.Instance(runtime, assumptions).apply(newGraph);
+                if (OptCanonicalizer.getValue()) {
+                    new CanonicalizerPhase.Instance(runtime, assumptions, !AOTCompilation.getValue()).apply(newGraph);
                 }
 
                 return newGraph;
@@ -278,7 +299,7 @@
     }
 
     private StructuredGraph getCachedGraph(ResolvedJavaMethod method) {
-        if (GraalOptions.CacheGraphs && cache != null) {
+        if (CacheGraphs.getValue() && cache != null) {
             StructuredGraph cachedGraph = cache.get(method);
             if (cachedGraph != null) {
                 return cachedGraph;
@@ -288,6 +309,8 @@
     }
 
     private StructuredGraph parseBytecodes(StructuredGraph newGraph, Assumptions assumptions) {
+        boolean hasMatureProfilingInfo = newGraph.method().getProfilingInfo().isMature();
+
         if (plan != null) {
             plan.runPhases(PhasePosition.AFTER_PARSING, newGraph);
         }
@@ -295,15 +318,12 @@
 
         new DeadCodeEliminationPhase().apply(newGraph);
 
-        if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase.Instance(runtime, assumptions).apply(newGraph);
+        if (OptCanonicalizer.getValue()) {
+            new CanonicalizerPhase.Instance(runtime, assumptions, !AOTCompilation.getValue()).apply(newGraph);
         }
 
-        if (GraalOptions.CullFrameStates) {
-            new CullFrameStatesPhase().apply(newGraph);
-        }
-        if (GraalOptions.CacheGraphs && cache != null) {
-            cache.put(newGraph.copy());
+        if (CacheGraphs.getValue() && cache != null) {
+            cache.put(newGraph.copy(), hasMatureProfilingInfo);
         }
         return newGraph;
     }
@@ -328,7 +348,7 @@
         }
 
         protected double computeMaximumSize(double relevance, int configuredMaximum) {
-            double inlineRatio = Math.min(GraalOptions.RelevanceCapForInlining, relevance);
+            double inlineRatio = Math.min(RelevanceCapForInlining.getValue(), relevance);
             return configuredMaximum * inlineRatio;
         }
 
@@ -340,7 +360,7 @@
         }
 
         protected boolean isIntrinsic(InlineInfo info) {
-            if (GraalOptions.AlwaysInlineIntrinsics) {
+            if (AlwaysInlineIntrinsics.getValue()) {
                 return onlyIntrinsics(info);
             } else {
                 return onlyForcedIntrinsics(info);
@@ -379,7 +399,7 @@
         protected static int determineNodeCount(InlineInfo info) {
             int nodes = 0;
             for (int i = 0; i < info.numberOfMethods(); i++) {
-                InlineableElement elem = info.inlineableElementAt(i);
+                Inlineable elem = info.inlineableElementAt(i);
                 if (elem != null) {
                     nodes += elem.getNodeCount();
                 }
@@ -390,10 +410,10 @@
         protected static double determineInvokeProbability(InlineInfo info) {
             double invokeProbability = 0;
             for (int i = 0; i < info.numberOfMethods(); i++) {
-                InlineableElement callee = info.inlineableElementAt(i);
+                Inlineable callee = info.inlineableElementAt(i);
                 Iterable<Invoke> invokes = callee.getInvokes();
                 if (invokes.iterator().hasNext()) {
-                    NodesToDoubles nodeProbabilities = new ComputeProbabilityClosure((StructuredGraph) callee).apply();
+                    NodesToDoubles nodeProbabilities = new ComputeProbabilityClosure(((InlineableGraph) callee).getGraph()).apply();
                     for (Invoke invoke : invokes) {
                         invokeProbability += nodeProbabilities.get(invoke.asNode());
                     }
@@ -410,7 +430,7 @@
         }
 
         public boolean continueInlining(StructuredGraph currentGraph) {
-            if (currentGraph.getNodeCount() >= GraalOptions.MaximumDesiredSize) {
+            if (currentGraph.getNodeCount() >= MaximumDesiredSize.getValue()) {
                 InliningUtil.logInliningDecision("inlining is cut off by MaximumDesiredSize");
                 metricInliningStoppedByMaxDesiredSize.increment();
                 return false;
@@ -425,10 +445,16 @@
             }
 
             double inliningBonus = getInliningBonus(info);
-
+            int nodes = determineNodeCount(info);
             int lowLevelGraphSize = previousLowLevelGraphSize(info);
-            if (GraalOptions.SmallCompiledLowLevelGraphSize > 0 && lowLevelGraphSize > GraalOptions.SmallCompiledLowLevelGraphSize * inliningBonus) {
-                return InliningUtil.logNotInlinedMethod(info, inliningDepth, "too large previous low-level graph: %d", lowLevelGraphSize);
+
+            if (SmallCompiledLowLevelGraphSize.getValue() > 0 && lowLevelGraphSize > SmallCompiledLowLevelGraphSize.getValue() * inliningBonus) {
+                return InliningUtil.logNotInlinedMethod(info, inliningDepth, "too large previous low-level graph (low-level-nodes: %d, relevance=%f, probability=%f, bonus=%f, nodes=%d)",
+                                lowLevelGraphSize, relevance, probability, inliningBonus, nodes);
+            }
+
+            if (nodes < TrivialInliningSize.getValue() * inliningBonus) {
+                return InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "trivial (relevance=%f, probability=%f, bonus=%f, nodes=%d)", relevance, probability, inliningBonus, nodes);
             }
 
             /*
@@ -437,23 +463,20 @@
              * useful to inline those methods but increases bootstrap time (maybe those methods are
              * also getting queued in the compilation queue concurrently)
              */
-
-            int nodes = determineNodeCount(info);
-            if (nodes < GraalOptions.TrivialInliningSize * inliningBonus) {
-                return InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "trivial (nodes=%d)", nodes);
+            double invokes = determineInvokeProbability(info);
+            if (LimitInlinedInvokes.getValue() > 0 && fullyProcessed && invokes > LimitInlinedInvokes.getValue() * inliningBonus) {
+                return InliningUtil.logNotInlinedMethod(info, inliningDepth, "callee invoke probability is too high (invokeP=%f, relevance=%f, probability=%f, bonus=%f, nodes=%d)", invokes,
+                                relevance, probability, inliningBonus, nodes);
             }
 
-            double invokes = determineInvokeProbability(info);
-            if (GraalOptions.LimitInlinedInvokes > 0 && fullyProcessed && invokes > GraalOptions.LimitInlinedInvokes * inliningBonus) {
-                return InliningUtil.logNotInlinedMethod(info, inliningDepth, "invoke probability is too high (%f)", invokes);
+            double maximumNodes = computeMaximumSize(relevance, (int) (MaximumInliningSize.getValue() * inliningBonus));
+            if (nodes <= maximumNodes) {
+                return InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d <= %f)", relevance, probability,
+                                inliningBonus, nodes, maximumNodes);
             }
 
-            double maximumNodes = computeMaximumSize(relevance, (int) (GraalOptions.MaximumInliningSize * inliningBonus));
-            if (nodes < maximumNodes) {
-                return InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "relevance-based (relevance=%f, nodes=%d)", relevance, nodes);
-            }
-
-            return InliningUtil.logNotInlinedMethod(info, inliningDepth, "(relevance=%f, probability=%f, bonus=%f)", relevance, probability, inliningBonus);
+            return InliningUtil.logNotInlinedMethod(info, inliningDepth, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d > %f)", relevance, probability, inliningBonus, nodes,
+                            maximumNodes);
         }
     }
 
@@ -784,7 +807,7 @@
         }
 
         public double invokeRelevance(Invoke invoke) {
-            return Math.min(GraalOptions.CapInheritedRelevance, relevance) * nodeRelevance.get(invoke.asNode());
+            return Math.min(CapInheritedRelevance.getValue(), relevance) * nodeRelevance.get(invoke.asNode());
         }
     }
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.phases.common;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.*;
@@ -64,7 +66,37 @@
         boolean isWorthInlining(InlineInfo info, int inliningDepth, double probability, double relevance, boolean fullyProcessed);
     }
 
-    public static class InlineableMacroNode implements InlineableElement {
+    public interface Inlineable {
+
+        int getNodeCount();
+
+        Iterable<Invoke> getInvokes();
+    }
+
+    public static class InlineableGraph implements Inlineable {
+
+        private final StructuredGraph graph;
+
+        public InlineableGraph(StructuredGraph graph) {
+            this.graph = graph;
+        }
+
+        @Override
+        public int getNodeCount() {
+            return graph.getNodeCount();
+        }
+
+        @Override
+        public Iterable<Invoke> getInvokes() {
+            return graph.getInvokes();
+        }
+
+        public StructuredGraph getGraph() {
+            return graph;
+        }
+    }
+
+    public static class InlineableMacroNode implements Inlineable {
 
         private final Class<? extends FixedWithNextNode> macroNodeClass;
 
@@ -98,7 +130,7 @@
      * Print a HotSpot-style inlining message to the console.
      */
     private static void printInlining(final ResolvedJavaMethod method, final Invoke invoke, final int inliningDepth, final boolean success, final String msg, final Object... args) {
-        if (GraalOptions.HotSpotPrintInlining) {
+        if (HotSpotPrintInlining.getValue()) {
             final int mod = method.getModifiers();
             // 1234567
             TTY.print("        ");     // print timestamp
@@ -236,13 +268,13 @@
 
         ResolvedJavaMethod methodAt(int index);
 
-        InlineableElement inlineableElementAt(int index);
+        Inlineable inlineableElementAt(int index);
 
         double probabilityAt(int index);
 
         double relevanceAt(int index);
 
-        void setInlinableElement(int index, InlineableElement inlineableElement);
+        void setInlinableElement(int index, Inlineable inlineableElement);
 
         /**
          * Performs the inlining described by this object and returns the node that represents the
@@ -275,10 +307,10 @@
             return invoke;
         }
 
-        protected static void inline(Invoke invoke, ResolvedJavaMethod concrete, InlineableElement inlineable, Assumptions assumptions, boolean receiverNullCheck) {
+        protected static void inline(Invoke invoke, ResolvedJavaMethod concrete, Inlineable inlineable, Assumptions assumptions, boolean receiverNullCheck) {
             StructuredGraph graph = invoke.asNode().graph();
-            if (inlineable instanceof StructuredGraph) {
-                StructuredGraph calleeGraph = (StructuredGraph) inlineable;
+            if (inlineable instanceof InlineableGraph) {
+                StructuredGraph calleeGraph = ((InlineableGraph) inlineable).getGraph();
                 InliningUtil.inline(invoke, calleeGraph, receiverNullCheck);
 
                 graph.getLeafGraphIds().add(calleeGraph.graphId());
@@ -329,11 +361,12 @@
     private static class ExactInlineInfo extends AbstractInlineInfo {
 
         protected final ResolvedJavaMethod concrete;
-        private InlineableElement inlineableElement;
+        private Inlineable inlineableElement;
 
         public ExactInlineInfo(Invoke invoke, ResolvedJavaMethod concrete) {
             super(invoke);
             this.concrete = concrete;
+            assert concrete != null;
         }
 
         @Override
@@ -375,13 +408,13 @@
         }
 
         @Override
-        public InlineableElement inlineableElementAt(int index) {
+        public Inlineable inlineableElementAt(int index) {
             assert index == 0;
             return inlineableElement;
         }
 
         @Override
-        public void setInlinableElement(int index, InlineableElement inlineableElement) {
+        public void setInlinableElement(int index, Inlineable inlineableElement) {
             assert index == 0;
             this.inlineableElement = inlineableElement;
         }
@@ -396,7 +429,7 @@
 
         private final ResolvedJavaMethod concrete;
         private final ResolvedJavaType type;
-        private InlineableElement inlineableElement;
+        private Inlineable inlineableElement;
 
         public TypeGuardInlineInfo(Invoke invoke, ResolvedJavaMethod concrete, ResolvedJavaType type) {
             super(invoke);
@@ -416,7 +449,7 @@
         }
 
         @Override
-        public InlineableElement inlineableElementAt(int index) {
+        public Inlineable inlineableElementAt(int index) {
             assert index == 0;
             return inlineableElement;
         }
@@ -434,7 +467,7 @@
         }
 
         @Override
-        public void setInlinableElement(int index, InlineableElement inlineableElement) {
+        public void setInlinableElement(int index, Inlineable inlineableElement) {
             assert index == 0;
             this.inlineableElement = inlineableElement;
         }
@@ -458,15 +491,13 @@
             LoadHubNode receiverHub = graph.add(new LoadHubNode(receiver, typeHub.kind()));
             CompareNode typeCheck = CompareNode.createCompareNode(Condition.EQ, receiverHub, typeHub);
             FixedGuardNode guard = graph.add(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile));
-            ValueAnchorNode anchor = graph.add(new ValueAnchorNode());
             assert invoke.predecessor() != null;
 
-            ValueNode anchoredReceiver = createAnchoredReceiver(graph, anchor, type, receiver, true);
+            ValueNode anchoredReceiver = createAnchoredReceiver(graph, guard, type, receiver, true);
             invoke.callTarget().replaceFirstInput(receiver, anchoredReceiver);
 
             graph.addBeforeFixed(invoke.asNode(), receiverHub);
             graph.addBeforeFixed(invoke.asNode(), guard);
-            graph.addBeforeFixed(invoke.asNode(), anchor);
         }
 
         @Override
@@ -489,7 +520,7 @@
         private final ArrayList<ProfiledType> ptypes;
         private final ArrayList<Double> concretesProbabilities;
         private final double notRecordedTypeProbability;
-        private final InlineableElement[] inlineableElements;
+        private final Inlineable[] inlineableElements;
 
         public MultiTypeGuardInlineInfo(Invoke invoke, ArrayList<ResolvedJavaMethod> concretes, ArrayList<Double> concretesProbabilities, ArrayList<ProfiledType> ptypes,
                         ArrayList<Integer> typesToConcretes, double notRecordedTypeProbability) {
@@ -502,7 +533,7 @@
             this.ptypes = ptypes;
             this.typesToConcretes = typesToConcretes;
             this.notRecordedTypeProbability = notRecordedTypeProbability;
-            this.inlineableElements = new InlineableElement[concretes.size()];
+            this.inlineableElements = new Inlineable[concretes.size()];
             this.methodProbabilities = computeMethodProbabilities();
             this.maximumMethodProbability = maximumMethodProbability();
             assert maximumMethodProbability > 0;
@@ -538,7 +569,7 @@
         }
 
         @Override
-        public InlineableElement inlineableElementAt(int index) {
+        public Inlineable inlineableElementAt(int index) {
             assert index >= 0 && index < concretes.size();
             return inlineableElements[index];
         }
@@ -554,7 +585,7 @@
         }
 
         @Override
-        public void setInlinableElement(int index, InlineableElement inlineableElement) {
+        public void setInlinableElement(int index, Inlineable inlineableElement) {
             assert index >= 0 && index < concretes.size();
             inlineableElements[index] = inlineableElement;
         }
@@ -668,7 +699,7 @@
                 replacementNodes.add(null);
             }
 
-            if (GraalOptions.OptTailDuplication) {
+            if (OptTailDuplication.getValue()) {
                 /*
                  * We might want to perform tail duplication at the merge after a type switch, if
                  * there are invokes that would benefit from the improvement in type information.
@@ -905,16 +936,12 @@
         @Override
         public void tryToDevirtualizeInvoke(MetaAccessProvider runtime, Assumptions assumptions) {
             if (hasSingleMethod()) {
-                tryToDevirtualizeSingleMethod(graph(), runtime);
+                devirtualizeWithTypeSwitch(graph(), InvokeKind.Special, concretes.get(0), runtime);
             } else {
                 tryToDevirtualizeMultipleMethods(graph(), runtime);
             }
         }
 
-        private void tryToDevirtualizeSingleMethod(StructuredGraph graph, MetaAccessProvider runtime) {
-            devirtualizeWithTypeSwitch(graph, InvokeKind.Special, concretes.get(0), runtime);
-        }
-
         private void tryToDevirtualizeMultipleMethods(StructuredGraph graph, MetaAccessProvider runtime) {
             MethodCallTargetNode methodCallTarget = (MethodCallTargetNode) invoke.callTarget();
             if (methodCallTarget.invokeKind() == InvokeKind.Interface) {
@@ -1154,7 +1181,7 @@
                 ArrayList<ResolvedJavaMethod> newConcreteMethods = new ArrayList<>();
                 ArrayList<Double> newConcreteMethodsProbabilities = new ArrayList<>();
                 for (int i = 0; i < concreteMethods.size(); ++i) {
-                    if (concreteMethodsProbabilities.get(i) >= GraalOptions.MegamorphicInliningMinMethodProbability) {
+                    if (concreteMethodsProbabilities.get(i) >= MegamorphicInliningMinMethodProbability.getValue()) {
                         newConcreteMethods.add(concreteMethods.get(i));
                         newConcreteMethodsProbabilities.add(concreteMethodsProbabilities.get(i));
                     }
@@ -1198,9 +1225,13 @@
         }
     }
 
-    private static PiNode createAnchoredReceiver(StructuredGraph graph, FixedNode anchor, ResolvedJavaType commonType, ValueNode receiver, boolean exact) {
+    private static PiNode createAnchoredReceiver(StructuredGraph graph, GuardingNode anchor, ResolvedJavaType commonType, ValueNode receiver, boolean exact) {
+        return createAnchoredReceiver(graph, anchor, receiver, exact ? StampFactory.exactNonNull(commonType) : StampFactory.declaredNonNull(commonType));
+    }
+
+    private static PiNode createAnchoredReceiver(StructuredGraph graph, GuardingNode anchor, ValueNode receiver, Stamp stamp) {
         // to avoid that floating reads on receiver fields float above the type check
-        return graph.unique(new PiNode(receiver, exact ? StampFactory.exactNonNull(commonType) : StampFactory.declaredNonNull(commonType), anchor));
+        return graph.unique(new PiNode(receiver, stamp, anchor));
     }
 
     // TODO (chaeubl): cleanup this method
@@ -1227,7 +1258,7 @@
     private static boolean checkTargetConditions(InliningData data, Replacements replacements, Invoke invoke, ResolvedJavaMethod method, OptimisticOptimizations optimisticOpts) {
         if (method == null) {
             return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "the method is not resolved");
-        } else if (Modifier.isNative(method.getModifiers()) && (!GraalOptions.Intrinsify || !InliningUtil.canIntrinsify(replacements, method))) {
+        } else if (Modifier.isNative(method.getModifiers()) && (!Intrinsify.getValue() || !InliningUtil.canIntrinsify(replacements, method))) {
             return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "it is a non-intrinsic native method");
         } else if (Modifier.isAbstract(method.getModifiers())) {
             return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "it is an abstract method");
@@ -1235,7 +1266,7 @@
             return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "the method's class is not initialized");
         } else if (!method.canBeInlined()) {
             return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "it is marked non-inlinable");
-        } else if (data.countRecursiveInlining(method) > GraalOptions.MaximumRecursiveInlining) {
+        } else if (data.countRecursiveInlining(method) > MaximumRecursiveInlining.getValue()) {
             return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "it exceeds the maximum recursive inlining depth");
         } else if (new OptimisticOptimizations(method).lessOptimisticThan(optimisticOpts)) {
             return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "the callee uses less optimistic optimizations than caller");
@@ -1269,6 +1300,18 @@
 
         FrameState stateAfter = invoke.stateAfter();
         assert stateAfter == null || stateAfter.isAlive();
+        if (receiverNullCheck) {
+            GuardingNode receiverNullCheckNode = receiverNullCheck(invoke);
+            if (receiverNullCheckNode != null) {
+                ValueNode receiver = invoke.callTarget().arguments().get(0);
+                Stamp piStamp = receiver.stamp();
+                if (piStamp instanceof ObjectStamp) {
+                    piStamp = piStamp.join(StampFactory.objectNonNull());
+                }
+                ValueNode anchoredReceiver = createAnchoredReceiver(graph, receiverNullCheckNode, receiver, piStamp);
+                invoke.callTarget().replaceFirstInput(receiver, anchoredReceiver);
+            }
+        }
 
         IdentityHashMap<Node, Node> replacements = new IdentityHashMap<>();
         ArrayList<Node> nodes = new ArrayList<>();
@@ -1300,9 +1343,6 @@
 
         Map<Node, Node> duplicates = graph.addDuplicates(nodes, replacements);
         FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode);
-        if (receiverNullCheck) {
-            receiverNullCheck(invoke);
-        }
         invoke.asNode().replaceAtPredecessor(firstCFGNodeDuplicate);
 
         FrameState stateAtExceptionEdge = null;
@@ -1408,15 +1448,17 @@
         return true;
     }
 
-    public static void receiverNullCheck(Invoke invoke) {
+    public static GuardingNode receiverNullCheck(Invoke invoke) {
         MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget();
         StructuredGraph graph = callTarget.graph();
         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.asNode(),
-                            graph.add(new FixedGuardNode(graph.unique(new IsNullNode(firstParam)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true)));
+            FixedGuardNode guard = graph.add(new FixedGuardNode(graph.unique(new IsNullNode(firstParam)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true));
+            graph.addBeforeFixed(invoke.asNode(), guard);
+            return guard;
         }
+        return null;
     }
 
     public static boolean canIntrinsify(Replacements replacements, ResolvedJavaMethod target) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InsertStateAfterPlaceholderPhase.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InsertStateAfterPlaceholderPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -48,6 +48,9 @@
 
         @Override
         public ValueNode canonical(CanonicalizerTool tool) {
+            if (!usages().isEmpty()) {
+                return this;
+            }
             if (stateAfter() == null) {
                 return null;
             }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.phases.common;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.util.*;
 
 import com.oracle.graal.graph.Graph.NodeChangedListener;
@@ -44,7 +46,7 @@
             if (canonicalizationRoots.isEmpty()) {
                 break;
             }
-            new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), canonicalizationRoots, null).apply(graph);
+            new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), !AOTCompilation.getValue(), canonicalizationRoots, null).apply(graph);
             canonicalizationRoots.clear();
         }
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.phases.common;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
@@ -69,6 +71,11 @@
         }
 
         @Override
+        public LoweringType getLoweringType() {
+            return loweringType;
+        }
+
+        @Override
         public GuardingNode createNullCheckGuard(GuardedNode guardedNode, ValueNode object) {
             if (object.objectStamp().nonNull()) {
                 // Short cut creation of null check guard if the object is known to be non-null.
@@ -95,7 +102,7 @@
             if (loweringType == LoweringType.AFTER_GUARDS) {
                 throw new GraalInternalError("Cannot create guards in after-guard lowering");
             }
-            if (GraalOptions.OptEliminateGuards) {
+            if (OptEliminateGuards.getValue()) {
                 for (Node usage : condition.usages()) {
                     if (!activeGuards.isNew(usage) && activeGuards.isMarked(usage) && ((GuardNode) usage).negated() == negated) {
                         return (GuardNode) usage;
@@ -103,7 +110,7 @@
                 }
             }
             GuardNode newGuard = guardAnchor.asNode().graph().unique(new GuardNode(condition, guardAnchor, deoptReason, action, negated));
-            if (GraalOptions.OptEliminateGuards) {
+            if (OptEliminateGuards.getValue()) {
                 activeGuards.grow();
                 activeGuards.mark(newGuard);
             }
@@ -149,7 +156,7 @@
             int mark = graph.getMark();
 
             IncrementalCanonicalizerPhase<PhaseContext> canonicalizer = new IncrementalCanonicalizerPhase<>();
-            canonicalizer.addPhase(round);
+            canonicalizer.appendPhase(round);
             canonicalizer.apply(graph, context);
 
             if (!round.deferred && !containsLowerable(graph.getNewNodes(mark))) {
@@ -203,7 +210,7 @@
                 }
             }
 
-            if (parentAnchor == null && GraalOptions.OptEliminateGuards) {
+            if (parentAnchor == null && OptEliminateGuards.getValue()) {
                 for (GuardNode guard : anchor.asNode().usages().filter(GuardNode.class)) {
                     activeGuards.clear(guard);
                 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/SafepointInsertionPhase.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/SafepointInsertionPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.phases.common;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
@@ -33,7 +35,7 @@
 
     @Override
     protected void run(StructuredGraph graph) {
-        if (GraalOptions.GenLoopSafepoints) {
+        if (GenLoopSafepoints.getValue()) {
             for (LoopEndNode loopEndNode : graph.getNodes(LoopEndNode.class)) {
                 if (!loopEndNode.canSafepoint()) {
                     continue;
@@ -43,8 +45,8 @@
             }
         }
 
-        if (GraalOptions.GenSafepoints) {
-            if (!GraalOptions.OptEliminateSafepoints || graph.getNodes(MethodCallTargetNode.class).isNotEmpty()) {
+        if (GenSafepoints.getValue()) {
+            if (!OptEliminateSafepoints.getValue() || graph.getNodes(MethodCallTargetNode.class).isNotEmpty()) {
                 for (ReturnNode returnNode : graph.getNodes(ReturnNode.class)) {
                     SafepointNode safepoint = graph.add(new SafepointNode());
                     graph.addBeforeFixed(returnNode, safepoint);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.phases.common;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.util.*;
 
 import com.oracle.graal.debug.*;
@@ -80,7 +82,7 @@
     public static final TailDuplicationDecision DEFAULT_DECISION = new TailDuplicationDecision() {
 
         public boolean doTransform(MergeNode merge, int fixedNodeCount) {
-            if (fixedNodeCount < GraalOptions.TailDuplicationTrivialSize) {
+            if (fixedNodeCount < TailDuplicationTrivialSize.getValue()) {
                 return true;
             }
             HashSet<PhiNode> improvements = new HashSet<>();
@@ -136,7 +138,7 @@
         // 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) && nodeProbabilities.get(merge) >= GraalOptions.TailDuplicationProbability) {
+            if (!(merge instanceof LoopBeginNode) && nodeProbabilities.get(merge) >= TailDuplicationProbability.getValue()) {
                 tailDuplicate(merge, DEFAULT_DECISION, null, phaseContext);
             }
         }
@@ -298,7 +300,7 @@
                     phi.setMerge(mergeAfter);
                 }
             }
-            new CanonicalizerPhase(null, graph.getNewNodes(startMark)).apply(graph, phaseContext);
+            new CanonicalizerPhase.Instance(phaseContext.getRuntime(), phaseContext.getAssumptions(), !AOTCompilation.getValue(), graph.getNewNodes(startMark), null).apply(graph);
             Debug.dump(graph, "After tail duplication at %s", merge);
         }
 
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,215 +22,325 @@
  */
 package com.oracle.graal.phases;
 
+import com.oracle.graal.options.*;
+
 /**
  * This class encapsulates options that control the behavior of the Graal compiler.
- * 
- * (thomaswue) WARNING: Fields of this class are treated as final by Graal.
  */
 // @formatter:off
 public final class GraalOptions {
 
-    // Checkstyle: stop
-    private static final boolean ____ = false;
-    // Checkstyle: resume
-
-    public static String  CompilerConfiguration              = "basic";
-    public static String  GraalRuntime                       = "basic";
+    @Option(help = "Enable use of compiler intrinsics")
+    public static final OptionValue<Boolean> Intrinsify = new OptionValue<>(true);
+    @Option(help = "Enable inlining of monomorphic calls")
+    static final OptionValue<Boolean> InlineMonomorphicCalls = new OptionValue<>(true);
+    @Option(help = "Enable inlining of polymorphic calls")
+    static final OptionValue<Boolean> InlinePolymorphicCalls = new OptionValue<>(true);
+    @Option(help = "Enable inlining of megamorphic calls")
+    static final OptionValue<Boolean> InlineMegamorphicCalls = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Double> MegamorphicInliningMinMethodProbability = new OptionValue<>(0.33D);
+    @Option(help = "")
+    public static final OptionValue<Integer> MaximumDesiredSize = new OptionValue<>(5000);
+    @Option(help = "")
+    public static final OptionValue<Integer> MaximumRecursiveInlining = new OptionValue<>(1);
 
     // inlining settings
-    public static boolean Inline                             = true;
-    public static boolean AlwaysInlineIntrinsics             = ____;
-    public static boolean Intrinsify                         = true;
-           static boolean InlineMonomorphicCalls             = true;
-           static boolean InlinePolymorphicCalls             = true;
-           static boolean InlineMegamorphicCalls             = true;
-    public static double  MegamorphicInliningMinMethodProbability = 0.33;
-    public static int     MaximumDesiredSize                 = 5000;
-    public static int     MaximumRecursiveInlining           = 1;
-    public static float   BoostInliningForEscapeAnalysis     = 2f;
-    public static float   RelevanceCapForInlining            = 1f;
-    public static float   CapInheritedRelevance              = 1f;
-    public static boolean IterativeInlining                  = ____;
+    @Option(help = "")
+    public static final OptionValue<Float> BoostInliningForEscapeAnalysis = new OptionValue<>(2f);
+    @Option(help = "")
+    public static final OptionValue<Float> RelevanceCapForInlining = new OptionValue<>(1f);
+    @Option(help = "")
+    public static final OptionValue<Float> CapInheritedRelevance = new OptionValue<>(1f);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IterativeInlining = new OptionValue<>(false);
 
-    public static int     TrivialInliningSize                = 10;
-    public static int     MaximumInliningSize                = 300;
-    public static int     SmallCompiledLowLevelGraphSize     = 300;
-    public static double  LimitInlinedInvokes                = 5.0;
+    @Option(help = "")
+    public static final OptionValue<Integer> TrivialInliningSize = new OptionValue<>(10);
+    @Option(help = "")
+    public static final OptionValue<Integer> MaximumInliningSize = new OptionValue<>(300);
+    @Option(help = "")
+    public static final OptionValue<Integer> SmallCompiledLowLevelGraphSize = new OptionValue<>(300);
+    @Option(help = "")
+    public static final OptionValue<Double> LimitInlinedInvokes = new OptionValue<>(5.0);
 
     // escape analysis settings
-    public static boolean PartialEscapeAnalysis              = true;
-    public static boolean EscapeAnalysisHistogram            = ____;
-    public static int     EscapeAnalysisIterations           = 2;
-    public static String  EscapeAnalyzeOnly                  = null;
-    public static int     MaximumEscapeAnalysisArrayLength   = 32;
-    public static boolean PEAInliningHints                   = ____;
+    @Option(help = "")
+    public static final OptionValue<Boolean> PartialEscapeAnalysis = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> EscapeAnalysisHistogram = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Integer> EscapeAnalysisIterations = new OptionValue<>(2);
+    @Option(help = "")
+    public static final OptionValue<String> EscapeAnalyzeOnly = new OptionValue<>(null);
+    @Option(help = "")
+    public static final OptionValue<Integer> MaximumEscapeAnalysisArrayLength = new OptionValue<>(32);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PEAInliningHints = new OptionValue<>(false);
 
-    public static double  TailDuplicationProbability         = 0.5;
-    public static int     TailDuplicationTrivialSize         = 1;
+    @Option(help = "")
+    public static final OptionValue<Double> TailDuplicationProbability = new OptionValue<>(0.5);
+    @Option(help = "")
+    public static final OptionValue<Integer> TailDuplicationTrivialSize = new OptionValue<>(1);
 
     // profiling information
-    public static int     DeoptsToDisableOptimisticOptimization = 40;
-    public static int     MatureExecutionsBranch             = 1;
-    public static int     MatureExecutionsPerSwitchCase      = 1;
-    public static int     MatureExecutionsTypeProfile        = 1;
+    @Option(help = "")
+    public static final OptionValue<Integer> DeoptsToDisableOptimisticOptimization = new OptionValue<>(40);
 
     // comilation queue
-    public static boolean DynamicCompilePriority             = ____;
-    public static String  CompileTheWorld                    = null;
-    public static int     CompileTheWorldStartAt             = 1;
-    public static int     CompileTheWorldStopAt              = Integer.MAX_VALUE;
+    @Option(help = "")
+    public static final OptionValue<Boolean> DynamicCompilePriority = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<String> CompileTheWorld = new OptionValue<>(null);
+    @Option(help = "")
+    public static final OptionValue<Integer> CompileTheWorldStartAt = new OptionValue<>(1);
+    @Option(help = "")
+    public static final OptionValue<Integer> CompileTheWorldStopAt = new OptionValue<>(Integer.MAX_VALUE);
 
     // graph caching
-    public static boolean CacheGraphs                        = true;
-    public static int     GraphCacheSize                     = 1000;
-    public static boolean PrintGraphCache                    = ____;
+    @Option(help = "")
+    public static final OptionValue<Boolean> CacheGraphs = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Integer> GraphCacheSize = new OptionValue<>(1000);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintGraphCache = new OptionValue<>(false);
 
     //loop transform settings TODO (gd) tune
-    public static boolean LoopPeeling                        = true;
-    public static boolean ReassociateInvariants              = true;
-    public static boolean FullUnroll                         = true;
-    public static boolean LoopUnswitch                       = true;
-    public static int     FullUnrollMaxNodes                 = 300;
-    public static int     ExactFullUnrollMaxNodes            = 1200;
-    public static float   MinimumPeelProbability             = 0.35f;
-    public static int     LoopMaxUnswitch                    = 3;
-    public static int     LoopUnswitchMaxIncrease            = 50;
-    public static int     LoopUnswitchUncertaintyBoost       = 5;
-    public static boolean UseLoopLimitChecks                 = true;
+    @Option(help = "")
+    public static final OptionValue<Boolean> LoopPeeling = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> ReassociateInvariants = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> FullUnroll = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> LoopUnswitch = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Integer> FullUnrollMaxNodes = new OptionValue<>(300);
+    @Option(help = "")
+    public static final OptionValue<Integer> ExactFullUnrollMaxNodes = new OptionValue<>(1200);
+    @Option(help = "")
+    public static final OptionValue<Float> MinimumPeelProbability = new OptionValue<>(0.35f);
+    @Option(help = "")
+    public static final OptionValue<Integer> LoopMaxUnswitch = new OptionValue<>(3);
+    @Option(help = "")
+    public static final OptionValue<Integer> LoopUnswitchMaxIncrease = new OptionValue<>(50);
+    @Option(help = "")
+    public static final OptionValue<Integer> LoopUnswitchUncertaintyBoost = new OptionValue<>(5);
+    @Option(help = "")
+    public static final OptionValue<Boolean> UseLoopLimitChecks = new OptionValue<>(true);
 
     // debugging settings
-    public static boolean ZapStackOnMethodEntry              = ____;
-    public static boolean DeoptALot                          = ____;
-    public static boolean VerifyPhases                       = false;
+    @Option(help = "")
+    public static final OptionValue<Boolean> ZapStackOnMethodEntry = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> DeoptALot = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> VerifyPhases = new OptionValue<>(false);
 
-    public static String  PrintFilter                        = null;
+    @Option(help = "")
+    public static final OptionValue<String> PrintFilter = new OptionValue<>(null);
 
     // Debug settings:
-    public static boolean BootstrapReplacements              = ____;
+    @Option(help = "")
+    public static final OptionValue<Boolean> BootstrapReplacements = new OptionValue<>(false);
 
     // Ideal graph visualizer output settings
-    public static boolean PrintBinaryGraphs                  = true;
-    public static boolean PrintCFG                           = ____;
-    public static boolean PrintIdealGraphFile                = ____;
-    public static String  PrintIdealGraphAddress             = "127.0.0.1";
-    public static int     PrintIdealGraphPort                = 4444;
-    public static int     PrintBinaryGraphPort               = 4445;
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintBinaryGraphs = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintCFG = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintIdealGraphFile = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<String> PrintIdealGraphAddress = new OptionValue<>("127.0.0.1");
+    @Option(help = "")
+    public static final OptionValue<Integer> PrintIdealGraphPort = new OptionValue<>(4444);
+    @Option(help = "")
+    public static final OptionValue<Integer> PrintBinaryGraphPort = new OptionValue<>(4445);
 
     // Other printing settings
-    public static boolean PrintCompilation                   = ____;
-    public static boolean PrintProfilingInformation          = ____;
-    public static boolean PrintIRWithLIR                     = ____;
-    public static boolean PrintCodeBytes                     = ____;
-    public static boolean PrintBailout                       = ____;
-    public static int     TraceLinearScanLevel               = 0;
-    public static int     TraceLIRGeneratorLevel             = 0;
-    public static boolean TraceEscapeAnalysis                = ____;
-    public static int     TraceBytecodeParserLevel           = 0;
-    public static boolean ExitVMOnBailout                    = ____;
-    public static boolean ExitVMOnException                  = true;
-    public static boolean PrintStackTraceOnException         = false;
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintCompilation = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintProfilingInformation = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintIRWithLIR = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintCodeBytes = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintBailout = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Integer> TraceLinearScanLevel = new OptionValue<>(0);
+    @Option(help = "")
+    public static final OptionValue<Integer> TraceLIRGeneratorLevel = new OptionValue<>(0);
+    @Option(help = "")
+    public static final OptionValue<Boolean> TraceEscapeAnalysis = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Integer> TraceBytecodeParserLevel = new OptionValue<>(0);
+    @Option(help = "")
+    public static final OptionValue<Boolean> ExitVMOnBailout = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> ExitVMOnException = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> PrintStackTraceOnException = new OptionValue<>(false);
 
     // HotSpot command line options
-    public static boolean HotSpotPrintCompilation            = ____;
-    public static boolean HotSpotPrintInlining               = ____;
+    @Option(help = "")
+    public static final OptionValue<Boolean> HotSpotPrintCompilation = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> HotSpotPrintInlining = new OptionValue<>(false);
 
     // Register allocator debugging
-    public static String  RegisterPressure                   = null;
+    @Option(help = "")
+    public static final OptionValue<String> RegisterPressure = new OptionValue<>(null);
 
     // Code generator settings
-    public static boolean ConditionalElimination             = true;
-    public static boolean CullFrameStates                    = ____;
-    public static boolean UseProfilingInformation            = true;
-           static boolean RemoveNeverExecutedCode            = true;
-           static boolean UseExceptionProbability            = true;
-           static boolean UseExceptionProbabilityForOperations = true;
-    public static boolean OmitHotExceptionStacktrace         = ____;
-    public static boolean GenSafepoints                      = true;
-    public static boolean GenLoopSafepoints                  = true;
-           static boolean UseTypeCheckHints                  = true;
-    public static boolean InlineVTableStubs                  = true;
-    public static boolean AlwaysInlineVTableStubs            = ____;
-    public static boolean GenAssertionCode                   = ____;
-    public static boolean AlignCallsForPatching              = true;
-    public static boolean ResolveClassBeforeStaticInvoke     = ____;
-    public static boolean CanOmitFrame                       = true;
-    public static int     SafepointPollOffset                = 256;
+    @Option(help = "")
+    public static final OptionValue<Boolean> ConditionalElimination = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> UseProfilingInformation = new OptionValue<>(true);
+    @Option(help = "")
+           static final OptionValue<Boolean> RemoveNeverExecutedCode = new OptionValue<>(true);
+           @Option(help = "")
+           static final OptionValue<Boolean> UseExceptionProbability = new OptionValue<>(true);
+           @Option(help = "")
+           static final OptionValue<Boolean> UseExceptionProbabilityForOperations = new OptionValue<>(true);
+           @Option(help = "")
+    public static final OptionValue<Boolean> OmitHotExceptionStacktrace = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> GenSafepoints = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> GenLoopSafepoints = new OptionValue<>(true);
+    @Option(help = "")
+           static final OptionValue<Boolean> UseTypeCheckHints = new OptionValue<>(true);
+           @Option(help = "")
+    public static final OptionValue<Boolean> InlineVTableStubs = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> AlwaysInlineVTableStubs = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> GenAssertionCode = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> AlignCallsForPatching = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> ResolveClassBeforeStaticInvoke = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> CanOmitFrame = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Integer> SafepointPollOffset = new OptionValue<>(256);
 
-    public static boolean MemoryAwareScheduling              = true;
+    @Option(help = "")
+    public static final OptionValue<Boolean> MemoryAwareScheduling = new OptionValue<>(true);
 
     // Translating tableswitch instructions
-    public static int     MinimumJumpTableSize               = 5;
-    public static int     RangeTestsSwitchDensity            = 5;
-    public static double  MinTableSwitchDensity              = 0.5;
+    @Option(help = "")
+    public static final OptionValue<Integer> MinimumJumpTableSize = new OptionValue<>(5);
+    @Option(help = "")
+    public static final OptionValue<Integer> RangeTestsSwitchDensity = new OptionValue<>(5);
+    @Option(help = "")
+    public static final OptionValue<Double> MinTableSwitchDensity = new OptionValue<>(0.5);
 
-    public static boolean DetailedAsserts                    = ____;
+    // Ahead of time compilation
+    @Option(help = "configure compiler to emit code compatible with AOT requirements for HotSpot")
+    public static final OptionValue<Boolean> AOTCompilation = new OptionValue<>(false);
 
     // Runtime settings
-    public static int     StackShadowPages                   = 2;
+    @Option(help = "")
+    public static final OptionValue<Integer> StackShadowPages = new OptionValue<>(2);
 
-    public static boolean SupportJsrBytecodes                = true;
+    @Option(help = "")
+    public static final OptionValue<Boolean> SupportJsrBytecodes = new OptionValue<>(true);
 
-    public static boolean OptAssumptions                     = true;
-    public static boolean OptConvertDeoptsToGuards           = true;
-    public static boolean OptReadElimination                 = true;
-    public static boolean OptEarlyReadElimination            = true;
-    public static boolean OptCanonicalizer                   = true;
-    public static boolean OptScheduleOutOfLoops              = true;
-    public static boolean OptEliminateGuards                 = true;
-    public static boolean OptEliminateSafepoints             = true;
-    public static boolean OptImplicitNullChecks              = true;
-    public static boolean OptLivenessAnalysis                = true;
-    public static boolean OptLoopTransform                   = true;
-    public static boolean OptFloatingReads                   = true;
-    public static boolean OptTailDuplication                 = true;
-    public static boolean OptEliminatePartiallyRedundantGuards = true;
-    public static boolean OptFilterProfiledTypes             = true;
-    public static boolean OptDevirtualizeInvokesOptimistically = true;
-    public static boolean OptPushThroughPi                   = true;
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptAssumptions = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptConvertDeoptsToGuards = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptReadElimination = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptCanonicalizer = new OptionValue<>(true);
+    @Option(help = "")
+     public static final OptionValue<Boolean> OptScheduleOutOfLoops = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptEliminateGuards = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptEliminateSafepoints = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptImplicitNullChecks = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptLivenessAnalysis = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptLoopTransform = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptFloatingReads = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptTailDuplication = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptEliminatePartiallyRedundantGuards = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptFilterProfiledTypes = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptDevirtualizeInvokesOptimistically = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> OptPushThroughPi = new OptionValue<>(true);
 
     // Intrinsification settings
-    public static boolean IntrinsifyObjectClone              = ____;
-    public static boolean IntrinsifyArrayCopy                = true;
-    public static boolean IntrinsifyObjectMethods            = true;
-    public static boolean IntrinsifySystemMethods            = true;
-    public static boolean IntrinsifyClassMethods             = true;
-    public static boolean IntrinsifyThreadMethods            = true;
-    public static boolean IntrinsifyUnsafeMethods            = true;
-    public static boolean IntrinsifyMathMethods              = true;
-    public static boolean IntrinsifyAESMethods               = true;
-    public static boolean IntrinsifyReflectionMethods        = true;
-    public static boolean IntrinsifyInstalledCodeMethods     = true;
-    public static boolean IntrinsifyCallSiteTarget           = true;
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifyObjectClone = new OptionValue<>(false);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifyArrayCopy = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifyObjectMethods = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifySystemMethods = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifyClassMethods = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifyThreadMethods = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifyUnsafeMethods = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifyMathMethods = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifyAESMethods = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifyReflectionMethods = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifyInstalledCodeMethods = new OptionValue<>(true);
+    @Option(help = "")
+    public static final OptionValue<Boolean> IntrinsifyCallSiteTarget = new OptionValue<>(true);
     /**
      * Counts the various paths taken through snippets.
      */
-    public static boolean SnippetCounters = false;
+    @Option(help = "")
+    public static final OptionValue<Boolean> SnippetCounters = new OptionValue<>(false);
 
     /**
      * If the probability that a checkcast will hit one the profiled types (up to {@link #CheckcastMaxHints})
      * is below this value, the checkcast will be compiled without hints.
      */
-    public static double CheckcastMinHintHitProbability = 0.5;
+    @Option(help = "")
+    public static final OptionValue<Double> CheckcastMinHintHitProbability = new OptionValue<>(0.5);
 
     /**
      * The maximum number of hint types that will be used when compiling a checkcast for which
      * profiling information is available. Note that {@link #CheckcastMinHintHitProbability}
      * also influences whether hints are used.
      */
-    public static int CheckcastMaxHints = 2;
-
-    /**
-     * @see #CheckcastMinHintHitProbability
-     */
-    public static double InstanceOfMinHintHitProbability = 0.5;
+    @Option(help = "")
+    public static final OptionValue<Integer> CheckcastMaxHints = new OptionValue<>(2);
 
     /**
-     * @see #CheckcastMaxHints
+     * If the probability that an instanceof will hit one the profiled types (up to {@link #InstanceOfMaxHints})
+     * is below this value, the instanceof will be compiled without hints.
      */
-    public static int InstanceOfMaxHints = 2;
+    @Option(help = "")
+    public static final OptionValue<Double> InstanceOfMinHintHitProbability = new OptionValue<>(0.5);
 
-    static {
-        // turn detailed assertions on when the general assertions are on (misusing the assert keyword for this)
-        assert (DetailedAsserts = true) == true;
-    }
+    /**
+     * The maximum number of hint types that will be used when compiling an instanceof for which
+     * profiling information is available. Note that {@link #InstanceOfMinHintHitProbability}
+     * also influences whether hints are used.
+     */
+    @Option(help = "")
+    public static final OptionValue<Integer> InstanceOfMaxHints = new OptionValue<>(2);
 }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java	Tue Jun 18 10:12:27 2013 +0200
@@ -79,39 +79,39 @@
     }
 
     public boolean removeNeverExecutedCode() {
-        return GraalOptions.RemoveNeverExecutedCode && enabledOpts.contains(Optimization.RemoveNeverExecutedCode);
+        return GraalOptions.RemoveNeverExecutedCode.getValue() && enabledOpts.contains(Optimization.RemoveNeverExecutedCode);
     }
 
     public boolean useTypeCheckHints() {
-        return GraalOptions.UseTypeCheckHints && enabledOpts.contains(Optimization.UseTypeCheckHints);
+        return GraalOptions.UseTypeCheckHints.getValue() && enabledOpts.contains(Optimization.UseTypeCheckHints);
     }
 
     public boolean inlineMonomorphicCalls() {
-        return GraalOptions.InlineMonomorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
+        return GraalOptions.InlineMonomorphicCalls.getValue() && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
     }
 
     public boolean inlinePolymorphicCalls() {
-        return GraalOptions.InlinePolymorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
+        return GraalOptions.InlinePolymorphicCalls.getValue() && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
     }
 
     public boolean inlineMegamorphicCalls() {
-        return GraalOptions.InlineMegamorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
+        return GraalOptions.InlineMegamorphicCalls.getValue() && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
     }
 
     public boolean devirtualizeInvokes() {
-        return GraalOptions.OptDevirtualizeInvokesOptimistically && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
+        return GraalOptions.OptDevirtualizeInvokesOptimistically.getValue() && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
     }
 
     public boolean useExceptionProbability() {
-        return GraalOptions.UseExceptionProbability && enabledOpts.contains(Optimization.UseExceptionProbability);
+        return GraalOptions.UseExceptionProbability.getValue() && enabledOpts.contains(Optimization.UseExceptionProbability);
     }
 
     public boolean useExceptionProbabilityForOperations() {
-        return GraalOptions.UseExceptionProbabilityForOperations && enabledOpts.contains(Optimization.UseExceptionProbabilityForOperations);
+        return GraalOptions.UseExceptionProbabilityForOperations.getValue() && enabledOpts.contains(Optimization.UseExceptionProbabilityForOperations);
     }
 
     public boolean useLoopLimitChecks() {
-        return GraalOptions.UseLoopLimitChecks && enabledOpts.contains(Optimization.UseLoopLimitChecks);
+        return GraalOptions.UseLoopLimitChecks.getValue() && enabledOpts.contains(Optimization.UseLoopLimitChecks);
     }
 
     public boolean lessOptimisticThan(OptimisticOptimizations other) {
@@ -124,6 +124,6 @@
     }
 
     private static boolean checkDeoptimizations(ProfilingInfo profilingInfo, DeoptimizationReason reason) {
-        return profilingInfo.getDeoptimizationCount(reason) < GraalOptions.DeoptsToDisableOptimisticOptimization;
+        return profilingInfo.getDeoptimizationCount(reason) < GraalOptions.DeoptsToDisableOptimisticOptimization.getValue();
     }
 }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhasePlan.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhasePlan.java	Tue Jun 18 10:12:27 2013 +0200
@@ -50,8 +50,7 @@
      */
     public static enum PhasePosition {
         AFTER_PARSING,
-        HIGH_LEVEL,
-        LOW_LEVEL
+        HIGH_LEVEL
     }
     // @formatter:on
 
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhaseSuite.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhaseSuite.java	Tue Jun 18 10:12:27 2013 +0200
@@ -34,7 +34,17 @@
         this.phases = new ArrayList<>();
     }
 
-    public final void addPhase(BasePhase<? super C> phase) {
+    /**
+     * Add a new phase at the beginning of this suite.
+     */
+    public final void prependPhase(BasePhase<? super C> phase) {
+        phases.add(0, phase);
+    }
+
+    /**
+     * Add a new phase at the end of this suite.
+     */
+    public final void appendPhase(BasePhase<? super C> phase) {
         phases.add(phase);
     }
 
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeInliningRelevanceClosure.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeInliningRelevanceClosure.java	Tue Jun 18 10:12:27 2013 +0200
@@ -24,7 +24,6 @@
 
 import java.util.*;
 
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.util.*;
@@ -56,14 +55,14 @@
 
         public ComputeInliningRelevanceIterator(StructuredGraph graph) {
             super(graph);
-            this.scopes = computeLowestPathProbabilities();
+            this.scopes = computeScopesAndProbabilities();
         }
 
         @Override
         protected void initializeScope() {
             Scope scope = scopes.get(currentScopeStart);
             parentRelevance = getParentScopeRelevance(scope);
-            currentProbability = scope.minPathProbability;
+            currentProbability = scope.probability;
         }
 
         private double getParentScopeRelevance(Scope scope) {
@@ -73,7 +72,7 @@
                 for (AbstractEndNode end : ((LoopBeginNode) scope.start).forwardEnds()) {
                     parentProbability += nodeProbabilities.get(end);
                 }
-                return parentProbability / scope.parent.minPathProbability;
+                return parentProbability / scope.parent.probability;
             } else {
                 assert scope.parent == null;
                 return 1.0;
@@ -90,12 +89,11 @@
             assert !Double.isNaN(relevance);
         }
 
-        private HashMap<FixedNode, Scope> computeLowestPathProbabilities() {
+        private HashMap<FixedNode, Scope> computeScopesAndProbabilities() {
             HashMap<FixedNode, Scope> result = new HashMap<>();
 
             for (Scope scope : computeScopes()) {
-                double lowestPathProbability = computeLowestPathProbability(scope);
-                scope.minPathProbability = Math.max(EPSILON, lowestPathProbability);
+                scope.probability = Math.max(EPSILON, nodeProbabilities.get(scope.start));
                 result.put(scope.start, scope);
             }
 
@@ -128,92 +126,13 @@
             processedLoops.put(loop, result);
             return result;
         }
-
-        private double computeLowestPathProbability(Scope scope) {
-            FixedNode scopeStart = scope.start;
-            ArrayList<FixedNode> pathBeginNodes = new ArrayList<>();
-            pathBeginNodes.add(scopeStart);
-            double minPathProbability = nodeProbabilities.get(scopeStart);
-            boolean isLoopScope = scopeStart instanceof LoopBeginNode;
-
-            do {
-                Node current = pathBeginNodes.remove(pathBeginNodes.size() - 1);
-                do {
-                    if (isLoopScope && current instanceof LoopExitNode && ((LoopBeginNode) scopeStart).loopExits().contains((LoopExitNode) current)) {
-                        return minPathProbability;
-                    } else if (current instanceof LoopBeginNode && current != scopeStart) {
-                        current = getMaxProbabilityLoopExit((LoopBeginNode) current, pathBeginNodes);
-                        minPathProbability = getMinPathProbability((FixedNode) current, minPathProbability);
-                    } else if (current instanceof ControlSplitNode) {
-                        current = getMaxProbabilitySux((ControlSplitNode) current, pathBeginNodes);
-                        minPathProbability = getMinPathProbability((FixedNode) current, minPathProbability);
-                    } else {
-                        assert current.successors().count() <= 1;
-                        current = current.successors().first();
-                    }
-                } while (current != null);
-            } while (!pathBeginNodes.isEmpty());
-
-            return minPathProbability;
-        }
-
-        private double getMinPathProbability(FixedNode current, double minPathProbability) {
-            if (current != null && nodeProbabilities.get(current) < minPathProbability) {
-                return nodeProbabilities.get(current);
-            }
-            return minPathProbability;
-        }
-
-        private Node getMaxProbabilitySux(ControlSplitNode controlSplit, ArrayList<FixedNode> pathBeginNodes) {
-            Node maxSux = null;
-            double maxProbability = 0.0;
-            int pathBeginCount = pathBeginNodes.size();
-
-            for (Node sux : controlSplit.successors()) {
-                double probability = controlSplit.probability((AbstractBeginNode) sux);
-                if (probability > maxProbability) {
-                    maxProbability = probability;
-                    maxSux = sux;
-                    truncate(pathBeginNodes, pathBeginCount);
-                } else if (probability == maxProbability) {
-                    pathBeginNodes.add((FixedNode) sux);
-                }
-            }
-
-            return maxSux;
-        }
-
-        private Node getMaxProbabilityLoopExit(LoopBeginNode loopBegin, ArrayList<FixedNode> pathBeginNodes) {
-            Node maxSux = null;
-            double maxProbability = 0.0;
-            int pathBeginCount = pathBeginNodes.size();
-
-            for (LoopExitNode sux : loopBegin.loopExits()) {
-                double probability = nodeProbabilities.get(sux);
-                if (probability > maxProbability) {
-                    maxProbability = probability;
-                    maxSux = sux;
-                    truncate(pathBeginNodes, pathBeginCount);
-                } else if (probability == maxProbability) {
-                    pathBeginNodes.add(sux);
-                }
-            }
-
-            return maxSux;
-        }
-
-        private void truncate(ArrayList<FixedNode> pathBeginNodes, int pathBeginCount) {
-            for (int i = pathBeginNodes.size() - pathBeginCount; i > 0; i--) {
-                pathBeginNodes.remove(pathBeginNodes.size() - 1);
-            }
-        }
     }
 
     private static class Scope {
 
         public final FixedNode start;
         public final Scope parent;
-        public double minPathProbability;
+        public double probability;
 
         public Scope(FixedNode start, Scope parent) {
             this.start = start;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java	Tue Jun 18 10:12:27 2013 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.util.*;
@@ -44,7 +45,6 @@
  * <li>{@link PropagateLoopFrequency} propagates the loop frequencies and multiplies each
  * {@link FixedNode}'s probability with its loop frequency.</li>
  * </ol>
- * TODO: add exception probability information to Invokes
  */
 public class ComputeProbabilityClosure {
 
@@ -63,12 +63,98 @@
     }
 
     public NodesToDoubles apply() {
+        adjustControlSplitProbabilities();
         new PropagateProbability(graph.start()).apply();
         computeLoopFactors();
         new PropagateLoopFrequency(graph.start()).apply();
+        assert verifyProbabilities();
         return nodeProbabilities;
     }
 
+    /**
+     * Assume that paths with a DeoptimizeNode at their end are taken infrequently.
+     */
+    private void adjustControlSplitProbabilities() {
+        HashSet<ControlSplitNode> result = new HashSet<>();
+        NodeBitMap visitedNodes = new NodeBitMap(graph);
+        for (DeoptimizeNode n : graph.getNodes(DeoptimizeNode.class)) {
+            if (n.action().doesInvalidateCompilation()) {
+                findParentControlSplitNodes(result, n, visitedNodes);
+            }
+        }
+
+        for (ControlSplitNode n : result) {
+            if (!allSuxVisited(n, visitedNodes)) {
+                modifyProbabilities(n, visitedNodes);
+            }
+        }
+    }
+
+    private static void findParentControlSplitNodes(HashSet<ControlSplitNode> result, DeoptimizeNode n, NodeBitMap visitedNodes) {
+        ArrayDeque<FixedNode> nodes = new ArrayDeque<>();
+        nodes.push(n);
+
+        Node currentNode;
+        do {
+            currentNode = nodes.pop();
+            visitedNodes.mark(currentNode);
+
+            for (Node pred : currentNode.cfgPredecessors()) {
+                FixedNode fixedPred = (FixedNode) pred;
+                if (visitedNodes.isMarked(fixedPred) && allPredsVisited(fixedPred, visitedNodes)) {
+                    DebugScope.dump(n.graph(), "ComputeProbabilityClosure");
+                    GraalInternalError.shouldNotReachHere(String.format("Endless loop because %s was already visited", fixedPred));
+                } else if (allSuxVisited(fixedPred, visitedNodes)) {
+                    nodes.push(fixedPred);
+                } else {
+                    assert fixedPred instanceof ControlSplitNode : "only control splits can have more than one sux";
+                    result.add((ControlSplitNode) fixedPred);
+                }
+            }
+        } while (!nodes.isEmpty());
+    }
+
+    private static void modifyProbabilities(ControlSplitNode controlSplit, NodeBitMap visitedNodes) {
+        assert !allSuxVisited(controlSplit, visitedNodes);
+        for (Node sux : controlSplit.successors()) {
+            if (visitedNodes.isMarked(sux)) {
+                controlSplit.setProbability((AbstractBeginNode) sux, 0);
+            }
+        }
+    }
+
+    private static boolean allSuxVisited(FixedNode node, NodeBitMap visitedNodes) {
+        return allVisited(node.successors(), visitedNodes);
+    }
+
+    private static boolean allPredsVisited(FixedNode node, NodeBitMap visitedNodes) {
+        return allVisited(node.cfgPredecessors(), visitedNodes);
+    }
+
+    private static boolean allVisited(Iterable<? extends Node> nodes, NodeBitMap visitedNodes) {
+        for (Node sux : nodes) {
+            if (!visitedNodes.contains(sux)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private boolean verifyProbabilities() {
+        if (doesNotAlwaysDeopt(graph)) {
+            for (DeoptimizeNode n : graph.getNodes(DeoptimizeNode.class)) {
+                if (n.action().doesInvalidateCompilation() && nodeProbabilities.get(n) > 0.01) {
+                    throw new AssertionError(String.format("%s with reason %s and probability %f in graph %s", n, n.reason(), nodeProbabilities.get(n), graph));
+                }
+            }
+        }
+        return true;
+    }
+
+    private static boolean doesNotAlwaysDeopt(StructuredGraph graph) {
+        return graph.getNodes(ReturnNode.class).iterator().hasNext();
+    }
+
     private void computeLoopFactors() {
         for (LoopInfo info : loopInfos) {
             double frequency = info.loopFrequency(nodeProbabilities);
@@ -204,19 +290,11 @@
         public void afterSplit(AbstractBeginNode node) {
             assert node.predecessor() != null;
             Node pred = node.predecessor();
-            if (pred instanceof Invoke) {
-                Invoke x = (Invoke) pred;
-                if (x.next() != node) {
-                    probability = 0;
-                }
-            } else {
-                assert pred instanceof ControlSplitNode;
-                ControlSplitNode x = (ControlSplitNode) pred;
-                double nodeProbability = x.probability(node);
-                assert nodeProbability >= 0.0 : "Node " + x + " provided negative probability for begin " + node + ": " + nodeProbability;
-                probability *= nodeProbability;
-                assert probability >= 0.0;
-            }
+            ControlSplitNode x = (ControlSplitNode) pred;
+            double nodeProbability = x.probability(node);
+            assert nodeProbability >= 0.0 : "Node " + x + " provided negative probability for begin " + node + ": " + nodeProbability;
+            probability *= nodeProbability;
+            assert probability >= 0.0;
         }
     }
 
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.phases.schedule;
 
 import static com.oracle.graal.api.meta.LocationIdentity.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 
@@ -172,7 +173,7 @@
     private final SchedulingStrategy selectedStrategy;
 
     public SchedulePhase() {
-        this(GraalOptions.OptScheduleOutOfLoops ? SchedulingStrategy.LATEST_OUT_OF_LOOPS : SchedulingStrategy.LATEST);
+        this(OptScheduleOutOfLoops.getValue() ? SchedulingStrategy.LATEST_OUT_OF_LOOPS : SchedulingStrategy.LATEST);
     }
 
     public SchedulePhase(SchedulingStrategy strategy) {
@@ -185,7 +186,7 @@
         earliestCache = graph.createNodeMap();
         blockToNodesMap = new BlockMap<>(cfg);
 
-        if (GraalOptions.MemoryAwareScheduling && selectedStrategy != SchedulingStrategy.EARLIEST && graph.getNodes(FloatingReadNode.class).isNotEmpty()) {
+        if (MemoryAwareScheduling.getValue() && selectedStrategy != SchedulingStrategy.EARLIEST && graph.getNodes(FloatingReadNode.class).isNotEmpty()) {
 
             assignBlockToNodes(graph, SchedulingStrategy.EARLIEST);
             sortNodesWithinBlocks(graph, SchedulingStrategy.EARLIEST);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,14 +22,23 @@
  */
 package com.oracle.graal.phases.tiers;
 
+import static com.oracle.graal.phases.tiers.Suites.Options.*;
+
 import java.util.*;
 
 import com.oracle.graal.graph.*;
+import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 
 public final class Suites {
 
-    public static final Suites DEFAULT;
+    static class Options {
+
+        // @formatter:off
+        @Option(help = "The compiler configuration to use")
+        static final OptionValue<String> CompilerConfiguration = new OptionValue<>("basic");
+        // @formatter:on
+    }
 
     private final PhaseSuite<HighTierContext> highTier;
     private final PhaseSuite<MidTierContext> midTier;
@@ -58,8 +67,6 @@
             }
             configurations.put(name.toLowerCase(), config);
         }
-
-        DEFAULT = createDefaultSuites();
     }
 
     private Suites(CompilerConfiguration config) {
@@ -69,7 +76,7 @@
     }
 
     public static Suites createDefaultSuites() {
-        return createSuites(GraalOptions.CompilerConfiguration);
+        return createSuites(CompilerConfiguration.getValue());
     }
 
     public static Suites createSuites(String name) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/SuitesProvider.java	Tue Jun 18 10:12:27 2013 +0200
@@ -0,0 +1,37 @@
+/*
+ * 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;
+
+public interface SuitesProvider {
+
+    /**
+     * Get the default phase suites of this compiler.
+     */
+    Suites getDefaultSuites();
+
+    /**
+     * Create a new set of phase suites. Initially, the suites are the same as the
+     * {@link #getDefaultSuites default} suites.
+     */
+    Suites createSuites();
+}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java	Tue Jun 18 10:12:27 2013 +0200
@@ -73,7 +73,7 @@
         for (ObjectEqualsNode cn : graph.getNodes().filter(ObjectEqualsNode.class)) {
             if (!isEqualsMethod(graph)) {
                 // bail out if we compare an object of type klass with == or != (except null checks)
-                assert !(checkUsage(cn.x(), cn.y()) && checkUsage(cn.y(), cn.x())) : "Verifcation of " + klass.getName() + " usage failed: Comparison " + cn.x() + " and" + cn.y() + " in " +
+                assert !(checkUsage(cn.x(), cn.y()) && checkUsage(cn.y(), cn.x())) : "Verifcation of " + klass.getName() + " usage failed: Comparing " + cn.x() + " and" + cn.y() + " in " +
                                 graph.method() + " must use .equals() for object equality, not '==' or '!='";
             }
         }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java	Tue Jun 18 10:12:27 2013 +0200
@@ -23,13 +23,13 @@
 package com.oracle.graal.printer;
 
 import static com.oracle.graal.compiler.GraalDebugConfig.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.io.*;
 import java.util.*;
 
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.phases.*;
 
 public class DebugEnvironment {
 
@@ -37,8 +37,8 @@
         Debug.enable();
         List<DebugDumpHandler> dumpHandlers = new ArrayList<>();
         dumpHandlers.add(new GraphPrinterDumpHandler());
-        if (GraalOptions.PrintCFG) {
-            if (GraalOptions.PrintBinaryGraphs) {
+        if (PrintCFG.getValue()) {
+            if (PrintBinaryGraphs.getValue()) {
                 TTY.println("CFG dumping slows down PrintBinaryGraphs: use -G:-PrintCFG to disable it");
             }
             dumpHandlers.add(new CFGPrinterObserver());
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.printer;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.io.*;
 import java.net.*;
 import java.nio.channels.*;
@@ -33,7 +35,6 @@
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.schedule.*;
 
 /**
@@ -60,7 +61,7 @@
                 return;
             }
             previousInlineContext.clear();
-            if (GraalOptions.PrintIdealGraphFile) {
+            if (PrintIdealGraphFile.getValue()) {
                 initializeFilePrinter();
             } else {
                 initializeNetworkPrinter();
@@ -75,7 +76,7 @@
 
     private void initializeFilePrinter() {
         String ext;
-        if (GraalOptions.PrintBinaryGraphs) {
+        if (PrintBinaryGraphs.getValue()) {
             ext = ".bgv";
         } else {
             ext = ".gv.xml";
@@ -91,7 +92,7 @@
             num = "-" + Integer.toString(++i);
         }
         try {
-            if (GraalOptions.PrintBinaryGraphs) {
+            if (PrintBinaryGraphs.getValue()) {
                 printer = new BinaryGraphPrinter(FileChannel.open(file.toPath(), StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW));
             } else {
                 printer = new IdealGraphPrinter(new FileOutputStream(file));
@@ -105,10 +106,10 @@
     }
 
     private void initializeNetworkPrinter() {
-        String host = GraalOptions.PrintIdealGraphAddress;
-        int port = GraalOptions.PrintBinaryGraphs ? GraalOptions.PrintBinaryGraphPort : GraalOptions.PrintIdealGraphPort;
+        String host = PrintIdealGraphAddress.getValue();
+        int port = PrintBinaryGraphs.getValue() ? PrintBinaryGraphPort.getValue() : PrintIdealGraphPort.getValue();
         try {
-            if (GraalOptions.PrintBinaryGraphs) {
+            if (PrintBinaryGraphs.getValue()) {
                 printer = new BinaryGraphPrinter(SocketChannel.open(new InetSocketAddress(host, port)));
             } else {
                 IdealGraphPrinter xmlPrinter = new IdealGraphPrinter(new Socket(host, port).getOutputStream());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/DynamicNewArrayTest.java	Tue Jun 18 10:12:27 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.replacements.test;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.test.*;
+
+/**
+ * Tests the implementation of Array.createInstance.
+ */
+public class DynamicNewArrayTest extends GraalCompilerTest {
+
+    private class Element {
+    }
+
+    @Test
+    public void test1() {
+        test("test1snippet");
+    }
+
+    @Test
+    public void test2() {
+        test("test2snippet");
+    }
+
+    @Test
+    public void test3() {
+        test("dynamic", Long.class, 7);
+    }
+
+    @Test
+    public void test4() {
+        test("dynamic", Boolean.class, -7);
+    }
+
+    @Test
+    public void test5() {
+        test("dynamic", byte.class, 7);
+    }
+
+    @Test
+    public void test6() {
+        test("dynamic", null, 5);
+    }
+
+    @Test
+    public void test7() {
+        Method method = getMethod("dynamic");
+        Result actual1 = executeActual(method, null, Element.class, 7);
+        Result actual2 = executeActualCheckDeopt(method, Collections.<DeoptimizationReason> singleton(DeoptimizationReason.Unresolved), null, Element.class, 7);
+        Result expected = executeExpected(method, null, Element.class, 7);
+        assertEquals(actual1, expected);
+        assertEquals(actual2, expected);
+    }
+
+    public static Object test1snippet() {
+        return Array.newInstance(Integer.class, 7);
+    }
+
+    public static Object test2snippet() {
+        return Array.newInstance(char.class, 7);
+    }
+
+    public static Object dynamic(Class<?> elementType, int length) {
+        return Array.newInstance(elementType, length);
+    }
+}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -53,7 +53,7 @@
                 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 CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
 
                 assertNotInGraph(graph, Invoke.class);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java	Tue Jun 18 10:12:27 2013 +0200
@@ -63,7 +63,7 @@
     }
 
     /**
-     * Tests monitor operations on {@link PartialEscapeAnalysisPhase virtual objects}.
+     * Tests monitor operations on {@link PartialEscapePhase virtual objects}.
      */
     @Test
     public void test3() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ArraySubstitutions.java	Tue Jun 18 10:12:27 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.replacements;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+
+/**
+ * Substitutions for {@link java.lang.reflect.Array} methods.
+ */
+@ClassSubstitution(java.lang.reflect.Array.class)
+public class ArraySubstitutions {
+
+    @MethodSubstitution
+    public static Object newArray(Class<?> componentType, int length) throws NegativeArraySizeException {
+        if (componentType == null) {
+            DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.NullCheckException);
+        }
+        return DynamicNewArrayNode.newArray(componentType, length);
+    }
+}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.replacements;
 
+import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.replacements.SnippetTemplate.*;
 
 import java.lang.reflect.*;
@@ -36,7 +37,6 @@
 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;
@@ -215,7 +215,8 @@
 
         public void lower(BoxNode box) {
             FloatingNode canonical = canonicalizeBoxing(box, runtime);
-            if (canonical != null) {
+            // if in AOT mode, we don't want to embed boxed constants.
+            if (!AOTCompilation.getValue() && canonical != null) {
                 box.graph().replaceFixedWithFloating(box, canonical);
             } else {
                 Arguments args = new Arguments(boxSnippets.get(box.getBoxingKind()));
@@ -237,7 +238,7 @@
         }
     }
 
-    private static final SnippetCounter.Group integerCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Integer intrinsifications") : null;
+    private static final SnippetCounter.Group integerCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("Integer intrinsifications") : null;
     private static final SnippetCounter valueOfCounter = new SnippetCounter(integerCounters, "valueOf", "valueOf intrinsification");
 
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,11 +22,12 @@
  */
 package com.oracle.graal.replacements;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.phases.*;
 
 /**
  * Method substitutions that are VM-independent.
@@ -39,7 +40,8 @@
             replacements.registerSubstitutions(clazz);
         }
 
-        if (GraalOptions.Intrinsify) {
+        if (Intrinsify.getValue()) {
+            replacements.registerSubstitutions(ArraySubstitutions.class);
             replacements.registerSubstitutions(MathSubstitutionsX86.class);
             replacements.registerSubstitutions(DoubleSubstitutions.class);
             replacements.registerSubstitutions(FloatSubstitutions.class);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Tue Jun 18 10:12:27 2013 +0200
@@ -108,12 +108,12 @@
     }
 
     /**
-     * The result of an instantiating an instanceof snippet. This enables a snippet instantiation to
-     * be re-used which reduces compile time and produces better code.
+     * The result of instantiating an instanceof snippet. This enables a snippet instantiation to be
+     * re-used which reduces compile time and produces better code.
      */
     public static final class Instantiation {
 
-        private PhiNode result;
+        private ValueNode result;
         private CompareNode condition;
         private ValueNode trueValue;
         private ValueNode falseValue;
@@ -125,9 +125,9 @@
             return result != null;
         }
 
-        void initialize(PhiNode phi, ValueNode t, ValueNode f) {
+        void initialize(ValueNode r, ValueNode t, ValueNode f) {
             assert !isInitialized();
-            this.result = phi;
+            this.result = r;
             this.trueValue = t;
             this.falseValue = f;
         }
@@ -137,8 +137,12 @@
          * 
          * @param testValue the returned condition is true if the result is equal to this value
          */
-        CompareNode asCondition(ValueNode testValue) {
+        LogicNode asCondition(ValueNode testValue) {
             assert isInitialized();
+            if (result.isConstant()) {
+                assert testValue.isConstant();
+                return LogicConstantNode.forBoolean(result.asConstant().equals(testValue.asConstant()), result.graph());
+            }
             if (condition == null || condition.y() != testValue) {
                 // Re-use previously generated condition if the trueValue for the test is the same
                 condition = createCompareNode(Condition.EQ, result, testValue);
@@ -207,10 +211,18 @@
 
         @Override
         public void replace(ValueNode oldNode, ValueNode newNode) {
+            if (newNode.isConstant()) {
+                LogicConstantNode logicConstant = LogicConstantNode.forBoolean(newNode.asConstant().asInt() != 0, newNode.graph());
+                usage.replaceFirstInput(oldNode, logicConstant);
+                // PrintStream out = System.out;
+                // out.println(newNode.graph() + ": " + this);
+                GraalInternalError.shouldNotReachHere(instanceOf.graph().toString());
+                return;
+            }
             assert newNode instanceof PhiNode;
             assert oldNode == instanceOf;
             newNode.inferStamp();
-            instantiation.initialize((PhiNode) newNode, trueValue, falseValue);
+            instantiation.initialize(newNode, trueValue, falseValue);
             usage.replaceFirstInput(oldNode, instantiation.asCondition(trueValue));
         }
     }
@@ -239,10 +251,18 @@
 
         @Override
         public void replace(ValueNode oldNode, ValueNode newNode) {
+            if (newNode.isConstant()) {
+                LogicConstantNode logicConstant = LogicConstantNode.forBoolean(newNode.asConstant().asInt() != 0, newNode.graph());
+                usage.replaceFirstInput(oldNode, logicConstant);
+                // PrintStream out = System.out;
+                // out.println(newNode.graph() + ": " + this);
+                GraalInternalError.shouldNotReachHere(instanceOf.graph().toString());
+                return;
+            }
             assert newNode instanceof PhiNode;
             assert oldNode == instanceOf;
             newNode.inferStamp();
-            instantiation.initialize((PhiNode) newNode, trueValue, falseValue);
+            instantiation.initialize(newNode, trueValue, falseValue);
             usage.replaceAtUsages(newNode);
             usage.clearInputs();
             assert usage.usages().isEmpty();
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -33,6 +33,7 @@
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
@@ -284,34 +285,8 @@
         if (newInstance instanceof ValueNode && (((ValueNode) newInstance).kind() != Kind.Object || ((ValueNode) newInstance).stamp() == StampFactory.forNodeIntrinsic())) {
             StructuredGraph graph = (StructuredGraph) newInstance.graph();
             for (CheckCastNode checkCastNode : newInstance.usages().filter(CheckCastNode.class).snapshot()) {
-                for (ProxyNode vpn : checkCastNode.usages().filter(ProxyNode.class).snapshot()) {
-                    graph.replaceFloating(vpn, checkCastNode);
-                }
                 for (Node checkCastUsage : checkCastNode.usages().snapshot()) {
-                    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;
-                        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);
-                    }
+                    checkCheckCastUsage(graph, newInstance, checkCastNode, checkCastUsage);
                 }
                 FixedNode next = checkCastNode.next();
                 checkCastNode.setNext(null);
@@ -320,4 +295,47 @@
             }
         }
     }
+
+    private static void checkCheckCastUsage(StructuredGraph graph, Node intrinsifiedNode, Node input, Node usage) {
+        if (usage instanceof ValueAnchorNode) {
+            ValueAnchorNode valueAnchorNode = (ValueAnchorNode) usage;
+            valueAnchorNode.removeAnchoredNode((ValueNode) input);
+            Debug.log("%s: Removed a ValueAnchor input", Debug.contextSnapshot(JavaMethod.class));
+        } else if (usage instanceof UnboxNode) {
+            UnboxNode unbox = (UnboxNode) usage;
+            unbox.replaceAtUsages(intrinsifiedNode);
+            graph.removeFixed(unbox);
+            Debug.log("%s: Removed an UnboxNode", Debug.contextSnapshot(JavaMethod.class));
+        } else if (usage instanceof MethodCallTargetNode) {
+            MethodCallTargetNode checkCastCallTarget = (MethodCallTargetNode) usage;
+            assert checkCastCallTarget.targetMethod().getAnnotation(NodeIntrinsic.class) != null : "checkcast at " + sourceLocation(input) +
+                            " not used by an unboxing method or node intrinsic, but by a call at " + sourceLocation(checkCastCallTarget.usages().first()) + " to " + checkCastCallTarget.targetMethod();
+            usage.replaceFirstInput(input, intrinsifiedNode);
+            Debug.log("%s: Checkcast used in an other node intrinsic", Debug.contextSnapshot(JavaMethod.class));
+        } else if (usage instanceof FrameState) {
+            usage.replaceFirstInput(input, null);
+            Debug.log("%s: Checkcast used in a FS", Debug.contextSnapshot(JavaMethod.class));
+        } else if (usage instanceof ReturnNode && ((ValueNode) intrinsifiedNode).stamp() == StampFactory.forNodeIntrinsic()) {
+            usage.replaceFirstInput(input, intrinsifiedNode);
+            Debug.log("%s: Checkcast used in a return with forNodeIntrinsic stamp", Debug.contextSnapshot(JavaMethod.class));
+        } else if (usage instanceof IsNullNode) {
+            assert usage.usages().count() == 1 && usage.usages().first().predecessor() == input;
+            graph.replaceFloating((FloatingNode) usage, LogicConstantNode.contradiction(graph));
+            Debug.log("%s: Replaced IsNull with false", Debug.contextSnapshot(JavaMethod.class));
+        } else if (usage instanceof ProxyNode) {
+            ProxyNode proxy = (ProxyNode) usage;
+            assert proxy.type() == PhiType.Value;
+            ProxyNode newProxy = graph.unique(new ProxyNode((ValueNode) intrinsifiedNode, proxy.proxyPoint(), PhiType.Value, proxy.getIdentity()));
+            for (Node proxyUsage : usage.usages().snapshot()) {
+                checkCheckCastUsage(graph, newProxy, proxy, proxyUsage);
+            }
+        } else if (usage instanceof PiNode) {
+            for (Node piUsage : usage.usages().snapshot()) {
+                checkCheckCastUsage(graph, intrinsifiedNode, usage, piUsage);
+            }
+        } else {
+            Debug.dump(graph, "exception");
+            assert false : sourceLocation(usage) + " has unexpected usage " + usage + " of checkcast at " + sourceLocation(input);
+        }
+    }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Tue Jun 18 10:12:27 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.replacements;
 
 import static com.oracle.graal.api.meta.MetaUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -320,9 +321,9 @@
             graphBuilder.apply(graph);
 
             new WordTypeVerificationPhase(runtime, target.wordKind).apply(graph);
-            if (GraalOptions.OptCanonicalizer) {
+            if (OptCanonicalizer.getValue()) {
                 new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph);
-                new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
+                new CanonicalizerPhase.Instance(runtime, assumptions, true).apply(graph);
             }
 
             return graph;
@@ -335,9 +336,9 @@
          * @param callee the graph that was inlined into {@code caller}
          */
         protected void afterInline(StructuredGraph caller, StructuredGraph callee) {
-            if (GraalOptions.OptCanonicalizer) {
+            if (OptCanonicalizer.getValue()) {
                 new WordTypeRewriterPhase(runtime, target.wordKind).apply(caller);
-                new CanonicalizerPhase.Instance(runtime, assumptions).apply(caller);
+                new CanonicalizerPhase.Instance(runtime, assumptions, true).apply(caller);
             }
         }
 
@@ -350,8 +351,8 @@
             new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph);
 
             new DeadCodeEliminationPhase().apply(graph);
-            if (GraalOptions.OptCanonicalizer) {
-                new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
+            if (OptCanonicalizer.getValue()) {
+                new CanonicalizerPhase.Instance(runtime, assumptions, true).apply(graph);
             }
         }
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Tue Jun 18 10:12:27 2013 +0200
@@ -34,6 +34,7 @@
 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.*;
@@ -191,7 +192,7 @@
         @Override
         public String toString() {
             StringBuilder result = new StringBuilder();
-            result.append("Parameters<").append(MetaUtil.format("%H.%n", info.method)).append(" [");
+            result.append("Parameters<").append(MetaUtil.format("%h.%n", info.method)).append(" [");
             String sep = "";
             for (int i = 0; i < info.getParameterCount(); i++) {
                 result.append(sep);
@@ -228,6 +229,38 @@
                 this.length = Array.getLength(value);
             }
         }
+
+        @Override
+        public String toString() {
+            if (value instanceof boolean[]) {
+                return Arrays.toString((boolean[]) value);
+            }
+            if (value instanceof byte[]) {
+                return Arrays.toString((byte[]) value);
+            }
+            if (value instanceof char[]) {
+                return Arrays.toString((char[]) value);
+            }
+            if (value instanceof short[]) {
+                return Arrays.toString((short[]) value);
+            }
+            if (value instanceof int[]) {
+                return Arrays.toString((int[]) value);
+            }
+            if (value instanceof long[]) {
+                return Arrays.toString((long[]) value);
+            }
+            if (value instanceof float[]) {
+                return Arrays.toString((float[]) value);
+            }
+            if (value instanceof double[]) {
+                return Arrays.toString((double[]) value);
+            }
+            if (value instanceof Object[]) {
+                return Arrays.toString((Object[]) value);
+            }
+            return String.valueOf(value);
+        }
     }
 
     static class CacheKey {
@@ -384,7 +417,7 @@
             new NodeIntrinsificationPhase(runtime).apply(snippetCopy);
             new WordTypeRewriterPhase(runtime, target.wordKind).apply(snippetCopy);
 
-            new CanonicalizerPhase.Instance(runtime, replacements.getAssumptions(), 0, null).apply(snippetCopy);
+            new CanonicalizerPhase.Instance(runtime, replacements.getAssumptions(), true, 0, null).apply(snippetCopy);
         }
         NodeIntrinsificationVerificationPhase.verify(snippetCopy);
 
@@ -440,8 +473,8 @@
                 if (loopBegin != null) {
                     LoopEx loop = new LoopsData(snippetCopy).loop(loopBegin);
                     int mark = snippetCopy.getMark();
-                    LoopTransformations.fullUnroll(loop, runtime, replacements.getAssumptions());
-                    new CanonicalizerPhase.Instance(runtime, replacements.getAssumptions(), mark, null).apply(snippetCopy);
+                    LoopTransformations.fullUnroll(loop, runtime, replacements.getAssumptions(), true);
+                    new CanonicalizerPhase.Instance(runtime, replacements.getAssumptions(), true, mark, null).apply(snippetCopy);
                 }
                 FixedNode explodeLoopNext = explodeLoop.next();
                 explodeLoop.clearSuccessors();
@@ -723,10 +756,14 @@
             } else {
                 returnValue = (ValueNode) duplicates.get(returnNode.result());
             }
-            assert returnValue != null || replacee.usages().isEmpty();
-            replacer.replace(replacee, returnValue);
+            Node returnDuplicate = duplicates.get(returnNode);
+            if (returnValue == null && replacee.usages().isNotEmpty() && replacee instanceof MemoryCheckpoint) {
+                replacer.replace(replacee, (ValueNode) returnDuplicate.predecessor());
+            } else {
+                assert returnValue != null || replacee.usages().isEmpty() : this + " " + returnValue + " " + returnNode + " " + replacee.usages();
+                replacer.replace(replacee, returnValue);
 
-            Node returnDuplicate = duplicates.get(returnNode);
+            }
             if (returnDuplicate.isAlive()) {
                 returnDuplicate.clearInputs();
                 returnDuplicate.replaceAndDelete(next);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -24,9 +24,10 @@
 
 import static com.oracle.graal.api.meta.LocationIdentity.*;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.HeapAccess.WriteBarrierType;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.word.*;
@@ -65,7 +66,7 @@
     @Override
     public void lower(LoweringTool tool, LoweringType loweringType) {
         IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, value.kind(), displacement, offset, graph(), 1);
-        WriteNode write = graph().add(new WriteNode(object, value, location, WriteBarrierType.NONE));
+        WriteNode write = graph().add(new WriteNode(object, value, location, WriteBarrierType.NONE, value.kind() == Kind.Object));
         graph().replaceFixedWithFixed(this, write);
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,17 +22,20 @@
  */
 package com.oracle.graal.replacements.nodes;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
 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.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.common.*;
 
-public class MacroNode extends AbstractStateSplit implements Lowerable {
+public class MacroNode extends AbstractStateSplit implements Lowerable, MemoryCheckpoint {
 
     @Input protected final NodeInputList<ValueNode> arguments;
 
@@ -106,4 +109,9 @@
             }
         }
     }
+
+    @Override
+    public LocationIdentity[] getLocationIdentities() {
+        return new LocationIdentity[]{ANY_LOCATION};
+    }
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java	Tue Jun 18 10:11:28 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,315 +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.virtual.phases.ea;
-
-import java.util.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.Virtualizable.EscapeState;
-import com.oracle.graal.nodes.virtual.*;
-
-class BlockState {
-
-    private final IdentityHashMap<VirtualObjectNode, ObjectState> objectStates = new IdentityHashMap<>();
-    private final IdentityHashMap<ValueNode, VirtualObjectNode> objectAliases;
-    private final IdentityHashMap<ValueNode, ValueNode> scalarAliases;
-    final HashMap<ReadCacheEntry, ValueNode> readCache;
-
-    static class ReadCacheEntry {
-
-        public final ResolvedJavaField identity;
-        public final ValueNode object;
-
-        public ReadCacheEntry(ResolvedJavaField identity, ValueNode object) {
-            this.identity = identity;
-            this.object = object;
-        }
-
-        @Override
-        public int hashCode() {
-            int result = 31 + ((identity == null) ? 0 : identity.hashCode());
-            return 31 * result + ((object == null) ? 0 : object.hashCode());
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            ReadCacheEntry other = (ReadCacheEntry) obj;
-            return identity == other.identity && object == other.object;
-        }
-
-        @Override
-        public String toString() {
-            return object + ":" + identity;
-        }
-    }
-
-    public BlockState() {
-        objectAliases = new IdentityHashMap<>();
-        scalarAliases = new IdentityHashMap<>();
-        readCache = new HashMap<>();
-    }
-
-    public BlockState(BlockState other) {
-        for (Map.Entry<VirtualObjectNode, ObjectState> entry : other.objectStates.entrySet()) {
-            objectStates.put(entry.getKey(), entry.getValue().cloneState());
-        }
-        objectAliases = new IdentityHashMap<>(other.objectAliases);
-        scalarAliases = new IdentityHashMap<>(other.scalarAliases);
-        readCache = new HashMap<>(other.readCache);
-    }
-
-    public void addReadCache(ValueNode object, ResolvedJavaField identity, ValueNode value) {
-        ValueNode cacheObject;
-        ObjectState obj = getObjectState(object);
-        if (obj != null) {
-            assert !obj.isVirtual();
-            cacheObject = obj.getMaterializedValue();
-        } else {
-            cacheObject = object;
-        }
-        readCache.put(new ReadCacheEntry(identity, cacheObject), value);
-    }
-
-    public ValueNode getReadCache(ValueNode object, ResolvedJavaField identity) {
-        ValueNode cacheObject;
-        ObjectState obj = getObjectState(object);
-        if (obj != null) {
-            assert !obj.isVirtual();
-            cacheObject = obj.getMaterializedValue();
-        } else {
-            cacheObject = object;
-        }
-        ValueNode cacheValue = readCache.get(new ReadCacheEntry(identity, cacheObject));
-        obj = getObjectState(cacheValue);
-        if (obj != null) {
-            assert !obj.isVirtual();
-            cacheValue = obj.getMaterializedValue();
-        } else {
-            cacheValue = getScalarAlias(cacheValue);
-        }
-        return cacheValue;
-    }
-
-    public void killReadCache() {
-        readCache.clear();
-    }
-
-    public void killReadCache(ResolvedJavaField identity) {
-        Iterator<Map.Entry<ReadCacheEntry, ValueNode>> iter = readCache.entrySet().iterator();
-        while (iter.hasNext()) {
-            Map.Entry<ReadCacheEntry, ValueNode> entry = iter.next();
-            if (entry.getKey().identity == identity) {
-                iter.remove();
-            }
-        }
-    }
-
-    public ObjectState getObjectState(VirtualObjectNode object) {
-        assert objectStates.containsKey(object);
-        return objectStates.get(object);
-    }
-
-    public ObjectState getObjectStateOptional(VirtualObjectNode object) {
-        return objectStates.get(object);
-    }
-
-    public ObjectState getObjectState(ValueNode value) {
-        VirtualObjectNode object = objectAliases.get(value);
-        return object == null ? null : getObjectState(object);
-    }
-
-    public BlockState cloneState() {
-        return new BlockState(this);
-    }
-
-    public void materializeBefore(FixedNode fixed, VirtualObjectNode virtual, EscapeState state, GraphEffectList materializeEffects) {
-        PartialEscapeClosure.METRIC_MATERIALIZATIONS.increment();
-        List<AllocatedObjectNode> objects = new ArrayList<>(2);
-        List<ValueNode> values = new ArrayList<>(8);
-        List<int[]> locks = new ArrayList<>(2);
-        List<ValueNode> otherAllocations = new ArrayList<>(2);
-        materializeWithCommit(fixed, virtual, objects, locks, values, otherAllocations, state);
-
-        materializeEffects.addMaterializationBefore(fixed, objects, locks, values, otherAllocations);
-    }
-
-    private void materializeWithCommit(FixedNode fixed, VirtualObjectNode virtual, List<AllocatedObjectNode> objects, List<int[]> locks, List<ValueNode> values, List<ValueNode> otherAllocations,
-                    EscapeState state) {
-        VirtualUtil.trace("materializing %s", virtual);
-        ObjectState obj = getObjectState(virtual);
-
-        ValueNode[] entries = obj.getEntries();
-        ValueNode representation = virtual.getMaterializedRepresentation(fixed, entries, obj.getLocks());
-        obj.escape(representation, state);
-        if (representation instanceof AllocatedObjectNode) {
-            objects.add((AllocatedObjectNode) representation);
-            locks.add(obj.getLocks());
-            int pos = values.size();
-            while (values.size() < pos + entries.length) {
-                values.add(null);
-            }
-            for (int i = 0; i < entries.length; i++) {
-                ObjectState entryObj = getObjectState(entries[i]);
-                if (entryObj != null) {
-                    if (entryObj.isVirtual()) {
-                        materializeWithCommit(fixed, entryObj.getVirtualObject(), objects, locks, values, otherAllocations, state);
-                    }
-                    values.set(pos + i, entryObj.getMaterializedValue());
-                } else {
-                    values.set(pos + i, entries[i]);
-                }
-            }
-            if (virtual instanceof VirtualInstanceNode) {
-                VirtualInstanceNode instance = (VirtualInstanceNode) virtual;
-                for (int i = 0; i < entries.length; i++) {
-                    readCache.put(new ReadCacheEntry(instance.field(i), representation), values.get(pos + i));
-                }
-            }
-        } else {
-            otherAllocations.add(representation);
-            assert obj.getLocks().length == 0;
-        }
-    }
-
-    void addAndMarkAlias(VirtualObjectNode virtual, ValueNode node, NodeBitMap usages) {
-        objectAliases.put(node, virtual);
-        if (node.isAlive()) {
-            for (Node usage : node.usages()) {
-                markVirtualUsages(usage, usages);
-            }
-        }
-    }
-
-    private void markVirtualUsages(Node node, NodeBitMap usages) {
-        if (!usages.isNew(node)) {
-            usages.mark(node);
-        }
-        if (node instanceof VirtualState) {
-            for (Node usage : node.usages()) {
-                markVirtualUsages(usage, usages);
-            }
-        }
-    }
-
-    public void addObject(VirtualObjectNode virtual, ObjectState state) {
-        objectStates.put(virtual, state);
-    }
-
-    public void addScalarAlias(ValueNode alias, ValueNode value) {
-        scalarAliases.put(alias, value);
-    }
-
-    public ValueNode getScalarAlias(ValueNode alias) {
-        ValueNode result = scalarAliases.get(alias);
-        return result == null ? alias : result;
-    }
-
-    public Iterable<ObjectState> getStates() {
-        return objectStates.values();
-    }
-
-    public Collection<VirtualObjectNode> getVirtualObjects() {
-        return objectAliases.values();
-    }
-
-    @Override
-    public String toString() {
-        return objectStates + " " + readCache;
-    }
-
-    public BlockState meetAliases(List<? extends BlockState> states) {
-        BlockState newState = new BlockState();
-
-        BlockState firstState = states.get(0);
-        newState.objectAliases.putAll(firstState.objectAliases);
-        for (int i = 1; i < states.size(); i++) {
-            BlockState state = states.get(i);
-            Iterator<Map.Entry<ValueNode, VirtualObjectNode>> iter = newState.objectAliases.entrySet().iterator();
-            while (iter.hasNext()) {
-                Map.Entry<ValueNode, VirtualObjectNode> entry = iter.next();
-                if (state.objectAliases.containsKey(entry.getKey())) {
-                    assert state.objectAliases.get(entry.getKey()) == entry.getValue();
-                } else {
-                    iter.remove();
-                }
-            }
-        }
-
-        newState.scalarAliases.putAll(firstState.scalarAliases);
-        for (int i = 1; i < states.size(); i++) {
-            BlockState state = states.get(i);
-            Iterator<Map.Entry<ValueNode, ValueNode>> iter = newState.scalarAliases.entrySet().iterator();
-            while (iter.hasNext()) {
-                Map.Entry<ValueNode, ValueNode> entry = iter.next();
-                if (state.scalarAliases.containsKey(entry.getKey())) {
-                    assert state.scalarAliases.get(entry.getKey()) == entry.getValue();
-                } else {
-                    iter.remove();
-                }
-            }
-        }
-
-        return newState;
-    }
-
-    public Map<ReadCacheEntry, ValueNode> getReadCache() {
-        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;
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsBlockState.java	Tue Jun 18 10:12:27 2013 +0200
@@ -0,0 +1,105 @@
+/*
+ * 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.virtual.phases.ea;
+
+import java.util.*;
+
+import com.oracle.graal.nodes.*;
+
+public abstract class EffectsBlockState<T extends EffectsBlockState<T>> {
+
+    protected final IdentityHashMap<ValueNode, ValueNode> scalarAliases;
+
+    protected EffectsBlockState() {
+        scalarAliases = new IdentityHashMap<>();
+    }
+
+    protected EffectsBlockState(EffectsBlockState<T> other) {
+        scalarAliases = new IdentityHashMap<>(other.scalarAliases);
+    }
+
+    public void addScalarAlias(ValueNode alias, ValueNode value) {
+        scalarAliases.put(alias, value);
+    }
+
+    public ValueNode getScalarAlias(ValueNode alias) {
+        ValueNode result = scalarAliases.get(alias);
+        return result == null ? alias : result;
+    }
+
+    @Override
+    public String toString() {
+        return "Scalar Aliases: " + scalarAliases.toString();
+    }
+
+    public void meetAliases(List<T> states) {
+        scalarAliases.putAll(states.get(0).scalarAliases);
+        for (int i = 1; i < states.size(); i++) {
+            EffectsBlockState<T> state = states.get(i);
+            meetMaps(scalarAliases, state.scalarAliases);
+        }
+    }
+
+    public boolean equivalentTo(T other) {
+        if (this == other) {
+            return true;
+        }
+        return scalarAliases.equals(other.scalarAliases);
+    }
+
+    protected static <K, V> boolean compareMaps(Map<K, V> left, Map<K, V> right) {
+        if (left.size() != right.size()) {
+            return false;
+        }
+        return compareMapsNoSize(left, right);
+    }
+
+    protected 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;
+    }
+
+    protected static <U, V> void meetMaps(Map<U, V> target, Map<U, V> source) {
+        Iterator<Map.Entry<U, V>> iter = target.entrySet().iterator();
+        while (iter.hasNext()) {
+            Map.Entry<U, V> entry = iter.next();
+            if (source.containsKey(entry.getKey())) {
+                assert source.get(entry.getKey()) == entry.getValue();
+            } else {
+                iter.remove();
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Tue Jun 18 10:12:27 2013 +0200
@@ -0,0 +1,216 @@
+/*
+ * 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.virtual.phases.ea;
+
+import static com.oracle.graal.phases.GraalOptions.*;
+
+import java.util.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.phases.graph.*;
+import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure;
+import com.oracle.graal.phases.graph.ReentrantBlockIterator.LoopInfo;
+import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.virtual.phases.ea.EffectList.Effect;
+
+public abstract class EffectsClosure<BlockT extends EffectsBlockState<BlockT>> extends EffectsPhase.Closure<BlockT> {
+
+    private final SchedulePhase schedule;
+
+    protected final BlockMap<GraphEffectList> blockEffects;
+    private final IdentityHashMap<Loop, GraphEffectList> loopMergeEffects = new IdentityHashMap<>();
+
+    private boolean changed;
+
+    public EffectsClosure(SchedulePhase schedule) {
+        this.schedule = schedule;
+        this.blockEffects = new BlockMap<>(schedule.getCFG());
+        for (Block block : schedule.getCFG().getBlocks()) {
+            blockEffects.put(block, new GraphEffectList());
+        }
+    }
+
+    @Override
+    public boolean hasChanged() {
+        return changed;
+    }
+
+    @Override
+    public void applyEffects() {
+        final StructuredGraph graph = schedule.getCFG().graph;
+        final ArrayList<Node> obsoleteNodes = new ArrayList<>(0);
+        BlockIteratorClosure<Void> closure = new BlockIteratorClosure<Void>() {
+
+            @Override
+            protected Void getInitialState() {
+                return null;
+            }
+
+            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);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            protected Void processBlock(Block block, Void currentState) {
+                apply(blockEffects.get(block), block);
+                if (TraceEscapeAnalysis.getValue()) {
+                    Debug.dump(graph, "after processing block %s", block);
+                }
+                return currentState;
+            }
+
+            @Override
+            protected Void merge(Block merge, List<Void> states) {
+                return null;
+            }
+
+            @Override
+            protected Void cloneState(Void oldState) {
+                return oldState;
+            }
+
+            @Override
+            protected List<Void> processLoop(Loop loop, Void initialState) {
+                LoopInfo<Void> info = ReentrantBlockIterator.processLoop(this, loop, initialState);
+                apply(loopMergeEffects.get(loop), loop);
+                return info.exitStates;
+            }
+        };
+        ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock());
+        assert VirtualUtil.assertNonReachable(graph, obsoleteNodes);
+    }
+
+    @Override
+    protected BlockT processBlock(Block block, BlockT state) {
+        VirtualUtil.trace("\nBlock: %s, preds: %s, succ: %s (", block, block.getPredecessors(), block.getSuccessors());
+
+        GraphEffectList effects = blockEffects.get(block);
+        FixedWithNextNode lastFixedNode = null;
+        for (Node node : schedule.getBlockToNodesMap().get(block)) {
+            changed |= processNode(node, state, effects, lastFixedNode);
+            if (node instanceof FixedWithNextNode) {
+                lastFixedNode = (FixedWithNextNode) node;
+            }
+        }
+        VirtualUtil.trace(")\n    end state: %s\n", state);
+        return state;
+    }
+
+    protected abstract boolean processNode(Node node, BlockT state, GraphEffectList effects, FixedWithNextNode lastFixedNode);
+
+    @Override
+    protected BlockT merge(Block merge, List<BlockT> states) {
+        assert blockEffects.get(merge).isEmpty();
+        MergeProcessor processor = createMergeProcessor(merge);
+        processor.merge(states);
+        processor.commitEnds(states);
+        blockEffects.get(merge).addAll(processor.mergeEffects);
+        blockEffects.get(merge).addAll(processor.afterMergeEffects);
+        return processor.newState;
+    }
+
+    @Override
+    protected final List<BlockT> processLoop(Loop loop, BlockT initialState) {
+        BlockT loopEntryState = initialState;
+        BlockT lastMergedState = cloneState(initialState);
+        MergeProcessor mergeProcessor = createMergeProcessor(loop.header);
+        for (int iteration = 0; iteration < 10; iteration++) {
+            LoopInfo<BlockT> info = ReentrantBlockIterator.processLoop(this, loop, cloneState(lastMergedState));
+
+            List<BlockT> states = new ArrayList<>();
+            states.add(initialState);
+            states.addAll(info.endStates);
+            mergeProcessor.merge(states);
+
+            Debug.log("================== %s", loop.header);
+            Debug.log("%s", mergeProcessor.newState);
+            Debug.log("===== vs.");
+            Debug.log("%s", lastMergedState);
+
+            if (mergeProcessor.newState.equivalentTo(lastMergedState)) {
+                mergeProcessor.commitEnds(states);
+
+                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++) {
+                    BlockT 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);
+    }
+
+    protected abstract void processLoopExit(LoopExitNode exitNode, BlockT initialState, BlockT exitState, GraphEffectList effects);
+
+    protected abstract MergeProcessor createMergeProcessor(Block merge);
+
+    protected class MergeProcessor {
+
+        protected final Block mergeBlock;
+        protected final MergeNode merge;
+
+        protected final GraphEffectList mergeEffects;
+        protected final GraphEffectList afterMergeEffects;
+        protected BlockT newState;
+
+        public MergeProcessor(Block mergeBlock) {
+            this.mergeBlock = mergeBlock;
+            this.merge = (MergeNode) mergeBlock.getBeginNode();
+            this.mergeEffects = new GraphEffectList();
+            this.afterMergeEffects = new GraphEffectList();
+        }
+
+        protected void merge(List<BlockT> states) {
+            newState = getInitialState();
+            newState.meetAliases(states);
+            mergeEffects.clear();
+            afterMergeEffects.clear();
+        }
+
+        @SuppressWarnings("unused")
+        protected void commitEnds(List<BlockT> states) {
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -0,0 +1,98 @@
+/*
+ * 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.virtual.phases.ea;
+
+import static com.oracle.graal.phases.GraalOptions.*;
+
+import java.util.concurrent.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.graph.*;
+import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.phases.tiers.*;
+
+public abstract class EffectsPhase<PhaseContextT extends PhaseContext> extends BasePhase<PhaseContextT> {
+
+    public abstract static class Closure<T> extends ReentrantBlockIterator.BlockIteratorClosure<T> {
+
+        public abstract boolean hasChanged();
+
+        public abstract void applyEffects();
+    }
+
+    private final int maxIterations;
+    private CanonicalizerPhase canonicalizer;
+
+    public EffectsPhase(int maxIterations, CanonicalizerPhase canonicalizer) {
+        this.maxIterations = maxIterations;
+        this.canonicalizer = canonicalizer;
+    }
+
+    @Override
+    protected void run(StructuredGraph graph, PhaseContextT context) {
+        runAnalysis(graph, context);
+    }
+
+    public boolean runAnalysis(final StructuredGraph graph, final PhaseContextT context) {
+        boolean changed = false;
+        for (int iteration = 0; iteration < maxIterations; iteration++) {
+            boolean currentChanged = Debug.scope("iteration " + iteration, new Callable<Boolean>() {
+
+                @Override
+                public Boolean call() {
+                    SchedulePhase schedule = new SchedulePhase();
+                    schedule.apply(graph, false);
+                    Closure<?> closure = createEffectsClosure(context, schedule);
+                    ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock());
+
+                    if (!closure.hasChanged()) {
+                        return false;
+                    }
+
+                    // apply the effects collected during this iteration
+                    closure.applyEffects();
+
+                    Debug.dump(graph, "after " + getName() + " iteration");
+
+                    new DeadCodeEliminationPhase().apply(graph);
+
+                    if (OptCanonicalizer.getValue()) {
+                        canonicalizer.apply(graph, context);
+                    }
+
+                    return true;
+                }
+            });
+            if (!currentChanged) {
+                break;
+            }
+            changed |= currentChanged;
+        }
+        return changed;
+    }
+
+    protected abstract Closure<?> createEffectsClosure(PhaseContextT context, SchedulePhase schedule);
+}
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.virtual.phases.ea;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.util.*;
 import java.util.concurrent.*;
 
@@ -36,21 +38,19 @@
 
     private final PhasePlan plan;
 
-    private final Replacements replacements;
     private final GraphCache cache;
     private final OptimisticOptimizations optimisticOpts;
-    private final boolean readElimination;
+    private final CanonicalizerPhase canonicalizer;
 
-    public IterativeInliningPhase(Replacements replacements, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts, boolean readElimination) {
-        this.replacements = replacements;
+    public IterativeInliningPhase(GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts, CanonicalizerPhase canonicalizer) {
         this.cache = cache;
         this.plan = plan;
         this.optimisticOpts = optimisticOpts;
-        this.readElimination = readElimination;
+        this.canonicalizer = canonicalizer;
     }
 
     public static final void trace(String format, Object... obj) {
-        if (GraalOptions.TraceEscapeAnalysis) {
+        if (TraceEscapeAnalysis.getValue()) {
             Debug.log(format, obj);
         }
     }
@@ -63,27 +63,27 @@
 
     private void runIterations(final StructuredGraph graph, final boolean simple, final HighTierContext context) {
         Boolean continueIteration = true;
-        for (int iteration = 0; iteration < GraalOptions.EscapeAnalysisIterations && continueIteration; iteration++) {
+        for (int iteration = 0; iteration < EscapeAnalysisIterations.getValue() && continueIteration; iteration++) {
             continueIteration = Debug.scope("iteration " + iteration, new Callable<Boolean>() {
 
                 @Override
                 public Boolean call() {
                     boolean progress = false;
-                    PartialEscapeAnalysisPhase ea = new PartialEscapeAnalysisPhase(false, readElimination);
+                    PartialEscapePhase ea = new PartialEscapePhase(false, canonicalizer);
                     boolean eaResult = ea.runAnalysis(graph, context);
                     progress |= eaResult;
 
-                    Map<Invoke, Double> hints = GraalOptions.PEAInliningHints ? PartialEscapeAnalysisPhase.getHints(graph) : null;
+                    Map<Invoke, Double> hints = PEAInliningHints.getValue() ? PartialEscapePhase.getHints(graph) : null;
 
-                    InliningPhase inlining = new InliningPhase(context.getRuntime(), hints, replacements, context.getAssumptions(), cache, plan, optimisticOpts);
+                    InliningPhase inlining = new InliningPhase(context.getRuntime(), hints, context.getReplacements(), context.getAssumptions(), cache, plan, optimisticOpts);
                     inlining.setMaxMethodsPerInlining(simple ? 1 : Integer.MAX_VALUE);
                     inlining.apply(graph);
                     progress |= inlining.getInliningCount() > 0;
 
                     new DeadCodeEliminationPhase().apply(graph);
 
-                    if (GraalOptions.ConditionalElimination && GraalOptions.OptCanonicalizer) {
-                        new CanonicalizerPhase().apply(graph, context);
+                    if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) {
+                        canonicalizer.apply(graph, context);
                         new IterativeConditionalEliminationPhase().apply(graph, context);
                     }
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java	Tue Jun 18 10:12:27 2013 +0200
@@ -34,7 +34,7 @@
  * the fields or array elements (called "entries") and the lock count if the object is still
  * virtual. If the object was materialized, it contains the current materialized value.
  */
-class ObjectState extends Virtualizable.State {
+public class ObjectState extends Virtualizable.State {
 
     private static final int[] EMPTY_INT_ARRAY = new int[0];
 
@@ -131,7 +131,6 @@
         return entries[index];
     }
 
-    @Override
     public void setEntry(int index, ValueNode value) {
         assert isVirtual();
         entries[index] = value;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java	Tue Jun 18 10:11:28 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,169 +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.virtual.phases.ea;
-
-import java.util.*;
-import java.util.concurrent.*;
-
-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.nodes.spi.*;
-import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.nodes.virtual.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.common.*;
-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.*;
-
-public class PartialEscapeAnalysisPhase extends BasePhase<HighTierContext> {
-
-    public abstract static class Closure<T> extends ReentrantBlockIterator.BlockIteratorClosure<T> {
-
-        public abstract boolean hasChanged();
-
-        public abstract void applyEffects();
-    }
-
-    private final CustomCanonicalizer customCanonicalizer;
-    private final boolean iterative;
-    private final boolean readElimination;
-
-    public PartialEscapeAnalysisPhase(boolean iterative, boolean readElimination) {
-        this(null, iterative, readElimination);
-    }
-
-    public PartialEscapeAnalysisPhase(CustomCanonicalizer customCanonicalizer, boolean iterative, boolean readElimination) {
-        this.customCanonicalizer = customCanonicalizer;
-        this.iterative = iterative;
-        this.readElimination = readElimination;
-    }
-
-    @Override
-    protected void run(StructuredGraph graph, HighTierContext context) {
-        runAnalysis(graph, context);
-    }
-
-    public boolean runAnalysis(final StructuredGraph graph, final HighTierContext context) {
-        if (!VirtualUtil.matches(graph, GraalOptions.EscapeAnalyzeOnly)) {
-            return false;
-        }
-
-        if (!readElimination) {
-            boolean analyzableNodes = false;
-            for (Node node : graph.getNodes()) {
-                if (node instanceof VirtualizableAllocation) {
-                    analyzableNodes = true;
-                    break;
-                }
-            }
-            if (!analyzableNodes) {
-                return false;
-            }
-        }
-
-        boolean continueIteration = true;
-        boolean changed = false;
-        for (int iteration = 0; iteration < GraalOptions.EscapeAnalysisIterations && continueIteration; iteration++) {
-            boolean currentChanged = Debug.scope("iteration " + iteration, new Callable<Boolean>() {
-
-                @Override
-                public Boolean call() {
-
-                    SchedulePhase schedule = new SchedulePhase();
-                    schedule.apply(graph, false);
-                    Closure<?> closure = createAnalysisClosure(context, schedule);
-                    ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock());
-
-                    if (!closure.hasChanged()) {
-                        return false;
-                    }
-
-                    // apply the effects collected during the escape analysis iteration
-                    closure.applyEffects();
-
-                    Debug.dump(graph, "after PartialEscapeAnalysis iteration");
-
-                    new DeadCodeEliminationPhase().apply(graph);
-
-                    if (GraalOptions.OptCanonicalizer) {
-                        new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), null, customCanonicalizer).apply(graph);
-                    }
-
-                    return true;
-                }
-            });
-            continueIteration = currentChanged && iterative;
-            changed |= currentChanged;
-        }
-
-        return changed;
-    }
-
-    protected Closure<?> createAnalysisClosure(final HighTierContext context, SchedulePhase schedule) {
-        return new PartialEscapeClosure<>(schedule, context.getRuntime(), context.getAssumptions());
-    }
-
-    public static Map<Invoke, Double> getHints(StructuredGraph graph) {
-        NodesToDoubles probabilities = new ComputeProbabilityClosure(graph).apply();
-        Map<Invoke, Double> hints = null;
-        for (CommitAllocationNode commit : graph.getNodes(CommitAllocationNode.class)) {
-            double sum = 0;
-            double invokeSum = 0;
-            for (Node commitUsage : commit.usages()) {
-                for (Node usage : commitUsage.usages()) {
-                    if (usage instanceof FixedNode) {
-                        sum += probabilities.get((FixedNode) usage);
-                    } else {
-                        if (usage instanceof MethodCallTargetNode) {
-                            invokeSum += probabilities.get(((MethodCallTargetNode) usage).invoke().asNode());
-                        }
-                        for (Node secondLevelUage : usage.usages()) {
-                            if (secondLevelUage instanceof FixedNode) {
-                                sum += probabilities.get(((FixedNode) secondLevelUage));
-                            }
-                        }
-                    }
-                }
-            }
-            // TODO(lstadler) get rid of this magic number
-            if (sum > 100 && invokeSum > 0) {
-                for (Node commitUsage : commit.usages()) {
-                    for (Node usage : commitUsage.usages()) {
-                        if (usage instanceof MethodCallTargetNode) {
-                            if (hints == null) {
-                                hints = new HashMap<>();
-                            }
-                            Invoke invoke = ((MethodCallTargetNode) usage).invoke();
-                            hints.put(invoke, sum / invokeSum);
-                        }
-                    }
-                }
-            }
-        }
-        return hints;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java	Tue Jun 18 10:12:27 2013 +0200
@@ -0,0 +1,214 @@
+/*
+ * 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.virtual.phases.ea;
+
+import java.util.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.Virtualizable.EscapeState;
+import com.oracle.graal.nodes.virtual.*;
+
+public abstract class PartialEscapeBlockState<T extends PartialEscapeBlockState<T>> extends EffectsBlockState<T> {
+
+    protected final IdentityHashMap<VirtualObjectNode, ObjectState> objectStates = new IdentityHashMap<>();
+    protected final IdentityHashMap<ValueNode, VirtualObjectNode> objectAliases;
+
+    /**
+     * Final subclass of PartialEscapeBlockState, for performance and to make everything behave
+     * nicely with generics.
+     */
+    public static final class Final extends PartialEscapeBlockState<Final> {
+
+        public Final() {
+        }
+
+        public Final(Final other) {
+            super(other);
+        }
+    }
+
+    protected PartialEscapeBlockState() {
+        objectAliases = new IdentityHashMap<>();
+    }
+
+    protected PartialEscapeBlockState(PartialEscapeBlockState<T> other) {
+        super(other);
+        for (Map.Entry<VirtualObjectNode, ObjectState> entry : other.objectStates.entrySet()) {
+            objectStates.put(entry.getKey(), entry.getValue().cloneState());
+        }
+        objectAliases = new IdentityHashMap<>(other.objectAliases);
+    }
+
+    public ObjectState getObjectState(VirtualObjectNode object) {
+        assert objectStates.containsKey(object);
+        return objectStates.get(object);
+    }
+
+    public ObjectState getObjectStateOptional(VirtualObjectNode object) {
+        return objectStates.get(object);
+    }
+
+    public ObjectState getObjectState(ValueNode value) {
+        VirtualObjectNode object = objectAliases.get(value);
+        return object == null ? null : getObjectState(object);
+    }
+
+    public void materializeBefore(FixedNode fixed, VirtualObjectNode virtual, EscapeState state, GraphEffectList materializeEffects) {
+        PartialEscapeClosure.METRIC_MATERIALIZATIONS.increment();
+        List<AllocatedObjectNode> objects = new ArrayList<>(2);
+        List<ValueNode> values = new ArrayList<>(8);
+        List<int[]> locks = new ArrayList<>(2);
+        List<ValueNode> otherAllocations = new ArrayList<>(2);
+        materializeWithCommit(fixed, virtual, objects, locks, values, otherAllocations, state);
+
+        materializeEffects.addMaterializationBefore(fixed, objects, locks, values, otherAllocations);
+    }
+
+    private void materializeWithCommit(FixedNode fixed, VirtualObjectNode virtual, List<AllocatedObjectNode> objects, List<int[]> locks, List<ValueNode> values, List<ValueNode> otherAllocations,
+                    EscapeState state) {
+        ObjectState obj = getObjectState(virtual);
+
+        ValueNode[] entries = obj.getEntries();
+        ValueNode representation = virtual.getMaterializedRepresentation(fixed, entries, obj.getLocks());
+        obj.escape(representation, state);
+        if (representation instanceof AllocatedObjectNode) {
+            objects.add((AllocatedObjectNode) representation);
+            locks.add(obj.getLocks());
+            int pos = values.size();
+            while (values.size() < pos + entries.length) {
+                values.add(null);
+            }
+            for (int i = 0; i < entries.length; i++) {
+                ObjectState entryObj = getObjectState(entries[i]);
+                if (entryObj != null) {
+                    if (entryObj.isVirtual()) {
+                        materializeWithCommit(fixed, entryObj.getVirtualObject(), objects, locks, values, otherAllocations, state);
+                    }
+                    values.set(pos + i, entryObj.getMaterializedValue());
+                } else {
+                    values.set(pos + i, entries[i]);
+                }
+            }
+            objectMaterialized(virtual, (AllocatedObjectNode) representation, values.subList(pos, pos + entries.length));
+        } else {
+            VirtualUtil.trace("materialized %s as %s", virtual, representation);
+            otherAllocations.add(representation);
+            assert obj.getLocks().length == 0;
+        }
+    }
+
+    protected void objectMaterialized(VirtualObjectNode virtual, AllocatedObjectNode representation, List<ValueNode> values) {
+        VirtualUtil.trace("materialized %s as %s with values %s", virtual, representation, values);
+    }
+
+    void addAndMarkAlias(VirtualObjectNode virtual, ValueNode node, NodeBitMap usages) {
+        objectAliases.put(node, virtual);
+        if (node.isAlive()) {
+            for (Node usage : node.usages()) {
+                markVirtualUsages(usage, usages);
+            }
+        }
+    }
+
+    private void markVirtualUsages(Node node, NodeBitMap usages) {
+        if (!usages.isNew(node)) {
+            usages.mark(node);
+        }
+        if (node instanceof VirtualState) {
+            for (Node usage : node.usages()) {
+                markVirtualUsages(usage, usages);
+            }
+        }
+    }
+
+    public void addObject(VirtualObjectNode virtual, ObjectState state) {
+        objectStates.put(virtual, state);
+    }
+
+    public Iterable<ObjectState> getStates() {
+        return objectStates.values();
+    }
+
+    public Collection<VirtualObjectNode> getVirtualObjects() {
+        return objectAliases.values();
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + ", Object Aliases: " + objectAliases + ", Object States: " + objectStates;
+    }
+
+    @Override
+    public void meetAliases(List<T> states) {
+        super.meetAliases(states);
+        objectAliases.putAll(states.get(0).objectAliases);
+        for (int i = 1; i < states.size(); i++) {
+            meetMaps(objectAliases, states.get(i).objectAliases);
+        }
+    }
+
+    @Override
+    public boolean equivalentTo(T other) {
+        if (!compareMaps(objectAliases, other.objectAliases) || !compareMaps(objectStates, other.objectStates)) {
+            return false;
+        }
+        return super.equivalentTo(other);
+    }
+
+    protected static <K, V> boolean compareMaps(Map<K, V> left, Map<K, V> right) {
+        if (left.size() != right.size()) {
+            return false;
+        }
+        return compareMapsNoSize(left, right);
+    }
+
+    protected 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;
+    }
+
+    protected static <U, V> void meetMaps(Map<U, V> target, Map<U, V> source) {
+        Iterator<Map.Entry<U, V>> iter = target.entrySet().iterator();
+        while (iter.hasNext()) {
+            Map.Entry<U, V> entry = iter.next();
+            if (source.containsKey(entry.getKey())) {
+                assert source.get(entry.getKey()) == entry.getValue();
+            } else {
+                iter.remove();
+            }
+        }
+    }
+
+}
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.virtual.phases.ea;
 
-import static com.oracle.graal.api.meta.LocationIdentity.*;
-
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
@@ -34,21 +32,14 @@
 import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.VirtualState.NodeClosure;
 import com.oracle.graal.nodes.cfg.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.spi.Virtualizable.EscapeState;
 import com.oracle.graal.nodes.virtual.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.graph.*;
-import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure;
-import com.oracle.graal.phases.graph.ReentrantBlockIterator.LoopInfo;
 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<BlockT extends BlockState> extends PartialEscapeAnalysisPhase.Closure<BlockT> {
+public abstract class PartialEscapeClosure<BlockT extends PartialEscapeBlockState<BlockT>> extends EffectsClosure<BlockT> {
 
     public static final DebugMetric METRIC_MATERIALIZATIONS = Debug.metric("Materializations");
     public static final DebugMetric METRIC_MATERIALIZATIONS_PHI = Debug.metric("MaterializationsPhi");
@@ -61,143 +52,63 @@
     public static final DebugMetric METRIC_MEMORYCHECKOINT = Debug.metric("MemoryCheckpoint");
 
     private final NodeBitMap usages;
-    private final SchedulePhase schedule;
-
-    private final BlockMap<GraphEffectList> blockEffects;
-    private final IdentityHashMap<Loop, GraphEffectList> loopMergeEffects = new IdentityHashMap<>();
-
     private final VirtualizerToolImpl tool;
-
     private final Map<Invoke, Double> hints = new IdentityHashMap<>();
 
-    private boolean changed;
+    /**
+     * Final subclass of PartialEscapeClosure, for performance and to make everything behave nicely
+     * with generics.
+     */
+    public static final class Final extends PartialEscapeClosure<PartialEscapeBlockState.Final> {
 
-    public PartialEscapeClosure(SchedulePhase schedule, MetaAccessProvider metaAccess, Assumptions assumptions) {
-        this.usages = schedule.getCFG().graph.createNodeBitMap();
-        this.schedule = schedule;
-        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 Final(SchedulePhase schedule, MetaAccessProvider metaAccess, Assumptions assumptions) {
+            super(schedule, metaAccess, assumptions);
+        }
+
+        @Override
+        protected PartialEscapeBlockState.Final getInitialState() {
+            return new PartialEscapeBlockState.Final();
+        }
+
+        @Override
+        protected PartialEscapeBlockState.Final cloneState(PartialEscapeBlockState.Final oldState) {
+            return new PartialEscapeBlockState.Final(oldState);
         }
     }
 
-    @SuppressWarnings("unchecked")
-    @Override
-    protected BlockT getInitialState() {
-        return (BlockT) new BlockState();
-    }
-
-    @Override
-    public boolean hasChanged() {
-        return changed;
-    }
-
-    @Override
-    public void applyEffects() {
-        final StructuredGraph graph = schedule.getCFG().graph;
-        final ArrayList<Node> obsoleteNodes = new ArrayList<>(0);
-        BlockIteratorClosure<Void> closure = new BlockIteratorClosure<Void>() {
-
-            @Override
-            protected Void getInitialState() {
-                return null;
-            }
-
-            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);
-                        }
-                    }
-                }
-            }
-
-            @Override
-            protected Void processBlock(Block block, Void currentState) {
-                apply(blockEffects.get(block), block);
-                return currentState;
-            }
-
-            @Override
-            protected Void merge(Block merge, List<Void> states) {
-                return null;
-            }
-
-            @Override
-            protected Void cloneState(Void oldState) {
-                return oldState;
-            }
-
-            @Override
-            protected List<Void> processLoop(Loop loop, Void initialState) {
-                LoopInfo<Void> info = ReentrantBlockIterator.processLoop(this, loop, initialState);
-                apply(loopMergeEffects.get(loop), loop);
-                return info.exitStates;
-            }
-        };
-        ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock());
-        assert VirtualUtil.assertNonReachable(graph, obsoleteNodes);
+    public PartialEscapeClosure(SchedulePhase schedule, MetaAccessProvider metaAccess, Assumptions assumptions) {
+        super(schedule);
+        this.usages = schedule.getCFG().graph.createNodeBitMap();
+        this.tool = new VirtualizerToolImpl(usages, metaAccess, assumptions);
     }
 
     public Map<Invoke, Double> getHints() {
         return hints;
     }
 
+    /**
+     * @return true if the node was deleted, false otherwise
+     */
     @Override
-    protected BlockT processBlock(Block block, BlockT state) {
-        GraphEffectList effects = blockEffects.get(block);
-        tool.setEffects(effects);
-
-        VirtualUtil.trace("\nBlock: %s (", block);
-        List<ScheduledNode> nodeList = schedule.getBlockToNodesMap().get(block);
-
-        FixedWithNextNode lastFixedNode = null;
-        for (Node node : nodeList) {
-            boolean deleted;
-            boolean isMarked = usages.isMarked(node);
-            if (isMarked || node instanceof VirtualizableRoot) {
-                VirtualUtil.trace("[[%s]] ", node);
-                FixedNode nextFixedNode = lastFixedNode == null ? null : lastFixedNode.next();
-                deleted = processNode((ValueNode) node, nextFixedNode, state, effects, isMarked);
-            } else {
-                VirtualUtil.trace("%s ", node);
-                deleted = false;
-            }
-            if (GraalOptions.OptEarlyReadElimination) {
-                if (!deleted && node instanceof MemoryCheckpoint) {
-                    METRIC_MEMORYCHECKOINT.increment();
-                    MemoryCheckpoint checkpoint = (MemoryCheckpoint) node;
-                    for (LocationIdentity identity : checkpoint.getLocationIdentities()) {
-                        if (identity instanceof ResolvedJavaField) {
-                            state.killReadCache((ResolvedJavaField) identity);
-                        } else if (identity == ANY_LOCATION) {
-                            state.killReadCache();
-                        }
-                    }
-                }
-            }
-            if (node instanceof FixedWithNextNode) {
-                lastFixedNode = (FixedWithNextNode) node;
-            }
+    protected boolean processNode(Node node, BlockT state, GraphEffectList effects, FixedWithNextNode lastFixedNode) {
+        boolean isMarked = usages.isMarked(node);
+        if (isMarked || node instanceof VirtualizableRoot) {
+            VirtualUtil.trace("[[%s]] ", node);
+            FixedNode nextFixedNode = lastFixedNode == null ? null : lastFixedNode.next();
+            return processNode((ValueNode) node, nextFixedNode, state, effects, isMarked);
+        } else {
+            VirtualUtil.trace("%s ", node);
+            return false;
         }
-        VirtualUtil.trace(")\n    end state: %s\n", state);
-        return state;
     }
 
     private boolean processNode(final ValueNode node, FixedNode insertBefore, final BlockT state, final GraphEffectList effects, boolean isMarked) {
-        tool.reset(state, node, insertBefore);
+        tool.reset(state, node, insertBefore, effects);
         if (node instanceof Virtualizable) {
             ((Virtualizable) node).virtualize(tool);
         }
         if (tool.isDeleted()) {
-            if (!(node instanceof CommitAllocationNode || node instanceof AllocatedObjectNode)) {
-                changed = true;
-            }
-            return true;
+            return !(node instanceof CommitAllocationNode || node instanceof AllocatedObjectNode);
         }
         if (isMarked) {
             if (node instanceof StateSplit) {
@@ -289,7 +200,7 @@
         return false;
     }
 
-    private static void ensureMaterialized(BlockState state, ObjectState obj, FixedNode materializeBefore, GraphEffectList effects, DebugMetric metric) {
+    private static void ensureMaterialized(PartialEscapeBlockState state, ObjectState obj, FixedNode materializeBefore, GraphEffectList effects, DebugMetric metric) {
         assert obj != null;
         if (obj.getState() == EscapeState.Virtual) {
             metric.increment();
@@ -300,70 +211,13 @@
         assert !obj.isVirtual();
     }
 
-    private static void replaceWithMaterialized(ValueNode value, Node usage, FixedNode materializeBefore, BlockState state, ObjectState obj, GraphEffectList effects, DebugMetric metric) {
+    private static void replaceWithMaterialized(ValueNode value, Node usage, FixedNode materializeBefore, PartialEscapeBlockState state, ObjectState obj, GraphEffectList effects, DebugMetric metric) {
         ensureMaterialized(state, obj, materializeBefore, effects, metric);
         effects.replaceFirstInput(usage, value, obj.getMaterializedValue());
     }
 
     @Override
-    protected BlockT merge(Block merge, List<BlockT> states) {
-        assert blockEffects.get(merge).isEmpty();
-        MergeProcessor<BlockT> processor = new MergeProcessor<>(merge, usages, blockEffects);
-        processor.merge(states);
-        blockEffects.get(merge).addAll(processor.mergeEffects);
-        blockEffects.get(merge).addAll(processor.afterMergeEffects);
-        return processor.newState;
-
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    protected BlockT cloneState(BlockState oldState) {
-        return (BlockT) oldState.cloneState();
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    protected List<BlockT> processLoop(Loop loop, BlockT initialState) {
-        BlockState loopEntryState = initialState;
-        BlockState lastMergedState = initialState;
-        MergeProcessor<BlockT> mergeProcessor = new MergeProcessor<>(loop.header, usages, blockEffects);
-        for (int iteration = 0; iteration < 10; iteration++) {
-            LoopInfo<BlockT> info = ReentrantBlockIterator.processLoop(this, loop, (BlockT) lastMergedState.cloneState());
-
-            List<BlockT> states = new ArrayList<>();
-            states.add(initialState);
-            states.addAll(info.endStates);
-            mergeProcessor.merge(states);
-
-            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) {
+    protected void processLoopExit(LoopExitNode exitNode, BlockT initialState, BlockT exitState, GraphEffectList effects) {
         HashMap<VirtualObjectNode, ProxyNode> proxies = new HashMap<>();
 
         for (ProxyNode proxy : exitNode.proxies()) {
@@ -404,41 +258,25 @@
                 }
             }
         }
-
-        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<BlockT extends BlockState> {
+    @Override
+    protected MergeProcessor createMergeProcessor(Block merge) {
+        return new MergeProcessor(merge);
+    }
 
-        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;
+    protected class MergeProcessor extends EffectsClosure<BlockT>.MergeProcessor {
 
         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 BlockT 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();
+        public MergeProcessor(Block mergeBlock) {
+            super(mergeBlock);
         }
 
-        private <T> PhiNode getCachedPhi(T virtual, Kind kind) {
+        protected <T> PhiNode getCachedPhi(T virtual, Kind kind) {
             PhiNode result = materializedPhis.get(virtual);
             if (result == null) {
                 result = new PhiNode(kind, merge);
@@ -474,9 +312,9 @@
             return result;
         }
 
-        @SuppressWarnings("unchecked")
-        private void merge(List<BlockT> states) {
-            newState = (BlockT) states.get(0).meetAliases(states);
+        @Override
+        protected void merge(List<BlockT> states) {
+            super.merge(states);
 
             /*
              * Iterative processing: Merging the materialized/virtual state of virtual objects can
@@ -511,14 +349,12 @@
                         locksMatch &= obj.locksEqual(startObj);
                     }
 
-                    assert virtual < states.size() || locksMatch : "mismatching lock counts at " + merge;
-
-                    if (virtual < states.size()) {
+                    if (virtual < states.size() || !locksMatch) {
                         if (singleValue == null) {
                             PhiNode materializedValuePhi = getCachedPhi(object, Kind.Object);
                             mergeEffects.addFloatingNode(materializedValuePhi, "materializedPhi");
                             for (int i = 0; i < states.size(); i++) {
-                                BlockState state = states.get(i);
+                                PartialEscapeBlockState state = states.get(i);
                                 ObjectState obj = objStates[i];
                                 materialized |= obj.isVirtual();
                                 Block predecessor = mergeBlock.getPredecessors().get(i);
@@ -577,8 +413,6 @@
                     }
                 }
             } while (materialized);
-
-            mergeReadCache(states);
         }
 
         private boolean processPhi(PhiNode phi, List<BlockT> states) {
@@ -664,62 +498,5 @@
             }
             return materialized;
         }
-
-        private void mergeReadCache(List<BlockT> 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);
-                        }
-                    }
-
-                }
-            }
-        }
-
-        private void mergeReadCachePhi(PhiNode phi, ResolvedJavaField identity, List<BlockT> 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;
-                }
-                values[i] = value;
-            }
-
-            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]);
-            }
-            newState.readCache.put(new ReadCacheEntry(identity, phi), phiNode);
-        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -0,0 +1,106 @@
+/*
+ * 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.virtual.phases.ea;
+
+import static com.oracle.graal.phases.GraalOptions.*;
+
+import java.util.*;
+
+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.util.*;
+import com.oracle.graal.nodes.virtual.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.graph.*;
+import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.phases.tiers.*;
+
+public class PartialEscapePhase extends EffectsPhase<PhaseContext> {
+
+    public PartialEscapePhase(boolean iterative, CanonicalizerPhase canonicalizer) {
+        super(iterative ? EscapeAnalysisIterations.getValue() : 1, canonicalizer);
+    }
+
+    @Override
+    protected void run(StructuredGraph graph, PhaseContext context) {
+        if (VirtualUtil.matches(graph, EscapeAnalyzeOnly.getValue())) {
+            boolean analyzableNodes = false;
+            for (Node node : graph.getNodes()) {
+                if (node instanceof VirtualizableAllocation) {
+                    analyzableNodes = true;
+                    break;
+                }
+            }
+            if (analyzableNodes) {
+                runAnalysis(graph, context);
+            }
+        }
+    }
+
+    @Override
+    protected Closure<?> createEffectsClosure(PhaseContext context, SchedulePhase schedule) {
+        return new PartialEscapeClosure.Final(schedule, context.getRuntime(), context.getAssumptions());
+    }
+
+    public static Map<Invoke, Double> getHints(StructuredGraph graph) {
+        NodesToDoubles probabilities = new ComputeProbabilityClosure(graph).apply();
+        Map<Invoke, Double> hints = null;
+        for (CommitAllocationNode commit : graph.getNodes(CommitAllocationNode.class)) {
+            double sum = 0;
+            double invokeSum = 0;
+            for (Node commitUsage : commit.usages()) {
+                for (Node usage : commitUsage.usages()) {
+                    if (usage instanceof FixedNode) {
+                        sum += probabilities.get((FixedNode) usage);
+                    } else {
+                        if (usage instanceof MethodCallTargetNode) {
+                            invokeSum += probabilities.get(((MethodCallTargetNode) usage).invoke().asNode());
+                        }
+                        for (Node secondLevelUage : usage.usages()) {
+                            if (secondLevelUage instanceof FixedNode) {
+                                sum += probabilities.get(((FixedNode) secondLevelUage));
+                            }
+                        }
+                    }
+                }
+            }
+            // TODO(lstadler) get rid of this magic number
+            if (sum > 100 && invokeSum > 0) {
+                for (Node commitUsage : commit.usages()) {
+                    for (Node usage : commitUsage.usages()) {
+                        if (usage instanceof MethodCallTargetNode) {
+                            if (hints == null) {
+                                hints = new HashMap<>();
+                            }
+                            Invoke invoke = ((MethodCallTargetNode) usage).invoke();
+                            hints.put(invoke, sum / invokeSum);
+                        }
+                    }
+                }
+            }
+        }
+        return hints;
+    }
+}
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,13 +22,14 @@
  */
 package com.oracle.graal.virtual.phases.ea;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import java.util.*;
 
 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.phases.*;
 
 public final class VirtualUtil {
 
@@ -105,12 +106,12 @@
     }
 
     public static void trace(String format, Object... obj) {
-        if (GraalOptions.TraceEscapeAnalysis) {
+        if (TraceEscapeAnalysis.getValue()) {
             Debug.log(format, obj);
         }
     }
 
-    static boolean matches(StructuredGraph graph, String filter) {
+    public static boolean matches(StructuredGraph graph, String filter) {
         if (filter != null) {
             if (filter.startsWith("~")) {
                 ResolvedJavaMethod method = graph.method();
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java	Tue Jun 18 10:12:27 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.virtual.phases.ea;
 
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
@@ -31,14 +33,12 @@
 import com.oracle.graal.nodes.spi.Virtualizable.State;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.virtual.*;
-import com.oracle.graal.phases.*;
 
 class VirtualizerToolImpl implements VirtualizerTool {
 
     private final NodeBitMap usages;
     private final MetaAccessProvider metaAccess;
     private final Assumptions assumptions;
-    private GraphEffectList effects;
 
     VirtualizerToolImpl(NodeBitMap usages, MetaAccessProvider metaAccess, Assumptions assumptions) {
         this.usages = usages;
@@ -47,9 +47,10 @@
     }
 
     private boolean deleted;
-    private BlockState state;
+    private PartialEscapeBlockState state;
     private ValueNode current;
     private FixedNode position;
+    private GraphEffectList effects;
 
     @Override
     public MetaAccessProvider getMetaAccessProvider() {
@@ -61,15 +62,12 @@
         return assumptions;
     }
 
-    public void setEffects(GraphEffectList effects) {
-        this.effects = effects;
-    }
-
-    public void reset(BlockState newState, ValueNode newCurrent, FixedNode newPosition) {
+    public void reset(PartialEscapeBlockState newState, ValueNode newCurrent, FixedNode newPosition, GraphEffectList newEffects) {
         deleted = false;
         state = newState;
         current = newCurrent;
         position = newPosition;
+        effects = newEffects;
     }
 
     public boolean isDeleted() {
@@ -86,16 +84,24 @@
         ObjectState obj = (ObjectState) objectState;
         assert obj != null && obj.isVirtual() : "not virtual: " + obj;
         ObjectState valueState = state.getObjectState(value);
+        ValueNode newValue = value;
         if (valueState == null) {
-            obj.setEntry(index, getReplacedValue(value));
+            newValue = getReplacedValue(value);
+            assert obj.getEntry(index) == null || obj.getEntry(index).kind() == newValue.kind() || (isObjectEntry(obj.getEntry(index)) && isObjectEntry(newValue));
         } else {
-            ValueNode newValue = value;
             if (valueState.getState() != EscapeState.Virtual) {
                 newValue = valueState.getMaterializedValue();
+                assert newValue.kind() == Kind.Object;
+            } else {
+                newValue = valueState.getVirtualObject();
             }
-            assert obj.getEntry(index) == null || obj.getEntry(index).kind() == newValue.kind();
-            obj.setEntry(index, newValue);
+            assert obj.getEntry(index) == null || isObjectEntry(obj.getEntry(index));
         }
+        obj.setEntry(index, newValue);
+    }
+
+    private static boolean isObjectEntry(ValueNode value) {
+        return value.kind() == Kind.Object || value instanceof VirtualObjectNode;
     }
 
     @Override
@@ -127,7 +133,6 @@
 
     @Override
     public void delete() {
-        assert current instanceof FixedWithNextNode;
         effects.deleteFixedNode((FixedWithNextNode) current);
         deleted = true;
     }
@@ -164,7 +169,7 @@
 
     @Override
     public int getMaximumEntryCount() {
-        return GraalOptions.MaximumEscapeAnalysisArrayLength;
+        return MaximumEscapeAnalysisArrayLength.getValue();
     }
 
     @Override
@@ -180,26 +185,4 @@
             }
         }
     }
-
-    @Override
-    public void addReadCache(ValueNode object, ResolvedJavaField identity, ValueNode value) {
-        if (GraalOptions.OptEarlyReadElimination) {
-            state.addReadCache(object, identity, value);
-        }
-    }
-
-    @Override
-    public ValueNode getReadCache(ValueNode object, ResolvedJavaField identity) {
-        if (GraalOptions.OptEarlyReadElimination) {
-            return state.getReadCache(object, identity);
-        }
-        return null;
-    }
-
-    @Override
-    public void killReadCache(ResolvedJavaField identity) {
-        if (GraalOptions.OptEarlyReadElimination) {
-            state.killReadCache(identity);
-        }
-    }
 }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Tue Jun 18 10:12:27 2013 +0200
@@ -29,9 +29,9 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.HeapAccess.WriteBarrierType;
 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.type.*;
 import com.oracle.graal.nodes.util.*;
@@ -310,7 +310,7 @@
     }
 
     private static ValueNode readOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location) {
-        ReadNode read = graph.add(new ReadNode(base, location, invoke.asNode().stamp()));
+        ReadNode read = graph.add(new ReadNode(base, location, invoke.asNode().stamp(), WriteBarrierType.NONE, false));
         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
@@ -319,7 +319,7 @@
     }
 
     private static ValueNode writeOp(StructuredGraph graph, ValueNode base, ValueNode value, Invoke invoke, LocationNode location) {
-        WriteNode write = graph.add(new WriteNode(base, value, location, WriteBarrierType.NONE));
+        WriteNode write = graph.add(new WriteNode(base, value, location, WriteBarrierType.NONE, false));
         write.setStateAfter(invoke.stateAfter());
         graph.addBeforeFixed(invoke.asNode(), write);
         return write;
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java	Tue Jun 18 10:12:27 2013 +0200
@@ -23,7 +23,7 @@
 package com.oracle.truffle.api;
 
 /**
- * Represents a section in the source code of a guest language program.
+ * Represents a contiguous text section within the source code of a guest language program.
  */
 public class SourceSection {
 
@@ -35,13 +35,26 @@
     private final int charLength;
 
     /**
-     * Creates a new object representing a section in the source code of a guest language program.
+     * Creates a new object representing a contiguous text section within the source code of a guest
+     * language program.
+     * <p>
+     * The starting location of the section is specified using two different coordinate:
+     * <ul>
+     * <li><b>(row, column)</b>: rows and columns are 1-based, so the first character in a source
+     * file is at position {@code (1,1)}.</li>
+     * <li><b>character index</b>: 0-based offset of the character from the beginning of the source,
+     * so the first character in a file is at index {@code 0}.</li>
+     * </ul>
+     * The <b>newline</b> that terminates each line counts as a single character for the purpose of
+     * a character index. The (row,column) coordinates of a newline character should never appear in
+     * a text section.
+     * <p>
      * 
-     * @param source object representing the source program this is should be a section of
+     * @param source object representing the complete source program that contains this section
      * @param identifier an identifier used when printing the section
-     * @param startLine the index of the start line of the section
-     * @param startColumn the index of the start column of the section
-     * @param charIndex the index of the first character of the section
+     * @param startLine the 1-based number of the start line of the section
+     * @param startColumn the 1-based number of the start column of the section
+     * @param charIndex the 0-based index of the first character of the section
      * @param charLength the length of the section in number of characters
      */
     public SourceSection(Source source, String identifier, int startLine, int startColumn, int charIndex, int charLength) {
@@ -54,7 +67,7 @@
     }
 
     /**
-     * Returns the source object representing the source program this is a section of.
+     * Returns the object representing the source program that contains this section.
      * 
      * @return the source object
      */
@@ -63,38 +76,42 @@
     }
 
     /**
-     * Returns the index of the start line of this source section (inclusive).
+     * Returns 1-based line number of the first character in this source section (inclusive).
      * 
-     * @return the start line
+     * @return the starting line number
      */
     public final int getStartLine() {
         return startLine;
     }
 
     /**
-     * Returns the index of the start column of this source section (inclusive).
+     * Returns the 1-based column number of the first character in this source section (inclusive).
      * 
-     * @return the start column
+     * @return the starting column number
      */
     public final int getStartColumn() {
         return startColumn;
     }
 
     /**
-     * Returns the index of the first character of this section. All characters of the source can be
-     * retrieved via the {@link Source#getCode()} method.
+     * Returns the 0-based index of the first character in this source section.
+     * <p>
+     * The complete text of the source that contains this section can be retrieved via
+     * {@link Source#getCode()}.
      * 
-     * @return the character index
+     * @return the starting character index
      */
     public final int getCharIndex() {
         return charIndex;
     }
 
     /**
-     * Returns the length of this section in characters. All characters of the source can be
-     * retrieved via the {@link Source#getCode()} method.
+     * Returns the length of this source section in characters.
+     * <p>
+     * The complete text of the source that contains this section can be retrieved via
+     * {@link Source#getCode()}.
      * 
-     * @return the character length
+     * @return the number of characters in the section
      */
     public final int getCharLength() {
         return charLength;
@@ -110,7 +127,7 @@
     }
 
     /**
-     * Returns the code represented by this code section.
+     * Returns text of the code represented by this source section.
      * 
      * @return the code as a String object
      */
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java	Tue Jun 18 10:12:27 2013 +0200
@@ -170,4 +170,13 @@
      * @return the new materialized frame
      */
     MaterializedFrame materialize();
+
+    /**
+     * To check whether the given {@link FrameSlot} has been initialized or not. An initialized slot
+     * has previously been read or modified.
+     * 
+     * @param slot the slot
+     * @return true if the slot is uninitialized.
+     */
+    boolean isInitialized(FrameSlot slot);
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java	Tue Jun 18 10:12:27 2013 +0200
@@ -112,6 +112,13 @@
         return clonedFrameDescriptor;
     }
 
+    public FrameDescriptor shallowCopy() {
+        FrameDescriptor clonedFrameDescriptor = new FrameDescriptor(this.typeConversion);
+        clonedFrameDescriptor.slots.addAll(slots);
+        clonedFrameDescriptor.identifierToSlotMap.putAll(identifierToSlotMap);
+        return clonedFrameDescriptor;
+    }
+
     void updateVersion() {
         version.invalidate();
         version = createVersion();
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotImpl.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotImpl.java	Tue Jun 18 10:12:27 2013 +0200
@@ -29,7 +29,7 @@
     private final int index;
     private FrameSlotKind kind;
 
-    protected FrameSlotImpl(FrameDescriptor descriptor, Object identifier, int index, FrameSlotKind kind) {
+    public FrameSlotImpl(FrameDescriptor descriptor, Object identifier, int index, FrameSlotKind kind) {
         this.descriptor = descriptor;
         this.identifier = identifier;
         this.index = index;
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/NativeFrame.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/NativeFrame.java	Tue Jun 18 10:12:27 2013 +0200
@@ -133,4 +133,9 @@
     public FrameDescriptor getFrameDescriptor() {
         throw new UnsupportedOperationException("native frame");
     }
+
+    @Override
+    public boolean isInitialized(FrameSlot slot) {
+        throw new UnsupportedOperationException("native frame");
+    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java	Tue Jun 18 10:12:27 2013 +0200
@@ -122,4 +122,9 @@
     public FrameDescriptor getFrameDescriptor() {
         return wrapped.getFrameDescriptor();
     }
+
+    @Override
+    public boolean isInitialized(FrameSlot slot) {
+        return wrapped.isInitialized(slot);
+    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java	Tue Jun 18 10:11:28 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java	Tue Jun 18 10:12:27 2013 +0200
@@ -201,4 +201,9 @@
             tags = Arrays.copyOf(tags, newSize);
         }
     }
+
+    @Override
+    public boolean isInitialized(FrameSlot slot) {
+        return (this.tags[slot.getIndex()] != FrameSlotKind.Illegal.ordinal());
+    }
 }
--- a/make/Makefile	Tue Jun 18 10:11:28 2013 +0200
+++ b/make/Makefile	Tue Jun 18 10:12:27 2013 +0200
@@ -516,6 +516,10 @@
 $(EXPORT_JRE_LIB_DIR)/%.jar: $(SHARED_DIR)/%.jar
 	$(install-file)
 
+# Shared options files
+$(EXPORT_JRE_LIB_DIR)/%.options: $(SHARED_DIR)/%.options
+	$(install-file)
+	
 # Include files (jvmti.h, jvmticmlr.h, jni.h, $(JDK_INCLUDE_SUBDIR)/jni_md.h, jmm.h, jfr.h)
 $(EXPORT_INCLUDE_DIR)/%: $(GEN_DIR)/jvmtifiles/%
 	$(install-file)
--- a/make/build-graal.xml	Tue Jun 18 10:11:28 2013 +0200
+++ b/make/build-graal.xml	Tue Jun 18 10:12:27 2013 +0200
@@ -28,7 +28,7 @@
   <property name="classes.dir" value="${shared.dir}/graal"/>
   <property name="jar.dir" value="${shared.dir}"/>
   <property name="jar.file" value="${jar.dir}/graal.jar"/>
-  <target depends="jar" name="main"/>
+  <target depends="options,jar" name="main"/>
   <target depends="cleanclasses" name="compile">
     <mkdir dir="${classes.dir}"/>
     <javac debug="on" destdir="${classes.dir}" includeantruntime="false">
@@ -39,10 +39,10 @@
       <src path="${src.dir}/com.oracle.graal.debug"/>
       <src path="${src.dir}/com.oracle.graal.api.replacements"/>
       <src path="${src.dir}/com.oracle.graal.nodes"/>
+      <src path="${src.dir}/com.oracle.graal.options"/>
       <src path="${src.dir}/com.oracle.graal.phases"/>
       <src path="${src.dir}/com.oracle.graal.phases.common"/>
       <src path="${src.dir}/com.oracle.graal.virtual"/>
-      <src path="${src.dir}/com.oracle.graal.options"/>
       <src path="${src.dir}/com.oracle.graal.loop"/>
       <src path="${src.dir}/com.oracle.graal.alloc"/>
       <src path="${src.dir}/com.oracle.graal.asm"/>
@@ -81,27 +81,14 @@
         <provider classname="com.oracle.graal.hotspot.replacements.HotSpotNmethodIntrinsics"/>
         <provider classname="com.oracle.graal.replacements.GraalMethodSubstitutions"/>
       </service>
-      <service type="com.oracle.graal.options.OptionProvider">
-        <provider classname="com.oracle.graal.compiler.GraalCompiler_VerifyUsageWithEquals"/>
-        <provider classname="com.oracle.graal.compiler.GraalDebugConfig_DebugEnabled"/>
-        <provider classname="com.oracle.graal.compiler.GraalDebugConfig_Dump"/>
-        <provider classname="com.oracle.graal.compiler.GraalDebugConfig_DumpOnError"/>
-        <provider classname="com.oracle.graal.compiler.GraalDebugConfig_Log"/>
-        <provider classname="com.oracle.graal.compiler.GraalDebugConfig_Meter"/>
-        <provider classname="com.oracle.graal.compiler.GraalDebugConfig_MethodFilter"/>
-        <provider classname="com.oracle.graal.compiler.GraalDebugConfig_PerThreadDebugValues"/>
-        <provider classname="com.oracle.graal.compiler.GraalDebugConfig_SummarizeDebugValues"/>
-        <provider classname="com.oracle.graal.compiler.GraalDebugConfig_SummarizePerPhase"/>
-        <provider classname="com.oracle.graal.compiler.GraalDebugConfig_Time"/>
-        <provider classname="com.oracle.graal.hotspot.CompilationTask_SlowQueueCutoff"/>
-        <provider classname="com.oracle.graal.hotspot.bridge.VMToCompilerImpl_BenchmarkDynamicCounters"/>
-        <provider classname="com.oracle.graal.hotspot.bridge.VMToCompilerImpl_GenericDynamicCounters"/>
-        <provider classname="com.oracle.graal.hotspot.bridge.VMToCompilerImpl_LogFile"/>
-        <provider classname="com.oracle.graal.hotspot.bridge.VMToCompilerImpl_PrintQueue"/>
-        <provider classname="com.oracle.graal.hotspot.bridge.VMToCompilerImpl_PriorityCompileQueue"/>
-        <provider classname="com.oracle.graal.hotspot.bridge.VMToCompilerImpl_SlowCompileThreads"/>
-        <provider classname="com.oracle.graal.hotspot.bridge.VMToCompilerImpl_Threads"/>
-        <provider classname="com.oracle.graal.hotspot.bridge.VMToCompilerImpl_TimedBootstrap"/>
+      <service type="com.oracle.graal.options.Options">
+        <provider classname="com.oracle.graal.compiler.GraalCompiler_Options"/>
+        <provider classname="com.oracle.graal.compiler.GraalDebugConfig_Options"/>
+        <provider classname="com.oracle.graal.hotspot.HotSpotGraalRuntime_Options"/>
+        <provider classname="com.oracle.graal.hotspot.bridge.VMToCompilerImpl_Options"/>
+        <provider classname="com.oracle.graal.phases.GraalOptions_Options"/>
+        <provider classname="com.oracle.graal.phases.common.InliningPhase_Options"/>
+        <provider classname="com.oracle.graal.phases.tiers.Suites_Options"/>
       </service>
       <service type="com.oracle.graal.phases.tiers.CompilerConfiguration">
         <provider classname="com.oracle.graal.compiler.phases.BasicCompilerConfiguration"/>
@@ -114,6 +101,14 @@
   <target name="cleanclasses">
     <delete dir="${classes.dir}"/>
   </target>
+  <target if="graal.options.exists" name="options">
+    <copy todir="${jar.dir}">
+      <filelist dir="${gamma.dir}" files="graal.options"/>
+    </copy>
+  </target>
+  <target name="check-graal-options-exists">
+    <available file="${gamma.dir}/graal.options" property="graal.options.exists"/>
+  </target>
   <target depends="cleanclasses" name="clean">
     <delete file="${jar.file}"/>
   </target>
--- a/make/solaris/makefiles/buildtree.make	Tue Jun 18 10:11:28 2013 +0200
+++ b/make/solaris/makefiles/buildtree.make	Tue Jun 18 10:12:27 2013 +0200
@@ -229,7 +229,9 @@
 	echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \
 	echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \
 	echo "$(call gamma-path,altsrc,os/posix/vm) \\"; \
-	echo "$(call gamma-path,commonsrc,os/posix/vm)"; \
+	echo "$(call gamma-path,commonsrc,os/posix/vm) \\"; \
+	echo "$(call gamma-path,altsrc,gpu/ptx) \\"; \
+	echo "$(call gamma-path,commonsrc,gpu/ptx)"; \
 	echo; \
 	echo "Src_Dirs_I = \\"; \
 	echo "$(call gamma-path,altsrc,share/vm/prims) \\"; \
@@ -244,8 +246,9 @@
 	echo "$(call gamma-path,commonsrc,os_cpu/$(OS_FAMILY)_$(ARCH)/vm) \\"; \
 	echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \
 	echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \
-	echo "$(call gamma-path,altsrc,os/posix/vm) \\"; \
-	echo "$(call gamma-path,commonsrc,os/posix/vm)"; \
+	echo "$(call gamma-path,commonsrc,os/posix/vm) \\"; \
+	echo "$(call gamma-path,altsrc,gpu) \\"; \
+	echo "$(call gamma-path,commonsrc,gpu)"; \
 	[ -n "$(CFLAGS_BROWSE)" ] && \
 	    echo && echo "CFLAGS_BROWSE = $(CFLAGS_BROWSE)"; \
 	[ -n "$(ENABLE_FULL_DEBUG_SYMBOLS)" ] && \
--- a/make/solaris/makefiles/vm.make	Tue Jun 18 10:11:28 2013 +0200
+++ b/make/solaris/makefiles/vm.make	Tue Jun 18 10:12:27 2013 +0200
@@ -194,7 +194,9 @@
 COMPILER2_PATHS +=  $(GENERATED)/adfiles
 
 GRAAL_PATHS += $(call altsrc,$(HS_COMMON_SRC)/share/vm/graal)
+GRAAL_PATHS += $(call altsrc,$(HS_COMMON_SRC)/gpu/ptx)
 GRAAL_PATHS += $(HS_COMMON_SRC)/share/vm/graal
+GRAAL_PATHS += $(HS_COMMON_SRC)/gpu/ptx
 
 # Include dirs per type.
 Src_Dirs/CORE      := $(CORE_PATHS)
--- a/mx/commands.py	Tue Jun 18 10:11:28 2013 +0200
+++ b/mx/commands.py	Tue Jun 18 10:12:27 2013 +0200
@@ -232,6 +232,8 @@
     machine = platform.uname()[4]
     if machine in ['amd64', 'AMD64', 'x86_64', 'i86pc']:
         return 'amd64'
+    if machine in ['sun4v']:
+        return 'sparc'
     if machine == 'i386' and mx.get_os() == 'darwin':
         try:
             # Support for Snow Leopard and earlier version of MacOSX
@@ -343,6 +345,7 @@
 
 def _installGraalJarInJdks(graalDist):
     graalJar = graalDist.path
+    graalOptions = join(_graal_home, 'graal.options')
     jdks = join(_graal_home, 'jdk' + str(mx.java().version))
     if exists(jdks):
         for e in os.listdir(jdks):
@@ -353,6 +356,9 @@
                 shutil.copyfile(graalJar, tmp)
                 os.close(fd)
                 shutil.move(tmp, join(jreLibDir, 'graal.jar'))
+                
+                if exists(graalOptions):
+                    shutil.copy(graalOptions, join(jreLibDir, 'graal.options'))
 
 # run a command in the windows SDK Debug Shell
 def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo={}):
@@ -458,7 +464,7 @@
     out.element('property', {'name' : 'jar.dir', 'value' : '${shared.dir}'})
     out.element('property', {'name' : 'jar.file', 'value' : '${jar.dir}/graal.jar'})
     
-    out.element('target', {'name' : 'main', 'depends' : 'jar'})
+    out.element('target', {'name' : 'main', 'depends' : 'options,jar'})
 
     serviceMap = {};
     def addService(service, provider):
@@ -513,6 +519,16 @@
     out.element('delete', {'dir' : '${classes.dir}'})
     out.close('target')
 
+    out.open('target', {'name' : 'options', 'if' : 'graal.options.exists'})
+    out.open('copy', {'todir' : '${jar.dir}'})
+    out.element('filelist', {'dir' : '${gamma.dir}', 'files' : 'graal.options'})
+    out.close('copy')
+    out.close('target')
+
+    out.open('target', {'name' : 'check-graal-options-exists'})
+    out.element('available', {'property' : 'graal.options.exists', 'file' : '${gamma.dir}/graal.options'})
+    out.close('target')
+    
     out.open('target', {'name' : 'clean', 'depends' : 'cleanclasses'})
     out.element('delete', {'file' : '${jar.file}'})
     out.close('target')
@@ -1028,6 +1044,11 @@
         vm(['-G:RegisterPressure=rbx,r11,r14,xmm3,xmm11,xmm14', '-esa', '-version'])
         tasks.append(t.stop())
 
+        _vmbuild = 'product'
+        t = Task('BootstrapWithAOTConfiguration:product')
+        vm(['-G:+AOTCompilation', '-G:+VerifyPhases', '-esa', '-version'])
+        tasks.append(t.stop())
+
         originalVm = _vm
         _vm = 'server' # hosted mode
         t = Task('UnitTests:hosted-product')
--- a/mx/projects	Tue Jun 18 10:11:28 2013 +0200
+++ b/mx/projects	Tue Jun 18 10:12:27 2013 +0200
@@ -32,6 +32,7 @@
 project@com.oracle.graal.api.runtime@sourceDirs=src
 project@com.oracle.graal.api.runtime@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.api.runtime@javaCompliance=1.7
+project@com.oracle.graal.api.runtime@workingSets=API,Graal
 
 # graal.api.test
 project@com.oracle.graal.api.test@subDir=graal
@@ -39,12 +40,14 @@
 project@com.oracle.graal.api.test@dependencies=JUNIT,com.oracle.graal.api.runtime
 project@com.oracle.graal.api.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.api.test@javaCompliance=1.7
+project@com.oracle.graal.api.test@workingSets=API,Graal,Test
 
 # graal.api.meta
 project@com.oracle.graal.api.meta@subDir=graal
 project@com.oracle.graal.api.meta@sourceDirs=src
 project@com.oracle.graal.api.meta@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.api.meta@javaCompliance=1.7
+project@com.oracle.graal.api.meta@workingSets=API,Graal
 
 # graal.api.meta.test
 project@com.oracle.graal.api.meta.test@subDir=graal
@@ -52,6 +55,7 @@
 project@com.oracle.graal.api.meta.test@dependencies=JUNIT,com.oracle.graal.api.meta,com.oracle.graal.api.runtime
 project@com.oracle.graal.api.meta.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.api.meta.test@javaCompliance=1.7
+project@com.oracle.graal.api.meta.test@workingSets=API,Graal,Test
 
 # graal.api.code
 project@com.oracle.graal.api.code@subDir=graal
@@ -59,6 +63,7 @@
 project@com.oracle.graal.api.code@dependencies=com.oracle.graal.api.meta
 project@com.oracle.graal.api.code@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.api.code@javaCompliance=1.7
+project@com.oracle.graal.api.code@workingSets=API,Graal
 
 # graal.api.replacements
 project@com.oracle.graal.api.replacements@subDir=graal
@@ -66,6 +71,7 @@
 project@com.oracle.graal.api.replacements@dependencies=com.oracle.graal.api.meta
 project@com.oracle.graal.api.replacements@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.api.replacements@javaCompliance=1.7
+project@com.oracle.graal.api.replacements@workingSets=API,Graal,Replacements
 
 # graal.service.processor
 project@com.oracle.graal.service.processor@subDir=graal
@@ -73,6 +79,7 @@
 project@com.oracle.graal.service.processor@dependencies=com.oracle.graal.api.runtime
 project@com.oracle.graal.service.processor@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.service.processor@javaCompliance=1.7
+project@com.oracle.graal.service.processor@workingSets=Codegen,HotSpot
 
 # graal.amd64
 project@com.oracle.graal.amd64@subDir=graal
@@ -80,6 +87,7 @@
 project@com.oracle.graal.amd64@dependencies=com.oracle.graal.api.code
 project@com.oracle.graal.amd64@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.amd64@javaCompliance=1.7
+project@com.oracle.graal.amd64@workingSets=Graal,AMD64
 
 # graal.ptx
 project@com.oracle.graal.ptx@subDir=graal
@@ -87,6 +95,7 @@
 project@com.oracle.graal.ptx@dependencies=com.oracle.graal.api.code
 project@com.oracle.graal.ptx@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.ptx@javaCompliance=1.7
+project@com.oracle.graal.ptx@workingSets=Graal,PTX
 
 # graal.sparc
 project@com.oracle.graal.sparc@subDir=graal
@@ -94,14 +103,16 @@
 project@com.oracle.graal.sparc@dependencies=com.oracle.graal.api.code
 project@com.oracle.graal.sparc@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.sparc@javaCompliance=1.7
+project@com.oracle.graal.sparc@workingSets=Graal,SPARC
 
 # graal.hotspot
 project@com.oracle.graal.hotspot@subDir=graal
 project@com.oracle.graal.hotspot@sourceDirs=src
 project@com.oracle.graal.hotspot@dependencies=com.oracle.graal.replacements,com.oracle.graal.printer
 project@com.oracle.graal.hotspot@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.hotspot@annotationProcessors=com.oracle.graal.replacements.verifier,com.oracle.graal.service.processor,com.oracle.graal.options
+project@com.oracle.graal.hotspot@annotationProcessors=com.oracle.graal.replacements.verifier,com.oracle.graal.service.processor
 project@com.oracle.graal.hotspot@javaCompliance=1.7
+project@com.oracle.graal.hotspot@workingSets=Graal,HotSpot
 
 # graal.hotspot.amd64
 project@com.oracle.graal.hotspot.amd64@subDir=graal
@@ -109,6 +120,7 @@
 project@com.oracle.graal.hotspot.amd64@dependencies=com.oracle.graal.hotspot,com.oracle.graal.compiler.amd64,com.oracle.graal.replacements.amd64
 project@com.oracle.graal.hotspot.amd64@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.amd64@javaCompliance=1.7
+project@com.oracle.graal.hotspot.amd64@workingSets=Graal,HotSpot,AMD64
 
 # graal.hotspot.sparc
 project@com.oracle.graal.hotspot.sparc@subDir=graal
@@ -116,6 +128,7 @@
 project@com.oracle.graal.hotspot.sparc@dependencies=com.oracle.graal.compiler.sparc
 project@com.oracle.graal.hotspot.sparc@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.sparc@javaCompliance=1.7
+project@com.oracle.graal.hotspot.sparc@workingSets=Graal,HotSpot,SPARC
 
 # graal.hotspot.server
 project@com.oracle.graal.hotspot.server@subDir=graal
@@ -123,6 +136,7 @@
 project@com.oracle.graal.hotspot.server@dependencies=com.oracle.graal.hotspot
 project@com.oracle.graal.hotspot.server@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.server@javaCompliance=1.7
+project@com.oracle.graal.hotspot.server@workingSets=Graal,HotSpot
 
 # graal.hotspot.test
 project@com.oracle.graal.hotspot.test@subDir=graal
@@ -130,6 +144,7 @@
 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
+project@com.oracle.graal.hotspot.test@workingSets=Graal,HotSpot,Test
 
 # graal.hotspot.amd64.test
 project@com.oracle.graal.hotspot.amd64.test@subDir=graal
@@ -137,18 +152,22 @@
 project@com.oracle.graal.hotspot.amd64.test@dependencies=com.oracle.graal.asm.amd64,com.oracle.graal.compiler.test
 project@com.oracle.graal.hotspot.amd64.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.amd64.test@javaCompliance=1.7
+project@com.oracle.graal.hotspot.amd64.test@workingSets=Graal,HotSpot,AMD64,Test
 
 # graal.options
 project@com.oracle.graal.options@subDir=graal
 project@com.oracle.graal.options@sourceDirs=src
 project@com.oracle.graal.options@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.options@javaCompliance=1.7
+project@com.oracle.graal.options@annotationProcessorForDependents=true
+project@com.oracle.graal.options@workingSets=Graal,Codegen
 
 # graal.graph
 project@com.oracle.graal.graph@subDir=graal
 project@com.oracle.graal.graph@sourceDirs=src
 project@com.oracle.graal.graph@dependencies=
 project@com.oracle.graal.graph@javaCompliance=1.7
+project@com.oracle.graal.graph@workingSets=Graal,Graph
 
 # graal.graph.test
 project@com.oracle.graal.graph.test@subDir=graal
@@ -156,12 +175,14 @@
 project@com.oracle.graal.graph.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.graph.test@dependencies=JUNIT,com.oracle.graal.graph
 project@com.oracle.graal.graph.test@javaCompliance=1.7
+project@com.oracle.graal.graph.test@workingSets=Graal,Graph,Test
 
 # graal.debug
 project@com.oracle.graal.debug@subDir=graal
 project@com.oracle.graal.debug@sourceDirs=src
 project@com.oracle.graal.debug@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.debug@javaCompliance=1.7
+project@com.oracle.graal.debug@workingSets=Graal,Debug
 
 # graal.debug.test
 project@com.oracle.graal.debug.test@subDir=graal
@@ -169,6 +190,7 @@
 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
+project@com.oracle.graal.debug.test@workingSets=Graal,Debug,Test
 
 # graal.lir
 project@com.oracle.graal.lir@subDir=graal
@@ -176,6 +198,7 @@
 project@com.oracle.graal.lir@dependencies=com.oracle.graal.asm,com.oracle.graal.nodes
 project@com.oracle.graal.lir@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.lir@javaCompliance=1.7
+project@com.oracle.graal.lir@workingSets=Graal,LIR
 
 # graal.lir.amd64
 project@com.oracle.graal.lir.amd64@subDir=graal
@@ -183,6 +206,7 @@
 project@com.oracle.graal.lir.amd64@dependencies=com.oracle.graal.lir,com.oracle.graal.asm.amd64
 project@com.oracle.graal.lir.amd64@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.lir.amd64@javaCompliance=1.7
+project@com.oracle.graal.lir.amd64@workingSets=Graal,LIR,AMD64
 
 # graal.lir.ptx
 project@com.oracle.graal.lir.ptx@subDir=graal
@@ -190,6 +214,7 @@
 project@com.oracle.graal.lir.ptx@dependencies=com.oracle.graal.asm.ptx,com.oracle.graal.lir
 project@com.oracle.graal.lir.ptx@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.lir.ptx@javaCompliance=1.7
+project@com.oracle.graal.lir.ptx@workingSets=Graal,LIR,PTX
 
 # graal.lir.sparc
 project@com.oracle.graal.lir.sparc@subDir=graal
@@ -197,6 +222,7 @@
 project@com.oracle.graal.lir.sparc@dependencies=com.oracle.graal.asm.sparc
 project@com.oracle.graal.lir.sparc@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.lir.sparc@javaCompliance=1.7
+project@com.oracle.graal.lir.sparc@workingSets=Graal,LIR,SPARC
 
 # graal.alloc
 project@com.oracle.graal.alloc@subDir=graal
@@ -204,6 +230,7 @@
 project@com.oracle.graal.alloc@dependencies=com.oracle.graal.nodes
 project@com.oracle.graal.alloc@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.alloc@javaCompliance=1.7
+project@com.oracle.graal.alloc@workingSets=Graal
 
 # graal.word
 project@com.oracle.graal.word@subDir=graal
@@ -211,6 +238,7 @@
 project@com.oracle.graal.word@dependencies=com.oracle.graal.phases
 project@com.oracle.graal.word@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.word@javaCompliance=1.7
+project@com.oracle.graal.word@workingSets=API,Graal
 
 # graal.replacements
 project@com.oracle.graal.replacements@subDir=graal
@@ -219,6 +247,7 @@
 project@com.oracle.graal.replacements@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.replacements@javaCompliance=1.7
 project@com.oracle.graal.replacements@annotationProcessors=com.oracle.graal.replacements.verifier,com.oracle.graal.service.processor
+project@com.oracle.graal.replacements@workingSets=Graal,Replacements
 
 # graal.replacements.amd64
 project@com.oracle.graal.replacements.amd64@subDir=graal
@@ -226,6 +255,7 @@
 project@com.oracle.graal.replacements.amd64@dependencies=com.oracle.graal.replacements
 project@com.oracle.graal.replacements.amd64@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.replacements.amd64@javaCompliance=1.7
+project@com.oracle.graal.replacements.amd64@workingSets=Graal,Replacements,AMD64
 
 # graal.replacements.test
 project@com.oracle.graal.replacements.test@subDir=graal
@@ -233,6 +263,7 @@
 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
+project@com.oracle.graal.replacements.test@workingSets=Graal,Replacements,Test
 
 # graal.replacements.verifier
 project@com.oracle.graal.replacements.verifier@subDir=graal
@@ -240,6 +271,7 @@
 project@com.oracle.graal.replacements.verifier@dependencies=com.oracle.graal.api.replacements
 project@com.oracle.graal.replacements.verifier@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.replacements.verifier@javaCompliance=1.7
+project@com.oracle.graal.replacements.verifier@workingSets=Graal,Replacements
 
 # graal.nodes
 project@com.oracle.graal.nodes@subDir=graal
@@ -247,13 +279,15 @@
 project@com.oracle.graal.nodes@dependencies=com.oracle.graal.api.code,com.oracle.graal.graph,com.oracle.graal.debug,com.oracle.graal.api.replacements
 project@com.oracle.graal.nodes@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.nodes@javaCompliance=1.7
+project@com.oracle.graal.nodes@workingSets=Graal,Graph
 
 # graal.phases
 project@com.oracle.graal.phases@subDir=graal
 project@com.oracle.graal.phases@sourceDirs=src
-project@com.oracle.graal.phases@dependencies=com.oracle.graal.nodes
+project@com.oracle.graal.phases@dependencies=com.oracle.graal.nodes,com.oracle.graal.options
 project@com.oracle.graal.phases@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.phases@javaCompliance=1.7
+project@com.oracle.graal.phases@workingSets=Graal,Phases
 
 # graal.phases.common
 project@com.oracle.graal.phases.common@subDir=graal
@@ -261,6 +295,7 @@
 project@com.oracle.graal.phases.common@dependencies=com.oracle.graal.phases
 project@com.oracle.graal.phases.common@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.phases.common@javaCompliance=1.7
+project@com.oracle.graal.phases.common@workingSets=Graal,Phases
 
 # graal.virtual
 project@com.oracle.graal.virtual@subDir=graal
@@ -268,6 +303,7 @@
 project@com.oracle.graal.virtual@dependencies=com.oracle.graal.phases.common
 project@com.oracle.graal.virtual@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.virtual@javaCompliance=1.7
+project@com.oracle.graal.virtual@workingSets=Graal,Phases
 
 # graal.loop
 project@com.oracle.graal.loop@subDir=graal
@@ -275,14 +311,16 @@
 project@com.oracle.graal.loop@dependencies=com.oracle.graal.phases.common
 project@com.oracle.graal.loop@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.loop@javaCompliance=1.7
+project@com.oracle.graal.loop@workingSets=Graal,Phases
 
 # graal.compiler
 project@com.oracle.graal.compiler@subDir=graal
 project@com.oracle.graal.compiler@sourceDirs=src
-project@com.oracle.graal.compiler@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.virtual,com.oracle.graal.options,com.oracle.graal.loop,com.oracle.graal.alloc,com.oracle.graal.lir
+project@com.oracle.graal.compiler@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.virtual,com.oracle.graal.loop,com.oracle.graal.alloc,com.oracle.graal.lir
 project@com.oracle.graal.compiler@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler@javaCompliance=1.7
-project@com.oracle.graal.compiler@annotationProcessors=com.oracle.graal.service.processor,com.oracle.graal.options
+project@com.oracle.graal.compiler@annotationProcessors=com.oracle.graal.service.processor
+project@com.oracle.graal.compiler@workingSets=Graal
 
 # graal.compiler.amd64
 project@com.oracle.graal.compiler.amd64@subDir=graal
@@ -290,6 +328,7 @@
 project@com.oracle.graal.compiler.amd64@dependencies=com.oracle.graal.compiler,com.oracle.graal.lir.amd64
 project@com.oracle.graal.compiler.amd64@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler.amd64@javaCompliance=1.7
+project@com.oracle.graal.compiler.amd64@workingSets=Graal,AMD64
 
 # graal.compiler.amd64.test
 project@com.oracle.graal.compiler.amd64.test@subDir=graal
@@ -297,6 +336,7 @@
 project@com.oracle.graal.compiler.amd64.test@dependencies=com.oracle.graal.compiler.test
 project@com.oracle.graal.compiler.amd64.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler.amd64.test@javaCompliance=1.7
+project@com.oracle.graal.compiler.amd64.test@workingSets=Graal,AMD64,Test
 
 # graal.compiler.ptx
 project@com.oracle.graal.compiler.ptx@subDir=graal
@@ -304,6 +344,7 @@
 project@com.oracle.graal.compiler.ptx@dependencies=com.oracle.graal.lir.ptx,com.oracle.graal.hotspot
 project@com.oracle.graal.compiler.ptx@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler.ptx@javaCompliance=1.7
+project@com.oracle.graal.compiler.ptx@workingSets=Graal,PTX
 
 # graal.compiler.ptx.test
 project@com.oracle.graal.compiler.ptx.test@subDir=graal
@@ -311,6 +352,7 @@
 project@com.oracle.graal.compiler.ptx.test@dependencies=com.oracle.graal.compiler.ptx,com.oracle.graal.compiler.test,com.oracle.graal.ptx
 project@com.oracle.graal.compiler.ptx.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler.ptx.test@javaCompliance=1.7
+project@com.oracle.graal.compiler.ptx.test@workingSets=Graal,PTX,Test
 
 # graal.compiler.sparc
 project@com.oracle.graal.compiler.sparc@subDir=graal
@@ -318,6 +360,7 @@
 project@com.oracle.graal.compiler.sparc@dependencies=com.oracle.graal.lir.sparc
 project@com.oracle.graal.compiler.sparc@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler.sparc@javaCompliance=1.7
+project@com.oracle.graal.compiler.sparc@workingSets=Graal,SPARC
 
 # graal.compiler.sparc.test
 project@com.oracle.graal.compiler.sparc.test@subDir=graal
@@ -325,12 +368,14 @@
 project@com.oracle.graal.compiler.sparc.test@dependencies=com.oracle.graal.compiler.sparc,com.oracle.graal.compiler.test
 project@com.oracle.graal.compiler.sparc.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler.sparc.test@javaCompliance=1.7
+project@com.oracle.graal.compiler.sparc.test@workingSets=Graal,SPARC,Test
 
 # graal.bytecode
 project@com.oracle.graal.bytecode@subDir=graal
 project@com.oracle.graal.bytecode@sourceDirs=src
 project@com.oracle.graal.bytecode@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.bytecode@javaCompliance=1.7
+project@com.oracle.graal.bytecode@workingSets=Graal,Java
 
 # graal.java
 project@com.oracle.graal.java@subDir=graal
@@ -338,6 +383,7 @@
 project@com.oracle.graal.java@dependencies=com.oracle.graal.phases,com.oracle.graal.bytecode
 project@com.oracle.graal.java@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.java@javaCompliance=1.7
+project@com.oracle.graal.java@workingSets=Graal,Java
 
 # graal.printer
 project@com.oracle.graal.printer@subDir=graal
@@ -345,6 +391,7 @@
 project@com.oracle.graal.printer@dependencies=com.oracle.graal.java,com.oracle.graal.compiler
 project@com.oracle.graal.printer@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.printer@javaCompliance=1.7
+project@com.oracle.graal.printer@workingSets=Graal,Graph
 
 # graal.test
 project@com.oracle.graal.test@subDir=graal
@@ -352,6 +399,7 @@
 project@com.oracle.graal.test@dependencies=JUNIT
 project@com.oracle.graal.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.test@javaCompliance=1.7
+project@com.oracle.graal.test@workingSets=Graal,Test
 
 # graal.compiler.test
 project@com.oracle.graal.compiler.test@subDir=graal
@@ -359,6 +407,7 @@
 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
+project@com.oracle.graal.compiler.test@workingSets=Graal,Test
 
 # graal.jtt
 project@com.oracle.graal.jtt@subDir=graal
@@ -366,6 +415,7 @@
 project@com.oracle.graal.jtt@dependencies=com.oracle.graal.compiler.test
 project@com.oracle.graal.jtt@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.jtt@javaCompliance=1.7
+project@com.oracle.graal.jtt@workingSets=Graal,Test
 
 # graal.asm
 project@com.oracle.graal.asm@subDir=graal
@@ -373,6 +423,7 @@
 project@com.oracle.graal.asm@dependencies=com.oracle.graal.api.code
 project@com.oracle.graal.asm@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.asm@javaCompliance=1.7
+project@com.oracle.graal.asm@workingSets=Graal,Assembler
 
 # graal.asm.test
 project@com.oracle.graal.asm.test@subDir=graal
@@ -380,6 +431,7 @@
 project@com.oracle.graal.asm.test@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.test,com.oracle.graal.asm
 project@com.oracle.graal.asm.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.asm.test@javaCompliance=1.7
+project@com.oracle.graal.asm.test@workingSets=Graal,Assembler,Test
 
 # graal.asm.amd64
 project@com.oracle.graal.asm.amd64@subDir=graal
@@ -387,6 +439,7 @@
 project@com.oracle.graal.asm.amd64@dependencies=com.oracle.graal.asm,com.oracle.graal.amd64
 project@com.oracle.graal.asm.amd64@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.asm.amd64@javaCompliance=1.7
+project@com.oracle.graal.asm.amd64@workingSets=Graal,Assembler,AMD64
 
 # graal.asm.amd64.test
 project@com.oracle.graal.asm.amd64.test@subDir=graal
@@ -394,6 +447,7 @@
 project@com.oracle.graal.asm.amd64.test@dependencies=com.oracle.graal.asm.test,com.oracle.graal.asm.amd64
 project@com.oracle.graal.asm.amd64.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.asm.amd64.test@javaCompliance=1.7
+project@com.oracle.graal.asm.amd64.test@workingSets=Graal,Assembler,AMD64,Test
 
 # graal.asm.ptx
 project@com.oracle.graal.asm.ptx@subDir=graal
@@ -401,6 +455,7 @@
 project@com.oracle.graal.asm.ptx@dependencies=com.oracle.graal.asm
 project@com.oracle.graal.asm.ptx@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.asm.ptx@javaCompliance=1.7
+project@com.oracle.graal.asm.ptx@workingSets=Graal,Assembler,PTX
 
 # graal.asm.sparc
 project@com.oracle.graal.asm.sparc@subDir=graal
@@ -408,6 +463,7 @@
 project@com.oracle.graal.asm.sparc@dependencies=com.oracle.graal.hotspot,com.oracle.graal.sparc
 project@com.oracle.graal.asm.sparc@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.asm.sparc@javaCompliance=1.7
+project@com.oracle.graal.asm.sparc@workingSets=Graal,Assembler,SPARC
 
 # truffle.api
 project@com.oracle.truffle.api@subDir=graal
@@ -415,6 +471,7 @@
 project@com.oracle.truffle.api@dependencies=
 project@com.oracle.truffle.api@checkstyle=com.oracle.graal.graph
 project@com.oracle.truffle.api@javaCompliance=1.7
+project@com.oracle.truffle.api@workingSets=API,Truffle
 
 # truffle.api.test
 project@com.oracle.truffle.api.test@subDir=graal
@@ -422,6 +479,7 @@
 project@com.oracle.truffle.api.test@dependencies=com.oracle.truffle.api,JUNIT
 project@com.oracle.truffle.api.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.truffle.api.test@javaCompliance=1.7
+project@com.oracle.truffle.api.test@workingSets=API,Truffle,Test
 
 # truffle.api.codegen
 project@com.oracle.truffle.api.codegen@subDir=graal
@@ -429,6 +487,7 @@
 project@com.oracle.truffle.api.codegen@dependencies=com.oracle.truffle.api
 project@com.oracle.truffle.api.codegen@checkstyle=com.oracle.graal.graph
 project@com.oracle.truffle.api.codegen@javaCompliance=1.7
+project@com.oracle.truffle.api.codegen@workingSets=API,Truffle,Codegen
 
 # truffle.api.codegen.test
 project@com.oracle.truffle.api.codegen.test@subDir=graal
@@ -437,6 +496,7 @@
 project@com.oracle.truffle.api.codegen.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.truffle.api.codegen.test@javaCompliance=1.7
 project@com.oracle.truffle.api.codegen.test@annotationProcessors=com.oracle.truffle.codegen.processor
+project@com.oracle.truffle.api.codegen.test@workingSets=API,Truffle,Codegen,Test
 
 # truffle.codegen.processor
 project@com.oracle.truffle.codegen.processor@subDir=graal
@@ -444,6 +504,7 @@
 project@com.oracle.truffle.codegen.processor@dependencies=com.oracle.truffle.api.codegen
 project@com.oracle.truffle.codegen.processor@checkstyle=com.oracle.graal.graph
 project@com.oracle.truffle.codegen.processor@javaCompliance=1.7
+project@com.oracle.truffle.codegen.processor@workingSets=Truffle,Codegen
 
 # truffle.sl
 project@com.oracle.truffle.sl@subDir=graal
@@ -452,6 +513,7 @@
 project@com.oracle.truffle.sl@checkstyle=com.oracle.graal.graph
 project@com.oracle.truffle.sl@javaCompliance=1.7
 project@com.oracle.truffle.sl@annotationProcessors=com.oracle.truffle.codegen.processor
+project@com.oracle.truffle.sl@workingSets=Truffle,SimpleLanguage
 
 # truffle.sl.test
 project@com.oracle.truffle.sl.test@subDir=graal
@@ -459,6 +521,7 @@
 project@com.oracle.truffle.sl.test@dependencies=com.oracle.truffle.sl,JUNIT
 project@com.oracle.truffle.sl.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.truffle.sl.test@javaCompliance=1.7
+project@com.oracle.truffle.sl.test@workingSets=Truffle,SimpleLanguage,Test
 
 
 
--- a/mxtool/mx.py	Tue Jun 18 10:11:28 2013 +0200
+++ b/mxtool/mx.py	Tue Jun 18 10:12:27 2013 +0200
@@ -125,6 +125,11 @@
     javaCompliance
         The minimum JDK version (format: x.y) to which the project's
         sources comply (required for non-native projects).
+    
+    workingSets
+        A comma separated list of working set names. The project belongs
+        to the given working sets, for which the eclipseinit command
+        will generate Eclipse configurations.
 
 Other properties can be specified for projects and libraries for use
 by extension commands.
@@ -146,6 +151,7 @@
 _libs = dict()
 _dists = dict()
 _suites = dict()
+_annotationProcessors = None
 _mainSuite = None
 _opts = None
 _java = None
@@ -197,13 +203,14 @@
         return isinstance(self, Library)
 
 class Project(Dependency):
-    def __init__(self, suite, name, srcDirs, deps, javaCompliance, d):
+    def __init__(self, suite, name, srcDirs, deps, javaCompliance, workingSets, d):
         Dependency.__init__(self, suite, name)
         self.srcDirs = srcDirs
         self.deps = deps
         self.checkstyleProj = name
         self.javaCompliance = JavaCompliance(javaCompliance) if javaCompliance is not None else None
         self.native = False
+        self.workingSets = workingSets
         self.dir = d
         
         # Create directories for projects that don't yet exist
@@ -219,8 +226,8 @@
         libraries if 'includeLibs' is true, to the 'deps' list.
         """
         childDeps = list(self.deps)
-        if includeAnnotationProcessors and hasattr(self, 'annotationProcessors') and len(self.annotationProcessors) > 0:
-            childDeps = self.annotationProcessors + childDeps
+        if includeAnnotationProcessors and len(self.annotation_processors()) > 0:
+            childDeps = self.annotation_processors() + childDeps
         if self in deps:
             return deps
         for name in childDeps:
@@ -408,6 +415,19 @@
         self._init_packages_and_imports()
         return self._imported_java_packages
 
+    def annotation_processors(self):
+        if not hasattr(self, '_annotationProcessors'):
+            ap = set()
+            if hasattr(self, '_declaredAnnotationProcessors'):
+                ap = set(self._declaredAnnotationProcessors)
+
+            # find dependencies that auto-inject themselves as annotation processors to all dependents                
+            allDeps = self.all_deps([], includeLibs=False, includeSelf=False, includeAnnotationProcessors=False)
+            for p in allDeps:
+                if hasattr(p, 'annotationProcessorForDependents') and p.annotationProcessorForDependents.lower() == 'true':
+                    ap.add(p.name)
+            self._annotationProcessors = list(ap)
+        return self._annotationProcessors
 
 class Library(Dependency):
     def __init__(self, suite, name, path, mustExist, urls, sourcePath, sourceUrls):
@@ -516,18 +536,19 @@
             ap = pop_list(attrs, 'annotationProcessors')
             #deps += ap
             javaCompliance = attrs.pop('javaCompliance', None)
-            subDir = attrs.pop('subDir', None);
+            subDir = attrs.pop('subDir', None)
             if subDir is None:
                 d = join(self.dir, name)
             else:
                 d = join(self.dir, subDir, name)
-            p = Project(self, name, srcDirs, deps, javaCompliance, d)
+            workingSets = attrs.pop('workingSets', None)
+            p = Project(self, name, srcDirs, deps, javaCompliance, workingSets, d)
             p.checkstyleProj = attrs.pop('checkstyle', name)
             p.native = attrs.pop('native', '') == 'true'
             if not p.native and p.javaCompliance is None:
                 abort('javaCompliance property required for non-native project ' + name)
             if len(ap) > 0:
-                p.annotationProcessors = ap
+                p._declaredAnnotationProcessors = ap
             p.__dict__.update(attrs)
             self.projects.append(p)
 
@@ -594,7 +615,6 @@
     def _post_init(self, opts):
         mxDir = join(self.dir, 'mx')
         self._load_projects(mxDir)
-        _suites[self.name] = self
         for p in self.projects:
             existing = _projects.get(p.name)
             if existing is not None:
@@ -705,10 +725,10 @@
     mxDir = join(d, 'mx')
     if not exists(mxDir) or not isdir(mxDir):
         return None
-    if not _suites.has_key(d):
-        suite = Suite(d, primary)
-        _suites[d] = suite
-        return suite
+    if len([s for s in _suites.itervalues() if s.dir == d]) == 0:
+        s = Suite(d, primary)
+        _suites[s.name] = s
+        return s
 
 def suites():
     """
@@ -731,6 +751,18 @@
     """
     return _projects.values()
 
+def annotation_processors():
+    """
+    Get the list of all loaded projects that define an annotation processor.
+    """
+    global _annotationProcessors
+    if _annotationProcessors is None:
+        ap = set()
+        for p in projects():
+            ap.update(p.annotation_processors())
+        _annotationProcessors = list(ap)
+    return _annotationProcessors
+
 def distribution(name, fatalIfMissing=True):
     """
     Get the distribution for a given name. This will abort if the named distribution does
@@ -1424,7 +1456,6 @@
             log('Excluding {0} from build (Java compliance level {1} required)'.format(p.name, p.javaCompliance))
             continue
 
-
         outputDir = p.output_dir()
         if exists(outputDir):
             if args.clean:
@@ -1515,8 +1546,9 @@
         if java().debug_port is not None:
             javacArgs += ['-J-Xdebug', '-J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(java().debug_port)]
 
-        if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0:
-            processorPath = classpath(p.annotationProcessors, resolve=True)
+        ap = p.annotation_processors()
+        if len(ap) > 0:
+            processorPath = classpath(ap, resolve=True)
             genDir = p.source_gen_dir();
             if exists(genDir):
                 shutil.rmtree(genDir)
@@ -1672,16 +1704,16 @@
     return 0
 
 def processorjars():
-    projects = set()
     
+    projs = set()
     for p in sorted_deps():
         if _isAnnotationProcessorDependency(p):
-            projects.add(p)
+            projs.add(p)
             
-    if len(projects) <= 0:
+    if len(projs) < 0:
         return
     
-    pnames = [p.name for p in projects]
+    pnames = [p.name for p in projs]
     build(['--projects', ",".join(pnames)])
     archive(pnames)
 
@@ -1823,6 +1855,12 @@
    Run Checkstyle over the Java sources. Any errors or warnings
    produced by Checkstyle result in a non-zero exit code."""
 
+    parser = ArgumentParser(prog='mx checkstyle')
+
+    parser.add_argument('-f', action='store_true', dest='force', help='force checking (disables timestamp checking)')
+    args = parser.parse_args(args)
+    
+    totalErrors = 0
     for p in sorted_deps():
         if p.native:
             continue
@@ -1831,6 +1869,11 @@
 
         if not exists(dotCheckstyle):
             continue
+        
+        # skip checking this Java project if its Java compliance level is "higher" than the configured JDK
+        if java().javaCompliance < p.javaCompliance:
+            log('Excluding {0} from checking (Java compliance level {1} required)'.format(p.name, p.javaCompliance))
+            continue
 
         for sourceDir in sourceDirs:
             javafilelist = []
@@ -1844,7 +1887,7 @@
             if not exists(dirname(timestampFile)):
                 os.makedirs(dirname(timestampFile))
             mustCheck = False
-            if exists(timestampFile):
+            if not args.force and exists(timestampFile):
                 timestamp = os.path.getmtime(timestampFile)
                 for f in javafilelist:
                     if os.path.getmtime(f) > timestamp:
@@ -1854,7 +1897,8 @@
                 mustCheck = True
 
             if not mustCheck:
-                log('[all Java sources in {0} already checked - skipping]'.format(sourceDir))
+                if _opts.verbose:
+                    log('[all Java sources in {0} already checked - skipping]'.format(sourceDir))
                 continue
 
             dotCheckstyleXML = xml.dom.minidom.parse(dotCheckstyle)
@@ -1914,7 +1958,7 @@
                     batch = javafilelist[:i]
                     javafilelist = javafilelist[i:]
                     try:
-                        run_java(['-Xmx1g', '-jar', library('CHECKSTYLE').get_path(True), '-f', 'xml', '-c', config, '-o', auditfileName] + batch)
+                        run_java(['-Xmx1g', '-jar', library('CHECKSTYLE').get_path(True), '-f', 'xml', '-c', config, '-o', auditfileName] + batch, nonZeroIsFatal=False)
                     finally:
                         if exists(auditfileName):
                             errors = []
@@ -1932,7 +1976,7 @@
                                 p.ParseFile(fp)
                             if len(errors) != 0:
                                 map(log, errors)
-                                return len(errors)
+                                totalErrors = totalErrors + len(errors)
                             else:
                                 if exists(timestampFile):
                                     os.utime(timestampFile, None)
@@ -1941,7 +1985,7 @@
             finally:
                 if exists(auditfileName):
                     os.unlink(auditfileName)
-    return 0
+    return totalErrors
 
 def clean(args, parser=None):
     """remove all class files, images, and executables
@@ -2142,7 +2186,7 @@
     return update_file(join(eclipseLaunches, name + '.launch'), launch)
 
 def eclipseinit(args, suite=None, buildProcessorJars=True):
-    """(re)generate Eclipse project configurations"""
+    """(re)generate Eclipse project configurations and working sets"""
 
     if suite is None:
         suite = _mainSuite
@@ -2172,7 +2216,7 @@
                 os.mkdir(srcDir)
             out.element('classpathentry', {'kind' : 'src', 'path' : src})
 
-        if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0:
+        if len(p.annotation_processors()) > 0:
             genDir = p.source_gen_dir();
             if not exists(genDir):
                 os.mkdir(genDir)
@@ -2296,22 +2340,22 @@
         eclipseSettingsDir = join(suite.dir, 'mx', 'eclipse-settings')
         if exists(eclipseSettingsDir):
             for name in os.listdir(eclipseSettingsDir):
-                if name == "org.eclipse.jdt.apt.core.prefs" and not (hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0):
+                if name == "org.eclipse.jdt.apt.core.prefs" and not len(p.annotation_processors()) > 0:
                     continue
                 path = join(eclipseSettingsDir, name)
                 if isfile(path):
                     with open(join(eclipseSettingsDir, name)) as f:
                         content = f.read()
                     content = content.replace('${javaCompliance}', str(p.javaCompliance))
-                    if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0:
+                    if len(p.annotation_processors()) > 0:
                         content = content.replace('org.eclipse.jdt.core.compiler.processAnnotations=disabled', 'org.eclipse.jdt.core.compiler.processAnnotations=enabled')
                     update_file(join(settingsDir, name), content)
         
-        if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0:
+        if len(p.annotation_processors()) > 0:
             out = XMLDoc()
             out.open('factorypath')
             out.element('factorypathentry', {'kind' : 'PLUGIN', 'id' : 'org.eclipse.jst.ws.annotations.core', 'enabled' : 'true', 'runInBatchMode' : 'false'})
-            for ap in p.annotationProcessors:
+            for ap in p.annotation_processors():
                 apProject = project(ap)
                 for dep in apProject.all_deps([], True):
                     if dep.isLibrary():
@@ -2330,28 +2374,14 @@
             update_file(join(p.dir, '.factorypath'), out.xml(indent='\t', newl='\n'))
 
     make_eclipse_attach('localhost', '8000', deps=projects())
+    generate_eclipse_workingsets(suite)
 
 
 def _isAnnotationProcessorDependency(p):
     """
     Determines if a given project is part of an annotation processor.
     """
-    processors = set()
-    
-    for otherProject in projects():
-        if hasattr(otherProject, 'annotationProcessors') and len(otherProject.annotationProcessors) > 0:
-            for processorName in otherProject.annotationProcessors:
-                processors.add(project(processorName, fatalIfMissing=True))
-                 
-    if p in processors:
-        return True
-    
-    for otherProject in processors:
-        deps = otherProject.all_deps([], True)
-        if p in deps:
-            return True
-    
-    return False
+    return p in sorted_deps(annotation_processors())
 
 def _genEclipseBuilder(dotProjectDoc, p, name, mxCommand, refresh=True, async=False, logToConsole=False, xmlIndent='\t', xmlStandalone=None):
     launchOut = XMLDoc();
@@ -2401,6 +2431,124 @@
     dotProjectDoc.close('dictionary')
     dotProjectDoc.close('arguments')
     dotProjectDoc.close('buildCommand')
+
+def generate_eclipse_workingsets(suite):
+    """
+    Populate the workspace's working set configuration with working sets generated from project data.
+    If the workspace already contains working set definitions, the existing ones will be retained and extended.
+    In case mx/env does not contain a WORKSPACE definition pointing to the workspace root directory, the Graal project root directory will be assumed.
+    If no workspace root directory can be identified, the Graal project root directory is used and the user has to place the workingsets.xml file by hand. 
+    """
+    
+    # identify the location where to look for workingsets.xml
+    wsfilename = 'workingsets.xml'
+    wsroot = suite.dir
+    if os.environ.has_key('WORKSPACE'):
+        wsroot = os.environ['WORKSPACE']
+    wsdir = join(wsroot, '.metadata/.plugins/org.eclipse.ui.workbench')
+    if not exists(wsdir):
+        wsdir = wsroot
+    wspath = join(wsdir, wsfilename)
+    
+    # gather working set info from project data
+    workingSets = dict()
+    for p in projects():
+        if p.workingSets is None:
+            continue
+        for w in p.workingSets.split(","):
+            if not workingSets.has_key(w):
+                workingSets[w] = [p.name]
+            else:
+                workingSets[w].append(p.name)
+    
+    if exists(wspath):
+        wsdoc = _copy_workingset_xml(wspath, workingSets)
+    else:
+        wsdoc = _make_workingset_xml(workingSets)
+    
+    update_file(wspath, wsdoc.xml(newl='\n'))
+
+def _make_workingset_xml(workingSets):
+    wsdoc = XMLDoc()
+    wsdoc.open('workingSetManager')
+    
+    for w in sorted(workingSets.keys()):
+        _workingset_open(wsdoc, w)
+        for p in workingSets[w]:
+            _workingset_element(wsdoc, p)
+        wsdoc.close('workingSet')
+    
+    wsdoc.close('workingSetManager')
+    return wsdoc
+
+def _copy_workingset_xml(wspath, workingSets):
+    target = XMLDoc()
+    target.open('workingSetManager')
+
+    parser = xml.parsers.expat.ParserCreate()
+    
+    class ParserState(object):
+        def __init__(self):
+            self.current_ws_name = 'none yet'
+            self.current_ws = None
+            self.seen_ws = list()
+            self.seen_projects = list()
+    
+    ps = ParserState()
+    
+    # parsing logic
+    def _ws_start(name, attributes):
+        if name == 'workingSet':
+            ps.current_ws_name = attributes['name']
+            if workingSets.has_key(ps.current_ws_name):
+                ps.current_ws = workingSets[ps.current_ws_name]
+                ps.seen_ws.append(ps.current_ws_name)
+                ps.seen_projects = list()
+            else:
+                ps.current_ws = None
+            target.open(name, attributes)
+            parser.StartElementHandler = _ws_item
+    
+    def _ws_end(name):
+        if name == 'workingSet':
+            if not ps.current_ws is None:
+                for p in ps.current_ws:
+                    if not p in ps.seen_projects:
+                        _workingset_element(target, p)
+            target.close('workingSet')
+            parser.StartElementHandler = _ws_start
+        elif name == 'workingSetManager':
+            # process all working sets that are new to the file
+            for w in sorted(workingSets.keys()):
+                if not w in ps.seen_ws:
+                    _workingset_open(target, w)
+                    for p in workingSets[w]:
+                        _workingset_element(target, p)
+                    target.close('workingSet')
+    
+    def _ws_item(name, attributes):
+        if name == 'item':
+            if ps.current_ws is None:
+                target.element(name, attributes)
+            else:
+                p_name = attributes['elementID'][1:] # strip off the leading '='
+                _workingset_element(target, p_name)
+                ps.seen_projects.append(p_name)
+    
+    # process document
+    parser.StartElementHandler = _ws_start
+    parser.EndElementHandler = _ws_end
+    with open(wspath, 'r') as wsfile:
+        parser.ParseFile(wsfile)
+    
+    target.close('workingSetManager')
+    return target
+
+def _workingset_open(wsdoc, ws):
+    wsdoc.open('workingSet', {'editPageID': 'org.eclipse.jdt.ui.JavaWorkingSetPage', 'factoryID': 'org.eclipse.ui.internal.WorkingSetFactory', 'id': 'wsid_' + ws, 'label': ws, 'name': ws})
+
+def _workingset_element(wsdoc, p):
+    wsdoc.element('item', {'elementID': '=' + p, 'factoryID': 'org.eclipse.jdt.ui.PersistableJavaElementFactory'})
     
 def netbeansinit(args, suite=None):
     """(re)generate NetBeans project configurations"""
@@ -2446,7 +2594,7 @@
         out.element('explicit-platform', {'explicit-source-supported' : 'true'})
         out.open('source-roots')
         out.element('root', {'id' : 'src.dir'})
-        if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0:
+        if len(p.annotation_processors()) > 0:
             out.element('root', {'id' : 'src.ap-source-output.dir'})
         out.close('source-roots')
         out.open('test-roots')
@@ -2486,7 +2634,7 @@
         annotationProcessorEnabled = "false"
         annotationProcessorReferences = ""
         annotationProcessorSrcFolder = ""
-        if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0:
+        if len(p.annotation_processors()) > 0:
             annotationProcessorEnabled = "true"
             annotationProcessorSrcFolder = "src.ap-source-output.dir=${build.generated.sources.dir}/ap-source-output"
 
@@ -2578,8 +2726,8 @@
         
         deps = p.all_deps([], True)
         annotationProcessorOnlyDeps = []
-        if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0:
-            for ap in p.annotationProcessors:
+        if len(p.annotation_processors()) > 0:
+            for ap in p.annotation_processors():
                 apProject = project(ap)
                 if not apProject in deps:
                     deps.append(apProject)
@@ -2640,6 +2788,7 @@
         shutil.rmtree(join(p.dir, 'nbproject'), ignore_errors=True)
         rm(join(p.dir, '.classpath'))
         rm(join(p.dir, '.project'))
+        rm(join(p.dir, '.factorypath'))
         rm(join(p.dir, 'build.xml'))
         rm(join(p.dir, 'eclipse-build.xml'))
         try:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/sparc/vm/codeInstaller_sparc.hpp	Tue Jun 18 10:12:27 2013 +0200
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+#ifndef CPU_SPARC_VM_CODEINSTALLER_SPARC_HPP
+#define CPU_SPARC_VM_CODEINSTALLER_SPARC_HPP
+
+inline jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
+  fatal("CodeInstaller::pd_next_offset - sparc unimp");
+  return 0;
+}
+
+inline void CodeInstaller::pd_site_DataPatch(oop constant, oop kind, bool inlined,
+                                             address instruction, int alignment, char typeChar) {
+  fatal("CodeInstaller::pd_site_DataPatch - sparc unimp");
+}
+
+inline void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
+  fatal("CodeInstaller::pd_relocate_CodeBlob - sparc unimp");
+}
+
+inline void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
+  fatal("CodeInstaller::pd_relocate_ForeignCall - sparc unimp");
+}
+
+inline void CodeInstaller::pd_relocate_JavaMethod(oop method, jint pc_offset) {
+  fatal("CodeInstaller::pd_relocate_JavaMethod - sparc unimp");
+}
+
+inline int32_t* CodeInstaller::pd_locate_operand(address instruction) {
+  fatal("CodeInstaller::pd_locate_operand - sparc unimp");
+  return (int32_t*)0;
+}
+
+#endif // CPU_SPARC_VM_CODEINSTALLER_SPARC_HPP
--- a/src/cpu/sparc/vm/graalGlobals_sparc.hpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/cpu/sparc/vm/graalGlobals_sparc.hpp	Tue Jun 18 10:12:27 2013 +0200
@@ -31,6 +31,32 @@
 // Sets the default values for platform dependent flags used by the Graal compiler.
 // (see graalGlobals.hpp)
 
-define_pd_global(intx, GraalSafepointPollOffset,     0    );
+#if !defined(COMPILER1) && !defined(COMPILER2)
+define_pd_global(bool, BackgroundCompilation,        true );
+define_pd_global(bool, UseTLAB,                      true );
+define_pd_global(bool, ResizeTLAB,                   true );
+define_pd_global(bool, InlineIntrinsics,             true );
+define_pd_global(bool, PreferInterpreterNativeStubs, false);
+define_pd_global(bool, TieredCompilation,            false);
+define_pd_global(intx, BackEdgeThreshold,            100000);
+
+define_pd_global(intx, OnStackReplacePercentage,     933  );
+define_pd_global(intx, FreqInlineSize,               325  );
+define_pd_global(intx, NewSizeThreadIncrease,        4*K  );
+define_pd_global(uintx,MetaspaceSize,                12*M );
+define_pd_global(bool, NeverActAsServerClassMachine, false);
+define_pd_global(uint64_t,MaxRAM,                    1ULL*G);
+define_pd_global(bool, CICompileOSR,                 true );
+define_pd_global(bool, ProfileTraps,                 true );
+define_pd_global(bool, UseOnStackReplacement,        true );
+define_pd_global(intx, CompileThreshold,             10000);
+define_pd_global(intx, InitialCodeCacheSize,         16*M );
+define_pd_global(intx, ReservedCodeCacheSize,        64*M );
+define_pd_global(bool, ProfileInterpreter,           true );
+define_pd_global(intx, CodeCacheExpansionSize,       64*K );
+define_pd_global(uintx,CodeCacheMinBlockLength,      4);
+define_pd_global(intx, TypeProfileWidth,             8);
+define_pd_global(intx, MethodProfileWidth,           4);
+#endif
 
 #endif // CPU_SPARC_VM_GRAALGLOBALS_SPARC_HPP
--- a/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp	Tue Jun 18 10:12:27 2013 +0200
@@ -27,11 +27,16 @@
 
  friend class AbstractInterpreterGenerator;
 
+  address generate_deopt_entry_for(TosState state, int step);
+
  private:
 
   address generate_normal_entry(bool synchronized);
   address generate_native_entry(bool synchronized);
-  address generate_abstract_entry(void);
+#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);
   address generate_accessor_entry(void);
--- a/src/cpu/sparc/vm/nativeInst_sparc.cpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/cpu/sparc/vm/nativeInst_sparc.cpp	Tue Jun 18 10:12:27 2013 +0200
@@ -24,6 +24,8 @@
 
 #include "precompiled.hpp"
 #include "asm/macroAssembler.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "code/codeCache.hpp"
 #include "memory/resourceArea.hpp"
 #include "nativeInst_sparc.hpp"
 #include "oops/oop.inline.hpp"
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Tue Jun 18 10:12:27 2013 +0200
@@ -1826,6 +1826,20 @@
   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.
+    __ set(nmethod::verified_entry_point_offset(), O0);
+    __ JMP(O0, 0);
+    __ delayed()->nop();
+    return;
+  }
+#endif
+
   // Now write the args into the outgoing interpreter space
   bool     has_receiver   = false;
   Register receiver_reg   = noreg;
--- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Tue Jun 18 10:12:27 2013 +0200
@@ -213,7 +213,7 @@
 }
 
 
-address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, int step) {
+address InterpreterGenerator::generate_deopt_entry_for(TosState state, int step) {
   address entry = __ pc();
   __ get_constant_pool_cache(LcpoolCache); // load LcpoolCache
   { Label L;
@@ -813,6 +813,19 @@
   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();
+
+  __ stop("graal-sparc unimp");
+
+  return entry_point;
+}
+
+#endif
+
 //
 // Interpreter stub for calling a native method. (asm interpreter)
 // This sets up a somewhat different looking stack for calling the native method
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/x86/vm/codeInstaller_x86.hpp	Tue Jun 18 10:12:27 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.
+ */
+#ifndef CPU_SPARC_VM_CODEINSTALLER_X86_HPP
+#define CPU_SPARC_VM_CODEINSTALLER_X86_HPP
+
+#include "compiler/disassembler.hpp"
+#include "runtime/javaCalls.hpp"
+#include "graal/graalEnv.hpp"
+#include "graal/graalCompiler.hpp"
+#include "graal/graalCodeInstaller.hpp"
+#include "graal/graalJavaAccess.hpp"
+#include "graal/graalCompilerToVM.hpp"
+#include "graal/graalRuntime.hpp"
+#include "asm/register.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "code/vmreg.hpp"
+
+inline jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
+  if (inst->is_call() || inst->is_jump()) {
+    assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size");
+    return (pc_offset + NativeCall::instruction_size);
+  } else if (inst->is_mov_literal64()) {
+    // mov+call instruction pair
+    jint offset = pc_offset + NativeMovConstReg::instruction_size;
+    u_char* call = (u_char*) (_instructions->start() + offset);
+    assert((call[0] == 0x40 || call[0] == 0x41) && call[1] == 0xFF, "expected call with rex/rexb prefix byte");
+    offset += 3; /* prefix byte + opcode byte + modrm byte */
+    return (offset);
+  } else if (inst->is_call_reg()) {
+    // the inlined vtable stub contains a "call register" instruction
+    assert(method != NULL, "only valid for virtual calls");
+    return (pc_offset + ((NativeCallReg *) inst)->next_instruction_offset());
+  } else {
+    fatal("unsupported type of instruction for call site");
+    return 0;
+  }
+}
+
+inline void CodeInstaller::pd_site_DataPatch(oop constant, oop kind, bool inlined,
+                                             address instruction, int alignment, char typeChar) {
+  switch (typeChar) {
+    case 'z':
+    case 'b':
+    case 's':
+    case 'c':
+    case 'i':
+      fatal("int-sized values not expected in DataPatch");
+      break;
+    case 'f':
+    case 'j':
+    case 'd': {
+      if (inlined) {
+        address operand = Assembler::locate_operand(instruction, Assembler::imm_operand);
+        *((jlong*) operand) = Constant::primitive(constant);
+      } else {
+        address operand = Assembler::locate_operand(instruction, Assembler::disp32_operand);
+        address next_instruction = Assembler::locate_next_instruction(instruction);
+        int size = _constants->size();
+        if (alignment > 0) {
+          guarantee(alignment <= _constants->alignment(), "Alignment inside constants section is restricted by alignment of section begin");
+          size = align_size_up(size, alignment);
+        }
+        // we don't care if this is a long/double/etc., the primitive field contains the right bits
+        address dest = _constants->start() + size;
+        _constants->set_end(dest + BytesPerLong);
+        *(jlong*) dest = Constant::primitive(constant);
+
+        long disp = dest - next_instruction;
+        assert(disp == (jint) disp, "disp doesn't fit in 32 bits");
+        *((jint*) operand) = (jint) disp;
+
+        _instructions->relocate(instruction, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand);
+        TRACE_graal_3("relocating (%c) at %p/%p with destination at %p (%d)", typeChar, instruction, operand, dest, size);
+      }
+      break;
+    }
+    case 'a': {
+      address operand = Assembler::locate_operand(instruction, Assembler::imm_operand);
+      Handle obj = Constant::object(constant);
+
+      jobject value = JNIHandles::make_local(obj());
+      *((jobject*) operand) = value;
+      _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
+      TRACE_graal_3("relocating (oop constant) at %p/%p", instruction, operand);
+      break;
+    }
+    default:
+      fatal(err_msg("unexpected Kind (%d) in DataPatch", typeChar));
+      break;
+  }
+}
+
+inline void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
+  if (cb->is_nmethod()) {
+    nmethod* nm = (nmethod*) cb;
+    nativeJump_at((address)inst)->set_jump_destination(nm->verified_entry_point());
+  } else {
+    nativeJump_at((address)inst)->set_jump_destination(cb->code_begin());
+  }
+  _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
+}
+
+inline void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
+  if (inst->is_call()) {
+    // NOTE: for call without a mov, the offset must fit a 32-bit immediate
+    //       see also CompilerToVM.getMaxCallTargetOffset()
+    NativeCall* call = nativeCall_at((address) (inst));
+    call->set_destination((address) foreign_call_destination);
+    _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
+  } else if (inst->is_mov_literal64()) {
+    NativeMovConstReg* mov = nativeMovConstReg_at((address) (inst));
+    mov->set_data((intptr_t) foreign_call_destination);
+    _instructions->relocate(mov->instruction_address(), runtime_call_Relocation::spec(), Assembler::imm_operand);
+  } else {
+    NativeJump* jump = nativeJump_at((address) (inst));
+    jump->set_jump_destination((address) foreign_call_destination);
+    _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
+  }
+  TRACE_graal_3("relocating (foreign call)  at %p", inst);
+}
+
+inline void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) {
+#ifdef ASSERT
+  Method* method = NULL;
+  // we need to check, this might also be an unresolved method
+  if (hotspot_method->is_a(HotSpotResolvedJavaMethod::klass())) {
+    method = getMethodFromHotSpotMethod(hotspot_method);
+  }
+#endif
+  switch (_next_call_type) {
+    case MARK_INLINE_INVOKE:
+      break;
+    case MARK_INVOKEVIRTUAL:
+    case MARK_INVOKEINTERFACE: {
+      assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
+
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_virtual_call_stub());
+      _instructions->relocate(call->instruction_address(),
+                                             virtual_call_Relocation::spec(_invoke_mark_pc),
+                                             Assembler::call32_operand);
+      break;
+    }
+    case MARK_INVOKESTATIC: {
+      assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
+
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_static_call_stub());
+      _instructions->relocate(call->instruction_address(),
+                                             relocInfo::static_call_type, Assembler::call32_operand);
+      break;
+    }
+    case MARK_INVOKESPECIAL: {
+      assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
+      _instructions->relocate(call->instruction_address(),
+                              relocInfo::opt_virtual_call_type, Assembler::call32_operand);
+      break;
+    }
+    default:
+      fatal("invalid _next_call_type value");
+      break;
+  }
+}
+
+inline int32_t* CodeInstaller::pd_locate_operand(address instruction) {
+  return (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand);
+}
+
+#endif // CPU_SPARC_VM_CODEINSTALLER_X86_HPP
+
--- a/src/share/vm/classfile/vmSymbols.hpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Tue Jun 18 10:12:27 2013 +0200
@@ -314,6 +314,7 @@
   template(com_oracle_graal_hotspot_meta_HotSpotMonitorValue,        "com/oracle/graal/hotspot/meta/HotSpotMonitorValue")             \
   template(com_oracle_graal_hotspot_debug_LocalImpl,                 "com/oracle/graal/hotspot/debug/LocalImpl")                      \
   AMD64_ONLY(template(com_oracle_graal_hotspot_amd64_AMD64HotSpotGraalRuntime,"com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime"))\
+  SPARC_ONLY(template(com_oracle_graal_hotspot_sparc_SPARCHotSpotGraalRuntime,"com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime"))\
   /* graal.api.meta */                                                                                                                \
   template(com_oracle_graal_api_meta_Constant,                       "com/oracle/graal/api/meta/Constant")                            \
   template(com_oracle_graal_api_meta_ConstantPool,                   "com/oracle/graal/api/meta/ConstantPool")                        \
@@ -351,7 +352,7 @@
   template(bootstrap_name,                        "bootstrap")                                                                        \
   template(shutdownCompiler_name,                 "shutdownCompiler")                                                                 \
   template(compileMethod_name,                    "compileMethod")                                                                    \
-  template(compileMethod_signature,               "(JLcom/oracle/graal/hotspot/meta/HotSpotResolvedObjectType;IZI)Z")                 \
+  template(compileMethod_signature,               "(JLcom/oracle/graal/hotspot/meta/HotSpotResolvedObjectType;IZI)V")                 \
   template(setOption_name,                        "setOption")                                                                        \
   template(setOption_signature,                   "(Ljava/lang/String;)Z")                                                            \
   template(createUnresolvedJavaMethod_name,       "createUnresolvedJavaMethod")                                                       \
--- a/src/share/vm/code/codeCache.cpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/code/codeCache.cpp	Tue Jun 18 10:12:27 2013 +0200
@@ -303,6 +303,15 @@
   }
 }
 
+#ifdef GRAAL
+void CodeCache::alive_nmethods_do_graal_methods(OopClosure* closure) {
+  assert_locked_or_safepoint(CodeCache_lock);
+  FOR_ALL_ALIVE_NMETHODS(nm) {
+    nm->mark_graal_reference(closure);
+  }
+}
+#endif
+
 int CodeCache::alignment_unit() {
   return (int)_heap->alignment_unit();
 }
--- a/src/share/vm/code/codeCache.hpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/code/codeCache.hpp	Tue Jun 18 10:12:27 2013 +0200
@@ -81,7 +81,12 @@
   static void blobs_do(CodeBlobClosure* f);         // iterates over all CodeBlobs
   static void nmethods_do(void f(nmethod* nm));     // iterates over all nmethods
   static void alive_nmethods_do(void f(nmethod* nm)); // iterates over all alive nmethods
-
+#ifdef GRAAL
+  //Special method iterating and marking all HotSpotNMethods which are weakly referenced by nmethods.
+  //This has to be done since the HotSpotNMethods are only referenced from within the nmethods and the GC
+  //believes they are dead since they are not marked.
+  static void alive_nmethods_do_graal_methods(OopClosure* closure);
+#endif
   // Lookup
   static CodeBlob* find_blob(void* start);
   static nmethod*  find_nmethod(void* start);
--- a/src/share/vm/code/nmethod.cpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/code/nmethod.cpp	Tue Jun 18 10:12:27 2013 +0200
@@ -1861,6 +1861,13 @@
 #endif
 }
 
+#ifdef GRAAL
+void nmethod::mark_graal_reference(OopClosure* f) {
+  if (_graal_installed_code != NULL) {
+    f->do_oop((oop*) &_graal_installed_code);
+  }
+}
+#endif
 
 // Iterate over metadata calling this function.   Used by RedefineClasses
 void nmethod::metadata_do(void f(Metadata*)) {
--- a/src/share/vm/code/nmethod.hpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/code/nmethod.hpp	Tue Jun 18 10:12:27 2013 +0200
@@ -743,6 +743,10 @@
     nm->metadata_do(Metadata::mark_on_stack);
   }
   void metadata_do(void f(Metadata*));
+
+#ifdef GRAAL
+  void mark_graal_reference(OopClosure* f);
+#endif
 };
 
 // Locks an nmethod so its code will not get removed and it will not
--- a/src/share/vm/compiler/compileBroker.cpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/compiler/compileBroker.cpp	Tue Jun 18 10:12:27 2013 +0200
@@ -1123,7 +1123,6 @@
   }
 #ifdef GRAALVM
   if (!JavaThread::current()->is_compiling()) {
-    method->set_queued_for_compilation();
     GraalCompiler::instance()->compile_method(method, osr_bci, is_compile_blocking(method, osr_bci));
   } else {
     // Recursive compile request => ignore.
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Tue Jun 18 10:12:27 2013 +0200
@@ -35,18 +35,23 @@
 #include "code/vmreg.hpp"
 
 #ifdef TARGET_ARCH_x86
+# include "codeInstaller_x86.hpp"
 # include "vmreg_x86.inline.hpp"
 #endif
 #ifdef TARGET_ARCH_sparc
+# include "codeInstaller_sparc.hpp"
 # include "vmreg_sparc.inline.hpp"
 #endif
 #ifdef TARGET_ARCH_zero
+# include "codeInstaller_zero.hpp"
 # include "vmreg_zero.inline.hpp"
 #endif
 #ifdef TARGET_ARCH_arm
+# include "codeInstaller_arm.hpp"
 # include "vmreg_arm.inline.hpp"
 #endif
 #ifdef TARGET_ARCH_ppc
+# include "codeInstaller_ppc.hpp"
 # include "vmreg_ppc.inline.hpp"
 #endif
 
@@ -199,8 +204,16 @@
       }
       return value;
 #else
+#ifdef TARGET_ARCH_sparc
+      ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, as_FloatRegister(number)->as_VMReg()));
+      if (type == T_DOUBLE) {
+        second = value;
+      }
+      return value;
+#else
       ShouldNotReachHere("Platform currently does not support floating point values.");
 #endif
+#endif
     }
   } else if (value->is_a(StackSlot::klass())) {
     if (type == T_DOUBLE) {
@@ -256,7 +269,8 @@
     arrayOop values = (arrayOop) VirtualObject::values(value);
     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);
+      oop object = ((objArrayOop) (values))->obj_at(i);
+      ScopeValue* value = get_hotspot_value(object, 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.
@@ -437,9 +451,8 @@
   memcpy(_instructions->start(), _code->base(T_BYTE), _code_size);
   _instructions->set_end(_instructions->start() + _code_size);
 
-  oop* sites = (oop*) _sites->base(T_OBJECT);
   for (int i = 0; i < _sites->length(); i++) {
-    oop site = sites[i];
+    oop site=((objArrayOop) (_sites))->obj_at(i);
     jint pc_offset = CompilationResult_Site::pcOffset(site);
 
     if (site->is_a(CompilationResult_Call::klass())) {
@@ -469,9 +482,8 @@
 
 #ifndef PRODUCT
   if (_comments != NULL) {
-    oop* comments = (oop*) _comments->base(T_OBJECT);
     for (int i = 0; i < _comments->length(); i++) {
-      oop comment = comments[i];
+      oop comment=((objArrayOop) (_comments))->obj_at(i);
       assert(comment->is_a(HotSpotCompiledCode_Comment::klass()), "cce");
       jint offset = HotSpotCompiledCode_Comment::pcOffset(comment);
       char* text = java_lang_String::as_utf8_string(HotSpotCompiledCode_Comment::text(comment));
@@ -531,9 +543,8 @@
   GrowableArray<intptr_t>* pcos = new GrowableArray<intptr_t> (num_handlers);
 
   if (_exception_handlers != NULL) {
-    oop* exception_handlers = (oop*) _exception_handlers->base(T_OBJECT);
     for (int i = 0; i < _exception_handlers->length(); i++) {
-      oop exc = exception_handlers[i];
+      oop exc=((objArrayOop) (_exception_handlers))->obj_at(i);
       jint pc_offset = CompilationResult_Site::pcOffset(exc);
       jint handler_offset = CompilationResult_ExceptionHandler::handlerPos(exc);
 
@@ -605,8 +616,7 @@
 
   for (jint i = 0; i < values->length(); i++) {
     ScopeValue* second = NULL;
-    oop value = ((oop*) values->base(T_OBJECT))[i];
-
+    oop value=((objArrayOop) (values))->obj_at(i);
     if (i < local_count) {
       ScopeValue* first = get_hotspot_value(value, _total_frame_size, objects, second, _oop_recorder);
       if (second != NULL) {
@@ -625,10 +635,11 @@
     if (second != NULL) {
       i++;
       assert(i < values->length(), "double-slot value not followed by Value.ILLEGAL");
-      assert(((oop*) values->base(T_OBJECT))[i] == Value::ILLEGAL(), "double-slot value not followed by Value.ILLEGAL");
+      assert(((objArrayOop) (values))->obj_at(i) == Value::ILLEGAL(), "double-slot value not followed by Value.ILLEGAL");
     }
   }
 
+
   _debug_recorder->dump_object_pool(objects);
 
   DebugToken* locals_token = _debug_recorder->create_scope_values(locals);
@@ -676,36 +687,15 @@
   assert((hotspot_method ? 1 : 0) + (foreign_call ? 1 : 0) == 1, "Call site needs exactly one type");
 
   NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset);
-  jint next_pc_offset = 0x0;
-  if (inst->is_call() || inst->is_jump()) {
-    assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size");
-    next_pc_offset = pc_offset + NativeCall::instruction_size;
-  } else if (inst->is_mov_literal64()) {
-    // mov+call instruction pair
-    next_pc_offset = pc_offset + NativeMovConstReg::instruction_size;
-    u_char* call = (u_char*) (_instructions->start() + next_pc_offset);
-    assert((call[0] == 0x40 || call[0] == 0x41) && call[1] == 0xFF, "expected call with rex/rexb prefix byte");
-    next_pc_offset += 3; /* prefix byte + opcode byte + modrm byte */
-  } else if (inst->is_call_reg()) {
-    // the inlined vtable stub contains a "call register" instruction
-    assert(hotspot_method != NULL, "only valid for virtual calls");
-    next_pc_offset = pc_offset + ((NativeCallReg *) inst)->next_instruction_offset();
-  } else {
-    fatal("unsupported type of instruction for call site");
-  }
-
+  jint next_pc_offset = CodeInstaller::pd_next_offset(inst, pc_offset, hotspot_method);
+  
   if (target->is_a(SystemDictionary::HotSpotInstalledCode_klass())) {
     assert(inst->is_jump(), "jump expected");
 
     CodeBlob* cb = (CodeBlob*) (address) HotSpotInstalledCode::codeBlob(target);
     assert(cb != NULL, "npe");
-    if (cb->is_nmethod()) {
-      nmethod* nm = (nmethod*) cb;
-      nativeJump_at((address)inst)->set_jump_destination(nm->verified_entry_point());
-    } else {
-      nativeJump_at((address)inst)->set_jump_destination(cb->code_begin());
-    }
-    _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
+    
+    CodeInstaller::pd_relocate_CodeBlob(cb, inst);
 
     return;
   }
@@ -722,65 +712,14 @@
 
   if (foreign_call != NULL) {
     jlong foreign_call_destination = HotSpotForeignCallLinkage::address(foreign_call);
-    if (inst->is_call()) {
-      // NOTE: for call without a mov, the offset must fit a 32-bit immediate
-      //       see also CompilerToVM.getMaxCallTargetOffset()
-      NativeCall* call = nativeCall_at((address) (inst));
-      call->set_destination((address) foreign_call_destination);
-      _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
-    } else if (inst->is_mov_literal64()) {
-      NativeMovConstReg* mov = nativeMovConstReg_at((address) (inst));
-      mov->set_data((intptr_t) foreign_call_destination);
-      _instructions->relocate(mov->instruction_address(), runtime_call_Relocation::spec(), Assembler::imm_operand);
-    } else {
-      NativeJump* jump = nativeJump_at((address) (inst));
-      jump->set_jump_destination((address) foreign_call_destination);
-      _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
-    }
-    TRACE_graal_3("relocating (foreign call)  at %p", inst);
+
+    CodeInstaller::pd_relocate_ForeignCall(inst, foreign_call_destination);
   } else { // method != NULL
     assert(hotspot_method != NULL, "unexpected JavaMethod");
-#ifdef ASSERT
-    Method* method = NULL;
-    // we need to check, this might also be an unresolved method
-    if (hotspot_method->is_a(HotSpotResolvedJavaMethod::klass())) {
-      method = getMethodFromHotSpotMethod(hotspot_method);
-    }
-#endif
     assert(debug_info != NULL, "debug info expected");
 
     TRACE_graal_3("method call");
-    switch (_next_call_type) {
-      case MARK_INLINE_INVOKE:
-        break;
-      case MARK_INVOKEVIRTUAL:
-      case MARK_INVOKEINTERFACE: {
-        assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
-
-        NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
-        call->set_destination(SharedRuntime::get_resolve_virtual_call_stub());
-        _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc), Assembler::call32_operand);
-        break;
-      }
-      case MARK_INVOKESTATIC: {
-        assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
-
-        NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
-        call->set_destination(SharedRuntime::get_resolve_static_call_stub());
-        _instructions->relocate(call->instruction_address(), relocInfo::static_call_type, Assembler::call32_operand);
-        break;
-      }
-      case MARK_INVOKESPECIAL: {
-        assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
-        NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
-        call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
-        _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type, Assembler::call32_operand);
-        break;
-      }
-      default:
-        fatal("invalid _next_call_type value");
-        break;
-    }
+    CodeInstaller::pd_relocate_JavaMethod(hotspot_method, pc_offset);
   }
   _next_call_type = MARK_INVOKE_INVALID;
   if (debug_info != NULL) {
@@ -795,59 +734,15 @@
   oop kind = Constant::kind(constant);
 
   address instruction = _instructions->start() + pc_offset;
-
   char typeChar = Kind::typeChar(kind);
   switch (typeChar) {
-    case 'z':
-    case 'b':
-    case 's':
-    case 'c':
-    case 'i':
-      fatal("int-sized values not expected in DataPatch");
-      break;
     case 'f':
     case 'j':
-    case 'd': {
+    case 'd':
       record_metadata_in_constant(constant, _oop_recorder);
-      if (inlined) {
-        address operand = Assembler::locate_operand(instruction, Assembler::imm_operand);
-        *((jlong*) operand) = Constant::primitive(constant);
-      } else {
-        address operand = Assembler::locate_operand(instruction, Assembler::disp32_operand);
-        address next_instruction = Assembler::locate_next_instruction(instruction);
-        int size = _constants->size();
-        if (alignment > 0) {
-          guarantee(alignment <= _constants->alignment(), "Alignment inside constants section is restricted by alignment of section begin");
-          size = align_size_up(size, alignment);
-        }
-        // we don't care if this is a long/double/etc., the primitive field contains the right bits
-        address dest = _constants->start() + size;
-        _constants->set_end(dest + BytesPerLong);
-        *(jlong*) dest = Constant::primitive(constant);
-
-        long disp = dest - next_instruction;
-        assert(disp == (jint) disp, "disp doesn't fit in 32 bits");
-        *((jint*) operand) = (jint) disp;
-
-        _instructions->relocate(instruction, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand);
-        TRACE_graal_3("relocating (%c) at %p/%p with destination at %p (%d)", typeChar, instruction, operand, dest, size);
-      }
-      break;
-    }
-    case 'a': {
-      address operand = Assembler::locate_operand(instruction, Assembler::imm_operand);
-      Handle obj = Constant::object(constant);
-
-      jobject value = JNIHandles::make_local(obj());
-      *((jobject*) operand) = value;
-      _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
-      TRACE_graal_3("relocating (oop constant) at %p/%p", instruction, operand);
-      break;
-    }
-    default:
-      fatal(err_msg("unexpected Kind (%d) in DataPatch", typeChar));
       break;
   }
+  CodeInstaller::pd_site_DataPatch(constant, kind, inlined, instruction, alignment, typeChar);
 }
 
 void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, oop site) {
@@ -892,7 +787,8 @@
         break;
       case MARK_POLL_NEAR: {
         NativeInstruction* ni = nativeInstruction_at(instruction);
-        int32_t* disp = (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand);
+        int32_t* disp = (int32_t*) pd_locate_operand(instruction);
+        // int32_t* disp = (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand);
         int32_t offset = *disp; // The Java code installed the polling page offset into the disp32 operand
         intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni;
         *disp = (int32_t)new_disp;
@@ -902,7 +798,8 @@
         break;
       case MARK_POLL_RETURN_NEAR: {
         NativeInstruction* ni = nativeInstruction_at(instruction);
-        int32_t* disp = (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand);
+        int32_t* disp = (int32_t*) pd_locate_operand(instruction);
+        // int32_t* disp = (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand);
         int32_t offset = *disp; // The Java code installed the polling page offset into the disp32 operand
         intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni;
         *disp = (int32_t)new_disp;
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Tue Jun 18 10:12:27 2013 +0200
@@ -75,6 +75,13 @@
   Dependencies*             _dependencies;
   ExceptionHandlerTable     _exception_handler_table;
 
+  jint pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method);
+  void pd_site_DataPatch(oop constant, oop kind, bool inlined, address instruction, int alignment, char typeChar);
+  void pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst);
+  void pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination);
+  void pd_relocate_JavaMethod(oop method, jint pc_offset);
+  int32_t* pd_locate_operand(address instruction);
+
 public:
 
   CodeInstaller(Handle& comp_result, GraalEnv::CodeInstallResult& result, CodeBlob*& cb, Handle installed_code, Handle triggered_deoptimizations);
@@ -106,4 +113,20 @@
 
 };
 
+#ifdef TARGET_ARCH_x86
+# include "codeInstaller_x86.hpp"
+#endif
+#ifdef TARGET_ARCH_sparc
+# include "codeInstaller_sparc.hpp"
+#endif
+#ifdef TARGET_ARCH_zero
+# error
+#endif
+#ifdef TARGET_ARCH_arm
+# error
+#endif
+#ifdef TARGET_ARCH_ppc
+# error
+#endif
+
 #endif // SHARE_VM_GRAAL_GRAAL_CODE_INSTALLER_HPP
--- a/src/share/vm/graal/graalCompiler.cpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/graal/graalCompiler.cpp	Tue Jun 18 10:12:27 2013 +0200
@@ -51,7 +51,7 @@
 
   uintptr_t heap_end = (uintptr_t) Universe::heap()->reserved_region().end();
   uintptr_t allocation_end = heap_end + ((uintptr_t)16) * 1024 * 1024 * 1024;
-  guarantee(heap_end < allocation_end, "heap end too close to end of address space (might lead to erroneous TLAB allocations)");
+  AMD64_ONLY(guarantee(heap_end < allocation_end, "heap end too close to end of address space (might lead to erroneous TLAB allocations)"));
   NOT_LP64(error("check TLAB allocation code for address space conflicts"));
 
   _deopted_leaf_graph_count = 0;
@@ -85,6 +85,7 @@
   {
     GRAAL_VM_ENTRY_MARK;
     HandleMark hm;
+    VMToCompiler::initOptions();
     for (int i = 0; i < Arguments::num_graal_args(); ++i) {
       const char* arg = Arguments::graal_args_array()[i];
       Handle option = java_lang_String::create_from_str(arg, THREAD);
@@ -162,9 +163,7 @@
 void GraalCompiler::compile_method(methodHandle method, int entry_bci, jboolean blocking) {
   GRAAL_EXCEPTION_CONTEXT
   if (!_initialized) {
-    method->clear_queued_for_compilation();
-    method->invocation_counter()->reset();
-    method->backedge_counter()->reset();
+    CompilationPolicy::policy()->delay_compilation(method());
     return;
   }
 
@@ -172,12 +171,8 @@
   ResourceMark rm;
   JavaThread::current()->set_is_compiling(true);
   Handle holder = GraalCompiler::createHotSpotResolvedObjectType(method, CHECK);
-  jboolean success = VMToCompiler::compileMethod(method(), holder, entry_bci, blocking, method->graal_priority());
+  VMToCompiler::compileMethod(method(), holder, entry_bci, blocking, method->graal_priority());
   JavaThread::current()->set_is_compiling(false);
-  if (success != JNI_TRUE) {
-    method->clear_queued_for_compilation();
-    CompilationPolicy::policy()->delay_compilation(method());
-  }
 }
 
 // Compilation entry point for methods
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Tue Jun 18 10:12:27 2013 +0200
@@ -591,11 +591,11 @@
 
   for (AllFieldStream fs(k()); !fs.done(); fs.next()) {
     if (!fs.access_flags().is_static()) {
-      Handle type = GraalCompiler::get_JavaTypeFromSignature(fs.signature(), k, Thread::current());
+      Handle type = GraalCompiler::get_JavaTypeFromSignature(fs.signature(), k, THREAD);
       int flags = fs.access_flags().as_int();
       bool internal = fs.access_flags().is_internal();
-      Handle name = java_lang_String::create_from_symbol(fs.name(), Thread::current());
-      Handle field = VMToCompiler::createJavaField(JNIHandles::resolve(klass), name, type, fs.offset(), flags, internal, Thread::current());
+      Handle name = java_lang_String::create_from_symbol(fs.name(), THREAD);
+      Handle field = VMToCompiler::createJavaField(JNIHandles::resolve(klass), name, type, fs.offset(), flags, internal, THREAD);
       fields.append(field());
     }
   }
@@ -603,7 +603,28 @@
   for (int i = 0; i < fields.length(); ++i) {
     field_array->obj_at_put(i, fields.at(i)());
   }
-  return JNIHandles::make_local(field_array());
+  return JNIHandles::make_local(THREAD, field_array());
+C2V_END
+
+C2V_VMENTRY(jobject, getMethods, (JNIEnv *, jobject, jobject klass))
+  ResourceMark rm;
+
+  instanceKlassHandle k(THREAD, java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(klass)));
+  Array<Method*>* methods = k->methods();
+  int methods_length = methods->length();
+
+  // Allocate result
+  objArrayOop r = oopFactory::new_objArray(SystemDictionary::HotSpotResolvedJavaMethod_klass(), methods_length, CHECK_NULL);
+  objArrayHandle result (THREAD, r);
+
+  for (int i = 0; i < methods_length; i++) {
+    methodHandle method(THREAD, methods->at(i));
+    Handle holder = JNIHandles::resolve(klass);
+    oop m = VMToCompiler::createResolvedJavaMethod(holder, method(), THREAD);
+    result->obj_at_put(i, m);
+  }
+
+  return JNIHandles::make_local(THREAD, result());
 C2V_END
 
 C2V_VMENTRY(jlong, getMaxCallTargetOffset, (JNIEnv *env, jobject, jlong addr))
@@ -647,6 +668,7 @@
   set_boolean("cAssertions", DEBUG_ONLY(true) NOT_DEBUG(false));
   set_boolean("verifyOops", VerifyOops);
   set_boolean("ciTime", CITime);
+  set_int("compileThreshold", CompileThreshold);
   set_boolean("compileTheWorld", CompileTheWorld);
   set_int("compileTheWorldStartAt", CompileTheWorldStartAt);
   set_int("compileTheWorldStopAt", CompileTheWorldStopAt);
@@ -658,8 +680,10 @@
   set_boolean("useAESIntrinsics", UseAESIntrinsics);
   set_boolean("useTLAB", UseTLAB);
   set_boolean("useG1GC", UseG1GC);
+#ifdef TARGET_ARCH_x86
   set_int("useSSE", UseSSE);
   set_int("useAVX", UseAVX);
+#endif
   set_int("codeEntryAlignment", CodeEntryAlignment);
   set_int("stackShadowPages", StackShadowPages);
   set_int("hubOffset", oopDesc::klass_offset_in_bytes());
@@ -691,16 +715,20 @@
   set_int("constantPoolHolderOffset", ConstantPool::pool_holder_offset_in_bytes());
   set_int("extraStackEntries", Method::extra_stack_entries());
   set_int("methodAccessFlagsOffset", in_bytes(Method::access_flags_offset()));
+  set_int("methodQueuedForCompilationBit", (int) JVM_ACC_QUEUED);
   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()));
+#ifdef TARGET_ARCH_x86
   set_boolean("isPollingPageFar", Assembler::is_polling_page_far());
+  set_int("runtimeCallStackSize", (jint)frame::arg_reg_save_area_bytes);
+#endif
   set_int("classMirrorOffset", in_bytes(Klass::java_mirror_offset()));
-  set_int("runtimeCallStackSize", (jint)frame::arg_reg_save_area_bytes);
   set_int("klassModifierFlagsOffset", in_bytes(Klass::modifier_flags_offset()));
   set_int("klassAccessFlagsOffset", in_bytes(Klass::access_flags_offset()));
   set_int("klassOffset", java_lang_Class::klass_offset_in_bytes());
+  set_int("arrayKlassOffset", java_lang_Class::array_klass_offset_in_bytes());
   set_int("graalMirrorInClassOffset", java_lang_Class::graal_mirror_offset_in_bytes());
   set_int("klassLayoutHelperOffset", in_bytes(Klass::layout_helper_offset()));
   set_int("klassSuperKlassOffset", in_bytes(Klass::super_offset()));
@@ -742,7 +770,9 @@
   set_int("threadTlabSizeOffset", in_bytes(JavaThread::tlab_size_offset()));
   set_int("threadAllocatedBytesOffset", in_bytes(JavaThread::allocated_bytes_offset()));
   set_int("threadLastJavaSpOffset", in_bytes(JavaThread::last_Java_sp_offset()));
+#ifdef TARGET_ARCH_x86
   set_int("threadLastJavaFpOffset", in_bytes(JavaThread::last_Java_fp_offset()));
+#endif
   set_int("threadLastJavaPcOffset", in_bytes(JavaThread::last_Java_pc_offset()));
   set_int("threadObjectResultOffset", in_bytes(JavaThread::vm_result_offset()));
   set_int("tlabSlowAllocationsOffset", in_bytes(JavaThread::tlab_slow_allocations_offset()));
@@ -796,8 +826,6 @@
   set_address("logPrintfAddress", GraalRuntime::log_printf);
   set_address("vmErrorAddress", GraalRuntime::vm_error);
   set_address("loadAndClearExceptionAddress", GraalRuntime::load_and_clear_exception);
-  set_address("writeBarrierPreAddress", GraalRuntime::write_barrier_pre);
-  set_address("writeBarrierPostAddress", GraalRuntime::write_barrier_post);
   set_address("javaTimeMillisAddress", CAST_FROM_FN_PTR(address, os::javaTimeMillis));
   set_address("javaTimeNanosAddress", CAST_FROM_FN_PTR(address, os::javaTimeNanos));
   set_address("arithmeticSinAddress", CAST_FROM_FN_PTR(address, SharedRuntime::dsin));
@@ -831,6 +859,12 @@
   set_int("vmIntrinsicLinkToSpecial", vmIntrinsics::_linkToSpecial);
   set_int("vmIntrinsicLinkToInterface", vmIntrinsics::_linkToInterface);
 
+  set_boolean("useCompressedOops", UseCompressedOops);
+  set_boolean("useCompressedKlassPointers", UseCompressedKlassPointers);
+  set_address("narrowOopBase", Universe::narrow_oop_base());
+  set_int("narrowOopShift", Universe::narrow_oop_shift());
+  set_int("logMinObjAlignment", LogMinObjAlignmentInBytes);
+
   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);
@@ -907,11 +941,6 @@
   return result;
 C2V_END
 
-C2V_VMENTRY(void, clearQueuedForCompilation, (JNIEnv *jniEnv, jobject, jobject resolvedMethod))
-  methodHandle method = getMethodFromHotSpotMethod(JNIHandles::resolve(resolvedMethod));
-  method->clear_queued_for_compilation();
-C2V_END
-
 C2V_VMENTRY(jobject, getCode, (JNIEnv *jniEnv, jobject,  jlong codeBlob))
   ResourceMark rm;
   HandleMark hm;
@@ -1195,6 +1224,7 @@
   {CC"lookupFieldInPool",             CC"("HS_RESOLVED_TYPE"IB)"FIELD,                                  FN_PTR(lookupFieldInPool)},
   {CC"resolveMethod",                 CC"("HS_RESOLVED_TYPE STRING STRING")"METHOD,                     FN_PTR(resolveMethod)},
   {CC"getInstanceFields",             CC"("HS_RESOLVED_TYPE")["HS_RESOLVED_FIELD,                       FN_PTR(getInstanceFields)},
+  {CC"getMethods",                    CC"("HS_RESOLVED_TYPE")["HS_RESOLVED_METHOD,                      FN_PTR(getMethods)},
   {CC"isTypeInitialized",             CC"("HS_RESOLVED_TYPE")Z",                                        FN_PTR(isTypeInitialized)},
   {CC"hasFinalizableSubclass",        CC"("HS_RESOLVED_TYPE")Z",                                        FN_PTR(hasFinalizableSubclass)},
   {CC"initializeType",                CC"("HS_RESOLVED_TYPE")V",                                        FN_PTR(initializeType)},
@@ -1212,7 +1242,6 @@
   {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)},
--- a/src/share/vm/graal/graalCompilerToVM.hpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.hpp	Tue Jun 18 10:12:27 2013 +0200
@@ -54,7 +54,7 @@
 
   oop next_arg(BasicType expectedType) {
     assert(_index < _args->length(), "out of bounds");
-    oop arg = ((oop*) _args->base(T_OBJECT))[_index++];
+    oop arg=((objArrayOop) (_args))->obj_at(_index++);
     assert(expectedType == T_OBJECT || java_lang_boxing_object::is_instance(arg, expectedType), "arg type mismatch");
     return arg;
   }
--- a/src/share/vm/graal/graalRuntime.cpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/graal/graalRuntime.cpp	Tue Jun 18 10:12:27 2013 +0200
@@ -304,14 +304,6 @@
   }
 JRT_END
 
-JRT_LEAF(void, GraalRuntime::write_barrier_pre(JavaThread* thread, oopDesc* obj))
-    thread->satb_mark_queue().enqueue(obj);
-JRT_END
-
-JRT_LEAF(void, GraalRuntime::write_barrier_post(JavaThread* thread, oopDesc* obj, void* card_addr))
-    thread->dirty_card_queue().enqueue(card_addr);
-JRT_END
-
 JRT_LEAF(void, GraalRuntime::monitorexit(JavaThread* thread, oopDesc* obj, BasicLock* lock))
   assert(thread == JavaThread::current(), "threads must correspond");
   assert(thread->last_Java_sp(), "last_Java_sp must be set");
--- a/src/share/vm/graal/graalRuntime.hpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/graal/graalRuntime.hpp	Tue Jun 18 10:12:27 2013 +0200
@@ -52,8 +52,6 @@
     LOG_OBJECT_ADDRESS = 0x04
   };
   static void log_object(JavaThread* thread, oop msg, jint flags);
-  static void write_barrier_pre(JavaThread* thread, oopDesc* obj);
-  static void write_barrier_post(JavaThread* thread, oopDesc* obj, void* card);
 };
 
 #endif // SHARE_VM_GRAAL_GRAAL_RUNTIME_HPP
--- a/src/share/vm/graal/graalVMToCompiler.cpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/graal/graalVMToCompiler.cpp	Tue Jun 18 10:12:27 2013 +0200
@@ -51,6 +51,9 @@
 #ifdef AMD64
     Symbol* name = vmSymbols::com_oracle_graal_hotspot_amd64_AMD64HotSpotGraalRuntime();
 #endif
+#ifdef SPARC
+    Symbol* name = vmSymbols::com_oracle_graal_hotspot_sparc_SPARCHotSpotGraalRuntime();
+#endif
     KlassHandle klass = loadClass(name);
 
     JavaValue result(T_OBJECT);
@@ -75,6 +78,13 @@
   return Handle(JNIHandles::resolve_non_null(_vmToCompilerPermObject));
 }
 
+void VMToCompiler::initOptions() {
+  KlassHandle compilerKlass = loadClass(vmSymbols::com_oracle_graal_hotspot_HotSpotOptions());
+  Thread* THREAD = Thread::current();
+  compilerKlass->initialize(THREAD);
+  check_pending_exception("Error while calling initOptions");
+}
+
 jboolean VMToCompiler::setOption(Handle option) {
   assert(!option.is_null(), "");
   KlassHandle compilerKlass = loadClass(vmSymbols::com_oracle_graal_hotspot_HotSpotOptions());
@@ -86,11 +96,11 @@
   return result.get_jboolean();
 }
 
-jboolean VMToCompiler::compileMethod(Method* method, Handle holder, int entry_bci, jboolean blocking, int priority) {
+void VMToCompiler::compileMethod(Method* method, Handle holder, int entry_bci, jboolean blocking, int priority) {
   assert(method != NULL, "just checking");
   assert(!holder.is_null(), "just checking");
   Thread* THREAD = Thread::current();
-  JavaValue result(T_BOOLEAN);
+  JavaValue result(T_VOID);
   JavaCallArguments args;
   args.push_oop(instance());
   args.push_long((jlong) (address) method);
@@ -100,7 +110,6 @@
   args.push_int(priority);
   JavaCalls::call_interface(&result, vmToCompilerKlass(), vmSymbols::compileMethod_name(), vmSymbols::compileMethod_signature(), &args, THREAD);
   check_pending_exception("Error while calling compileMethod");
-  return result.get_jboolean();
 }
 
 void VMToCompiler::shutdownCompiler() {
--- a/src/share/vm/graal/graalVMToCompiler.hpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/graal/graalVMToCompiler.hpp	Tue Jun 18 10:12:27 2013 +0200
@@ -50,11 +50,14 @@
     return _graalRuntimePermObject;
   }
 
+  // public static boolean HotSpotOptions.<clinit>();
+  static void initOptions();
+
   // public static boolean HotSpotOptions.setOption(String option);
   static jboolean setOption(Handle option);
 
   // public abstract boolean compileMethod(long vmId, String name, int entry_bci, boolean blocking);
-  static jboolean compileMethod(Method* method, Handle holder, int entry_bci, jboolean blocking, int priority);
+  static void compileMethod(Method* method, Handle holder, int entry_bci, jboolean blocking, int priority);
 
   // public abstract void shutdownCompiler();
   static void shutdownCompiler();
--- a/src/share/vm/memory/referenceProcessor.cpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/memory/referenceProcessor.cpp	Tue Jun 18 10:12:27 2013 +0200
@@ -32,6 +32,10 @@
 #include "oops/oop.inline.hpp"
 #include "runtime/java.hpp"
 #include "runtime/jniHandles.hpp"
+#ifdef GRAAL
+#include "code/codeCache.hpp"
+#include "code/nmethod.hpp"
+#endif
 
 ReferencePolicy* ReferenceProcessor::_always_clear_soft_ref_policy = NULL;
 ReferencePolicy* ReferenceProcessor::_default_soft_ref_policy      = NULL;
@@ -243,6 +247,9 @@
       task_executor->set_single_threaded_mode();
     }
     process_phaseJNI(is_alive, keep_alive, complete_gc);
+#ifdef GRAAL
+    process_phaseGraalNMethods(keep_alive, complete_gc);
+#endif
   }
 }
 
@@ -284,6 +291,14 @@
   complete_gc->do_void();
 }
 
+#ifdef GRAAL
+void ReferenceProcessor::process_phaseGraalNMethods(OopClosure*  keep_alive,
+                                                    VoidClosure* complete_gc) {
+  CodeCache::alive_nmethods_do_graal_methods(keep_alive);
+  complete_gc->do_void();
+}
+
+#endif
 
 template <class T>
 bool enqueue_discovered_ref_helper(ReferenceProcessor* ref,
--- a/src/share/vm/memory/referenceProcessor.hpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/memory/referenceProcessor.hpp	Tue Jun 18 10:12:27 2013 +0200
@@ -293,6 +293,10 @@
   void process_phaseJNI(BoolObjectClosure* is_alive,
                         OopClosure*        keep_alive,
                         VoidClosure*       complete_gc);
+#ifdef GRAAL
+  void process_phaseGraalNMethods(OopClosure*        keep_alive,
+                        VoidClosure*       complete_gc);
+#endif
 
   // Work methods used by the method process_discovered_reflist
   // Phase1: keep alive all those referents that are otherwise
--- a/src/share/vm/oops/klass.hpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/oops/klass.hpp	Tue Jun 18 10:12:27 2013 +0200
@@ -148,10 +148,7 @@
   Klass*      _primary_supers[_primary_super_limit];
   // java/lang/Class instance mirroring this class
   oop       _java_mirror;
-#ifdef GRAAL
-  // com/oracle/graal/hotspot/HotSpotResolvedObjectType mirroring this class
-  oop       _graal_mirror;
-#endif
+
   // Superclass
   Klass*      _super;
   // First subclass (NULL if none); _subklass->next_sibling() is next one
@@ -252,12 +249,6 @@
   oop java_mirror() const              { return _java_mirror; }
   void set_java_mirror(oop m) { klass_oop_store(&_java_mirror, m); }
 
-#ifdef GRAAL
-  // Graal mirror
-  oop graal_mirror() const               { return _graal_mirror; }
-  void set_graal_mirror(oop m)           { oop_store((oop*) &_graal_mirror, m); }
-#endif
-
   // modifier flags
   jint modifier_flags() const          { return _modifier_flags; }
   void set_modifier_flags(jint flags)  { _modifier_flags = flags; }
@@ -317,7 +308,6 @@
   static ByteSize layout_helper_offset()         { return in_ByteSize(offset_of(Klass, _layout_helper)); }
   static ByteSize access_flags_offset()          { return in_ByteSize(offset_of(Klass, _access_flags)); }
 #ifdef GRAAL
-  static ByteSize graal_mirror_offset()          { return in_ByteSize(offset_of(Klass, _graal_mirror)); }
   static ByteSize next_sibling_offset()          { return in_ByteSize(offset_of(Klass, _next_sibling)); }
   static ByteSize subklass_offset()              { return in_ByteSize(offset_of(Klass, _subklass)); }
 #endif
--- a/src/share/vm/prims/unsafe.cpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/prims/unsafe.cpp	Tue Jun 18 10:12:27 2013 +0200
@@ -174,17 +174,29 @@
   OrderAccess::release_store_fence((volatile type_name*)index_oop_from_field_offset_long(p, offset), x);
 
 // Macros for oops that check UseCompressedOops
-
+#ifndef GRAAL
 #define GET_OOP_FIELD(obj, offset, v) \
-  oop p = JNIHandles::resolve(obj);   \
-  oop v;                              \
-  if (UseCompressedOops) {            \
+  oop p = JNIHandles::resolve(obj); \
+  oop v; \
+  if (UseCompressedOops) { \
     narrowOop n = *(narrowOop*)index_oop_from_field_offset_long(p, offset); \
-    v = oopDesc::decode_heap_oop(n);                                \
-  } else {                            \
-    v = *(oop*)index_oop_from_field_offset_long(p, offset);                 \
+    v = oopDesc::decode_heap_oop(n); \
+  } else { \
+    v = *(oop*)index_oop_from_field_offset_long(p, offset); \
   }
-
+#else
+#define GET_OOP_FIELD(obj, offset, v) \
+   oop p = JNIHandles::resolve(obj); \
+   oop v; \
+   /* Uncompression is not performed to unsafeAccess with null object.
+    * This concerns accesses to the metaspace such as the classMirrorOffset which is not compressed.*/ \
+   if (UseCompressedOops && p!=NULL && offset>=oopDesc::header_size()) { \
+     narrowOop n = *(narrowOop*)index_oop_from_field_offset_long(p, offset); \
+     v = oopDesc::decode_heap_oop(n); \
+   } else { \
+     v = *(oop*)index_oop_from_field_offset_long(p, offset); \
+   }
+#endif
 
 // Get/SetObject must be special-cased, since it works with handles.
 
--- a/src/share/vm/runtime/arguments.cpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/runtime/arguments.cpp	Tue Jun 18 10:12:27 2013 +0200
@@ -2102,9 +2102,8 @@
       warning("UseCompressedOops is disabled, because it is not supported by Graal");
       FLAG_SET_CMDLINE(bool, UseCompressedOops, false);
     } else {
-      jio_fprintf(defaultStream::error_stream(),
-                    "CompressedOops are not supported in Graal at the moment\n");
-      status = false;
+      status = true;
+      FLAG_SET_CMDLINE(bool, UseCompressedOops, true);
     }
   } else {
     // This prevents the flag being set to true by set_ergonomics_flags()
--- a/src/share/vm/runtime/compilationPolicy.cpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/runtime/compilationPolicy.cpp	Tue Jun 18 10:12:27 2013 +0200
@@ -422,6 +422,11 @@
 
   if (is_compilation_enabled() && can_be_compiled(m)) {
     nmethod* nm = m->code();
+#ifdef GRAALVM
+    if (m->queued_for_compilation()) {
+      delay_compilation(m());
+    } else
+#endif
     if (nm == NULL ) {
       CompileBroker::compile_method(m, InvocationEntryBci, comp_level, m, hot_count, comment, thread);
     }
--- a/src/share/vm/runtime/fieldDescriptor.cpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/runtime/fieldDescriptor.cpp	Tue Jun 18 10:12:27 2013 +0200
@@ -27,9 +27,6 @@
 #include "classfile/vmSymbols.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.inline.hpp"
-#include "oops/annotations.hpp"
-#include "oops/instanceKlass.hpp"
-#include "oops/fieldStreams.hpp"
 #include "runtime/fieldDescriptor.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/signature.hpp"
--- a/src/share/vm/runtime/fieldDescriptor.hpp	Tue Jun 18 10:11:28 2013 +0200
+++ b/src/share/vm/runtime/fieldDescriptor.hpp	Tue Jun 18 10:12:27 2013 +0200
@@ -25,7 +25,10 @@
 #ifndef SHARE_VM_RUNTIME_FIELDDESCRIPTOR_HPP
 #define SHARE_VM_RUNTIME_FIELDDESCRIPTOR_HPP
 
+#include "oops/annotations.hpp"
 #include "oops/constantPool.hpp"
+#include "oops/fieldStreams.hpp"
+#include "oops/instanceKlass.hpp"
 #include "oops/symbol.hpp"
 #include "runtime/fieldType.hpp"
 #include "utilities/accessFlags.hpp"