changeset 5379:c862951e769d

moved checkcast lowering into LoweringPhase and added -G:HIRLowerCheckcast option to enable it (disabled by default) as it is not yet stable
author Doug Simon <doug.simon@oracle.com>
date Fri, 11 May 2012 12:20:36 +0200
parents 333b0089a909
children 8be0c73cf118
files graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/LowerCheckCastPhase.java graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippets.java graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/FloatingReadTest.java
diffstat 12 files changed, 136 insertions(+), 111 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Fri May 11 11:57:29 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Fri May 11 12:20:36 2012 +0200
@@ -169,7 +169,7 @@
         }
 
         graph.mark();
-        new LoweringPhase(runtime).apply(graph);
+        new LoweringPhase(runtime, assumptions).apply(graph);
         new CanonicalizerPhase(target, runtime, assumptions, true, null).apply(graph);
 
         if (GraalOptions.Lower) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Fri May 11 11:57:29 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Fri May 11 12:20:36 2012 +0200
@@ -256,6 +256,13 @@
     public static int InstanceOfMaxHints = 1;
 
     /**
+     * Use HIR lowering instead of LIR lowering for checkcast instructions.
+     * Only checkcasts in methods in a class whose name contains this option will be HIR lowered.
+     * TDOD (dnsimon) remove once HIR checkcast lowering works reliably
+     */
+    public static String HIRLowerCheckcast;
+
+    /**
      * The profiling info cache directory.
      */
     public static String PICache = null;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java	Fri May 11 11:57:29 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java	Fri May 11 12:20:36 2012 +0200
@@ -27,7 +27,9 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 
 /**
@@ -36,9 +38,11 @@
 public class LoweringPhase extends Phase {
 
     private final GraalRuntime runtime;
+    private final CiAssumptions assumptions;
 
-    public LoweringPhase(GraalRuntime runtime) {
+    public LoweringPhase(GraalRuntime runtime, CiAssumptions assumptions) {
         this.runtime = runtime;
+        this.assumptions = assumptions;
     }
 
     @Override
@@ -67,10 +71,19 @@
                 // TODO (thomaswue): Document why this must not be called on floating nodes.
                 throw new UnsupportedOperationException();
             }
+
+            @Override
+            public CiAssumptions assumptions() {
+                return assumptions;
+            }
         };
         for (Node node : processed) {
-            if (node instanceof Lowerable) {
-                assert !(node instanceof FixedNode) || node.predecessor() == null;
+            if (node instanceof CheckCastNode) {
+                // This is a checkcast that was created while lowering some other node (e.g. StoreIndexed).
+                // This checkcast must now be LIR lowered.
+                // TODO (dnsimon) this is temp workaround that will be removed
+            } else if (node instanceof Lowerable) {
+                assert !(node instanceof FixedNode) || node.predecessor() == null : node;
                 ((Lowerable) node).lower(loweringTool);
             }
         }
@@ -135,6 +148,11 @@
                 activeGuards.mark(newGuard);
                 return newGuard;
             }
+
+            @Override
+            public CiAssumptions assumptions() {
+                return assumptions;
+            }
         };
 
         // Lower the instructions of this block.
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Fri May 11 11:57:29 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Fri May 11 12:20:36 2012 +0200
@@ -40,6 +40,7 @@
 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.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.max.cri.ci.*;
@@ -921,11 +922,12 @@
                     final StructuredGraph snippetGraph,
                     final boolean explodeLoops,
                     final IsImmutablePredicate immutabilityPredicate,
+                    final CiLoweringTool tool,
                     final Object... args) {
         Debug.scope("InliningSnippet", snippetGraph.method(), new Runnable() {
             @Override
             public void run() {
-                inlineSnippet0(runtime, replacee, anchor, snippetGraph, explodeLoops, immutabilityPredicate, args);
+                inlineSnippet0(runtime, replacee, anchor, snippetGraph, explodeLoops, immutabilityPredicate, tool, args);
             }
         });
     }
@@ -935,7 +937,10 @@
                     StructuredGraph snippetGraph,
                     boolean explodeLoops,
                     IsImmutablePredicate immutabilityPredicate,
-                    Object... args) {
+                    CiLoweringTool tool, Object... args) {
+
+        Debug.dump(replacee.graph(), "Before lowering %s", replacee);
+
         // Copy snippet graph, replacing parameters with given args in the process
         StructuredGraph snippetCopy = new StructuredGraph(snippetGraph.name, snippetGraph.method());
         IdentityHashMap<Node, Node> replacements = new IdentityHashMap<>();
@@ -967,16 +972,20 @@
                 LoopBeginNode loopBegin = loop.loopBegin();
                 SuperBlock wholeLoop = LoopTransformUtil.wholeLoop(loop);
                 Debug.dump(snippetCopy, "Before exploding loop %s", loopBegin);
+                int peel = 0;
                 while (!loopBegin.isDeleted()) {
                     snippetCopy.mark();
                     LoopTransformUtil.peel(loop, wholeLoop);
+                    Debug.dump(snippetCopy, "After peel %d", peel);
                     new CanonicalizerPhase(null, runtime, null, true, immutabilityPredicate).apply(snippetCopy);
+                    peel++;
                 }
                 Debug.dump(snippetCopy, "After exploding loop %s", loopBegin);
             }
+            new DeadCodeEliminationPhase().apply(snippetCopy);
         }
 
-        // Gather the nodes in the snippets that are to be inlined
+        // Gather the nodes in the snippet that are to be inlined
         ArrayList<Node> nodes = new ArrayList<>();
         ReturnNode returnNode = null;
         StartNode entryPointNode = snippetCopy.start();
@@ -1003,21 +1012,39 @@
 
         // Inline the gathered snippet nodes
         StructuredGraph graph = (StructuredGraph) replacee.graph();
+        graph.mark();
         Map<Node, Node> duplicates = graph.addDuplicates(nodes, replacements);
+        Debug.dump(graph, "After inlining snippet %s", snippetCopy.method());
 
         // Remove all frame states from the inlined snippet graph. Snippets must be atomic (i.e. free
         // of side-effects that prevent deoptimizing to a point before the snippet).
-        for (Node node : duplicates.values()) {
+        if (tool != null) {
+            boolean innerLowering = false;
+            for (Node node : duplicates.values()) {
+                if (node instanceof Lowerable) {
+                    innerLowering = true;
+                    ((Lowerable) node).lower(tool);
+
+                }
+            }
+            if (innerLowering) {
+                Debug.dump(graph, "After inner lowering");
+            }
+        }
+
+        for (Node node : graph.getNewNodes()) {
             if (node instanceof StateSplit) {
                 StateSplit stateSplit = (StateSplit) node;
                 FrameState frameState = stateSplit.stateAfter();
-                assert !stateSplit.hasSideEffect() : "snippets cannot contain side-effecting node " + node;
+                assert !stateSplit.hasSideEffect() : "snippets cannot contain side-effecting node " + node + "\n    " + replacee.graph();
                 if (frameState != null) {
                     stateSplit.setStateAfter(null);
                 }
             }
         }
 
+        Debug.dump(graph, "After removing frame states");
+
         // Rewire the control flow graph around the replacee
         FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode);
         anchor.replaceAtPredecessors(firstCFGNodeDuplicate);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java	Fri May 11 11:57:29 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java	Fri May 11 12:20:36 2012 +0200
@@ -148,8 +148,7 @@
             return null;
         }
         Debug.setConfig(Debug.fixedConfig(true, true, false, false, dumpHandlers, output));
-        // sync "Exception occured in scope: " with mx/sanitycheck.py::Test.__init__
-        Debug.log(String.format("Exception occured in scope: %s", Debug.currentScope()));
+        Debug.log(String.format("Exception occurred in scope: %s", Debug.currentScope()));
         for (Object o : Debug.context()) {
             Debug.log("Context obj %s", o);
             if (o instanceof Graph) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Fri May 11 11:57:29 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Fri May 11 12:20:36 2012 +0200
@@ -53,7 +53,6 @@
 
     private final Compiler compiler;
     private IntrinsifyArrayCopyPhase intrinsifyArrayCopy;
-    private LowerCheckCastPhase lowerCheckCastPhase;
 
     public final HotSpotTypePrimitive typeBoolean;
     public final HotSpotTypePrimitive typeChar;
@@ -116,12 +115,8 @@
                 @Override
                 public void run() {
                     VMToCompilerImpl.this.intrinsifyArrayCopy = new IntrinsifyArrayCopyPhase(runtime);
-                    VMToCompilerImpl.this.lowerCheckCastPhase = new LowerCheckCastPhase(runtime);
                     GraalIntrinsics.installIntrinsics(runtime, runtime.getCompiler().getTarget());
-                    Snippets.install(runtime, runtime.getCompiler().getTarget(), new SystemSnippets());
-                    Snippets.install(runtime, runtime.getCompiler().getTarget(), new UnsafeSnippets());
-                    Snippets.install(runtime, runtime.getCompiler().getTarget(), new ArrayCopySnippets());
-                    Snippets.install(runtime, runtime.getCompiler().getTarget(), new CheckCastSnippets());
+                    runtime.installSnippets();
                 }
             });
 
@@ -495,7 +490,6 @@
         if (GraalOptions.Intrinsify) {
             phasePlan.addPhase(PhasePosition.HIGH_LEVEL, intrinsifyArrayCopy);
         }
-        phasePlan.addPhase(PhasePosition.HIGH_LEVEL, lowerCheckCastPhase);
         return phasePlan;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java	Fri May 11 11:57:29 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java	Fri May 11 12:20:36 2012 +0200
@@ -28,18 +28,24 @@
 import java.util.*;
 
 import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.phases.*;
+import com.oracle.graal.compiler.phases.CanonicalizerPhase.IsImmutablePredicate;
 import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.compiler.util.*;
 import com.oracle.graal.cri.*;
+import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.Compiler;
 import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.hotspot.snippets.*;
 import com.oracle.graal.hotspot.target.amd64.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.snippets.*;
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ci.CiTargetMethod.Call;
 import com.oracle.max.cri.ci.CiTargetMethod.DataPatch;
@@ -58,6 +64,7 @@
     final HotSpotRegisterConfig regConfig;
     private final HotSpotRegisterConfig globalStubRegConfig;
     private final Compiler compiler;
+    private RiResolvedMethod checkcastSnippet;
 
     public HotSpotRuntime(HotSpotVMConfig config, Compiler compiler) {
         this.config = config;
@@ -68,6 +75,19 @@
         System.setProperty(Backend.BACKEND_CLASS_PROPERTY, HotSpotAMD64Backend.class.getName());
     }
 
+    public void installSnippets() {
+        Snippets.install(this, compiler.getTarget(), new SystemSnippets());
+        Snippets.install(this, compiler.getTarget(), new UnsafeSnippets());
+        Snippets.install(this, compiler.getTarget(), new ArrayCopySnippets());
+        Snippets.install(this, compiler.getTarget(), new CheckCastSnippets());
+        try {
+            checkcastSnippet = getRiMethod(CheckCastSnippets.class.getDeclaredMethod("checkcast", Object.class, Object.class, Object[].class, boolean.class));
+        } catch (NoSuchMethodException e) {
+            throw new GraalInternalError(e);
+        }
+    }
+
+
     @Override
     public int codeOffset() {
         return 0;
@@ -330,6 +350,7 @@
             CiKind elementKind = storeIndexed.elementKind();
             LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index());
             ValueNode value = storeIndexed.value();
+            CheckCastNode checkcast = null;
             ValueNode array = storeIndexed.array();
             if (elementKind == CiKind.Object && !value.isNullConstant()) {
                 // Store check!
@@ -337,7 +358,7 @@
                     RiResolvedType elementType = array.exactType().componentType();
                     if (elementType.superType() != null) {
                         ConstantNode type = ConstantNode.forCiConstant(elementType.getEncoding(Representation.ObjectHub), this, graph);
-                        CheckCastNode checkcast = graph.add(new CheckCastNode(type, elementType, value));
+                        checkcast = graph.add(new CheckCastNode(type, elementType, value));
                         graph.addBeforeFixed(storeIndexed, checkcast);
                         value = checkcast;
                     } else {
@@ -348,7 +369,7 @@
                     FloatingReadNode arrayClass = graph.unique(new FloatingReadNode(array, null, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph), StampFactory.objectNonNull()));
                     arrayClass.setGuard(guard);
                     FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, null, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.arrayClassElementOffset, graph), StampFactory.objectNonNull()));
-                    CheckCastNode checkcast = graph.add(new CheckCastNode(arrayElementKlass, null, value));
+                    checkcast = graph.add(new CheckCastNode(arrayElementKlass, null, value));
                     graph.addBeforeFixed(storeIndexed, checkcast);
                     value = checkcast;
                 }
@@ -362,6 +383,9 @@
             if (elementKind == CiKind.Object && !value.isNullConstant()) {
                 graph.addAfterFixed(memoryWrite, graph.add(new ArrayWriteBarrier(array, arrayLocation)));
             }
+            if (checkcast != null) {
+                checkcast.lower(tool);
+            }
         } else if (n instanceof UnsafeLoadNode) {
             UnsafeLoadNode load = (UnsafeLoadNode) n;
             assert load.kind() != CiKind.Illegal;
@@ -387,6 +411,31 @@
             ReadNode memoryRead = graph.add(new ReadNode(objectClassNode.object(), location, StampFactory.objectNonNull()));
             memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(objectClassNode.object(), false)), RiDeoptReason.NullCheckException, RiDeoptAction.InvalidateReprofile, StructuredGraph.INVALID_GRAPH_ID));
             graph.replaceFixed(objectClassNode, memoryRead);
+        } else if (n instanceof CheckCastNode) {
+            if (GraalOptions.HIRLowerCheckcast != null && graph.method() != null && graph.method().holder().name().contains(GraalOptions.HIRLowerCheckcast)) {
+                final Map<CiConstant, CiConstant> hintHubsSet = new IdentityHashMap<>();
+                IsImmutablePredicate immutabilityPredicate = new IsImmutablePredicate() {
+                    public boolean apply(CiConstant constant) {
+                        return hintHubsSet.containsKey(constant);
+                    }
+                };
+                CheckCastNode checkcast = (CheckCastNode) n;
+                ValueNode hub = checkcast.targetClassInstruction();
+                ValueNode object = checkcast.object();
+                TypeCheckHints hints = new TypeCheckHints(checkcast.targetClass(), checkcast.profile(), tool.assumptions(), GraalOptions.CheckcastMinHintHitProbability, GraalOptions.CheckcastMaxHints);
+                StructuredGraph snippetGraph = (StructuredGraph) checkcastSnippet.compilerStorage().get(Graph.class);
+                assert snippetGraph != null : CheckCastSnippets.class.getSimpleName() + " should be installed";
+                HotSpotKlassOop[] hintHubs = new HotSpotKlassOop[hints.types.length];
+                for (int i = 0; i < hintHubs.length; i++) {
+                    hintHubs[i] = ((HotSpotType) hints.types[i]).klassOop();
+                }
+                final CiConstant hintHubsConst = CiConstant.forObject(hintHubs);
+                hintHubsSet.put(hintHubsConst, hintHubsConst);
+                Debug.log("Lowering checkcast in %s: node=%s, hintsHubs=%s, exact=%b", graph, checkcast, Arrays.toString(hints.types), hints.exact);
+
+                InliningUtil.inlineSnippet(this, checkcast, checkcast, snippetGraph, true, immutabilityPredicate, tool, hub, object, hintHubsConst, CiConstant.forBoolean(hints.exact));
+                new DeadCodeEliminationPhase().apply(graph);
+            }
         } else {
             assert false : "Node implementing Lowerable not handled: " + n;
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/LowerCheckCastPhase.java	Fri May 11 11:57:29 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.snippets;
-
-import java.util.*;
-
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
-import com.oracle.graal.compiler.phases.CanonicalizerPhase.IsImmutablePredicate;
-import com.oracle.graal.compiler.util.*;
-import com.oracle.graal.cri.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.hotspot.ri.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ri.*;
-import com.oracle.max.criutils.*;
-
-/**
- * Lowers a {@link CheckCastNode} by replacing it with the graph of a {@linkplain CheckCastSnippets checkcast snippet}.
- */
-public class LowerCheckCastPhase extends Phase {
-    private final GraalRuntime runtime;
-    private final RiResolvedMethod checkcast;
-
-    public LowerCheckCastPhase(GraalRuntime runtime) {
-        this.runtime = runtime;
-        try {
-            checkcast = runtime.getRiMethod(CheckCastSnippets.class.getDeclaredMethod("checkcast", Object.class, Object.class, Object[].class, boolean.class));
-        } catch (NoSuchMethodException e) {
-            throw new GraalInternalError(e);
-        }
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        final Map<CiConstant, CiConstant> hintHubsSet = new IdentityHashMap<>();
-        IsImmutablePredicate immutabilityPredicate = new IsImmutablePredicate() {
-            public boolean apply(CiConstant constant) {
-                return hintHubsSet.containsKey(constant);
-            }
-        };
-        for (CheckCastNode node : graph.getNodes(CheckCastNode.class)) {
-            ValueNode hub = node.targetClassInstruction();
-            ValueNode object = node.object();
-            CiAssumptions assumptions = null;
-            TypeCheckHints hints = new TypeCheckHints(node.targetClass(), node.profile(), assumptions, GraalOptions.CheckcastMinHintHitProbability, GraalOptions.CheckcastMaxHints);
-            StructuredGraph snippetGraph = (StructuredGraph) checkcast.compilerStorage().get(Graph.class);
-            assert snippetGraph != null : CheckCastSnippets.class.getSimpleName() + " should be installed";
-            HotSpotKlassOop[] hintHubs = new HotSpotKlassOop[hints.types.length];
-            for (int i = 0; i < hintHubs.length; i++) {
-                hintHubs[i] = ((HotSpotType) hints.types[i]).klassOop();
-            }
-            final CiConstant hintHubsConst = CiConstant.forObject(hintHubs);
-            hintHubsSet.put(hintHubsConst, hintHubsConst);
-            Debug.log("Lowering checkcast in %s: node=%s, hintsHubs=%s, exact=%b", graph, node, Arrays.toString(hints.types), hints.exact);
-
-            InliningUtil.inlineSnippet(runtime, node, node, snippetGraph, true, immutabilityPredicate, hub, object, hintHubsConst, CiConstant.forBoolean(hints.exact));
-        }
-        if (!hintHubsSet.isEmpty()) {
-            Debug.log("Lowered %d checkcasts in %s ", hintHubsSet.size(), graph);
-            new DeadCodeEliminationPhase().apply(graph);
-            new CanonicalizerPhase(null, runtime, null, false, immutabilityPredicate).apply(graph);
-        }
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java	Fri May 11 11:57:29 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java	Fri May 11 12:20:36 2012 +0200
@@ -23,11 +23,13 @@
 package com.oracle.graal.cri;
 
 import com.oracle.graal.graph.*;
+import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 
 public interface CiLoweringTool {
     GraalRuntime getRuntime();
     Node getGuardAnchor();
     Node createGuard(Node condition, RiDeoptReason deoptReason, RiDeoptAction action, long leafGraphId);
+    CiAssumptions assumptions();
 }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Fri May 11 11:57:29 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Fri May 11 12:20:36 2012 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.java;
 
+import com.oracle.graal.cri.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -34,7 +35,7 @@
 /**
  * Implements a type check that results in a {@link ClassCastException} if it fails.
  */
-public final class CheckCastNode extends FixedWithNextNode implements Canonicalizable, LIRLowerable, Node.IterableNodeType, TypeFeedbackProvider, TypeCanonicalizable {
+public final class CheckCastNode extends FixedWithNextNode implements Canonicalizable, LIRLowerable, Lowerable, Node.IterableNodeType, TypeFeedbackProvider, TypeCanonicalizable {
 
     @Input private ValueNode object;
     @Input private ValueNode targetClassInstruction;
@@ -60,6 +61,11 @@
     }
 
     @Override
+    public void lower(CiLoweringTool tool) {
+        tool.getRuntime().lower(this, tool);
+    }
+
+    @Override
     public void generate(LIRGeneratorTool gen) {
         gen.visitCheckCast(this);
     }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippets.java	Fri May 11 11:57:29 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippets.java	Fri May 11 12:20:36 2012 +0200
@@ -108,7 +108,7 @@
                     MethodCallTargetNode callTarget = invoke.callTarget();
                     RiResolvedMethod targetMethod = callTarget.targetMethod();
                     RiResolvedType holder = targetMethod.holder();
-                    if (holder.isSubtypeOf(runtime.getType(SnippetsInterface.class))) {
+                    if (enclosedInSnippetsClass(holder)) {
                         StructuredGraph targetGraph = (StructuredGraph) targetMethod.compilerStorage().get(Graph.class);
                         if (targetGraph == null) {
                             targetGraph = buildSnippetGraph(targetMethod, runtime, target, pool);
@@ -140,6 +140,17 @@
 
                 return graph;
             }
+
+            private boolean enclosedInSnippetsClass(RiResolvedType holder) {
+                Class enclosingClass = holder.toJava();
+                while (enclosingClass != null) {
+                    if (SnippetsInterface.class.isAssignableFrom(enclosingClass)) {
+                        return true;
+                    }
+                    enclosingClass = enclosingClass.getEnclosingClass();
+                }
+                return false;
+            }
         });
 
     }
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/FloatingReadTest.java	Fri May 11 11:57:29 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/FloatingReadTest.java	Fri May 11 12:20:36 2012 +0200
@@ -52,7 +52,7 @@
 
     private void test(String snippet) {
         StructuredGraph graph = parse(snippet);
-        new LoweringPhase(runtime()).apply(graph);
+        new LoweringPhase(runtime(), null).apply(graph);
         new FloatingReadPhase().apply(graph);
 
         ReturnNode returnNode = null;