changeset 3091:bee93b329be2

merge
author Lukas Stadler <lukas.stadler@jku.at>
date Tue, 28 Jun 2011 19:22:42 +0200
parents 536528f48708 (current diff) 1ddf16c7271d (diff)
children f34c90b89f54
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractMemoryMergeNode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MemoryMergeNode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java src/share/vm/graal/graalCodeInstaller.cpp src/share/vm/graal/graalJavaAccess.hpp
diffstat 48 files changed, 1842 insertions(+), 277 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Tue Jun 28 19:14:28 2011 +0200
+++ b/.hgignore	Tue Jun 28 19:22:42 2011 +0200
@@ -17,6 +17,10 @@
 \.orig$
 output\.txt$
 output\.cfg$
+^Test.java$
+^diff1.txt$
+^diff2.txt$
+^test.xml$
 java\.hprof\.txt$
 /nbproject/private/
 ^graal/hotspot/java$
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java	Tue Jun 28 19:22:42 2011 +0200
@@ -72,7 +72,7 @@
         Graph.verificationListeners.add(new VerificationListener() {
             @Override
             public void verificationFailed(Node n, String message) {
-                GraalCompiler.this.fireCompilationEvent(new CompilationEvent(currentCompilation, "Verification Error on Node " + n.id(), currentCompilation.graph, true, false));
+                GraalCompiler.this.fireCompilationEvent(new CompilationEvent(currentCompilation, "Verification Error on Node " + n.id(), currentCompilation.graph, true, false, true));
                 for (Node p : n.predecessors()) {
                     TTY.println("predecessor: " + p);
                 }
@@ -142,7 +142,7 @@
         if (GraalOptions.PrintDOTGraphToPdf) {
             addCompilationObserver(new GraphvizPrinterObserver(true));
         }
-        if (GraalOptions.PrintIdealGraphLevel != 0 || GraalOptions.Plot) {
+        if (GraalOptions.PrintIdealGraphLevel != 0 || GraalOptions.Plot || GraalOptions.PlotOnError) {
             CompilationObserver observer;
             if (GraalOptions.PrintIdealGraphFile) {
                 observer = new IdealGraphPrinterObserver();
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Tue Jun 28 19:22:42 2011 +0200
@@ -85,6 +85,7 @@
 
     // Ideal graph visualizer output settings
     public static boolean Plot                               = ____;
+    public static boolean PlotOnError                        = ____;
     public static int     PrintIdealGraphLevel               = 0;
     public static boolean PrintIdealGraphFile                = ____;
     public static String  PrintIdealGraphAddress             = "127.0.0.1";
@@ -108,6 +109,7 @@
     public static boolean TraceDeadCodeElimination           = ____;
     public static boolean TraceEscapeAnalysis                = ____;
     public static boolean TraceMemoryMaps                    = ____;
+    public static boolean TraceReadElimination               = ____;
     public static int     TraceBytecodeParserLevel           = 0;
     public static boolean QuietBailout                       = ____;
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Tue Jun 28 19:22:42 2011 +0200
@@ -1915,7 +1915,7 @@
         } while (current != null);
 
         for (CiValue val : values) {
-            assert val != null;
+//            assert val != null;
         }
 
         CiVirtualObject vobj = CiVirtualObject.get(type, values, obj.id());
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java	Tue Jun 28 19:22:42 2011 +0200
@@ -24,6 +24,7 @@
 
 import java.io.*;
 import java.util.*;
+import java.util.AbstractMap.SimpleImmutableEntry;
 import java.util.Map.Entry;
 
 import com.oracle.max.graal.compiler.ir.*;
@@ -109,10 +110,14 @@
         flush();
     }
 
+    public void print(Graph graph, String title, boolean shortNames) {
+        print(graph, title, shortNames, Collections.<String, Object>emptyMap());
+    }
+
     /**
      * Prints an entire {@link Graph} with the specified title, optionally using short names for nodes.
      */
-    public void print(Graph graph, String title, boolean shortNames) {
+    public void print(Graph graph, String title, boolean shortNames, Map<String, Object> debugObjects) {
         stream.printf(" <graph name='%s'>%n", escape(title));
         noBlockNodes.clear();
         IdentifyBlocksPhase schedule = null;
@@ -121,12 +126,17 @@
             schedule.apply(graph);
         } catch (Throwable t) {
             // nothing to do here...
-            t.printStackTrace();
+            //t.printStackTrace();
         }
-        List<Loop> loops = LoopUtil.computeLoops(graph);
+        List<Loop> loops = null;
+        try {
+            LoopUtil.computeLoops(graph);
+        } catch (Throwable t) {
+
+        }
 
         stream.println("  <nodes>");
-        List<Edge> edges = printNodes(graph, shortNames, schedule == null ? null : schedule.getNodeToBlock(), loops);
+        List<Edge> edges = printNodes(graph, shortNames, schedule == null ? null : schedule.getNodeToBlock(), loops, debugObjects);
         stream.println("  </nodes>");
 
         stream.println("  <edges>");
@@ -148,11 +158,52 @@
         flush();
     }
 
-    private List<Edge> printNodes(Graph graph, boolean shortNames, NodeMap<Block> nodeToBlock, List<Loop> loops) {
+    private List<Edge> printNodes(Graph graph, boolean shortNames, NodeMap<Block> nodeToBlock, List<Loop> loops, Map<String, Object> debugObjects) {
         ArrayList<Edge> edges = new ArrayList<Edge>();
         NodeBitMap loopExits = graph.createNodeBitMap();
-        for (Loop loop : loops) {
-            loopExits.markAll(loop.exist());
+        if (loops != null) {
+            for (Loop loop : loops) {
+                loopExits.setUnion(loop.exits());
+            }
+        }
+
+        Map<Node, Set<Entry<String, Integer>>> colors = new HashMap<Node, Set<Entry<String, Integer>>>();
+        Map<Node, Set<String>> bits = new HashMap<Node, Set<String>>();
+        if (debugObjects != null) {
+            for (Entry<String, Object> entry : debugObjects.entrySet()) {
+                String name = entry.getKey();
+                Object obj = entry.getValue();
+                if (obj instanceof NodeMap) {
+                    Map<Object, Integer> colorNumbers = new HashMap<Object, Integer>();
+                    int nextColor = 0;
+                    NodeMap<?> map = (NodeMap<?>) obj;
+                    for (Entry<Node, ?> mapEntry : map.entries()) {
+                        Node node = mapEntry.getKey();
+                        Object color = mapEntry.getValue();
+                        Integer colorNumber = colorNumbers.get(color);
+                        if (colorNumber == null) {
+                            colorNumber = nextColor++;
+                            colorNumbers.put(color, colorNumber);
+                        }
+                        Set<Entry<String, Integer>> nodeColors = colors.get(node);
+                        if (nodeColors == null) {
+                            nodeColors = new HashSet<Entry<String, Integer>>();
+                            colors.put(node, nodeColors);
+                        }
+                        nodeColors.add(new SimpleImmutableEntry<String, Integer>(name + "Color", colorNumber));
+                    }
+                } else if (obj instanceof NodeBitMap) {
+                    NodeBitMap bitmap = (NodeBitMap) obj;
+                    for (Node node : bitmap) {
+                        Set<String> nodeBits = bits.get(node);
+                        if (nodeBits == null) {
+                            nodeBits = new HashSet<String>();
+                            bits.put(node, nodeBits);
+                        }
+                        nodeBits.add(name);
+                    }
+                }
+            }
         }
 
         for (Node node : graph.getNodes()) {
@@ -188,17 +239,35 @@
                 stream.printf("    <p name='loopExit'>true</p>%n");
             }
             StringBuilder sb = new StringBuilder();
-            for (Loop loop : loops) {
-                if (loop.nodes().isMarked(node)) {
-                    if (sb.length() > 0) {
-                        sb.append(", ");
+            if (loops != null) {
+                for (Loop loop : loops) {
+                    if (loop.nodes().isMarked(node)) {
+                        if (sb.length() > 0) {
+                            sb.append(", ");
+                        }
+                        sb.append(loop.loopBegin().id());
                     }
-                    sb.append(loop.loopBegin().id());
                 }
             }
             if (sb.length() > 0) {
                 stream.printf("    <p name='loops'>%s</p>%n", sb);
             }
+
+            Set<Entry<String, Integer>> nodeColors = colors.get(node);
+            if (nodeColors != null) {
+                for (Entry<String, Integer> color : nodeColors) {
+                    String name = color.getKey();
+                    Integer value = color.getValue();
+                    stream.printf("    <p name='%s'>%d</p>%n", name, value);
+                }
+            }
+            Set<String> nodeBits = bits.get(node);
+            if (nodeBits != null) {
+                for (String bit : nodeBits) {
+                    stream.printf("    <p name='%s'>true</p>%n", bit);
+                }
+            }
+
             for (Entry<Object, Object> entry : props.entrySet()) {
                 String key = entry.getKey().toString();
                 String value = entry.getValue() == null ? "null" : entry.getValue().toString();
@@ -237,11 +306,9 @@
         stream.printf("   <block name='%d'>%n", block.blockID());
         stream.printf("    <successors>%n");
         for (Block sux : block.getSuccessors()) {
-//            if (sux.firstNode() instanceof LoopBegin && block.lastNode() instanceof LoopEnd) { //TODO gd
-//                // Skip back edges.
-//            } else {
+            if (sux != null) {
                 stream.printf("     <successor name='%d'/>%n", sux.blockID());
-//            }
+            }
         }
         stream.printf("    </successors>%n");
         stream.printf("    <nodes>%n");
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinterObserver.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinterObserver.java	Tue Jun 28 19:22:42 2011 +0200
@@ -67,7 +67,7 @@
     public void compilationStarted(CompilationEvent event) {
         assert (stream == null && printer == null);
 
-        if (!TTY.isSuppressed()) {
+        if ((!TTY.isSuppressed() && GraalOptions.Plot) || (GraalOptions.PlotOnError && event.isErrorEvent())) {
             String name = event.getMethod().holder().name();
             name = name.substring(1, name.length() - 1).replace('/', '.');
             name = name + "." + event.getMethod().name();
@@ -140,9 +140,12 @@
 
     @Override
     public void compilationEvent(CompilationEvent event) {
+        if (printer == null && event.isErrorEvent()) {
+            this.compilationStarted(event); // lazy start
+        }
         if (printer != null && event.getGraph() != null && event.isHIRValid()) {
             Graph graph = event.getGraph();
-            printer.print(graph, event.getLabel(), true);
+            printer.print(graph, event.getLabel(), true, event.getDebugObjects());
         }
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Tue Jun 28 19:22:42 2011 +0200
@@ -1053,7 +1053,7 @@
             lastState = fs;
         } else if (block.blockPredecessors().size() == 1) {
             FrameState fs = block.blockPredecessors().get(0).lastState();
-            assert fs != null; //TODO gd maybe this assert should be removed
+            assert fs != null;
             if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
                 TTY.println("STATE CHANGE (singlePred)");
                 if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
@@ -1464,6 +1464,9 @@
     }
 
     private void moveToPhi(Merge merge, Node pred) {
+        if (GraalOptions.TraceLIRGeneratorLevel >= 1) {
+            TTY.println("MOVE TO PHI from " + pred + " to " + merge);
+        }
         int nextSuccIndex = merge.phiPredecessorIndex(pred);
         PhiResolver resolver = new PhiResolver(this);
         for (Phi phi : merge.phis()) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Tue Jun 28 19:22:42 2011 +0200
@@ -114,6 +114,7 @@
         if (GraalOptions.Lower) {
             new LoweringPhase(compilation.runtime).apply(graph);
             new MemoryPhase().apply(graph);
+            new ReadEliminationPhase().apply(graph);
         }
 
         IdentifyBlocksPhase schedule = new IdentifyBlocksPhase(true);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractMemoryCheckpointNode.java	Tue Jun 28 19:22:42 2011 +0200
@@ -0,0 +1,54 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public abstract class AbstractMemoryCheckpointNode extends StateSplit {
+
+    private static final int SUCCESSOR_COUNT = 0;
+    private static final int INPUT_COUNT = 0;
+
+    public AbstractMemoryCheckpointNode(Graph graph) {
+        this(CiKind.Illegal, 0, 0, graph);
+    }
+
+    public AbstractMemoryCheckpointNode(CiKind result, int inputCount, int successorCount, Graph graph) {
+        super(result, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    }
+
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> debugProperties = super.getDebugProperties();
+        debugProperties.put("memoryCheckpoint", "true");
+        return debugProperties;
+    }
+
+    public List<Node> mergedNodes() {
+        return inputs().variablePart();
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractMemoryMergeNode.java	Tue Jun 28 19:14:28 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +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.max.graal.compiler.ir;
-
-import java.util.*;
-
-import com.oracle.max.graal.graph.*;
-import com.sun.cri.ci.*;
-
-
-public abstract class AbstractMemoryMergeNode extends StateSplit {
-
-    private static final int SUCCESSOR_COUNT = 0;
-    private static final int INPUT_COUNT = 0;
-
-    public AbstractMemoryMergeNode(Graph graph) {
-        this(CiKind.Illegal, 0, 0, graph);
-    }
-
-    public AbstractMemoryMergeNode(CiKind result, int inputCount, int successorCount, Graph graph) {
-        super(result, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
-    }
-
-    public List<Node> mergedNodes() {
-        return inputs().variablePart();
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessMonitor.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessMonitor.java	Tue Jun 28 19:22:42 2011 +0200
@@ -28,7 +28,7 @@
 /**
  * The {@code AccessMonitor} instruction is the base class of both monitor acquisition and release.
  */
-public abstract class AccessMonitor extends AbstractMemoryMergeNode {
+public abstract class AccessMonitor extends AbstractMemoryCheckpointNode {
 
     private static final int INPUT_COUNT = 2;
     private static final int INPUT_OBJECT = 0;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessNode.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessNode.java	Tue Jun 28 19:22:42 2011 +0200
@@ -27,10 +27,11 @@
 import com.sun.cri.ci.*;
 
 
-public abstract class AccessNode extends StateSplit {
-    private static final int INPUT_COUNT = 2;
+public abstract class AccessNode extends AbstractMemoryCheckpointNode {
+    private static final int INPUT_COUNT = 3;
     private static final int INPUT_NODE = 0;
-    private static final int INPUT_GUARD = 1;
+    private static final int INPUT_LOCATION = 1;
+    private static final int INPUT_GUARD = 2;
 
     private static final int SUCCESSOR_COUNT = 0;
 
@@ -58,12 +59,16 @@
     }
 
     public LocationNode location() {
-        return location;
+        return (LocationNode) inputs().get(super.inputCount() + INPUT_LOCATION);
+    }
+
+    public void setLocation(LocationNode n) {
+        inputs().set(super.inputCount() + INPUT_LOCATION, n);
     }
 
     public AccessNode(CiKind kind, Value object, LocationNode location, int inputCount, int successorCount, Graph graph) {
         super(kind, INPUT_COUNT + inputCount, SUCCESSOR_COUNT + successorCount, graph);
-        this.location = location;
+        setLocation(location);
         setObject(object);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/EndNode.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/EndNode.java	Tue Jun 28 19:22:42 2011 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.max.graal.compiler.ir;
 
+import java.util.*;
+
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
@@ -67,4 +69,9 @@
         assertTrue(predecessors().size() <= 1, "at most one predecessor");
         return true;
     }
+
+    @Override
+    public Iterable< ? extends Node> dataUsages() {
+        return Collections.emptyList();
+    }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java	Tue Jun 28 19:22:42 2011 +0200
@@ -34,7 +34,7 @@
 /**
  * The {@code Invoke} instruction represents all kinds of method calls.
  */
-public final class Invoke extends AbstractMemoryMergeNode implements ExceptionEdgeInstruction {
+public final class Invoke extends AbstractMemoryCheckpointNode implements ExceptionEdgeInstruction {
 
     private final int argumentCount;
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LocationNode.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LocationNode.java	Tue Jun 28 19:22:42 2011 +0200
@@ -34,13 +34,13 @@
 
     private int displacement;
     private CiKind valueKind;
-    private Object identity;
+    private Object locationIdentity;
 
     public LocationNode(Object identity, CiKind kind, int displacement, Graph graph) {
         super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.displacement = displacement;
         this.valueKind = kind;
-        this.identity = identity;
+        this.locationIdentity = identity;
     }
 
     @Override
@@ -62,10 +62,18 @@
 
     @Override
     public Node copy(Graph into) {
-        return new LocationNode(identity, valueKind, displacement, into);
+        return new LocationNode(locationIdentity, valueKind, displacement, into);
     }
 
     public CiValue createAddress(LIRGenerator lirGenerator, Value object) {
         return new CiAddress(valueKind, lirGenerator.load(object), displacement);
     }
+
+    public Object locationIdentity() {
+        return locationIdentity;
+    }
+
+    public boolean same(LocationNode location) {
+        return valueKind == location.valueKind && displacement == location.displacement;
+    }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopBegin.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopBegin.java	Tue Jun 28 19:22:42 2011 +0200
@@ -28,10 +28,9 @@
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.graph.*;
 
-public class LoopBegin extends Merge{
+public class LoopBegin extends Merge {
     public LoopBegin(Graph graph) {
         super(graph);
-        this.addEnd(new EndNode(graph));
     }
 
     public LoopEnd loopEnd() {
@@ -83,6 +82,16 @@
         throw Util.shouldNotReachHere("unknown pred : " + pred + "(sp=" + forwardEdge() + ", le=" + this.loopEnd() + ")");
     }
 
+    @Override
+    public Node phiPredecessorAt(int index) {
+        if (index == 0) {
+            return forwardEdge();
+        } else if (index == 1) {
+            return loopEnd();
+        }
+        throw Util.shouldNotReachHere();
+    }
+
     public Collection<LoopCounter> counters() {
         return Util.filter(this.usages(), LoopCounter.class);
     }
@@ -109,6 +118,12 @@
     }
 
     @Override
+    public Node singlePredecessor() {
+        assert endCount() == 1;
+        return endAt(0).singlePredecessor();
+    }
+
+    @Override
     public Iterable< ? extends Node> dataUsages() {
         final Iterator< ? extends Node> dataUsages = super.dataUsages().iterator();
         return new Iterable<Node>() {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MemoryMergeNode.java	Tue Jun 28 19:14:28 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +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.max.graal.compiler.ir;
-
-import com.oracle.max.graal.compiler.gen.*;
-import com.oracle.max.graal.graph.*;
-import com.sun.cri.ci.*;
-
-
-public final class MemoryMergeNode extends AbstractMemoryMergeNode {
-
-    private static final int SUCCESSOR_COUNT = 0;
-    private static final int INPUT_COUNT = 0;
-
-    public MemoryMergeNode(Graph graph) {
-        this(CiKind.Illegal, 0, 0, graph);
-    }
-
-    public MemoryMergeNode(CiKind result, int inputCount, int successorCount, Graph graph) {
-        super(result, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
-    }
-
-    @Override
-    public <T extends Op> T lookup(Class<T> clazz) {
-        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
-            return null;
-        }
-        return super.lookup(clazz);
-    }
-
-    @Override
-    public Node copy(Graph into) {
-        return new MemoryMergeNode(into);
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Merge.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Merge.java	Tue Jun 28 19:22:42 2011 +0200
@@ -337,6 +337,10 @@
         return endIndex(end);
     }
 
+    public Node phiPredecessorAt(int index) {
+        return endAt(index);
+    }
+
     public Collection<Phi> phis() {
         return Util.filter(this.usages(), Phi.class);
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Phi.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Phi.java	Tue Jun 28 19:22:42 2011 +0200
@@ -22,7 +22,10 @@
  */
 package com.oracle.max.graal.compiler.ir;
 
+import java.util.*;
+
 import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.ir.StateSplit.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
 
@@ -59,6 +62,7 @@
     }
 
     public void setMerge(Merge n) {
+        assert n != null;
         inputs().set(super.inputCount() + INPUT_MERGE, n);
     }
 
@@ -156,4 +160,16 @@
         x.isDead = isDead;
         return x;
     }
+
+    @Override
+    public Iterable<? extends Node> dataInputs() {
+        final Iterator< ? extends Node> input = super.dataInputs().iterator();
+        return new Iterable<Node>() {
+            @Override
+            public Iterator<Node> iterator() {
+                // TODO Auto-generated method stub
+                return new FilteringIterator(input, Merge.class);
+            }
+        };
+    }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java	Tue Jun 28 19:22:42 2011 +0200
@@ -26,7 +26,6 @@
 
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.gen.*;
-import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
@@ -179,7 +178,7 @@
         return properties;
     }
 
-    @Override
+    /*@Override
     public Iterable<? extends Node> dataUsages() {
         final Iterator<? extends Node> dataUsages = super.dataUsages().iterator();
         return new Iterable<Node>() {
@@ -188,5 +187,5 @@
                 return new StateSplit.FilteringIterator(dataUsages, FrameState.class);
             }
         };
-    }
+    }*/
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/WriteMemoryCheckpointNode.java	Tue Jun 28 19:22:42 2011 +0200
@@ -0,0 +1,55 @@
+/*
+ * 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class WriteMemoryCheckpointNode extends AbstractMemoryCheckpointNode {
+
+    private static final int SUCCESSOR_COUNT = 0;
+    private static final int INPUT_COUNT = 0;
+
+    public WriteMemoryCheckpointNode(Graph graph) {
+        this(CiKind.Illegal, 0, 0, graph);
+    }
+
+    public WriteMemoryCheckpointNode(CiKind result, int inputCount, int successorCount, Graph graph) {
+        super(result, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    }
+
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return null;
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new WriteMemoryCheckpointNode(into);
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/FrameMap.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/FrameMap.java	Tue Jun 28 19:22:42 2011 +0200
@@ -33,7 +33,6 @@
 import com.sun.cri.ci.*;
 import com.sun.cri.ci.CiCallingConvention.*;
 import com.sun.cri.ri.*;
-import com.sun.cri.util.*;
 
 /**
  * This class is used to build the stack frame layout for a compiled method.
@@ -130,7 +129,7 @@
             incomingArguments = new CiCallingConvention(new CiValue[0], 0);
         } else {
             CiKind receiver = !isStatic(method.accessFlags()) ? method.holder().kind() : null;
-            incomingArguments = getCallingConvention(CRIUtil.signatureToKinds(method.signature(), receiver), JavaCallee);
+            incomingArguments = getCallingConvention(CiUtil.signatureToKinds(method.signature(), receiver), JavaCallee);
         }
     }
 
@@ -142,7 +141,7 @@
      * @return a {@link CiCallingConvention} instance describing the location of parameters and the return value
      */
     public CiCallingConvention getCallingConvention(CiKind[] signature, Type type) {
-        CiCallingConvention cc = compilation.registerConfig.getCallingConvention(type, signature, compilation.target);
+        CiCallingConvention cc = compilation.registerConfig.getCallingConvention(type, signature, compilation.target, false);
         if (type == RuntimeCall) {
             assert cc.stackSize == 0 : "runtime call should not have stack arguments";
         } else if (type.out) {
@@ -189,7 +188,7 @@
 
         this.spillSlotCount = spillSlotCount;
         int frameSize = offsetToStackBlocksEnd();
-        frameSize += compilation.registerConfig.getCalleeSaveArea().size;
+        frameSize += compilation.registerConfig.getCalleeSaveLayout().size;
         this.frameSize = compilation.target.alignFrameSize(frameSize);
     }
 
@@ -364,7 +363,7 @@
     }
 
     public int offsetToCalleeSaveAreaStart() {
-        return offsetToCalleeSaveAreaEnd() - compilation.registerConfig.getCalleeSaveArea().size;
+        return offsetToCalleeSaveAreaEnd() - compilation.registerConfig.getCalleeSaveLayout().size;
     }
 
     public int offsetToCalleeSaveAreaEnd() {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/observer/CompilationEvent.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/observer/CompilationEvent.java	Tue Jun 28 19:22:42 2011 +0200
@@ -52,6 +52,8 @@
     private CiTargetMethod targetMethod;
     private boolean hirValid = false;
     private boolean lirValid = false;
+    private boolean errorEvent;
+    private Map<String, Object> debugObjects;
 
     private Interval[] intervals;
     private int intervalsSize;
@@ -68,10 +70,23 @@
     }
 
     public CompilationEvent(GraalCompilation compilation, String label, Graph graph, boolean hirValid, boolean lirValid) {
+        this(compilation, label, graph, hirValid, lirValid, false, (Map<String, Object>) null);
+    }
+    public CompilationEvent(GraalCompilation compilation, String label, Graph graph, boolean hirValid, boolean lirValid, boolean error) {
+        this(compilation, label, graph, hirValid, lirValid, error, (Map<String, Object>) null);
+    }
+
+    public CompilationEvent(GraalCompilation compilation, String label, Graph graph, boolean hirValid, boolean lirValid, Map<String, Object> debugObjects) {
+        this(compilation, label, graph, hirValid, lirValid, false, debugObjects);
+    }
+
+    public CompilationEvent(GraalCompilation compilation, String label, Graph graph, boolean hirValid, boolean lirValid, boolean error, Map<String, Object> debugObjects) {
         this(compilation, label);
         this.graph = graph;
         this.hirValid = hirValid;
         this.lirValid = lirValid;
+        this.debugObjects = debugObjects;
+        this.errorEvent = error;
     }
 
     public CompilationEvent(GraalCompilation compilation, String label, Graph graph, boolean hirValid, boolean lirValid, CiTargetMethod targetMethod) {
@@ -128,6 +143,10 @@
         return lirValid;
     }
 
+    public boolean isErrorEvent() {
+        return errorEvent;
+    }
+
     public Interval[] getIntervals() {
         if (intervalsCopy == null && intervals != null) {
             // deferred copy of the valid range of the intervals array
@@ -139,4 +158,9 @@
     public int getCodeSize() {
         return codeSize;
     }
+
+
+    public Map<String, Object> getDebugObjects() {
+        return debugObjects;
+    }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Tue Jun 28 19:22:42 2011 +0200
@@ -201,7 +201,7 @@
         List<Loop> loops = LoopUtil.computeLoops(graph);
         NodeBitMap loopExits = graph.createNodeBitMap();
         for (Loop loop : loops) {
-            loopExits.markAll(loop.exist());
+            loopExits.setUnion(loop.exits());
         }
 
         // remove Placeholders
@@ -1167,6 +1167,7 @@
         if (block.firstInstruction == null) {
             if (block.isLoopHeader) {
                 LoopBegin loopBegin = new LoopBegin(graph);
+                loopBegin.addEnd(new EndNode(graph));
                 LoopEnd loopEnd = new LoopEnd(graph);
                 loopEnd.setLoopBegin(loopBegin);
                 Placeholder pBegin = new Placeholder(graph);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java	Tue Jun 28 19:22:42 2011 +0200
@@ -26,6 +26,7 @@
 
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.compiler.util.LoopUtil.Loop;
 import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
@@ -35,14 +36,21 @@
 
     @Override
     protected void run(Graph graph) {
-        for (LoopBegin n : graph.getNodes(LoopBegin.class)) {
-            doLoop(n);
+        List<Loop> loops = LoopUtil.computeLoops(graph);
+
+//        for (Loop loop : loops) {
+//            LoopUtil.peelLoop(loop);
+//        }
+//        loops = LoopUtil.computeLoops(graph); // TODO (gd) avoid recomputing loops
+
+        for (Loop loop : loops) {
+            doLoopCounters(loop);
         }
     }
 
-    private void doLoop(LoopBegin loopBegin) {
-        NodeBitMap loopNodes = LoopUtil.computeLoopNodes(loopBegin);
-        List<LoopCounter> counters = findLoopCounters(loopBegin, loopNodes);
+    private void doLoopCounters(Loop loop) {
+        LoopBegin loopBegin = loop.loopBegin();
+        List<LoopCounter> counters = findLoopCounters(loopBegin, loop.nodes());
         mergeLoopCounters(counters, loopBegin);
     }
 
@@ -102,6 +110,9 @@
                 if (phi.valueCount() == 2) {
                     Value backEdge = phi.valueAt(1);
                     Value init = phi.valueAt(0);
+                    if (loopNodes.isNew(init) || loopNodes.isNew(backEdge)) {
+                        continue;
+                    }
                     if (loopNodes.isMarked(init)) {
                         // try to reverse init/backEdge order
                         Value tmp = backEdge;
@@ -127,7 +138,7 @@
                             useCounterAfterAdd = true;
                         }
                     }
-                    if (stride != null && !loopNodes.isMarked(stride)) {
+                    if (stride != null && !loopNodes.isNew(stride) &&  !loopNodes.isMarked(stride)) {
                         Graph graph = loopBegin.graph();
                         LoopCounter counter = new LoopCounter(init.kind, init, stride, loopBegin, graph);
                         counters.add(counter);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/MemoryPhase.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/MemoryPhase.java	Tue Jun 28 19:22:42 2011 +0200
@@ -30,85 +30,224 @@
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
 
 public class MemoryPhase extends Phase {
 
     public static class MemoryMap {
 
         private final Block block;
-        private HashMap<Object, Node> locationToWrite;
-        private HashMap<Object, List<Node>> locationToReads;
+        private HashMap<Object, Node> locationForWrite;
+        private HashMap<Object, Node> locationForRead;
+        private Node mergeForWrite;
+        private Node mergeForRead;
+        private int mergeOperationCount;
+        private Node loopCheckPoint;
+        private MemoryMap loopEntryMap;
 
         public MemoryMap(Block b, MemoryMap memoryMap) {
             this(b);
+            if (b.firstNode() instanceof LoopBegin) {
+                loopCheckPoint = new WriteMemoryCheckpointNode(b.firstNode().graph());
+                mergeForWrite = loopCheckPoint;
+                mergeForRead = loopCheckPoint;
+                this.loopEntryMap = memoryMap;
+            } else {
+                memoryMap.locationForWrite.putAll(memoryMap.locationForWrite);
+                memoryMap.locationForRead.putAll(memoryMap.locationForRead);
+                mergeForWrite = memoryMap.mergeForWrite;
+                mergeForRead = memoryMap.mergeForRead;
+            }
         }
 
         public MemoryMap(Block b) {
-            block = b;
-            locationToWrite = new HashMap<Object, Node>();
-            locationToReads = new HashMap<Object, List<Node>>();
             if (GraalOptions.TraceMemoryMaps) {
                 TTY.println("Creating new memory map for block B" + b.blockID());
             }
+
+            block = b;
+            locationForWrite = new HashMap<Object, Node>();
+            locationForRead = new HashMap<Object, Node>();
+            StartNode startNode = b.firstNode().graph().start();
+            if (b.firstNode() == startNode) {
+                WriteMemoryCheckpointNode checkpoint = new WriteMemoryCheckpointNode(startNode.graph());
+                checkpoint.setNext((FixedNode) startNode.start());
+                startNode.setStart(checkpoint);
+                mergeForWrite = checkpoint;
+                mergeForRead = checkpoint;
+            }
         }
 
-        public void mergeWith(MemoryMap memoryMap) {
+        public Node getLoopCheckPoint() {
+            return loopCheckPoint;
+        }
+
+        public MemoryMap getLoopEntryMap() {
+            return loopEntryMap;
+        }
+
+        public void resetMergeOperationCount() {
+            mergeOperationCount = 0;
+        }
+
+        public void mergeWith(MemoryMap memoryMap, Block block) {
             if (GraalOptions.TraceMemoryMaps) {
                 TTY.println("Merging with memory map of block B" + memoryMap.block.blockID());
             }
+            mergeForWrite = mergeNodes(mergeForWrite, memoryMap.mergeForWrite, locationForWrite, memoryMap.locationForWrite, block);
+            mergeForRead = mergeNodes(mergeForRead, memoryMap.mergeForRead, locationForRead, memoryMap.locationForRead, block);
+            mergeOperationCount++;
         }
 
-        public void createMemoryMerge(AbstractMemoryMergeNode memMerge) {
+        private Node mergeNodes(Node mergeLeft, Node mergeRight, HashMap<Object, Node> locationLeft, HashMap<Object, Node> locationRight, Block block) {
             if (GraalOptions.TraceMemoryMaps) {
-                TTY.println("Creating memory merge at node " + memMerge.id());
+                TTY.println("Merging main merge nodes: " + mergeLeft.id() + " and " + mergeRight.id());
+            }
+
+            for (Entry<Object, Node> e : locationRight.entrySet()) {
+                if (!locationLeft.containsKey(e.getKey())) {
+                    // Only available in right map => create correct node for left map.
+                    if (GraalOptions.TraceMemoryMaps) {
+                        TTY.println("Only right map " + e.getKey());
+                    }
+                    Node leftNode = mergeLeft;
+                    if (leftNode instanceof Phi && ((Phi) leftNode).merge() == block.firstNode()) {
+                        leftNode = leftNode.copyWithEdges();
+                    }
+                    locationLeft.put(e.getKey(), leftNode);
+                }
+            }
+
+            for (Entry<Object, Node> e : locationLeft.entrySet()) {
+                if (locationRight.containsKey(e.getKey())) {
+                    // Available in both maps.
+                    if (GraalOptions.TraceMemoryMaps) {
+                        TTY.println("Merging entries for location " + e.getKey());
+                    }
+                    locationLeft.put(e.getKey(), mergeNodes(e.getValue(), locationRight.get(e.getKey()), block));
+                } else {
+                    // Only available in left map.
+                    if (GraalOptions.TraceMemoryMaps) {
+                        TTY.println("Only available in left map " + e.getKey());
+                    }
+                    locationLeft.put(e.getKey(), mergeNodes(e.getValue(), mergeRight, block));
+                }
             }
 
-            for (Entry<Object, Node> writeEntry : locationToWrite.entrySet()) {
+            return mergeNodes(mergeLeft, mergeRight, block);
+        }
+
+        private Node mergeNodes(Node original, Node newValue, Block block) {
+            if (original == newValue) {
+                // Nothing to merge.
+                if (GraalOptions.TraceMemoryMaps) {
+                    TTY.println("Nothing to merge both nodes are " + original.id());
+                }
+                return original;
+            }
+            Merge m = (Merge) block.firstNode();
+            if (original instanceof Phi && ((Phi) original).merge() == m) {
+                Phi phi = (Phi) original;
+                phi.addInput(newValue);
+                if (GraalOptions.TraceMemoryMaps) {
+                    TTY.println("Add new input to phi " + original.id());
+                }
+                assert phi.valueCount() <= phi.merge().endCount();
+                return original;
+            } else {
+                Phi phi = new Phi(CiKind.Illegal, m, m.graph());
+                phi.makeDead(); // Phi does not produce a value, it is only a memory phi.
+                for (int i = 0; i < mergeOperationCount + 1; ++i) {
+                    phi.addInput(original);
+                }
+                phi.addInput(newValue);
+                if (GraalOptions.TraceMemoryMaps) {
+                    TTY.println("Creating new phi " + phi.id());
+                }
+                assert phi.valueCount() <= phi.merge().endCount() + ((phi.merge() instanceof LoopBegin) ? 1 : 0) : phi.merge() + "/" + phi.valueCount() + "/" + phi.merge().endCount() + "/" + mergeOperationCount;
+                return phi;
+            }
+        }
+
+        public void createWriteMemoryMerge(AbstractMemoryCheckpointNode memMerge) {
+            if (GraalOptions.TraceMemoryMaps) {
+                TTY.println("Creating write memory checkpoint at node " + memMerge.id());
+            }
+
+            // Merge in all writes.
+            for (Entry<Object, Node> writeEntry : locationForWrite.entrySet()) {
                 memMerge.mergedNodes().add(writeEntry.getValue());
             }
-
-            for (Entry<Object, List<Node>> readEntry : locationToReads.entrySet()) {
-                memMerge.mergedNodes().addAll(readEntry.getValue());
-            }
-
-            locationToReads.clear();
-            locationToWrite.clear();
+            locationForWrite.clear();
+            mergeForWrite = memMerge;
         }
 
-        public void registerWrite(Object location, Node node) {
+        public void createReadWriteMemoryCheckpoint(AbstractMemoryCheckpointNode memMerge) {
+            if (GraalOptions.TraceMemoryMaps) {
+                TTY.println("Creating readwrite memory checkpoint at node " + memMerge.id());
+            }
+            createWriteMemoryMerge(memMerge);
+            locationForRead.clear();
+            mergeForRead = memMerge;
+        }
+
+        public void registerWrite(WriteNode node) {
+            Object location = node.location().locationIdentity();
             if (GraalOptions.TraceMemoryMaps) {
                 TTY.println("Register write to " + location + " at node " + node.id());
             }
 
-            if (locationToWrite.containsKey(location)) {
-                Node prevWrite = locationToWrite.get(location);
-                node.inputs().add(prevWrite);
+            // Create dependency on previous write to same location.
+            node.inputs().variablePart().add(getLocationForWrite(node));
+
+            locationForWrite.put(location, node);
+            locationForRead.put(location, node);
+        }
+
+        public Node getLocationForWrite(WriteNode node) {
+            Object location = node.location().locationIdentity();
+            if (locationForWrite.containsKey(location)) {
+                Node prevWrite = locationForWrite.get(location);
+                return prevWrite;
+            } else {
+                return mergeForWrite;
+            }
+        }
+
+        public void registerRead(ReadNode node) {
+            if (GraalOptions.TraceMemoryMaps) {
+                TTY.println("Register read to node " + node.id());
             }
 
-            if (locationToReads.containsKey(location)) {
-                for (Node prevRead : locationToReads.get(location)) {
-                    node.inputs().add(prevRead);
-                }
-            }
-            locationToWrite.put(location, node);
-            locationToReads.remove(location);
+            // Create dependency on previous node that creates the memory state for this location.
+            node.inputs().variablePart().add(getLocationForRead(node));
         }
 
-        public void registerRead(Object location, Node node) {
-            if (GraalOptions.TraceMemoryMaps) {
-                TTY.println("Register read to " + location + " at node " + node.id());
+        public Node getLocationForRead(ReadNode node) {
+            Object location = node.location().locationIdentity();
+            if (locationForRead.containsKey(location)) {
+                return locationForRead.get(location);
             }
+            return mergeForRead;
+        }
 
-            if (locationToWrite.containsKey(location)) {
-                Node prevWrite = locationToWrite.get(location);
-                node.inputs().add(prevWrite);
+        public void replaceCheckPoint(Node loopCheckPoint) {
+            List<Node> usages = new ArrayList<Node>(loopCheckPoint.usages());
+            for (Node n : usages) {
+                replaceCheckPoint(loopCheckPoint, n);
             }
+        }
 
-            if (!locationToReads.containsKey(location)) {
-                locationToReads.put(location, new ArrayList<Node>());
+        private void replaceCheckPoint(Node loopCheckPoint, Node n) {
+            if (n instanceof ReadNode) {
+                n.inputs().replace(loopCheckPoint, getLocationForRead((ReadNode) n));
+            } else if (n instanceof WriteNode) {
+                n.inputs().replace(loopCheckPoint, getLocationForWrite((WriteNode) n));
+            } else if (n instanceof WriteMemoryCheckpointNode) {
+                n.inputs().replace(loopCheckPoint, mergeForWrite);
+            } else {
+                n.inputs().replace(loopCheckPoint, mergeForRead);
             }
-            locationToReads.get(location).add(node);
-            TTY.println("entrySet size" + locationToReads.entrySet());
         }
     }
 
@@ -120,11 +259,11 @@
         List<Block> blocks = s.getBlocks();
         MemoryMap[] memoryMaps = new MemoryMap[blocks.size()];
         for (final Block b : blocks) {
-            process(b, memoryMaps);
+            process(b, memoryMaps, s.getNodeToBlock());
         }
     }
 
-    private void process(final Block b, MemoryMap[] memoryMaps) {
+    private void process(final Block b, MemoryMap[] memoryMaps, NodeMap<Block> nodeMap) {
         // Visit every block at most once.
         if (memoryMaps[b.blockID()] != null) {
             return;
@@ -132,7 +271,7 @@
 
         // Process predecessors before this block.
         for (Block pred : b.getPredecessors()) {
-            process(pred, memoryMaps);
+            process(pred, memoryMaps, nodeMap);
         }
 
         // Create initial memory map for the block.
@@ -142,24 +281,44 @@
         } else {
             map = new MemoryMap(b, memoryMaps[b.getPredecessors().get(0).blockID()]);
             for (int i = 1; i < b.getPredecessors().size(); ++i) {
-                map.mergeWith(memoryMaps[b.getPredecessors().get(0).blockID()]);
+                assert b.firstNode() instanceof Merge : b.firstNode();
+                Block block = b.getPredecessors().get(i);
+                map.mergeWith(memoryMaps[block.blockID()], b);
             }
         }
 
-        // Lower the instructions of this block.
+        // Create the floating memory checkpoint instructions.
         for (final Node n : b.getInstructions()) {
-            // This memory merge node is not lowered => create a memory merge nevertheless.
-            if (n instanceof AbstractMemoryMergeNode) {
-                map.createMemoryMerge((AbstractMemoryMergeNode) n);
-            } else if (n instanceof ReadNode) {
+            if (n instanceof ReadNode) {
                 ReadNode readNode = (ReadNode) n;
-
+                readNode.replaceAtPredecessors(readNode.next());
+                readNode.setNext(null);
+                map.registerRead(readNode);
             } else if (n instanceof WriteNode) {
                 WriteNode writeNode = (WriteNode) n;
-
+                WriteMemoryCheckpointNode checkpoint = new WriteMemoryCheckpointNode(writeNode.graph());
+                checkpoint.setStateAfter(writeNode.stateAfter());
+                writeNode.setStateAfter(null);
+                checkpoint.setNext(writeNode.next());
+                writeNode.setNext(null);
+                writeNode.replaceAtPredecessors(checkpoint);
+                map.registerWrite(writeNode);
+                map.createWriteMemoryMerge(checkpoint);
+            } else if (n instanceof AbstractMemoryCheckpointNode) {
+                map.createReadWriteMemoryCheckpoint((AbstractMemoryCheckpointNode) n);
             }
         }
 
         memoryMaps[b.blockID()] = map;
+        if (b.lastNode() instanceof LoopEnd) {
+            LoopEnd end = (LoopEnd) b.lastNode();
+            LoopBegin begin = end.loopBegin();
+            Block beginBlock = nodeMap.get(begin);
+            MemoryMap memoryMap = memoryMaps[beginBlock.blockID()];
+            memoryMap.getLoopEntryMap().resetMergeOperationCount();
+            memoryMap.getLoopEntryMap().mergeWith(map, beginBlock);
+            Node loopCheckPoint = memoryMap.getLoopCheckPoint();
+            memoryMap.getLoopEntryMap().replaceCheckPoint(loopCheckPoint);
+        }
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java	Tue Jun 28 19:22:42 2011 +0200
@@ -62,7 +62,21 @@
             GraalTimers.get(getName()).start();
         }
         //System.out.println("Starting Phase " + getName());
-        run(graph);
+        try {
+            run(graph);
+        } catch (AssertionError t) {
+            GraalCompilation compilation = GraalCompilation.compilation();
+            if (compilation.compiler.isObserved() && this.getClass() != IdentifyBlocksPhase.class) {
+                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "AssertionError in " + getName(), graph, true, false, true));
+            }
+            throw t;
+        } catch (RuntimeException t) {
+            GraalCompilation compilation = GraalCompilation.compilation();
+            if (compilation.compiler.isObserved() && this.getClass() != IdentifyBlocksPhase.class) {
+                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "RuntimeException in " + getName(), graph, true, false, true));
+            }
+            throw t;
+        }
         //System.out.println("Finished Phase " + getName());
         if (GraalOptions.Time) {
             GraalTimers.get(getName()).stop();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ReadEliminationPhase.java	Tue Jun 28 19:22:42 2011 +0200
@@ -0,0 +1,50 @@
+/*
+ * 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.max.graal.compiler.phases;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+
+/**
+ * Duplicates every node in the graph to test the implementation of the {@link com.oracle.max.graal.graph.Node#copy()} method in node subclasses.
+ */
+public class ReadEliminationPhase extends Phase {
+
+    @Override
+    protected void run(Graph graph) {
+        for (ReadNode n : graph.getNodes(ReadNode.class)) {
+            Node memoryInput = n.inputs().variablePart().get(0);
+            if (memoryInput instanceof WriteNode) {
+                WriteNode other = (WriteNode) memoryInput;
+                if (other.object() == n.object() && other.location().same(n.location())) {
+                    if (GraalOptions.TraceReadElimination) {
+                        TTY.println("Eliminated memory read " + n + "and replaced with node " + other.value());
+                    }
+                    n.replaceAndDelete(other.value());
+                }
+            }
+        }
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java	Tue Jun 28 19:22:42 2011 +0200
@@ -172,6 +172,10 @@
         return "B" + blockID;
     }
 
+    public boolean isLoopHeader() {
+        return firstNode instanceof LoopBegin;
+    }
+
     public Block dominator() {
         return dominator;
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java	Tue Jun 28 19:22:42 2011 +0200
@@ -74,10 +74,9 @@
         if (b.lastNode() == null) {
             b.setFirstNode(n);
             b.setLastNode(n);
+            b.getInstructions().add(n);
         } else {
-            if (b.firstNode() != b.lastNode()) {
-                b.getInstructions().add(0, b.firstNode());
-            }
+            b.getInstructions().add(0, n);
             b.setFirstNode(n);
         }
 
@@ -321,15 +320,15 @@
         List<Node> sortedInstructions = new ArrayList<Node>(instructions.size() + 2);
 
         assert !map.isMarked(b.firstNode()) && nodeToBlock.get(b.firstNode()) == b;
-        assert !instructions.contains(b.firstNode());
-        assert !instructions.contains(b.lastNode());
+//        assert !instructions.contains(b.firstNode());
+//        assert !instructions.contains(b.lastNode());
         assert !map.isMarked(b.lastNode()) && nodeToBlock.get(b.lastNode()) == b;
 
-        addToSorting(b, b.firstNode(), sortedInstructions, map);
+        //addToSorting(b, b.firstNode(), sortedInstructions, map);
         for (Node i : instructions) {
             addToSorting(b, i, sortedInstructions, map);
         }
-        addToSorting(b, b.lastNode(), sortedInstructions, map);
+        //addToSorting(b, b.lastNode(), sortedInstructions, map);
 
         // Make sure that last node gets really last (i.e. when a frame state successor hangs off it).
         Node lastSorted = sortedInstructions.get(sortedInstructions.size() - 1);
@@ -351,6 +350,11 @@
             }
         }
         b.setInstructions(sortedInstructions);
+//        TTY.println();
+//        TTY.println("B" + b.blockID());
+//        for (Node n : sortedInstructions) {
+//            TTY.println("n=" + n);
+//        }
     }
 
     private void addToSorting(Block b, Node i, List<Node> sortedInstructions, NodeBitMap map) {
@@ -358,9 +362,19 @@
             return;
         }
 
+        if (i instanceof WriteNode) {
+            // Make sure every ReadNode that is connected to the same memory state is executed before every write node.
+            WriteNode wn = (WriteNode) i;
+            // TODO: Iterate over variablePart.
+            wn.inputs().variablePart();
+        }
+
         FrameState state = null;
+        WriteNode writeNode = null;
         for (Node input : i.inputs()) {
-            if (input instanceof FrameState) {
+            if (input instanceof WriteNode && !map.isMarked(input) && nodeToBlock.get(input) == b) {
+                writeNode = (WriteNode) input;
+            } else if (input instanceof FrameState) {
                 state = (FrameState) input;
             } else {
                 addToSorting(b, input, sortedInstructions, map);
@@ -373,20 +387,12 @@
 
         map.mark(i);
 
-        for (Node succ : i.successors()) {
-            if (succ instanceof FrameState) {
-                addToSorting(b, succ, sortedInstructions, map);
-            }
-        }
-
-        if (state != null) {
-            addToSorting(b, state, sortedInstructions, map);
-        }
+        addToSorting(b, state, sortedInstructions, map);
+        assert writeNode == null || !map.isMarked(writeNode);
+        addToSorting(b, writeNode, sortedInstructions, map);
 
         // Now predecessors and inputs are scheduled => we can add this node.
-        if (!(i instanceof FrameState)) {
-            sortedInstructions.add(i);
-        }
+        sortedInstructions.add(i);
     }
 
     private void computeDominators() {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64GlobalStubEmitter.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64GlobalStubEmitter.java	Tue Jun 28 19:22:42 2011 +0200
@@ -98,7 +98,7 @@
         emitStandardForward(null, runtimeCall);
         String name = "stub-" + runtimeCall;
         CiTargetMethod targetMethod = tasm.finishTargetMethod(name, runtime, registerRestoreEpilogueOffset, true);
-        Object stubObject = runtime.registerGlobalStub(targetMethod, name);
+        Object stubObject = runtime.registerCompilerStub(targetMethod, name);
         return new GlobalStub(null, runtimeCall.resultKind, stubObject, argsSize, argOffsets, resultOffset);
     }
 
@@ -128,7 +128,7 @@
 
         String name = "stub-" + stub;
         CiTargetMethod targetMethod = tasm.finishTargetMethod(name, runtime, registerRestoreEpilogueOffset, true);
-        Object stubObject = runtime.registerGlobalStub(targetMethod, name);
+        Object stubObject = runtime.registerCompilerStub(targetMethod, name);
         return new GlobalStub(stub, stub.resultKind, stubObject, argsSize, argOffsets, resultOffset);
     }
 
@@ -238,7 +238,7 @@
         assembler.emitXirInstructions(null, template.fastPath, labels, operands, null);
         epilogue();
         CiTargetMethod targetMethod = tasm.finishTargetMethod(template.name, runtime, registerRestoreEpilogueOffset, true);
-        Object stubObject = runtime.registerGlobalStub(targetMethod, template.name);
+        Object stubObject = runtime.registerCompilerStub(targetMethod, template.name);
         return new GlobalStub(null, template.resultOperand.kind, stubObject, argsSize, argOffsets, resultOffset);
     }
 
@@ -377,7 +377,7 @@
     }
 
     private void completeSavePrologue() {
-        CiCalleeSaveArea csa = compiler.globalStubRegisterConfig.getCalleeSaveArea();
+        CiCalleeSaveLayout csa = compiler.globalStubRegisterConfig.getCalleeSaveLayout();
         this.saveSize = csa.size;
         int entryCodeOffset = runtime.codeOffset();
         if (entryCodeOffset != 0) {
@@ -396,7 +396,7 @@
         registerRestoreEpilogueOffset = asm.codeBuffer.position();
 
         if (savedAllRegisters) {
-            CiCalleeSaveArea csa = compiler.globalStubRegisterConfig.getCalleeSaveArea();
+            CiCalleeSaveLayout csa = compiler.globalStubRegisterConfig.getCalleeSaveLayout();
             int frameToCSA = 0;
             asm.restore(csa, frameToCSA);
         } else {
@@ -419,7 +419,7 @@
 
     private void forwardRuntimeCall(CiRuntimeCall call) {
         // Load arguments
-        CiCallingConvention cc = compiler.globalStubRegisterConfig.getCallingConvention(RuntimeCall, call.arguments, target);
+        CiCallingConvention cc = compiler.globalStubRegisterConfig.getCallingConvention(RuntimeCall, call.arguments, target, false);
         for (int i = 0; i < cc.locations.length; ++i) {
             CiValue location = cc.locations[i];
             loadArgument(i, location.asRegister());
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java	Tue Jun 28 19:22:42 2011 +0200
@@ -1965,7 +1965,7 @@
                             masm.movl(new CiAddress(CiKind.Int, AMD64.rsp.asValue(), i * intSize), 0xC1C1C1C1);
                         }
                     }
-                    CiCalleeSaveArea csa = compilation.registerConfig.getCalleeSaveArea();
+                    CiCalleeSaveLayout csa = compilation.registerConfig.getCalleeSaveLayout();
                     if (csa.size != 0) {
                         int frameToCSA = frameMap.offsetToCalleeSaveAreaStart();
                         assert frameToCSA >= 0;
@@ -1976,7 +1976,7 @@
                 case PopFrame: {
                     int frameSize = initialFrameSizeInBytes();
 
-                    CiCalleeSaveArea csa = compilation.registerConfig.getCalleeSaveArea();
+                    CiCalleeSaveLayout csa = compilation.registerConfig.getCalleeSaveLayout();
                     if (csa.size != 0) {
                         registerRestoreEpilogueOffset = masm.codeBuffer.position();
                         // saved all registers, restore all registers
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/GraphUtil.java	Tue Jun 28 19:22:42 2011 +0200
@@ -0,0 +1,272 @@
+/*
+ * 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.max.graal.compiler.util;
+
+import java.util.*;
+import java.util.Map.Entry;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.observer.*;
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.graph.*;
+
+public class GraphUtil {
+
+    public static interface ColoringLambda<T> {
+        T color(Iterable<T> incomming, Merge merge);
+    }
+
+    /**
+     * colors down, applying the lambda at merge points, starting at the pre-colored points.
+     */
+    public static <T> void colorCFGDown(NodeMap<T> colors, ColoringLambda<T> lambda) {
+        List<Node> startingPoints = new LinkedList<Node>();
+        for (Entry<Node, T> entry : colors.entries()) {
+            startingPoints.add(entry.getKey());
+        }
+        NodeWorkList work = colors.graph().createNodeWorkList();
+        for (Node startingPoint : startingPoints) {
+            if (startingPoint instanceof Merge) {
+                work.addAll(colorCFGDownToMerge(((Merge) startingPoint).next(), colors.get(startingPoint), colors));
+            } else {
+                work.addAll(colorCFGDownToMerge(startingPoint, colors.get(startingPoint), colors));
+            }
+        }
+        for (Node n : work) {
+            //System.out.println("Color : work on " + n);
+            Merge merge = (Merge) n;
+            ArrayList<T> incomming = new ArrayList<T>(2);
+            for (EndNode end : merge.cfgPredecessors()) {
+                incomming.add(colors.get(end));
+            }
+            T color = lambda.color(incomming, merge);
+            if (color != null) {
+                colors.set(merge, color);
+                work.addAll(colorCFGDownToMerge(merge.next(), color, colors));
+            } else {
+                work.addAgain(merge);
+            }
+        }
+    }
+
+    private static <T> Collection<Merge> colorCFGDownToMerge(Node from, T color, NodeMap<T> colors) {
+        //System.out.println("colorCFGDownToMerge(" + from + ", " + color + ", colors)");
+        NodeFlood work = from.graph().createNodeFlood();
+        Collection<Merge> merges = new LinkedList<Merge>();
+        work.add(from);
+        for (Node node : work) {
+            //System.out.println("colorToMerge : work on " + node);
+            Node current = node;
+            while (current != null) {
+                //System.out.println("colorToMerge : current " + current);
+                if (current instanceof Merge) {
+                    merges.add((Merge) current);
+                    break;
+                }
+                colors.set(current, color);
+                if (current instanceof FixedNodeWithNext) {
+                    current = ((FixedNodeWithNext) current).next();
+                } else if (current instanceof EndNode) {
+                    current = ((EndNode) current).merge();
+                } else {
+                    if (current instanceof ControlSplit) {
+                        for (Node sux : current.cfgSuccessors()) {
+                            work.add(sux);
+                        }
+                    }
+                    current = null;
+                }
+            }
+        }
+        //System.out.println("return " + merges);
+        return merges;
+    }
+
+    public static interface ColorSplitingLambda<T> {
+        void fixSplit(Node oldNode, Node newNode, T color);
+        void fixNode(Node node, T color);
+        Value fixPhiInput(Value input, T color);
+        boolean explore(Node n);
+    }
+
+    // TODO (gd) rework that code around Phi handling : too complicated
+    public static <T> void splitFromColoring(NodeMap<T> coloring, ColorSplitingLambda<T> lambda) {
+        Map<Node, T> internalColoring = new HashMap<Node, T>();
+        NodeWorkList work = coloring.graph().createNodeWorkList();
+        for (Entry<Node, T> entry : coloring.entries()) {
+            T color = entry.getValue();
+            Node node = entry.getKey();
+            work.add(node);
+            internalColoring.put(node, color);
+        }
+        Set<T> colors = new HashSet<T>();
+        try {
+            for (Node node : work) {
+                //System.out.println("Split : work on " + node);
+                if (node instanceof Phi) {
+                    Phi phi = (Phi) node;
+                    Merge merge = phi.merge();
+                    for (int i = 0; i < phi.valueCount(); i++) {
+                        Value v = phi.valueAt(i);
+                        if (v != null) {
+                            T color = internalColoring.get(merge.phiPredecessorAt(i));
+                            Value replace = lambda.fixPhiInput(v, color);
+                            if (replace != v) {
+                                phi.setValueAt(i, replace);
+                            }
+                        }
+                    }
+                } else {
+                    boolean delay = false;
+                    colors.clear();
+                    T originalColoringColor = coloring.get(node);
+                    if (originalColoringColor == null && internalColoring.get(node) != null) {
+                        //System.out.println("Split : ori == null && intern != null -> continue");
+                        continue;
+                    }
+                    if (originalColoringColor == null) {
+                        for (Node usage : node.dataUsages()) {
+                            if (usage instanceof Phi) {
+                                Phi phi = (Phi) usage;
+                                Merge merge = phi.merge();
+                                //System.out.println("Split merge : " + merge + ".endCount = " + merge.endCount() + " phi " + phi + ".valueCount : " + phi.valueCount());
+                                for (int i = 0; i < phi.valueCount(); i++) {
+                                    Value v = phi.valueAt(i);
+                                    if (v == node) {
+                                        T color = internalColoring.get(merge.phiPredecessorAt(i));
+                                        if (color == null) {
+                                            //System.out.println("Split : color from " + usage + " is null");
+                                            delay = true;
+                                            break;
+                                        }
+                                        colors.add(color);
+                                    }
+                                }
+                            } else {
+                                T color = internalColoring.get(usage);
+                                if (color == null) {
+                                    //System.out.println("Split : color from " + usage + " is null");
+                                    delay = true;
+                                    break;
+                                }
+                                colors.add(color);
+                            }
+                        }
+                        if (delay) {
+                            //System.out.println("Split : delay");
+                            work.addAgain(node);
+                            continue;
+                        }
+                    } else {
+                        colors.add(originalColoringColor);
+                    }
+                    if (colors.size() == 1) {
+                        //System.out.println("Split : 1 color, coloring, fixing");
+                        T color = colors.iterator().next();
+                        internalColoring.put(node, color);
+                        lambda.fixNode(node, color);
+                    } else {
+                        //System.out.println("Split : " + colors.size() + " colors, coloring, spliting, fixing");
+                        for (T color : colors) {
+                            Node newNode = node.copy();
+                            for (int i = 0; i < node.inputs().size(); i++) {
+                                Node input = node.inputs().get(i);
+                                newNode.inputs().setOrExpand(i, input);
+                            }
+                            for (int i = 0; i < node.successors().size(); i++) {
+                                Node input = node.successors().get(i);
+                                newNode.successors().setOrExpand(i, input);
+                            }
+                            internalColoring.put(newNode, color);
+                            lambda.fixSplit(node, newNode, color);
+                            LinkedList<Node> dataUsages = new LinkedList<Node>();
+                            for (Node usage : node.dataUsages()) {
+                                dataUsages.add(usage);
+                            }
+                            for (Node usage : dataUsages) {
+                                if (usage instanceof Phi) {
+                                    Phi phi = (Phi) usage;
+                                    Merge merge = phi.merge();
+                                    for (int i = 0; i < phi.valueCount(); i++) {
+                                        Value v = phi.valueAt(i);
+                                        if (v == node) {
+                                            T uColor = internalColoring.get(merge.endAt(i));
+                                            if (uColor == color) {
+                                                phi.setValueAt(i, (Value) newNode);
+                                            }
+                                        }
+                                    }
+                                } else {
+                                    T uColor = internalColoring.get(usage);
+                                    if (uColor == color) {
+                                        usage.inputs().replace(node, newNode);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+
+                if (node instanceof StateSplit) {
+                    FrameState stateAfter = ((StateSplit) node).stateAfter();
+                    if (stateAfter != null && lambda.explore(stateAfter) && !work.isNew(stateAfter)) {
+                        //System.out.println("Split : Add framestate to work");
+                        work.add(stateAfter);
+                    }
+                }
+
+                if (node instanceof Merge) {
+                    for (Node usage : node.usages()) {
+                        if (!work.isNew(usage)) {
+                            work.add(usage);
+                        }
+                    }
+                }
+
+                if (node instanceof LoopEnd) {
+                    work.add(((LoopEnd) node).loopBegin());
+                }
+
+                for (Node input : node.dataInputs()) {
+                    if (lambda.explore(input) && coloring.get(input) == null && !work.isNew(input)) {
+                        //System.out.println("Split : Add input " + input + " to work from " + node);
+                        work.add(input);
+                    }
+                }
+            }
+        } catch (RuntimeException re) {
+            re.printStackTrace();
+            GraalCompilation compilation = GraalCompilation.compilation();
+            if (compilation.compiler.isObserved()) {
+                NodeMap<T> debugColoring = coloring.graph().createNodeMap();
+                for (Entry<Node, T> entry : internalColoring.entrySet()) {
+                    debugColoring.set(entry.getKey(), entry.getValue());
+                }
+                Map<String, Object> debug = new HashMap<String, Object>();
+                debug.put("split", debugColoring);
+                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "RuntimeException in split", coloring.graph(), true, false, debug));
+            }
+        }
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/LoopUtil.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/LoopUtil.java	Tue Jun 28 19:22:42 2011 +0200
@@ -23,10 +23,17 @@
 package com.oracle.max.graal.compiler.util;
 
 import java.util.*;
+import java.util.Map.Entry;
 
+import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.observer.*;
 import com.oracle.max.graal.compiler.schedule.*;
+import com.oracle.max.graal.compiler.util.GraphUtil.ColorSplitingLambda;
+import com.oracle.max.graal.compiler.util.GraphUtil.ColoringLambda;
+import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
 
 public class LoopUtil {
 
@@ -34,11 +41,11 @@
         private final LoopBegin loopBegin;
         private final NodeBitMap nodes;
         private Loop parent;
-        private final List<FixedNode> exits;
-        public Loop(LoopBegin loopBegin, NodeBitMap nodes) {
+        private final NodeBitMap exits;
+        public Loop(LoopBegin loopBegin, NodeBitMap nodes, NodeBitMap exits) {
             this.loopBegin = loopBegin;
             this.nodes = nodes;
-            this.exits = new LinkedList<FixedNode>();
+            this.exits = exits;
         }
 
         public LoopBegin loopBegin() {
@@ -53,7 +60,7 @@
             return parent;
         }
 
-        public List<FixedNode> exist() {
+        public NodeBitMap exits() {
             return exits;
         }
 
@@ -62,11 +69,29 @@
         }
     }
 
+    private static class PeelingResult {
+        public final FixedNode begin;
+        public final FixedNode end;
+        public final NodeMap<Placeholder> exits;
+        public final NodeMap<Placeholder> phis;
+        public final NodeMap<Node> phiInits;
+        public final NodeMap<Node> dataOut;
+        public PeelingResult(FixedNode begin, FixedNode end, NodeMap<Placeholder> exits, NodeMap<Placeholder> phis, NodeMap<Node> phiInits, NodeMap<Node> dataOut) {
+            this.begin = begin;
+            this.end = end;
+            this.exits = exits;
+            this.phis = phis;
+            this.phiInits = phiInits;
+            this.dataOut = dataOut;
+        }
+    }
+
     public static List<Loop> computeLoops(Graph graph) {
         List<Loop> loops = new LinkedList<LoopUtil.Loop>();
         for (LoopBegin loopBegin : graph.getNodes(LoopBegin.class)) {
             NodeBitMap nodes = computeLoopNodes(loopBegin);
-            Loop loop = new Loop(loopBegin, nodes);
+            NodeBitMap exits = graph.createNodeBitMap();
+            Loop loop = new Loop(loopBegin, nodes, exits);
             NodeFlood workCFG = graph.createNodeFlood();
             workCFG.add(loopBegin.loopEnd());
             for (Node n : workCFG) {
@@ -76,7 +101,7 @@
                 if (IdentifyBlocksPhase.trueSuccessorCount(n) > 1) {
                     for (Node sux : n.cfgSuccessors()) {
                         if (!nodes.isMarked(sux) && sux instanceof FixedNode) {
-                            loop.exits.add((FixedNode) sux);
+                            exits.mark(sux);
                         }
                     }
                 }
@@ -99,30 +124,38 @@
     }
 
     public static NodeBitMap computeLoopNodes(LoopBegin loopBegin) {
-        LoopEnd loopEnd = loopBegin.loopEnd();
-        NodeBitMap loopNodes = loopBegin.graph().createNodeBitMap();
-        NodeFlood workCFG = loopBegin.graph().createNodeFlood();
+        return computeLoopNodesFrom(loopBegin, loopBegin.loopEnd());
+    }
+    private static boolean recurse = false;
+    public static NodeBitMap computeLoopNodesFrom(LoopBegin loopBegin, FixedNode from) {
         NodeFlood workData1 = loopBegin.graph().createNodeFlood();
         NodeFlood workData2 = loopBegin.graph().createNodeFlood();
-        workCFG.add(loopEnd);
-        for (Node n : workCFG) {
+        NodeBitMap loopNodes = markUpCFG(loopBegin, from);
+        loopNodes.mark(loopBegin);
+        for (Node n : loopNodes) {
             workData1.add(n);
             workData2.add(n);
-            loopNodes.mark(n);
-            if (n == loopBegin) {
-                continue;
-            }
-            if (n instanceof LoopBegin) {
-                workCFG.add(((LoopBegin) n).loopEnd());
-            }
-            for (Node pred : n.cfgPredecessors()) {
-                workCFG.add(pred);
-            }
         }
         NodeBitMap inOrAfter = loopBegin.graph().createNodeBitMap();
         for (Node n : workData1) {
             inOrAfter.mark(n);
             for (Node usage : n.dataUsages()) {
+                if (usage instanceof Phi) { // filter out data graph cycles
+                    Phi phi = (Phi) usage;
+                    if (!phi.isDead()) {
+                        Merge merge = phi.merge();
+                        if (merge instanceof LoopBegin) {
+                            LoopBegin phiLoop = (LoopBegin) merge;
+                            int backIndex = phiLoop.phiPredecessorIndex(phiLoop.loopEnd());
+                            if (backIndex >= phi.valueCount()) {
+                                System.out.println("Wierd phi : " + phi);
+                            }
+                            if (phi.valueAt(backIndex) == n) {
+                                continue;
+                            }
+                        }
+                    }
+                }
                 workData1.add(usage);
             }
         }
@@ -138,8 +171,442 @@
                 }
             }
         }
-        inOrBefore.setIntersect(inOrAfter);
-        loopNodes.setUnion(inOrBefore);
+        /*if (!recurse) {
+            recurse = true;
+            GraalCompilation compilation = GraalCompilation.compilation();
+            if (compilation.compiler.isObserved()) {
+                Map<String, Object> debug = new HashMap<String, Object>();
+                debug.put("loopNodes", loopNodes);
+                debug.put("inOrAfter", inOrAfter);
+                debug.put("inOrBefore", inOrBefore);
+                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "Compute loop nodes", loopBegin.graph(), true, false, debug));
+            }
+            recurse = false;
+        }*/
+        inOrAfter.setIntersect(inOrBefore);
+        loopNodes.setUnion(inOrAfter);
+        return loopNodes;
+    }
+
+    private static NodeBitMap markUpCFG(LoopBegin loopBegin, FixedNode from) {
+        NodeFlood workCFG = loopBegin.graph().createNodeFlood();
+        workCFG.add(from);
+        NodeBitMap loopNodes = loopBegin.graph().createNodeBitMap();
+        for (Node n : workCFG) {
+            if (n == loopBegin) {
+                continue;
+            }
+            loopNodes.mark(n);
+            if (n instanceof LoopBegin) {
+                workCFG.add(((LoopBegin) n).loopEnd());
+            }
+            for (Node pred : n.cfgPredecessors()) {
+                workCFG.add(pred);
+            }
+        }
         return loopNodes;
     }
+
+    public static void ifDoWhileTransform(Loop loop, If split) {
+        assert loop.nodes().isMarked(split);
+        FixedNode noExit = split.trueSuccessor();
+        FixedNode exit = split.falseSuccessor();
+        if (loop.nodes().isMarked(exit) && !loop.nodes().isMarked(noExit)) {
+            FixedNode tmp = noExit;
+            noExit = exit;
+            exit = tmp;
+        }
+        assert !loop.nodes().isMarked(exit);
+        assert loop.nodes().isMarked(noExit);
+
+        PeelingResult peeling = preparePeeling(loop, split);
+        rewirePeeling(peeling, loop, split);
+        // TODO (gd) move peeled part to the end, rewire dataOut
+    }
+
+    public static void peelLoop(Loop loop) {
+        LoopEnd loopEnd = loop.loopBegin().loopEnd();
+        PeelingResult peeling = preparePeeling(loop, loopEnd);
+        GraalCompilation compilation = GraalCompilation.compilation();
+        if (compilation.compiler.isObserved()) {
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After peeling preparation", loopEnd.graph(), true, false));
+        }
+        /*System.out.println("Peeling : ");
+        System.out.println(" begin = " + peeling.begin);
+        System.out.println(" end = " + peeling.end);
+        System.out.println(" Phis :");
+        for (Entry<Node, Placeholder> entry : peeling.phis.entries()) {
+            System.out.println("  - " + entry.getKey() + " -> " + entry.getValue());
+        }
+        System.out.println(" Exits :");
+        for (Entry<Node, Placeholder> entry : peeling.exits.entries()) {
+            System.out.println("  - " + entry.getKey() + " -> " + entry.getValue());
+        }
+        System.out.println(" PhiInits :");
+        for (Entry<Node, Node> entry : peeling.phiInits.entries()) {
+            System.out.println("  - " + entry.getKey() + " -> " + entry.getValue());
+        }
+        System.out.println(" DataOut :");
+        for (Entry<Node, Node> entry : peeling.dataOut.entries()) {
+            System.out.println("  - " + entry.getKey() + " -> " + entry.getValue());
+        }*/
+        rewirePeeling(peeling, loop, loopEnd);
+        if (compilation.compiler.isObserved()) {
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After rewirePeeling", loopEnd.graph(), true, false));
+        }
+    }
+
+    private static void rewirePeeling(PeelingResult peeling, Loop loop, FixedNode from) {
+        LoopBegin loopBegin = loop.loopBegin();
+        Graph graph = loopBegin.graph();
+        Node loopPred = loopBegin.singlePredecessor();
+        if (loopPred instanceof FixedNodeWithNext) {
+            ((FixedNodeWithNext) loopPred).setNext(peeling.begin);
+        } else if (loopPred instanceof StartNode) {
+            ((StartNode) loopPred).setStart(peeling.begin);
+        } else {
+            Util.shouldNotReachHere();
+        }
+        NodeBitMap loopNodes = loop.nodes();
+        Node originalLast = from;
+        if (originalLast == loopBegin.loopEnd()) {
+            originalLast = loopBegin.loopEnd().singlePredecessor();
+        }
+        int size = originalLast.successors().size();
+        boolean found = false;
+        for (int i = 0; i < size; i++) {
+            Node sux = originalLast.successors().get(i);
+            if (sux == null) {
+                continue;
+            }
+            if (loopNodes.isMarked(sux)) {
+                assert !found;
+                peeling.end.successors().set(i, loopBegin.forwardEdge());
+                found = true;
+            }
+        }
+        assert found;
+        int phiInitIndex = loopBegin.phiPredecessorIndex(loopBegin.forwardEdge());
+        for (Entry<Node, Placeholder> entry : peeling.phis.entries()) {
+            Phi phi = (Phi) entry.getKey();
+            Placeholder p = entry.getValue();
+            p.replaceAndDelete(phi.valueAt(phiInitIndex));
+        }
+        for (Entry<Node, Node> entry : peeling.phiInits.entries()) {
+            Phi phi = (Phi) entry.getKey();
+            Node newInit = entry.getValue();
+            phi.setValueAt(phiInitIndex, (Value) newInit);
+        }
+
+        if (from == loopBegin.loopEnd()) {
+            for (LoopCounter counter : loopBegin.counters()) {
+                counter.setInit(new IntegerAdd(counter.kind, counter.init(), counter.stride(), graph));
+            }
+        }
+        NodeMap<NodeMap<Value>> newExitValues = graph.createNodeMap();
+        List<Node> exitPoints = new LinkedList<Node>();
+        for (Node exit : loop.exits()) {
+            exitPoints.add(exit);
+        }
+        for (Entry<Node, Placeholder> entry : peeling.exits.entries()) {
+            Placeholder original = (Placeholder) entry.getKey();
+            Placeholder newExit = entry.getValue();
+            FixedNode next = original.next();
+            EndNode oEnd = new EndNode(graph);
+            EndNode nEnd = new EndNode(graph);
+            Merge merge = new Merge(graph);
+            merge.setNext(next);
+            FrameState newState = newExit.stateAfter();
+            merge.addEnd(nEnd);
+            merge.setStateAfter(newState);
+            //newState.merge(merge, original.stateAfter());
+            merge.addEnd(oEnd);
+            original.setNext(oEnd);
+            newExit.setStateAfter(null);
+            newExit.replaceAndDelete(nEnd);
+
+            exitPoints.add(nEnd);
+        }
+
+        for (Entry<Node, Placeholder> entry : peeling.exits.entries()) {
+            Placeholder original = (Placeholder) entry.getKey();
+            EndNode oEnd = (EndNode) original.next();
+            Merge merge = oEnd.merge();
+            EndNode nEnd = merge.endAt(1 - merge.phiPredecessorIndex(oEnd));
+            FrameState newState = merge.stateAfter();
+            NodeArray oInputs = original.stateAfter().inputs();
+            NodeArray nInputs = newState.inputs();
+            int oSize = oInputs.size();
+            for (int i = 0; i < oSize; i++) {
+                Node newValue = nInputs.get(i);
+                Node originalValue = oInputs.get(i);
+                if (newValue != originalValue) {
+                    NodeMap<Value> phiMap = newExitValues.get(originalValue);
+                    if (phiMap == null) {
+                        phiMap = graph.createNodeMap();
+                        newExitValues.set(originalValue, phiMap);
+                    }
+                    phiMap.set(oEnd, (Value) originalValue);
+                    phiMap.set(nEnd, (Value) newValue);
+
+                    phiMap = newExitValues.get(newValue);
+                    if (phiMap == null) {
+                        phiMap = graph.createNodeMap();
+                        newExitValues.set(newValue, phiMap);
+                    }
+                    phiMap.set(oEnd, (Value) originalValue);
+                    phiMap.set(nEnd, (Value) newValue);
+                }
+            }
+            /*Placeholder original = (Placeholder) entry.getKey();
+            Merge merge = ((EndNode) original.next()).merge();
+            FrameState newState = merge.stateAfter();
+            NodeArray oInputs = original.stateAfter().inputs();
+            NodeArray nInputs = newState.inputs();
+            int oSize = oInputs.size();
+            for (int i = 0; i < oSize; i++) {
+                Node newValue = nInputs.get(i);
+                Node originalValue = oInputs.get(i);
+                if (newValue != originalValue && newValue instanceof Phi) {
+                    Phi newPhi = (Phi) newValue;
+                    assert newPhi.valueAt(1) == originalValue;
+                    NodeMap<Value> phiMap = newExitValues.get(originalValue);
+                    if (phiMap == null) {
+                        phiMap = graph.createNodeMap();
+                        newExitValues.set(originalValue, phiMap);
+                    }
+                    phiMap.set(merge, newPhi);
+                }
+            }*/
+        }
+        for (Entry<Node, NodeMap<Value>> entry : newExitValues.entries()) {
+            Value original = (Value) entry.getKey();
+            NodeMap<Value> pointToValue = entry.getValue();
+            for (Node exit : exitPoints) {
+                Node valueAtExit = pointToValue.get(exit);
+                if (valueAtExit == null) {
+                    pointToValue.set(exit, original);
+                }
+            }
+        }
+
+        replaceValuesAtLoopExits(newExitValues, loop, exitPoints);
+    }
+
+    private static void replaceValuesAtLoopExits(final NodeMap<NodeMap<Value>> newExitValues, Loop loop, List<Node> exitPoints) {
+        Graph graph = loop.loopBegin().graph();
+        final NodeMap<Node> colors = graph.createNodeMap();
+
+        // prepare inital colors
+        for (Node exitPoint : exitPoints) {
+                colors.set(exitPoint, exitPoint);
+        }
+
+        /*System.out.println("newExitValues");
+        for (Entry<Node, NodeMap<Value>> entry : newExitValues.entries()) {
+            System.out.println(" - " + entry.getKey() + " :");
+            for (Entry<Node, Value> entry2 : entry.getValue().entries()) {
+                System.out.println("    + " + entry2.getKey() + " -> " + entry2.getValue());
+            }
+        }*/
+
+        // color
+        GraphUtil.colorCFGDown(colors, new ColoringLambda<Node>() {
+            @Override
+            public Node color(Iterable<Node> incomming, Merge merge) {
+                Node color = null;
+                for (Node c : incomming) {
+                    if (c == null) {
+                        return null;
+                    }
+                    if (color == null) {
+                        color = c;
+                    } else if (color != c) {
+                        return merge;
+                    }
+                }
+                return color;
+            }
+        });
+
+        final NodeBitMap inOrBefore = inOrBefore(loop);
+
+        GraalCompilation compilation = GraalCompilation.compilation();
+        if (compilation.compiler.isObserved()) {
+            Map<String, Object> debug = new HashMap<String, Object>();
+            debug.put("loopExits", colors);
+            debug.put("inOrBefore", inOrBefore);
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After coloring", graph, true, false, debug));
+        }
+
+        GraphUtil.splitFromColoring(colors, new ColorSplitingLambda<Node>(){
+            @Override
+            public void fixSplit(Node oldNode, Node newNode, Node color) {
+                this.fixNode(newNode, color);
+            }
+            private Value getValueAt(Node point, NodeMap<Value> valueMap, CiKind kind) {
+                Value value = valueMap.get(point);
+                if (value != null) {
+                    return value;
+                }
+                Merge merge = (Merge) point;
+                ArrayList<Value> values = new ArrayList<Value>(merge.phiPredecessorCount());
+                Value v = null;
+                boolean createPhi = false;
+                for (EndNode end : merge.cfgPredecessors()) {
+                    Value valueAt = getValueAt(colors.get(end), valueMap, kind);
+                    if (v == null) {
+                        v = valueAt;
+                    } else if (v != valueAt) {
+                        createPhi = true;
+                    }
+                    values.add(valueAt);
+                }
+                if (createPhi) {
+                    Phi phi = new Phi(kind, merge, merge.graph());
+                    valueMap.set(point, phi);
+                    for (EndNode end : merge.cfgPredecessors()) {
+                        phi.addInput(getValueAt(colors.get(end), valueMap, kind));
+                    }
+                    return phi;
+                } else {
+                    assert v != null;
+                    valueMap.set(point, v);
+                    return v;
+                }
+            }
+            @Override
+            public boolean explore(Node n) {
+                return !inOrBefore.isNew(n) && !inOrBefore.isMarked(n) && !(n instanceof Local); //TODO (gd) hum
+            }
+            @Override
+            public void fixNode(Node node, Node color) {
+                for (int i = 0; i < node.inputs().size(); i++) {
+                    Node input = node.inputs().get(i);
+                    if (input == null || newExitValues.isNew(input)) {
+                        continue;
+                    }
+                    NodeMap<Value> valueMap = newExitValues.get(input);
+                    if (valueMap != null) {
+                        Value replacement = getValueAt(color, valueMap, ((Value) input).kind);
+                        //if (!(replacement instanceof Phi && replacement == node)) { // handle the Phi that were created when merging loop exits
+                            node.inputs().set(i, replacement);
+                        //}
+                    }
+                }
+            }
+            @Override
+            public Value fixPhiInput(Value input, Node color) {
+                if (newExitValues.isNew(input)) {
+                    return input;
+                }
+                NodeMap<Value> valueMap = newExitValues.get(input);
+                if (valueMap != null) {
+                    return getValueAt(color, valueMap, input.kind);
+                }
+                return input;
+            }});
+
+        if (compilation.compiler.isObserved()) {
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After split from colors", graph, true, false));
+        }
+    }
+
+    private static PeelingResult preparePeeling(Loop loop, FixedNode from) {
+        LoopBegin loopBegin = loop.loopBegin();
+        Graph graph = loopBegin.graph();
+        NodeBitMap marked = computeLoopNodesFrom(loopBegin, from);
+        if (from == loopBegin.loopEnd()) {
+            marked.clear(from);
+        }
+        marked.clear(loopBegin);
+        Map<Node, Node> replacements = new HashMap<Node, Node>();
+        NodeMap<Placeholder> phis = graph.createNodeMap();
+        NodeMap<Placeholder> exits = graph.createNodeMap();
+
+        for (Node exit : loop.exits()) {
+            if (marked.isMarked(exit.singlePredecessor())) {
+                marked.mark(((Placeholder) exit).stateAfter());
+                Placeholder p = new Placeholder(graph);
+                replacements.put(exit, p);
+                exits.set(exit, p);
+            }
+        }
+
+        for (Node n : marked) {
+            if (n instanceof StateSplit) {
+                FrameState stateAfter = ((StateSplit) n).stateAfter();
+                if (stateAfter != null) {
+                    marked.mark(stateAfter);
+                }
+            }
+            if (n instanceof Phi && ((Phi) n).merge() == loopBegin) {
+                Placeholder p = new Placeholder(graph);
+                replacements.put(n, p);
+                phis.set(n, p);
+                marked.clear(n);
+            }
+            for (Node input : n.dataInputs()) {
+                if (!marked.isMarked(input) && (!(input instanceof Phi) || ((Phi) input).merge() != loopBegin)) {
+                    replacements.put(input, input);
+                }
+            }
+        }
+
+        GraalCompilation compilation = GraalCompilation.compilation();
+        if (compilation.compiler.isObserved()) {
+            Map<String, Object> debug = new HashMap<String, Object>();
+            debug.put("marked", marked);
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "Before addDuplicate", loopBegin.graph(), true, false, debug));
+        }
+
+        Map<Node, Node> duplicates = graph.addDuplicate(marked, replacements);
+
+        NodeMap<Node> dataOut = graph.createNodeMap();
+        for (Node n : marked) {
+            for (Node usage : n.dataUsages()) {
+                if (!marked.isMarked(usage)
+                                && !loop.nodes().isNew(usage) && loop.nodes().isMarked(usage)
+                                && !((usage instanceof Phi) || ((Phi) usage).merge() != loopBegin)) {
+                    dataOut.set(n, duplicates.get(n));
+                    break;
+                }
+            }
+        }
+        NodeMap<Node> phiInits = graph.createNodeMap();
+        int backIndex = loopBegin.phiPredecessorIndex(loopBegin.loopEnd());
+        int fowardIndex = loopBegin.phiPredecessorIndex(loopBegin.forwardEdge());
+        for (Phi phi : loopBegin.phis()) {
+            Value backValue = phi.valueAt(backIndex);
+            if (marked.isMarked(backValue)) {
+                phiInits.set(phi, duplicates.get(backValue));
+            } else if (backValue instanceof Phi && ((Phi) backValue).merge() == loopBegin) {
+                Phi backPhi = (Phi) backValue;
+                phiInits.set(phi, backPhi.valueAt(fowardIndex));
+            }
+        }
+
+        FixedNode newBegin = (FixedNode) duplicates.get(loopBegin.next());
+        FixedNode newFrom = (FixedNode) duplicates.get(from == loopBegin.loopEnd() ? from.singlePredecessor() : from);
+        return new PeelingResult(newBegin, newFrom, exits, phis, phiInits, dataOut);
+    }
+
+    private static NodeBitMap inOrBefore(Loop loop) {
+        Graph graph = loop.loopBegin().graph();
+        NodeBitMap inOrBefore = graph.createNodeBitMap();
+        NodeFlood work = graph.createNodeFlood();
+        work.addAll(loop.nodes());
+        for (Node n : work) {
+            inOrBefore.mark(n);
+            for (Node pred : n.predecessors()) {
+                work.add(pred);
+            }
+            for (Node in : n.inputs()) {
+                if (in != null) {
+                    work.add(in);
+                }
+            }
+        }
+        return inOrBefore;
+    }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Tue Jun 28 19:22:42 2011 +0200
@@ -424,6 +424,15 @@
         return null;
     }
 
+    public StateSplit stateSplit() {
+        for (Node n : usages()) {
+            if (n instanceof StateSplit) {
+                return (StateSplit) n;
+            }
+        }
+        return null;
+    }
+
     /**
      * The interface implemented by a client of {@link FrameState#forEachPhi(Merge, PhiProcedure)} and
      * {@link FrameState#forEachLivePhi(Merge, PhiProcedure)}.
@@ -471,7 +480,7 @@
 
     @Override
     public String toString() {
-        StringBuilder sb = new StringBuilder();
+        /*StringBuilder sb = new StringBuilder();
         String nl = String.format("%n");
         sb.append("[bci: ").append(bci).append("]").append(nl);
         for (int i = 0; i < localsSize(); ++i) {
@@ -486,7 +495,8 @@
             Value value = lockAt(i);
             sb.append(String.format("  lock[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind.javaName, value));
         }
-        return sb.toString();
+        return sb.toString();*/
+        return super.toString();
     }
 
     @Override
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRegisterConfig.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRegisterConfig.java	Tue Jun 28 19:22:42 2011 +0200
@@ -72,7 +72,7 @@
         xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
     };
 
-    private final CiCalleeSaveArea registerSaveArea;
+    private final CiCalleeSaveLayout registerSaveArea;
 
 
     public HotSpotRegisterConfig(HotSpotVMConfig config, boolean globalStubConfig) {
@@ -83,9 +83,9 @@
         }
 
         if (globalStubConfig) {
-            registerSaveArea = new CiCalleeSaveArea(-1, 8, rsaRegs);
+            registerSaveArea = new CiCalleeSaveLayout(0, -1, 8, rsaRegs);
         } else {
-            registerSaveArea = CiCalleeSaveArea.EMPTY;
+            registerSaveArea = new CiCalleeSaveLayout(0, 0, 0, new CiRegister[0]);
         }
 
         attributesMap = RiRegisterAttributes.createMap(this, AMD64.allRegisters);
@@ -104,18 +104,18 @@
     }
 
     @Override
-    public CiCallingConvention getCallingConvention(Type type, CiKind[] parameters, CiTarget target) {
+    public CiCallingConvention getCallingConvention(Type type, CiKind[] parameters, CiTarget target, boolean stackOnly) {
         if (type == Type.NativeCall) {
             throw new UnsupportedOperationException();
         }
-        return callingConvention(parameters, type, target);
+        return callingConvention(parameters, type, target, stackOnly);
     }
 
     public CiRegister[] getCallingConventionRegisters(Type type, RegisterFlag flag) {
         return allParameterRegisters;
     }
 
-    private CiCallingConvention callingConvention(CiKind[] types, Type type, CiTarget target) {
+    private CiCallingConvention callingConvention(CiKind[] types, Type type, CiTarget target, boolean stackOnly) {
         CiValue[] locations = new CiValue[types.length];
 
         int currentGeneral = 0;
@@ -134,14 +134,14 @@
                 case Long:
                 case Word:
                 case Object:
-                    if (currentGeneral < generalParameterRegisters.length) {
+                    if (!stackOnly && currentGeneral < generalParameterRegisters.length) {
                         CiRegister register = generalParameterRegisters[currentGeneral++];
                         locations[i] = register.asValue(kind);
                     }
                     break;
                 case Float:
                 case Double:
-                    if (currentXMM < xmmParameterRegisters.length) {
+                    if (!stackOnly && currentXMM < xmmParameterRegisters.length) {
                         CiRegister register = xmmParameterRegisters[currentXMM++];
                         locations[i] = register.asValue(kind);
                     }
@@ -193,7 +193,7 @@
         return rsp;
     }
 
-    public CiCalleeSaveArea getCalleeSaveArea() {
+    public CiCalleeSaveLayout getCalleeSaveLayout() {
         return registerSaveArea;
     }
 
@@ -202,7 +202,7 @@
         String res = String.format(
              "Allocatable: " + Arrays.toString(getAllocatableRegisters()) + "%n" +
              "CallerSave:  " + Arrays.toString(getCallerSaveRegisters()) + "%n" +
-             "CalleeSave:  " + getCalleeSaveArea() + "%n" +
+             "CalleeSave:  " + getCalleeSaveLayout() + "%n" +
              "Scratch:     " + getScratchRegister() + "%n");
         return res;
     }
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java	Tue Jun 28 19:22:42 2011 +0200
@@ -82,8 +82,8 @@
                     return "{" + call.runtimeCall.name() + "}";
                 } else if (call.symbol != null) {
                     return "{" + call.symbol + "}";
-                } else if (call.globalStubID != null) {
-                    return "{" + call.globalStubID + "}";
+                } else if (call.stubID != null) {
+                    return "{" + call.stubID + "}";
                 } else {
                     return "{" + call.method + "}";
                 }
@@ -178,7 +178,7 @@
     }
 
     @Override
-    public Object registerGlobalStub(CiTargetMethod targetMethod, String name) {
+    public Object registerCompilerStub(CiTargetMethod targetMethod, String name) {
         return HotSpotTargetMethod.installStub(compiler, targetMethod, name);
     }
 
@@ -266,10 +266,6 @@
             memoryWrite.setGuard((GuardNode) tool.createGuard(new IsNonNull(field.object(), graph)));
             memoryWrite.setStateAfter(field.stateAfter());
             memoryWrite.setNext(field.next());
-
-            //MemoryMergeNode memoryMergeNode = new MemoryMergeNode(graph);
-            //memoryMergeNode.setStateAfter(field.stateAfter());
-            //tool.createMemoryMerge(memoryMergeNode);
             if (field.field().kind() == CiKind.Object && !field.value().isNullConstant()) {
                 FieldWriteBarrier writeBarrier = new FieldWriteBarrier(field.object(), graph);
                 memoryWrite.setNext(writeBarrier);
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotXirGenerator.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotXirGenerator.java	Tue Jun 28 19:22:42 2011 +0200
@@ -96,7 +96,7 @@
                 XirOperand temp = asm.createRegisterTemp("temp (r10)", CiKind.Word, AMD64.r10);
                 XirOperand cache = asm.createRegisterTemp("cache (rax)", CiKind.Word, AMD64.rax);
 
-                CiCallingConvention conventions = registerConfig.getCallingConvention(JavaCallee, new CiKind[] {CiKind.Object}, target);
+                CiCallingConvention conventions = registerConfig.getCallingConvention(JavaCallee, new CiKind[] {CiKind.Object}, target, false);
                 XirOperand receiver = asm.createRegisterTemp("receiver", CiKind.Word, conventions.locations[0].asRegister());
 
                 asm.pload(CiKind.Word, temp, receiver, asm.i(config.hubOffset), false);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalColoringFilter.java	Tue Jun 28 19:22:42 2011 +0200
@@ -0,0 +1,79 @@
+/*
+ * 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.sun.hotspot.igv.graal.filters;
+
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.filter.AbstractFilter;
+import com.sun.hotspot.igv.graph.Diagram;
+import com.sun.hotspot.igv.graph.Figure;
+import java.awt.Color;
+import java.util.List;
+
+public class GraalColoringFilter extends AbstractFilter {
+    
+    private String colorName;
+
+    public GraalColoringFilter(String colorName) {
+        this.colorName = colorName;
+    }
+
+    public String getName() {
+        return "Graal Coloring Filter (" + colorName + ")";
+    }
+
+    public void apply(Diagram d) {
+        List<Figure> figures = d.getFigures();
+        int colors = 0;
+        for (Figure f : figures) {
+            Properties p = f.getProperties();
+            final String prop = p.get(colorName + "Color");
+            if (prop == null) {
+                continue;
+            }
+            try {
+                int color = Integer.parseInt(prop);
+                if (color > colors) {
+                    colors = color;
+                }
+            } catch (NumberFormatException nfe) {
+                // nothing to do
+            }
+        }
+        colors++;
+        for (Figure f : figures) {
+            Properties p = f.getProperties();
+            final String prop = p.get(colorName + "Color");
+            if (prop == null) {
+                continue;
+            }
+            try {
+                int color = Integer.parseInt(prop);
+                Color c = Color.getHSBColor((float) color / colors, 1.0f, 0.7f);
+                f.setColor(c);
+            } catch (NumberFormatException nfe) {
+                // nothing to do
+            }
+        }
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java	Tue Jun 28 19:14:28 2011 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java	Tue Jun 28 19:22:42 2011 +0200
@@ -28,6 +28,7 @@
 import com.sun.hotspot.igv.graph.Connection;
 import com.sun.hotspot.igv.graph.Diagram;
 import com.sun.hotspot.igv.graph.Figure;
+import com.sun.hotspot.igv.graph.InputSlot;
 import com.sun.hotspot.igv.graph.OutputSlot;
 import java.awt.Color;
 import java.util.List;
@@ -39,8 +40,9 @@
  */
 public class GraalEdgeColorFilter extends AbstractFilter {
 
-    private Color successorColor = Color.ORANGE;
+    private Color successorColor = Color.BLUE;
     private Color usageColor = Color.RED;
+    private Color memoryColor = Color.GREEN;
 
     public GraalEdgeColorFilter() {
     }
@@ -53,7 +55,6 @@
         List<Figure> figures = d.getFigures();
         for (Figure f : figures) {
             Properties p = f.getProperties();
-
             int succCount = Integer.parseInt(p.get("successorCount"));
             for (OutputSlot os : f.getOutputSlots()) {
                 Color color;
@@ -69,6 +70,22 @@
                 }
             }
         }
+        for (Figure f : figures) {
+            Properties p = f.getProperties();
+            int predCount = Integer.parseInt(p.get("predecessorCount"));
+            int inputCount = Integer.parseInt(p.get("inputCount"));
+            int variableInputCount = Integer.parseInt(p.get("variableInputCount"));
+            if (p.get("memoryCheckpoint") != null) {
+                for (InputSlot is : f.getInputSlots()) {
+                    if (is.getPosition() > predCount + inputCount - variableInputCount) {
+                        is.setColor(memoryColor);
+                        for (Connection c : is.getConnections()) {
+                            c.setColor(memoryColor);
+                        }
+                    }
+                }
+            }
+        }
     }
 
     public Color getUsageColor() {
@@ -78,7 +95,15 @@
     public void setUsageColor(Color usageColor) {
         this.usageColor = usageColor;
     }
+    
+    public void setMemoryColor(Color memoryColor) {
+        this.memoryColor = memoryColor;
+    }
 
+    public Color getMemoryColor() {
+        return memoryColor;
+    }
+    
     public Color getSuccessorColor() {
         return successorColor;
     }
--- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/color.filter	Tue Jun 28 19:14:28 2011 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/color.filter	Tue Jun 28 19:22:42 2011 +0200
@@ -1,9 +1,11 @@
 colorize("name", ".*", white);
-colorize("name", "StartNode|EndNode|LoopBegin|LoopEnd|Return", red);
+colorize("name", "StartNode|EndNode|LoopBegin|LoopEnd|Return", orange);
 colorize("name", "Phi:.*", magenta);
 colorize("name", "FrameState@.*", new java.awt.Color(0.5, 0.8, 1.0));
 colorize("name", "If", pink);
 colorize("name", "const.*", new java.awt.Color(0.7, 0.7, 0.7));
 colorize("name", "Local", new java.awt.Color(0.85, 0.85, 0.85));
 colorize("name", "\\+|-|\\*|/", cyan);
-colorize("name", "Comp .*", yellow);
\ No newline at end of file
+colorize("name", "Comp .*", yellow);
+
+colorize("notInOwnBlock", "true", red);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Text Editor/build/classes/at/ssw/visualizer/texteditor/Bundle.properties	Tue Jun 28 19:22:42 2011 +0200
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=Text Editor
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Text Editor/build/classes/at/ssw/visualizer/texteditor/layer.xml	Tue Jun 28 19:22:42 2011 +0200
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
+<filesystem>
+    <attr name="Editors\Preferences\Defaults\org-netbeans-modules-editor-preferences-mac.xml\position" intvalue="200"/>
+    <attr name="Editors\Preferences\Defaults\org-netbeans-modules-editor-preferences.xml\position" intvalue="100"/>
+    <folder name="Editors">
+        <folder name="Preferences">
+            <folder name="Defaults">
+                <file name="at-ssw-visualizer-texteditor-preferences.xml" url="preferences.xml">
+                    <attr name="position" intvalue="300"/>
+                </file>
+            </folder>
+        </folder>
+    </folder>
+</filesystem>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Text Editor/build/classes/at/ssw/visualizer/texteditor/preferences.xml	Tue Jun 28 19:22:42 2011 +0200
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE editor-preferences PUBLIC "-//NetBeans//DTD Editor Preferences 1.0//EN" "http://www.netbeans.org/dtds/EditorPreferences-1_0.dtd">
+
+<editor-preferences>
+    <entry name="code-folding-enable" value="true" javaType="java.lang.Boolean" />
+</editor-preferences>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Text Editor/build/depcache/dependencies.txt	Tue Jun 28 19:22:42 2011 +0200
@@ -0,0 +1,282 @@
+||:at.ssw.visualizer.texteditor.Editor
+at.ssw.visualizer.core.selection.SelectionManager
+at.ssw.visualizer.core.selection.SelectionProvider
+org.openide.text.CloneableEditor
+javax.swing.JEditorPane
+at.ssw.visualizer.texteditor.Editor$2
+at.ssw.visualizer.texteditor.Editor$1
+at.ssw.visualizer.core.selection.Selection
+at.ssw.visualizer.texteditor.Editor
+at.ssw.visualizer.texteditor.EditorSupport
+||:at.ssw.visualizer.texteditor.EditorSupport
+java.lang.StringBuilder
+java.lang.UnsupportedOperationException
+org.openide.windows.CloneableOpenSupport$Env
+org.openide.text.CloneableEditorSupport
+at.ssw.visualizer.texteditor.EditorSupport$Env
+javax.swing.text.StyledDocument
+org.openide.windows.CloneableOpenSupport
+at.ssw.visualizer.texteditor.model.Text
+org.openide.cookies.EditorCookie$Observable
+com.sun.hotspot.igv.data.InputGraph
+org.openide.cookies.EditCookie
+org.openide.cookies.EditorCookie
+org.openide.text.CloneableEditorSupport$Env
+at.ssw.visualizer.texteditor.EditorSupport
+com.sun.hotspot.igv.data.Group
+||:at.ssw.visualizer.texteditor.fold.FoldManager$SideBarFactory
+java.lang.Object
+at.ssw.visualizer.texteditor.fold.FoldManager$SideBarFactory
+org.netbeans.editor.SideBarFactory
+at.ssw.visualizer.texteditor.fold.FoldManager
+org.netbeans.editor.CodeFoldingSideBar
+||:at.ssw.visualizer.texteditor.model.FoldingRegion
+at.ssw.visualizer.texteditor.model.FoldingRegion
+at.ssw.visualizer.texteditor.model.TextRegion
+||:at.ssw.visualizer.texteditor.tooltip.StyledToolTip
+java.awt.Color
+javax.swing.border.LineBorder
+java.awt.BorderLayout
+java.lang.StringBuilder
+java.awt.Dimension
+at.ssw.visualizer.texteditor.tooltip.StyledToolTip
+javax.swing.JEditorPane
+javax.swing.JPanel
+||:at.ssw.visualizer.texteditor.model.TextRegion
+java.lang.Object
+at.ssw.visualizer.texteditor.model.TextRegion
+||:at.ssw.visualizer.texteditor.view.AbstractTextViewTopComponent$1
+java.lang.Object
+at.ssw.visualizer.texteditor.view.AbstractTextViewTopComponent
+at.ssw.visualizer.texteditor.view.AbstractTextViewTopComponent$1
+javax.swing.event.ChangeListener
+||:at.ssw.visualizer.texteditor.model.TextBuilder
+java.lang.StringBuilder
+com.sun.hotspot.igv.data.InputBlock
+java.util.HashSet
+java.util.Set
+java.util.List
+java.util.ArrayList
+at.ssw.visualizer.texteditor.model.Text
+at.ssw.visualizer.texteditor.model.TextBuilder
+java.util.Iterator
+java.util.HashMap
+java.util.Map
+[Lat.ssw.visualizer.texteditor.model.FoldingRegion;
+at.ssw.visualizer.texteditor.model.FoldingRegion
+java.lang.Object
+java.lang.String
+||:at.ssw.visualizer.texteditor.view.AbstractTextViewTopComponent
+at.ssw.visualizer.texteditor.view.AbstractTextViewTopComponent
+javax.swing.JScrollPane
+at.ssw.visualizer.core.selection.SelectionManager
+javax.swing.JEditorPane
+javax.swing.BorderFactory
+java.awt.BorderLayout
+com.sun.hotspot.igv.data.InputGraph
+[Lcom.sun.hotspot.igv.data.InputBlock;
+at.ssw.visualizer.core.selection.Selection
+org.openide.windows.TopComponent
+at.ssw.visualizer.texteditor.view.AbstractTextViewTopComponent$1
+java.util.Arrays
+||:at.ssw.visualizer.texteditor.tooltip.ToolTipAction
+at.ssw.visualizer.texteditor.model.Scanner
+org.netbeans.editor.PopupManager
+org.netbeans.editor.Utilities
+org.netbeans.editor.TokenID
+org.netbeans.editor.PopupManager$HorizontalBounds
+org.netbeans.modules.editor.NbEditorKit$NbBuildToolTipAction
+org.netbeans.editor.BaseDocument
+org.netbeans.editor.EditorUI
+at.ssw.visualizer.texteditor.model.Text
+javax.swing.plaf.TextUI
+java.awt.event.MouseEvent
+org.netbeans.modules.editor.NbEditorKit
+org.netbeans.editor.ext.ToolTipSupport
+at.ssw.visualizer.texteditor.tooltip.ToolTipAction
+javax.swing.text.JTextComponent
+at.ssw.visualizer.texteditor.tooltip.StyledToolTip
+org.netbeans.editor.PopupManager$Placement
+||:at.ssw.visualizer.texteditor.fold.FoldManager$FoldManagerFactory
+java.lang.Object
+org.netbeans.spi.editor.fold.FoldManagerFactory
+at.ssw.visualizer.texteditor.fold.FoldManager$FoldManagerFactory
+at.ssw.visualizer.texteditor.fold.FoldManager
+||:at.ssw.visualizer.core.selection.Selection
+[Ljavax.swing.event.ChangeListener;
+at.ssw.visualizer.core.selection.Selection$1
+javax.swing.event.ChangeListener
+java.util.List
+java.util.ArrayList
+at.ssw.visualizer.core.selection.SelectionManager
+java.lang.Class
+java.util.HashMap
+java.util.Map
+javax.swing.event.ChangeEvent
+at.ssw.visualizer.core.selection.Selection
+java.lang.Object
+javax.swing.Timer
+||:at.ssw.visualizer.texteditor.model.BlockRegion
+at.ssw.visualizer.texteditor.model.BlockRegion
+at.ssw.visualizer.texteditor.model.TextRegion
+||:at.ssw.visualizer.texteditor.highlight.HighlightsContainer$HighlightsLayerFactory
+at.ssw.visualizer.texteditor.highlight.HighlightsContainer
+at.ssw.visualizer.texteditor.model.Text
+org.netbeans.spi.editor.highlighting.HighlightsLayerFactory
+org.netbeans.spi.editor.highlighting.HighlightsLayer
+java.lang.Object
+javax.swing.text.Document
+org.netbeans.spi.editor.highlighting.ZOrder
+org.netbeans.spi.editor.highlighting.HighlightsLayerFactory$Context
+at.ssw.visualizer.texteditor.highlight.HighlightsContainer$HighlightsLayerFactory
+||:at.ssw.visualizer.texteditor.highlight.HighlightsContainer
+javax.swing.text.JTextComponent
+org.netbeans.spi.editor.highlighting.support.AbstractHighlightsContainer
+org.netbeans.api.editor.mimelookup.MimeLookup
+org.openide.util.WeakListeners
+org.netbeans.api.editor.mimelookup.MimePath
+javax.swing.text.SimpleAttributeSet
+at.ssw.visualizer.texteditor.highlight.HighlightsContainer$HighlightsLayerFactory
+org.openide.util.Lookup
+javax.swing.event.CaretListener
+at.ssw.visualizer.texteditor.highlight.HighlightsContainer
+at.ssw.visualizer.texteditor.model.Text
+at.ssw.visualizer.texteditor.model.Scanner
+org.netbeans.api.editor.settings.FontColorSettings
+at.ssw.visualizer.texteditor.highlight.HighlightsContainer$1
+javax.swing.text.Caret
+org.netbeans.editor.TokenID
+at.ssw.visualizer.texteditor.highlight.HighlightsContainer$RegionSequence
+javax.swing.text.Document
+||:at.ssw.visualizer.core.selection.Selection$1
+java.lang.Object
+at.ssw.visualizer.core.selection.Selection
+at.ssw.visualizer.core.selection.Selection$1
+java.awt.event.ActionListener
+||:at.ssw.visualizer.texteditor.model.HoverParser
+java.lang.Object
+java.util.Iterator
+java.lang.String
+java.lang.StringBuilder
+java.lang.UnsupportedOperationException
+at.ssw.visualizer.texteditor.model.HoverParser
+||:at.ssw.visualizer.texteditor.Editor$2
+at.ssw.visualizer.texteditor.Editor
+java.util.ArrayList
+javax.swing.event.CaretEvent
+java.util.List
+[Lcom.sun.hotspot.igv.data.InputBlock;
+com.sun.hotspot.igv.data.InputBlock
+java.util.Map
+java.util.Collection
+at.ssw.visualizer.core.selection.Selection
+at.ssw.visualizer.texteditor.model.BlockRegion
+java.util.Iterator
+javax.swing.event.CaretListener
+at.ssw.visualizer.texteditor.Editor$2
+at.ssw.visualizer.texteditor.model.Text
+java.lang.Math
+java.lang.Object
+javax.swing.JEditorPane
+javax.swing.text.Document
+||:at.ssw.visualizer.texteditor.EditorSupport$Env
+java.lang.UnsupportedOperationException
+org.openide.text.CloneableEditorSupport
+at.ssw.visualizer.texteditor.EditorSupport$Env
+java.beans.VetoableChangeSupport
+at.ssw.visualizer.texteditor.model.Text
+java.io.ByteArrayInputStream
+java.io.IOException
+java.lang.Object
+at.ssw.visualizer.texteditor.EditorSupport
+org.openide.text.CloneableEditorSupport$Env
+java.beans.PropertyChangeSupport
+java.lang.String
+||:at.ssw.visualizer.texteditor.Editor$1
+java.lang.Math
+at.ssw.visualizer.texteditor.model.BlockRegion
+javax.swing.event.ChangeListener
+at.ssw.visualizer.texteditor.model.Text
+javax.swing.JEditorPane
+java.util.Map
+[Lcom.sun.hotspot.igv.data.InputBlock;
+at.ssw.visualizer.texteditor.Editor$1
+at.ssw.visualizer.core.selection.Selection
+java.lang.Object
+javax.swing.text.Document
+at.ssw.visualizer.texteditor.Editor
+java.util.Arrays
+||:at.ssw.visualizer.texteditor.model.Text
+java.lang.String
+[Lat.ssw.visualizer.texteditor.model.TextRegion;
+java.lang.Object
+java.util.Iterator
+java.util.Map
+java.util.Set
+at.ssw.visualizer.texteditor.model.Text
+at.ssw.visualizer.texteditor.model.TextRegion
+||:at.ssw.visualizer.core.selection.SelectionProvider
+java.lang.Object
+at.ssw.visualizer.core.selection.SelectionProvider
+||:at.ssw.visualizer.texteditor.EditorKit
+javax.swing.Action
+at.ssw.visualizer.texteditor.tooltip.ToolTipAction
+at.ssw.visualizer.texteditor.EditorKit
+org.netbeans.modules.editor.NbEditorKit
+javax.swing.text.TextAction
+||:at.ssw.visualizer.core.selection.SelectionManager
+at.ssw.visualizer.core.selection.Selection
+java.lang.Object
+at.ssw.visualizer.core.selection.SelectionManager
+||:at.ssw.visualizer.texteditor.model.Scanner
+at.ssw.visualizer.texteditor.model.Scanner
+javax.swing.text.BadLocationException
+java.lang.Math
+java.util.Set
+java.util.BitSet
+java.lang.Class
+java.util.logging.Level
+java.util.logging.Logger
+javax.swing.text.Document
+java.lang.String
+org.netbeans.editor.Syntax
+||:at.ssw.visualizer.texteditor.fold.FoldManager
+at.ssw.visualizer.texteditor.fold.FoldManager$FoldManagerFactory
+javax.swing.text.BadLocationException
+at.ssw.visualizer.texteditor.fold.FoldManager
+org.netbeans.api.editor.fold.FoldType
+at.ssw.visualizer.texteditor.fold.FoldManager$SideBarFactory
+org.netbeans.spi.editor.fold.FoldManager
+at.ssw.visualizer.texteditor.model.Text
+java.lang.Class
+java.util.logging.Level
+java.util.logging.Logger
+at.ssw.visualizer.texteditor.model.FoldingRegion
+java.lang.Object
+org.netbeans.api.editor.fold.FoldHierarchy
+javax.swing.text.Document
+javax.swing.text.JTextComponent
+org.netbeans.spi.editor.fold.FoldOperation
+||:at.ssw.visualizer.texteditor.highlight.HighlightsContainer$1
+java.lang.Object
+javax.swing.event.CaretListener
+at.ssw.visualizer.texteditor.highlight.HighlightsContainer
+at.ssw.visualizer.texteditor.highlight.HighlightsContainer$1
+javax.swing.text.Document
+||:at.ssw.visualizer.texteditor.hyperlink.HyperlinkProvider
+at.ssw.visualizer.texteditor.model.Scanner
+org.netbeans.editor.Utilities
+at.ssw.visualizer.texteditor.hyperlink.HyperlinkProvider
+org.netbeans.editor.TokenID
+org.netbeans.lib.editor.hyperlink.spi.HyperlinkProvider
+at.ssw.visualizer.texteditor.model.Text
+java.lang.Object
+javax.swing.text.Document
+at.ssw.visualizer.texteditor.model.TextRegion
+javax.swing.text.JTextComponent
+||:at.ssw.visualizer.texteditor.highlight.HighlightsContainer$RegionSequence
+java.lang.Object
+org.netbeans.spi.editor.highlighting.HighlightsSequence
+at.ssw.visualizer.texteditor.highlight.HighlightsContainer
+at.ssw.visualizer.texteditor.highlight.HighlightsContainer$RegionSequence
+at.ssw.visualizer.texteditor.model.TextRegion
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Text Editor/build/no-license.txt	Tue Jun 28 19:22:42 2011 +0200
@@ -0,0 +1,1 @@
+[NO LICENSE SPECIFIED]
\ No newline at end of file
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Tue Jun 28 19:14:28 2011 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Tue Jun 28 19:22:42 2011 +0200
@@ -567,7 +567,7 @@
   oop runtime_call = CiTargetMethod_Call::runtimeCall(site);
   oop hotspot_method = CiTargetMethod_Call::method(site);
   oop symbol = CiTargetMethod_Call::symbol(site);
-  oop global_stub = CiTargetMethod_Call::globalStubID(site);
+  oop global_stub = CiTargetMethod_Call::stubID(site);
 
   oop debug_info = CiTargetMethod_Call::debugInfo(site);
 
--- a/src/share/vm/graal/graalJavaAccess.hpp	Tue Jun 28 19:14:28 2011 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Tue Jun 28 19:22:42 2011 +0200
@@ -117,7 +117,7 @@
     oop_field(CiTargetMethod_Call, runtimeCall, "Lcom/sun/cri/ci/CiRuntimeCall;")       \
     oop_field(CiTargetMethod_Call, method, "Lcom/sun/cri/ri/RiMethod;")                 \
     oop_field(CiTargetMethod_Call, symbol, "Ljava/lang/String;")                        \
-    oop_field(CiTargetMethod_Call, globalStubID, "Ljava/lang/Object;")                  \
+    oop_field(CiTargetMethod_Call, stubID, "Ljava/lang/Object;")                        \
     oop_field(CiTargetMethod_Call, debugInfo, "Lcom/sun/cri/ci/CiDebugInfo;")           \
   end_class                                                                             \
   start_class(CiTargetMethod_DataPatch)                                                 \