changeset 10033:9d6f0c55cda7

Merge
author Christos Kotselidis <christos.kotselidis@oracle.com>
date Wed, 12 Jun 2013 11:37:45 +0200
parents 4a7dc38ae96b (current diff) c4a0e878868f (diff)
children 6cbb7fb49de5
files
diffstat 12 files changed, 306 insertions(+), 78 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java	Wed Jun 12 11:36:54 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java	Wed Jun 12 11:37:45 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	Wed Jun 12 11:36:54 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java	Wed Jun 12 11:37:45 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.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Wed Jun 12 11:36:54 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Wed Jun 12 11:37:45 2013 +0200
@@ -30,13 +30,18 @@
 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.hotspot.phases.*;
 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
@@ -56,18 +61,48 @@
     }
 
     @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);
+        assert result.getNodes().filter(ConstantNode.class).count() == 1;
+        assert result.getNodes(FloatingReadNode.class).count() == 2;
+    }
+
+    @Test
+    public void testStaticFinalObject() {
+        StructuredGraph result = compile("getStaticFinalObject", false);
+        assert result.getNodes().filter(ConstantNode.class).count() == 1;
+        assert result.getNodes(FloatingReadNode.class).count() == 0;
+    }
+
+    public static Class getClassObject() {
+        return AheadOfTimeCompilationTest.class;
     }
 
     @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 testClassObjectAOT() {
+        StructuredGraph result = compile("getClassObject", true);
+
+        NodeIterable<ConstantNode> filter = result.getNodes().filter(ConstantNode.class);
+        assert filter.count() == 1;
+        HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) runtime.lookupJavaType(AheadOfTimeCompilationTest.class);
+        assert filter.first().asConstant().equals(type.klass());
+
+        assert result.getNodes(FloatingReadNode.class).count() == 1;
+        assert result.getNodes(ReadNode.class).count() == 0;
+    }
+
+    @Test
+    public void testClassObject() {
+        StructuredGraph result = compile("getClassObject", false);
+
+        NodeIterable<ConstantNode> filter = result.getNodes().filter(ConstantNode.class);
+        assert filter.count() == 1;
+        Object mirror = filter.first().asConstant().asObject();
+        assert mirror.getClass().equals(Class.class);
+        assert mirror.equals(AheadOfTimeCompilationTest.class);
+
+        assert result.getNodes(FloatingReadNode.class).count() == 0;
+        assert result.getNodes(ReadNode.class).count() == 0;
     }
 
     private StructuredGraph compile(String test, boolean compileAOT) {
@@ -82,8 +117,13 @@
         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();
+        if (compileAOT) {
+            suitesLocal.getHighTier().addPhase(new LoadJavaMirrorWithKlassPhase());
+        }
         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);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethod.java	Wed Jun 12 11:36:54 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethod.java	Wed Jun 12 11:37:45 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	Wed Jun 12 11:36:54 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodUnresolved.java	Wed Jun 12 11:37:45 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	Wed Jun 12 11:36:54 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Wed Jun 12 11:37:45 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);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java	Wed Jun 12 11:37:45 2013 +0200
@@ -0,0 +1,63 @@
+/*
+ * 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.HeapAccess.WriteBarrierType;
+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());
+                if (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));
+                    ReadNode readNode = graph.add(new ReadNode(klassNode, location, stamp, WriteBarrierType.NONE, false));
+
+                    FixedNode afterStart = graph.start().next();
+                    graph.start().setNext(readNode);
+                    readNode.setNext(afterStart);
+
+                    graph.replaceFloating(node, readNode);
+                }
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java	Wed Jun 12 11:36:54 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java	Wed Jun 12 11:37:45 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	Wed Jun 12 11:36:54 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Wed Jun 12 11:37:45 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,6 +32,7 @@
 
 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 +58,35 @@
 public class InstanceOfSnippets implements Snippets {
 
     /**
+     * A test against a set of hints derived from a profile with 100% precise coverage of seen
+     * types. This snippet deoptimizes on any path that contradicts the profile.
+     */
+    @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) {
+                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;
+            }
+        }
+        DeoptimizeNode.deopt(InvalidateReprofile, OptimizedTypeCheckViolated);
+        return falseValue;
+    }
+
+    /**
      * A test against a final type.
      */
     @Snippet
@@ -136,6 +169,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 +189,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 == 1.0D) {
+                    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 +215,9 @@
                 args.add("trueValue", replacer.trueValue);
                 args.add("falseValue", replacer.falseValue);
                 args.addConst("checkNull", !object.stamp().nonNull());
+                if (hintInfo.hintHitProbability == 1.0D) {
+                    args.addConst("nullSeen", hintInfo.profile.getNullSeen() != TriState.FALSE);
+                }
                 return args;
 
             } else {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Wed Jun 12 11:36:54 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Wed Jun 12 11:37:45 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.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Wed Jun 12 11:36:54 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Wed Jun 12 11:37:45 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	Wed Jun 12 11:36:54 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Wed Jun 12 11:37:45 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 float[]) {
+                return Arrays.toString((short[]) value);
+            }
+            if (value instanceof float[]) {
+                return Arrays.toString((int[]) value);
+            }
+            if (value instanceof float[]) {
+                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 {