changeset 10018:53f090c5975a

Merge.
author Christian Haeubl <haeubl@ssw.jku.at>
date Thu, 13 Jun 2013 09:41:06 +0200
parents 4d9d0cb1520a (current diff) 7709bb831916 (diff)
children 4ebe31e19892 7f2e23d309b3
files
diffstat 28 files changed, 482 insertions(+), 100 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java	Thu Jun 13 09:41:06 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/src/com/oracle/graal/api/meta/JavaTypeProfile.java	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java	Thu Jun 13 09:41:06 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.compiler.sparc.test/src/com/oracle/graal/compiler/sparc/test/BasicSPARCTest.java	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.compiler.sparc.test/src/com/oracle/graal/compiler/sparc/test/BasicSPARCTest.java	Thu Jun 13 09:41:06 2013 +0200
@@ -26,7 +26,6 @@
 
 import org.junit.Test;
 
-
 public class BasicSPARCTest extends SPARCTestBase {
 
     @Test
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu Jun 13 09:41:06 2013 +0200
@@ -141,7 +141,7 @@
             new VerifyUsageWithEquals(runtime, Register.class).apply(graph);
         }
 
-        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(OptCanonicalizeReads.getValue());
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!AOTCompilation.getValue());
         HighTierContext highTierContext = new HighTierContext(runtime, assumptions, replacements);
 
         if (OptCanonicalizer.getValue()) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Thu Jun 13 09:41:06 2013 +0200
@@ -34,10 +34,10 @@
 public class HighTier extends PhaseSuite<HighTierContext> {
 
     public HighTier() {
-        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(OptCanonicalizeReads.getValue());
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!AOTCompilation.getValue());
 
         if (FullUnroll.getValue()) {
-            addPhase(new LoopFullUnrollPhase(OptCanonicalizeReads.getValue()));
+            addPhase(new LoopFullUnrollPhase(!AOTCompilation.getValue()));
         }
 
         if (OptTailDuplication.getValue()) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Thu Jun 13 09:41:06 2013 +0200
@@ -32,7 +32,7 @@
 public class MidTier extends PhaseSuite<MidTierContext> {
 
     public MidTier() {
-        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(OptCanonicalizeReads.getValue());
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!AOTCompilation.getValue());
 
         if (OptPushThroughPi.getValue()) {
             addPhase(new PushThroughPiPhase());
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Thu Jun 13 09:41:06 2013 +0200
@@ -30,13 +30,17 @@
 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
@@ -50,43 +54,136 @@
 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
-    @Ignore
-    public void testStaticFinalObject1() {
-        StructuredGraph result2 = compile("getStaticFinalObject", true);
-        assert result2.getNodes().filter(ConstantNode.class).count() == 1;
-        assert result2.getNodes(FloatingReadNode.class).count() == 1;
+    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 testStaticFinalObject2() {
-        StructuredGraph result1 = compile("getStaticFinalObject", false);
-        assert result1.getNodes().filter(ConstantNode.class).count() == 1;
-        assert result1.getNodes(FloatingReadNode.class).count() == 0;
+    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());
     }
 
     private StructuredGraph compile(String test, boolean compileAOT) {
         StructuredGraph graph = parse(test);
         ResolvedJavaMethod method = graph.method();
 
-        boolean originalSetting = OptCanonicalizeReads.getValue();
-        OptCanonicalizeReads.setValue(!compileAOT);
+        boolean originalSetting = AOTCompilation.getValue();
+        AOTCompilation.setValue(compileAOT);
         PhasePlan phasePlan = new PhasePlan();
         final StructuredGraph graphCopy = graph.copy();
         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(), suites);
+                        new SpeculationLog(), suitesLocal);
         addMethod(method, compResult, graphCopy);
 
-        OptCanonicalizeReads.setValue(originalSetting);
+        AOTCompilation.setValue(originalSetting);
 
         return graph;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethod.java	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethod.java	Thu Jun 13 09:41:06 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/HotSpotMethodUnresolved.java	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodUnresolved.java	Thu Jun 13 09:41:06 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/HotSpotResolvedJavaMethod.java	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Thu Jun 13 09:41:06 2013 +0200
@@ -22,7 +22,6 @@
  */
 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.*;
@@ -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);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu Jun 13 09:41:06 2013 +0200
@@ -1073,6 +1073,14 @@
     public Suites createSuites() {
         Suites ret = Suites.createDefaultSuites();
 
+        if (AOTCompilation.getValue()) {
+            // lowering introduces class constants, therefore it must be after lowering
+            ret.getHighTier().addPhase(new LoadJavaMirrorWithKlassPhase());
+            if (VerifyPhases.getValue()) {
+                ret.getHighTier().addPhase(new AheadOfTimeVerifcationPhase());
+            }
+        }
+
         ret.getMidTier().addPhase(new WriteBarrierAdditionPhase());
         if (VerifyPhases.getValue()) {
             ret.getMidTier().addPhase(new WriteBarrierVerificationPhase());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerifcationPhase.java	Thu Jun 13 09:41:06 2013 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.phases;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+
+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	Thu Jun 13 09:41:06 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.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.*;
+
+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);
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java	Thu Jun 13 09:41:06 2013 +0200
@@ -172,12 +172,10 @@
             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/InstanceOfSnippets.java	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Thu Jun 13 09:41:06 2013 +0200
@@ -22,6 +22,9 @@
  */
 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.*;
@@ -29,12 +32,14 @@
 
 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.*;
 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;
@@ -54,6 +59,41 @@
 public class InstanceOfSnippets implements Snippets {
 
     /**
+     * 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 GraalOptions#InstanceOfFullCoverageSpeculationThreshold
+     */
+    @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(InvalidateReprofile, OptimizedTypeCheckViolated);
+        return falseValue;
+    }
+
+    /**
      * A test against a final type.
      */
     @Snippet
@@ -136,6 +176,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");
@@ -155,12 +196,16 @@
                 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 >= InstanceOfFullCoverageSpeculationThreshold.getValue()) {
+                    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 +222,9 @@
                 args.add("trueValue", replacer.trueValue);
                 args.add("falseValue", replacer.falseValue);
                 args.addConst("checkNull", !object.stamp().nonNull());
+                if (hintInfo.hintHitProbability >= InstanceOfFullCoverageSpeculationThreshold.getValue()) {
+                    args.addConst("nullSeen", hintInfo.profile.getNullSeen() != TriState.FALSE);
+                }
                 return args;
 
             } else {
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Thu Jun 13 09:41:06 2013 +0200
@@ -33,6 +33,7 @@
 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.StandardOp.MoveOp;
@@ -667,6 +668,8 @@
         } 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);
         }
@@ -681,9 +684,12 @@
                 masm.shlq(resRegister, logMinObjAlignment);
             }
         } else {
-            // Otherwise the narrow heap base is added to the shifted address.
+            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.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Thu Jun 13 09:41:06 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/java/ExceptionObjectNode.java	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Thu Jun 13 09:41:06 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	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java	Thu Jun 13 09:41:06 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.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java	Thu Jun 13 09:41:06 2013 +0200
@@ -45,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(), OptCanonicalizeReads.getValue(), 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	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Thu Jun 13 09:41:06 2013 +0200
@@ -195,7 +195,7 @@
 
             if (OptCanonicalizer.getValue()) {
                 int markBeforeCanonicalization = callerGraph.getMark();
-                new CanonicalizerPhase.Instance(runtime, callerAssumptions, OptCanonicalizeReads.getValue(), 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)) {
@@ -280,7 +280,7 @@
                 }
 
                 if (OptCanonicalizer.getValue()) {
-                    new CanonicalizerPhase.Instance(runtime, assumptions, OptCanonicalizeReads.getValue()).apply(newGraph);
+                    new CanonicalizerPhase.Instance(runtime, assumptions, !AOTCompilation.getValue()).apply(newGraph);
                 }
 
                 return newGraph;
@@ -309,7 +309,7 @@
         new DeadCodeEliminationPhase().apply(newGraph);
 
         if (OptCanonicalizer.getValue()) {
-            new CanonicalizerPhase.Instance(runtime, assumptions, OptCanonicalizeReads.getValue()).apply(newGraph);
+            new CanonicalizerPhase.Instance(runtime, assumptions, !AOTCompilation.getValue()).apply(newGraph);
         }
 
         if (CullFrameStates.getValue()) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Thu Jun 13 09:41:06 2013 +0200
@@ -46,7 +46,7 @@
             if (canonicalizationRoots.isEmpty()) {
                 break;
             }
-            new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), OptCanonicalizeReads.getValue(), 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/TailDuplicationPhase.java	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Thu Jun 13 09:41:06 2013 +0200
@@ -300,7 +300,7 @@
                     phi.setMerge(mergeAfter);
                 }
             }
-            new CanonicalizerPhase.Instance(phaseContext.getRuntime(), phaseContext.getAssumptions(), OptCanonicalizeReads.getValue(), graph.getNewNodes(startMark), null).apply(graph);
+            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	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Thu Jun 13 09:41:06 2013 +0200
@@ -241,6 +241,10 @@
     @Option(help = "")
     public static final OptionValue<Double> MinTableSwitchDensity = new OptionValue<>(0.5);
 
+    // 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
     @Option(help = "")
     public static final OptionValue<Integer> StackShadowPages = new OptionValue<>(2);
@@ -257,8 +261,6 @@
     @Option(help = "")
     public static final OptionValue<Boolean> OptCanonicalizer = new OptionValue<>(true);
     @Option(help = "")
-    public static final OptionValue<Boolean> OptCanonicalizeReads = 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);
@@ -330,14 +332,25 @@
     public static final OptionValue<Integer> CheckcastMaxHints = new OptionValue<>(2);
 
     /**
-     * @see #CheckcastMinHintHitProbability
+     * 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.
      */
     @Option(help = "")
     public static final OptionValue<Double> InstanceOfMinHintHitProbability = new OptionValue<>(0.5);
 
     /**
-     * @see #CheckcastMaxHints
+     * 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);
+
+    /**
+     * If the probability that an instanceof will hit one the profiled types (up to {@link #InstanceOfMaxHints})
+     * is above this value, the compiled instanceof will deoptimize if all hints are missed.
+     */
+    @Option(help = "")
+    public static final OptionValue<Double> InstanceOfFullCoverageSpeculationThreshold = new OptionValue<>(0.998);
+
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Thu Jun 13 09:41:06 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/SnippetTemplate.java	Thu Jun 13 09:40:36 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Thu Jun 13 09:41:06 2013 +0200
@@ -192,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);
@@ -229,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 {
--- a/mx/commands.py	Thu Jun 13 09:40:36 2013 +0200
+++ b/mx/commands.py	Thu Jun 13 09:41:06 2013 +0200
@@ -1044,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', '-esa', '-version'])
+        tasks.append(t.stop())
+
         originalVm = _vm
         _vm = 'server' # hosted mode
         t = Task('UnitTests:hosted-product')
--- a/src/share/vm/runtime/arguments.cpp	Thu Jun 13 09:40:36 2013 +0200
+++ b/src/share/vm/runtime/arguments.cpp	Thu Jun 13 09:41:06 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()