changeset 5426:3f6496caa1a4

Merge
author Lukas Stadler <lukas.stadler@jku.at>
date Tue, 22 May 2012 16:31:30 +0200
parents 0364a2a874b8 (current diff) b26a95cf8e3d (diff)
children 142237644367 ab31310d4af9
files graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/types/PropagateTypeCachePhase.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java
diffstat 16 files changed, 260 insertions(+), 133 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Tue May 22 16:19:02 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Tue May 22 16:31:30 2012 +0200
@@ -169,13 +169,8 @@
         if (GraalOptions.OptCanonicalizer) {
             new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
         }
-        if (GraalOptions.OptGVN) {
-            new GlobalValueNumberingPhase().apply(graph);
-        }
 
-        int mark = graph.getMark();
         new LoweringPhase(runtime, assumptions).apply(graph);
-        new CanonicalizerPhase(target, runtime, assumptions, mark, null).apply(graph);
 
         if (GraalOptions.CullFrameStates) {
             new CullFrameStatesPhase().apply(graph);
@@ -201,9 +196,6 @@
         if (GraalOptions.OptCanonicalizer) {
             new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
         }
-        if (GraalOptions.OptGVN) {
-            new GlobalValueNumberingPhase().apply(graph);
-        }
         new DeadCodeEliminationPhase().apply(graph);
 
         plan.runPhases(PhasePosition.MID_LEVEL, graph);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java	Tue May 22 16:19:02 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java	Tue May 22 16:31:30 2012 +0200
@@ -22,52 +22,86 @@
  */
 package com.oracle.graal.compiler.phases;
 
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ri.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Graph.InputChangedListener;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
 
 public class CanonicalizerPhase extends Phase {
     private static final int MAX_ITERATION_PER_NODE = 10;
     private static final DebugMetric METRIC_CANONICALIZED_NODES = Debug.metric("CanonicalizedNodes");
     private static final DebugMetric METRIC_CANONICALIZATION_CONSIDERED_NODES = Debug.metric("CanonicalizationConsideredNodes");
     private static final DebugMetric METRIC_SIMPLIFICATION_CONSIDERED_NODES = Debug.metric("SimplificationConsideredNodes");
+    public static final DebugMetric METRIC_GLOBAL_VALUE_NUMBERING_HITS = Debug.metric("GlobalValueNumberingHits");
 
-    private int newNodesMark;
+    private final int newNodesMark;
     private final CiTarget target;
     private final CiAssumptions assumptions;
     private final RiRuntime runtime;
     private final IsImmutablePredicate immutabilityPredicate;
+    private final Iterable<Node> initWorkingSet;
+
+    private NodeWorkList workList;
+    private Tool tool;
 
     public CanonicalizerPhase(CiTarget target, RiRuntime runtime, CiAssumptions assumptions) {
-        this(target, runtime, assumptions, -1, null);
+        this(target, runtime, assumptions, null, 0, null);
     }
 
     /**
-     * @param newNodesMark if non-negative, then only the {@linkplain Graph#getNewNodes(int) new nodes} specified by
+     * @param target
+     * @param runtime
+     * @param assumptions
+     * @param workingSet the initial working set of nodes on which the canonicalizer works, should be an auto-grow node bitmap
+     * @param immutabilityPredicate
+     */
+    public CanonicalizerPhase(CiTarget target, RiRuntime runtime, CiAssumptions assumptions, Iterable<Node> workingSet, IsImmutablePredicate immutabilityPredicate) {
+        this(target, runtime, assumptions, workingSet, 0, immutabilityPredicate);
+    }
+
+    /**
+     * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by
      *            this mark are processed otherwise all nodes in the graph are processed
      */
     public CanonicalizerPhase(CiTarget target, RiRuntime runtime, CiAssumptions assumptions, int newNodesMark, IsImmutablePredicate immutabilityPredicate) {
+        this(target, runtime, assumptions, null, newNodesMark, immutabilityPredicate);
+    }
+
+    private CanonicalizerPhase(CiTarget target, RiRuntime runtime, CiAssumptions assumptions, Iterable<Node> workingSet, int newNodesMark, IsImmutablePredicate immutabilityPredicate) {
         this.newNodesMark = newNodesMark;
         this.target = target;
         this.assumptions = assumptions;
         this.runtime = runtime;
         this.immutabilityPredicate = immutabilityPredicate;
+        this.initWorkingSet = workingSet;
     }
 
     @Override
     protected void run(StructuredGraph graph) {
-        boolean newNodes = newNodesMark >= 0;
-        NodeWorkList nodeWorkList = graph.createNodeWorkList(!newNodes, MAX_ITERATION_PER_NODE);
-        if (newNodes) {
-            nodeWorkList.addAll(graph.getNewNodes(newNodesMark));
+        if (initWorkingSet == null) {
+            workList = graph.createNodeWorkList(newNodesMark == 0, MAX_ITERATION_PER_NODE);
+            if (newNodesMark > 0) {
+                workList.addAll(graph.getNewNodes(newNodesMark));
+            }
+        } else {
+            workList = graph.createNodeWorkList(newNodesMark == 0, MAX_ITERATION_PER_NODE);
+            workList.addAll(initWorkingSet);
         }
+        tool = new Tool(workList, runtime, target, assumptions, immutabilityPredicate);
+        processWorkSet(graph);
 
-        canonicalize(graph, nodeWorkList, runtime, target, assumptions, immutabilityPredicate);
+        while (graph.getUsagesDroppedNodesCount() > 0) {
+            for (Node n : graph.getAndCleanUsagesDroppedNodes()) {
+                if (!n.isDeleted() && n.usages().size() == 0 && GraphUtil.isFloatingNode().apply(n)) {
+                    n.safeDelete();
+                }
+            }
+        }
     }
 
     public interface IsImmutablePredicate {
@@ -78,15 +112,56 @@
         boolean apply(CiConstant constant);
     }
 
-    public static void canonicalize(StructuredGraph graph, NodeWorkList nodeWorkList, RiRuntime runtime, CiTarget target, CiAssumptions assumptions, IsImmutablePredicate immutabilityPredicate) {
-        graph.trackInputChange(nodeWorkList);
-        Tool tool = new Tool(nodeWorkList, runtime, target, assumptions, immutabilityPredicate);
-        for (Node node : nodeWorkList) {
+    private void processWorkSet(StructuredGraph graph) {
+        graph.trackInputChange(new InputChangedListener() {
+            @Override
+            public void inputChanged(Node node) {
+                workList.addAgain(node);
+            }
+        });
+
+        for (Node n : workList) {
+            processNode(n, graph);
+        }
+
+        graph.stopTrackingInputChange();
+    }
+
+    private void processNode(Node n, StructuredGraph graph) {
+        if (n.isAlive()) {
             METRIC_PROCESSED_NODES.increment();
-            if (node instanceof Canonicalizable) {
-                METRIC_CANONICALIZATION_CONSIDERED_NODES.increment();
-                int mark = graph.getMark();
-                ValueNode canonical = ((Canonicalizable) node).canonical(tool);
+
+            if (tryGlobalValueNumbering(n, graph)) {
+                return;
+            }
+            int mark = graph.getMark();
+            tryCanonicalize(n, graph, tool);
+
+            for (Node node : graph.getNewNodes(mark)) {
+                workList.add(node);
+            }
+        }
+    }
+
+    public static boolean tryGlobalValueNumbering(Node n, StructuredGraph graph) {
+        if (n.getNodeClass().valueNumberable()) {
+            Node newNode = graph.findDuplicate(n);
+            if (newNode != null) {
+                assert !(n instanceof FixedNode || newNode instanceof FixedNode);
+                n.replaceAtUsages(newNode);
+                n.safeDelete();
+                METRIC_GLOBAL_VALUE_NUMBERING_HITS.increment();
+                Debug.log("GVN applied and new node is %1s", newNode);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static void tryCanonicalize(Node node, StructuredGraph graph, SimplifierTool tool) {
+        if (node instanceof Canonicalizable) {
+            METRIC_CANONICALIZATION_CONSIDERED_NODES.increment();
+            ValueNode canonical = ((Canonicalizable) node).canonical(tool);
 //     cases:                                           original node:
 //                                         |Floating|Fixed-unconnected|Fixed-connected|
 //                                         --------------------------------------------
@@ -99,72 +174,62 @@
 //                          Fixed-connected|   2    |        X        |       6       |
 //                                         --------------------------------------------
 //       X: must not happen (checked with assertions)
-                if (canonical == node) {
-                    Debug.log("Canonicalizer: work on %s", node);
-                } else {
-                    Debug.log("Canonicalizer: replacing %s with %s", node, canonical);
+            if (canonical == node) {
+                Debug.log("Canonicalizer: work on %s", node);
+            } else {
+                Debug.log("Canonicalizer: replacing %s with %s", node, canonical);
 
-                    METRIC_CANONICALIZED_NODES.increment();
-                    if (node instanceof FloatingNode) {
-                        if (canonical == null) {
-                            // case 1
-                            graph.removeFloating((FloatingNode) node);
-                        } else {
-                            // case 2
-                            assert !(canonical instanceof FixedNode) || canonical.predecessor() != null : node + " -> " + canonical +
-                                            " : replacement should be floating or fixed and connected";
-                            graph.replaceFloating((FloatingNode) node, canonical);
-                        }
+                METRIC_CANONICALIZED_NODES.increment();
+                if (node instanceof FloatingNode) {
+                    if (canonical == null) {
+                        // case 1
+                        graph.removeFloating((FloatingNode) node);
                     } else {
-                        assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")";
-                        if (canonical == null) {
-                            // case 3
-                            graph.removeFixed((FixedWithNextNode) node);
-                        } else if (canonical instanceof FloatingNode) {
-                            // case 4
-                            graph.replaceFixedWithFloating((FixedWithNextNode) node, (FloatingNode) canonical);
+                        // case 2
+                        assert !(canonical instanceof FixedNode) || canonical.predecessor() != null : node + " -> " + canonical +
+                                        " : replacement should be floating or fixed and connected";
+                        graph.replaceFloating((FloatingNode) node, canonical);
+                    }
+                } else {
+                    assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")";
+                    if (canonical == null) {
+                        // case 3
+                        graph.removeFixed((FixedWithNextNode) node);
+                    } else if (canonical instanceof FloatingNode) {
+                        // case 4
+                        graph.replaceFixedWithFloating((FixedWithNextNode) node, (FloatingNode) canonical);
+                    } else {
+                        assert canonical instanceof FixedNode;
+                        if (canonical.predecessor() == null) {
+                            assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors";
+                            // case 5
+                            graph.replaceFixedWithFixed((FixedWithNextNode) node, (FixedWithNextNode) canonical);
                         } else {
-                            assert canonical instanceof FixedNode;
-                            if (canonical.predecessor() == null) {
-                                assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors";
-                                // case 5
-                                graph.replaceFixedWithFixed((FixedWithNextNode) node, (FixedWithNextNode) canonical);
-                            } else {
-                                assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors";
-                                // case 6
-                                node.replaceAtUsages(canonical);
-                                graph.removeFixed((FixedWithNextNode) node);
-                            }
+                            assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors";
+                            // case 6
+                            node.replaceAtUsages(canonical);
+                            graph.removeFixed((FixedWithNextNode) node);
                         }
                     }
-                    nodeWorkList.addAll(graph.getNewNodes(mark));
-                }
-            } else if (node instanceof Simplifiable) {
-                Debug.log("Canonicalizer: simplifying %s", node);
-                METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment();
-                ((Simplifiable) node).simplify(tool);
-            }
-        }
-        graph.stopTrackingInputChange();
-        while (graph.getUsagesDroppedNodesCount() > 0) {
-            for (Node n : graph.getAndCleanUsagesDroppedNodes()) {
-                if (!n.isDeleted() && n.usages().size() == 0 && GraphUtil.isFloatingNode().apply(n)) {
-                    n.safeDelete();
                 }
             }
+        } else if (node instanceof Simplifiable) {
+            Debug.log("Canonicalizer: simplifying %s", node);
+            METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment();
+            ((Simplifiable) node).simplify(tool);
         }
     }
 
     private static final class Tool implements SimplifierTool {
 
-        private final NodeWorkList nodeWorkList;
+        private final NodeWorkList nodeWorkSet;
         private final RiRuntime runtime;
         private final CiTarget target;
         private final CiAssumptions assumptions;
         private final IsImmutablePredicate immutabilityPredicate;
 
-        public Tool(NodeWorkList nodeWorkList, RiRuntime runtime, CiTarget target, CiAssumptions assumptions, IsImmutablePredicate immutabilityPredicate) {
-            this.nodeWorkList = nodeWorkList;
+        public Tool(NodeWorkList nodeWorkSet, RiRuntime runtime, CiTarget target, CiAssumptions assumptions, IsImmutablePredicate immutabilityPredicate) {
+            this.nodeWorkSet = nodeWorkSet;
             this.runtime = runtime;
             this.target = target;
             this.assumptions = assumptions;
@@ -200,7 +265,7 @@
 
         @Override
         public void addToWorkList(Node node) {
-            nodeWorkList.add(node);
+            nodeWorkSet.add(node);
         }
 
         @Override
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/FloatingReadPhase.java	Tue May 22 16:19:02 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/FloatingReadPhase.java	Tue May 22 16:31:30 2012 +0200
@@ -153,6 +153,16 @@
             } else {
                 floatingRead = graph.unique(new FloatingReadNode(readNode.object(), readNode.location(), getLocationForRead(readNode), readNode.stamp(), readNode.dependencies()));
             }
+            ValueAnchorNode anchor = null;
+            for (GuardNode guard : readNode.dependencies().filter(GuardNode.class)) {
+                if (anchor == null) {
+                    anchor = graph.add(new ValueAnchorNode());
+                }
+                anchor.addAnchoredValue(guard);
+            }
+            if (anchor != null) {
+                graph.addAfterFixed(readNode, anchor);
+            }
             graph.replaceFixedWithFloating(readNode, floatingRead);
         }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java	Tue May 22 16:19:02 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java	Tue May 22 16:31:30 2012 +0200
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.cri.*;
+import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
@@ -84,10 +85,13 @@
     protected void run(final StructuredGraph graph) {
         // Step 1: repeatedly lower fixed nodes until no new ones are created
         NodeBitMap processed = graph.createNodeBitMap();
+        int  i = 0;
         while (true) {
             int mark = graph.getMark();
             ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, false, true, true);
             processBlock(cfg.getStartBlock(), graph.createNodeBitMap(), processed, null);
+            Debug.dump(graph, "Lowering iteration %d", i++);
+            new CanonicalizerPhase(null, runtime, assumptions, mark, null).apply(graph);
 
             if (graph.getNewNodes(mark).filter(FixedNode.class).isEmpty()) {
                 break;
@@ -151,7 +155,7 @@
             }
         }
 
-        if (parentAnchor == null) {
+        if (parentAnchor == null && GraalOptions.OptEliminateGuards) {
             for (GuardNode guard : anchor.usages().filter(GuardNode.class)) {
                 activeGuards.clear(guard);
             }
@@ -178,8 +182,10 @@
                     }
                 }
                 GuardNode newGuard = guardAnchor.graph().unique(new GuardNode((BooleanNode) condition, guardAnchor, deoptReason, action, negated, leafGraphId));
-                activeGuards.grow();
-                activeGuards.mark(newGuard);
+                if (GraalOptions.OptEliminateGuards) {
+                    activeGuards.grow();
+                    activeGuards.mark(newGuard);
+                }
                 return newGuard;
             }
         };
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/types/PropagateTypeCachePhase.java	Tue May 22 16:19:02 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/types/PropagateTypeCachePhase.java	Tue May 22 16:31:30 2012 +0200
@@ -25,17 +25,18 @@
 import java.io.*;
 import java.util.*;
 
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ri.*;
 import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.compiler.schedule.*;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.Graph.InputChangedListener;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.types.*;
 import com.oracle.graal.nodes.spi.types.TypeCanonicalizable.Result;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
 
 public class PropagateTypeCachePhase extends Phase {
 
@@ -45,7 +46,6 @@
     private final RiRuntime runtime;
     private final CiAssumptions assumptions;
 
-    private NodeWorkList changedNodes;
     private StructuredGraph currentGraph;
     private SchedulePhase schedule;
 
@@ -109,20 +109,30 @@
             }
         }
 
-        changedNodes = graph.createNodeWorkList(false, 10);
 
         schedule = new SchedulePhase();
         schedule.apply(graph);
 
+        final NodeBitMap changedNodes = graph.createNodeBitMap(true);
+        graph.trackInputChange(new InputChangedListener() {
+            @Override
+            public void inputChanged(Node node) {
+                changedNodes.mark(node);
+            }
+        });
+
         new Iterator().apply(schedule.getCFG().getStartBlock());
 
+        graph.stopTrackingInputChange();
+
         Debug.dump(graph, "After PropagateType iteration");
         if (changes > 0) {
 //            totalChanges += changes;
 //            out.println(graph.method() + ": " + changes + " changes");
         }
 
-        CanonicalizerPhase.canonicalize(graph, changedNodes, runtime, target, assumptions, null);
+        new CanonicalizerPhase(target, runtime, assumptions, changedNodes, null).apply(graph);
+
 // outputGraph(graph);
     }
 
@@ -232,7 +242,6 @@
                                 assert node instanceof FixedWithNextNode;
                                 currentGraph.replaceFixed((FixedWithNextNode) node, replacement);
                             }
-                            changedNodes.addAll(replacement.usages());
                         }
                     }
                     if (node.isAlive() && node instanceof TypeFeedbackProvider) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Tue May 22 16:19:02 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Tue May 22 16:31:30 2012 +0200
@@ -960,7 +960,7 @@
         assert localCount == args.length : "snippet argument count mismatch";
         snippetCopy.addDuplicates(snippetGraph.getNodes(), replacements);
         if (!replacements.isEmpty()) {
-            new CanonicalizerPhase(null, runtime, null, -1, immutabilityPredicate).apply(snippetCopy);
+            new CanonicalizerPhase(null, runtime, null, 0, immutabilityPredicate).apply(snippetCopy);
         }
 
         // Explode all loops in the snippet if requested
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Tue May 22 16:19:02 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Tue May 22 16:31:30 2012 +0200
@@ -48,7 +48,7 @@
     private GraphEventLog eventLog;
 
     ArrayList<Node> usagesDropped = new ArrayList<>();
-    NodeWorkList inputChanged;
+    InputChangedListener inputChanged;
     private final HashMap<CacheEntry, Node> cachedNodes = new HashMap<>();
 
     private static final class CacheEntry {
@@ -159,8 +159,12 @@
         return result;
     }
 
-    public void trackInputChange(NodeWorkList worklist) {
-        this.inputChanged = worklist;
+    public interface InputChangedListener {
+        void inputChanged(Node node);
+    }
+
+    public void trackInputChange(InputChangedListener inputChangedListener) {
+        this.inputChanged = inputChangedListener;
     }
 
     public void stopTrackingInputChange() {
@@ -386,7 +390,11 @@
     }
 
     public NodeBitMap createNodeBitMap() {
-        return new NodeBitMap(this);
+        return createNodeBitMap(false);
+    }
+
+    public NodeBitMap createNodeBitMap(boolean autoGrow) {
+        return new NodeBitMap(this, autoGrow);
     }
 
     public <T> NodeMap<T> createNodeMap() {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Tue May 22 16:19:02 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Tue May 22 16:31:30 2012 +0200
@@ -25,6 +25,7 @@
 import java.lang.annotation.*;
 import java.util.*;
 
+import com.oracle.graal.graph.Graph.InputChangedListener;
 import com.oracle.graal.graph.NodeClass.*;
 
 
@@ -191,9 +192,9 @@
                 assert assertTrue(result, "not found in usages, old input: %s", oldInput);
             }
             if (newInput != null) {
-                NodeWorkList inputChanged = graph.inputChanged;
+                InputChangedListener inputChanged = graph.inputChanged;
                 if (inputChanged != null) {
-                    inputChanged.addAgain(this);
+                    inputChanged.inputChanged(this);
                 }
                 newInput.usages.add(this);
             }
@@ -251,9 +252,9 @@
             boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other);
             assert assertTrue(result, "not found in inputs, usage: %s", usage);
             if (other != null) {
-                NodeWorkList inputChanged = graph.inputChanged;
+                InputChangedListener inputChanged = graph.inputChanged;
                 if (inputChanged != null) {
-                    inputChanged.addAgain(usage);
+                    inputChanged.inputChanged(usage);
                 }
                 other.usages.add(usage);
             }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java	Tue May 22 16:19:02 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java	Tue May 22 16:31:30 2012 +0200
@@ -22,18 +22,22 @@
  */
 package com.oracle.graal.graph;
 
-import java.util.Collection;
-import java.util.Iterator;
+import java.util.*;
 
 
 
 public final class NodeBitMap implements Iterable<Node>{
-
+    private final boolean autoGrow;
     private final BitMap bitMap;
     private final Graph graph;
 
     public NodeBitMap(Graph graph) {
+        this(graph, false);
+    }
+
+    public NodeBitMap(Graph graph, boolean autoGrow) {
         this.graph = graph;
+        this.autoGrow = autoGrow;
         bitMap = new BitMap(graph.nodeIdCount());
     }
 
@@ -63,6 +67,9 @@
     }
 
     public boolean isMarked(Node node) {
+        if (autoGrow && isNew(node)) {
+            return false;
+        }
         assert check(node);
         return bitMap.get(node.id());
     }
@@ -72,11 +79,17 @@
     }
 
     public void mark(Node node) {
+        if (autoGrow && isNew(node)) {
+            grow();
+        }
         assert check(node);
         bitMap.set(node.id());
     }
 
     public void clear(Node node) {
+        if (autoGrow && isNew(node)) {
+            return;
+        }
         assert check(node);
         bitMap.clear(node.id());
     }
@@ -105,7 +118,7 @@
         return bitMap.toBinaryString();
     }
 
-    public <T extends Node> void markAll(Collection<T> nodes) {
+    public <T extends Node> void markAll(Iterable<T> nodes) {
         for (Node node : nodes) {
             mark(node);
         }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java	Tue May 22 16:19:02 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java	Tue May 22 16:31:30 2012 +0200
@@ -43,6 +43,9 @@
     public FilteredNodeIterable<T> filter(NodePredicate predicate) {
         return new FilteredNodeIterable<>(this).and(predicate);
     }
+    public FilteredNodeIterable<T> nonNull() {
+        return new FilteredNodeIterable<>(this).and(NodePredicates.isNotNull());
+    }
     public List<T> snapshot() {
         ArrayList<T> list = new ArrayList<>();
         for (T n : this) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java	Tue May 22 16:19:02 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java	Tue May 22 16:31:30 2012 +0200
@@ -289,7 +289,6 @@
             ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n;
             SafeReadNode safeReadArrayLength = safeReadArrayLength(arrayLengthNode.array(), StructuredGraph.INVALID_GRAPH_ID);
             graph.replaceFixedWithFixed(arrayLengthNode, safeReadArrayLength);
-            safeReadArrayLength.lower(tool);
         } else if (n instanceof LoadFieldNode) {
             LoadFieldNode field = (LoadFieldNode) n;
             int displacement = ((HotSpotField) field.field()).offset();
@@ -389,9 +388,6 @@
             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;
@@ -471,12 +467,12 @@
         return safeRead(array.graph(), CiKind.Int, array, config.arrayLengthOffset, StampFactory.positiveInt(), leafGraphId);
     }
 
-    private Node createBoundsCheck(AccessIndexedNode n, CiLoweringTool tool) {
-        SafeReadNode arrayLength = safeReadArrayLength(n.array(), n.leafGraphId());
-        Node guard = tool.createGuard(n.graph().unique(new IntegerBelowThanNode(n.index(), arrayLength)), RiDeoptReason.BoundsCheckException, RiDeoptAction.InvalidateReprofile, n.leafGraphId());
+    private static Node createBoundsCheck(AccessIndexedNode n, CiLoweringTool tool) {
+        StructuredGraph graph = (StructuredGraph) n.graph();
+        ArrayLengthNode arrayLength = graph.add(new ArrayLengthNode(n.array()));
+        Node guard = tool.createGuard(graph.unique(new IntegerBelowThanNode(n.index(), arrayLength)), RiDeoptReason.BoundsCheckException, RiDeoptAction.InvalidateReprofile, n.leafGraphId());
 
-        ((StructuredGraph) n.graph()).addBeforeFixed(n, arrayLength);
-        arrayLength.lower(tool);
+        graph.addBeforeFixed(n, arrayLength);
         return guard;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java	Tue May 22 16:19:02 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java	Tue May 22 16:31:30 2012 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.type.*;
 
 public abstract class FixedNode extends ValueNode {
@@ -32,6 +33,10 @@
         super(stamp);
     }
 
+    public FixedNode(Stamp stamp, Node... dependencies) {
+        super(stamp, dependencies);
+    }
+
     public double probability() {
         return probability;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java	Tue May 22 16:19:02 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java	Tue May 22 16:31:30 2012 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.type.*;
 
 /**
@@ -41,4 +42,8 @@
     public FixedWithNextNode(Stamp stamp) {
         super(stamp);
     }
+
+    public FixedWithNextNode(Stamp stamp, Node... dependencies) {
+        super(stamp, dependencies);
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Tue May 22 16:19:02 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Tue May 22 16:31:30 2012 +0200
@@ -72,7 +72,10 @@
         CiConstant constantIndex = index.asConstant();
         if (constantIndex != null && constantIndex.kind.stackKind().isInt()) {
             long constantIndexLong = constantIndex.asInt();
-            if (indexScalingEnabled && tool.target() != null) {
+            if (indexScalingEnabled) {
+                if (tool.target() == null) {
+                    return this;
+                }
                 constantIndexLong *= tool.target().sizeInBytes(getValueKind());
             }
             constantIndexLong += displacement();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Tue May 22 16:19:02 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Tue May 22 16:31:30 2012 +0200
@@ -22,12 +22,12 @@
  */
 package com.oracle.graal.nodes.extended;
 
-import com.oracle.max.cri.ci.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.max.cri.ci.*;
 
 /**
  * The ValueAnchor instruction keeps non-CFG (floating) nodes above a certain point in the graph.
@@ -35,15 +35,8 @@
 
 public final class ValueAnchorNode extends FixedWithNextNode implements Canonicalizable, LIRLowerable, Node.IterableNodeType {
 
-    @Input private ValueNode object;
-
-    public ValueNode object() {
-        return object;
-    }
-
-    public ValueAnchorNode(ValueNode object) {
-        super(StampFactory.illegal());
-        this.object = object;
+    public ValueAnchorNode(ValueNode... values) {
+        super(StampFactory.illegal(), values);
     }
 
     @Override
@@ -51,23 +44,36 @@
         // Nothing to emit, since this node is used for structural purposes only.
     }
 
+    public void addAnchoredValue(ValueNode value) {
+        this.dependencies().add(value);
+    }
+
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        if (object == null) {
-            return null;
-        }
-        if (object instanceof ConstantNode) {
+        if (this.predecessor() instanceof ValueAnchorNode) {
+            // transfer values and remove
+            ValueAnchorNode previousAnchor = (ValueAnchorNode) this.predecessor();
+            for (Node node : dependencies().nonNull()) {
+                previousAnchor.dependencies().add(node);
+            }
             return null;
         }
-        if (object instanceof IntegerDivNode || object instanceof IntegerRemNode) {
-            if (((ArithmeticNode) object).y().isConstant()) {
-                CiConstant  constant = ((ArithmeticNode) object).y().asConstant();
-                assert constant.kind == object.kind() : constant.kind + " != " + object.kind();
-                if (constant.asLong() != 0) {
-                    return null;
+        for (Node node : dependencies().nonNull()) {
+            if (node instanceof ConstantNode) {
+                continue;
+            }
+            if (node instanceof IntegerDivNode || node instanceof IntegerRemNode) {
+                ArithmeticNode arithmeticNode = (ArithmeticNode) node;
+                if (arithmeticNode.y().isConstant()) {
+                    CiConstant  constant = arithmeticNode.y().asConstant();
+                    assert constant.kind == arithmeticNode.kind() : constant.kind + " != " + arithmeticNode.kind();
+                    if (constant.asLong() != 0) {
+                        continue;
+                    }
                 }
             }
+            return this; // still necessary
         }
-        return this;
+        return null; // no node which require an anchor found
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Tue May 22 16:19:02 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Tue May 22 16:31:30 2012 +0200
@@ -74,10 +74,15 @@
     public ValueNode canonical(CanonicalizerTool tool) {
         assert object() != null : this;
 
-        RiResolvedType objectDeclaredType = object().declaredType();
-        if (objectDeclaredType != null && targetClass != null && objectDeclaredType.isSubtypeOf(targetClass)) {
-            // we don't have to check for null types here because they will also pass the checkcast.
-            return object();
+        if (targetClass != null) {
+            RiResolvedType objectType = object().exactType();
+            if (objectType == null) {
+                objectType = object().declaredType();
+            }
+            if (objectType != null && objectType.isSubtypeOf(targetClass)) {
+                // we don't have to check for null types here because they will also pass the checkcast.
+                return object();
+            }
         }
 
         CiConstant constant = object().asConstant();