changeset 2848:c061a6be3728

merge
author Gilles Duboscq <gilles.duboscq@oracle.com>
date Tue, 31 May 2011 15:19:30 +0200
parents caf55daa41dc (current diff) adc4b3ec0a8c (diff)
children 463657856f86
files graal/GraalCompiler/src/com/oracle/max/graal/schedule/Schedule.java graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java graal/GraalCompiler/src/com/sun/c1x/graph/CriticalEdgeFinder.java graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java graal/GraalCompiler/src/com/sun/c1x/ir/Local.java graal/GraalCompiler/src/com/sun/c1x/ir/NegateOp.java graal/GraalCompiler/src/com/sun/c1x/ir/Throw.java
diffstat 39 files changed, 197 insertions(+), 496 deletions(-) [+]
line wrap: on
line diff
--- a/graal/GraalCompiler/src/com/oracle/max/graal/schedule/Block.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/oracle/max/graal/schedule/Block.java	Tue May 31 15:19:30 2011 +0200
@@ -34,7 +34,6 @@
     private final List<Block> successors = new ArrayList<Block>();
     private final List<Block> predecessors = new ArrayList<Block>();
     private List<Node> instructions = new ArrayList<Node>();
-    private boolean exceptionEntry;
     private Block dominator;
     private final List<Block> dominators = new ArrayList<Block>();
 
@@ -93,14 +92,6 @@
         return blockID;
     }
 
-    public void setExceptionEntry(boolean b) {
-        exceptionEntry = b;
-    }
-
-    public boolean isExceptionEntry() {
-        return exceptionEntry;
-    }
-
     /**
      * Iterate over this block, its exception handlers, and its successors, in that order.
      *
--- a/graal/GraalCompiler/src/com/oracle/max/graal/schedule/Schedule.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/oracle/max/graal/schedule/Schedule.java	Tue May 31 15:19:30 2011 +0200
@@ -86,7 +86,7 @@
     }
 
     public static boolean isBlockEnd(Node n) {
-        return trueSuccessorCount(n) > 1 || n instanceof Anchor || n instanceof Return || n instanceof Throw;
+        return trueSuccessorCount(n) > 1 || n instanceof Anchor || n instanceof Return || n instanceof Unwind;
     }
 
     private void identifyBlocks() {
@@ -128,7 +128,6 @@
                     // We have a single predecessor => check its successor count.
                     if (isBlockEnd(singlePred)) {
                         Block b = assignBlock(n);
-                        b.setExceptionEntry(singlePred instanceof Throw);
                         blockBeginNodes.add(n);
                     } else {
                         assignBlock(n, nodeToBlock.get(singlePred));
@@ -395,9 +394,6 @@
         for (Block b : blocks) {
            TTY.println();
            TTY.print(b.toString());
-           if (b.isExceptionEntry()) {
-               TTY.print(" (ex)");
-           }
 
            TTY.print(" succs=");
            for (Block succ : b.getSuccessors()) {
@@ -436,6 +432,9 @@
     }
 
     public static int trueSuccessorCount(Node n) {
+        if (n == null) {
+            return 0;
+        }
         int i = 0;
         for (Node s : n.successors()) {
             if (isCFG(s)) {
@@ -444,4 +443,21 @@
         }
         return i;
     }
+
+    public static int truePredecessorCount(Node n) {
+        if (n == null) {
+            return 0;
+        }
+        int i = 0;
+        for (Node s : n.predecessors()) {
+            if (isCFG(s)) {
+                i++;
+            }
+        }
+
+        if (n instanceof LoopBegin) {
+            i++;
+        }
+        return i;
+    }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScan.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScan.java	Tue May 31 15:19:30 2011 +0200
@@ -746,8 +746,6 @@
 
         // Perform a backward dataflow analysis to compute liveOut and liveIn for each block.
         // The loop is executed until a fixpoint is reached (no changes in an iteration)
-        // Exception handlers must be processed because not all live values are
-        // present in the state array, e.g. because of global value numbering
         do {
             changeOccurred = false;
 
@@ -1974,13 +1972,6 @@
             }
 
             if (op.info != null) {
-                // exception handling
-//                if (compilation.hasExceptionHandlers()) {
-//                    if (op.exceptionEdge() != null && op.exceptionEdge().lir() != null) {
-//                        assignLocations(op.exceptionEdge().lir().instructionsList(), iw);
-//                    }
-//                }
-
                 // compute reference map and debug information
                 computeDebugInfo(iw, op);
             }
--- a/graal/GraalCompiler/src/com/sun/c1x/alloc/RegisterVerifier.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/alloc/RegisterVerifier.java	Tue May 31 15:19:30 2011 +0200
@@ -101,7 +101,7 @@
         } while (!workList.isEmpty());
     }
 
-    void processBlock(LIRBlock block) {
+    private void processBlock(LIRBlock block) {
         if (C1XOptions.TraceLinearScanLevel >= 2) {
             TTY.println();
             TTY.println("processBlock B%d", block.blockID());
@@ -133,21 +133,7 @@
         }
     }
 
-    void processXhandler(LIRBlock xhandler, Interval[] inputState) {
-        if (C1XOptions.TraceLinearScanLevel >= 2) {
-            TTY.println("processXhandler B%d", xhandler.blockID());
-        }
-
-        // must copy state because it is modified
-        inputState = copy(inputState);
-
-        if (xhandler.lir() != null) {
-            processOperations(xhandler.lir(), inputState);
-        }
-        processSuccessor(xhandler, inputState);
-    }
-
-    void processSuccessor(LIRBlock block, Interval[] inputState) {
+    private void processSuccessor(LIRBlock block, Interval[] inputState) {
         Interval[] savedState = stateForBlock(block);
 
         if (savedState != null) {
@@ -258,11 +244,6 @@
                 }
             }
 
-            // process xhandler before output and temp operands
-            if (op.exceptionEdge() != null) {
-                processXhandler(op.exceptionEdge(), inputState);
-            }
-
             // set temp operands (some operations use temp operands also as output operands, so can't set them null)
             n = op.operandCount(LIRInstruction.OperandMode.Temp);
             for (int j = 0; j < n; j++) {
--- a/graal/GraalCompiler/src/com/sun/c1x/asm/TargetMethodAssembler.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/asm/TargetMethodAssembler.java	Tue May 31 15:19:30 2011 +0200
@@ -140,11 +140,11 @@
 
     public void recordExceptionHandlers(int pcOffset, LIRDebugInfo info) {
         if (info != null) {
-            if (info.exceptionEdge != null) {
+            if (info.exceptionEdge() != null) {
                 if (exceptionInfoList == null) {
                     exceptionInfoList = new ArrayList<ExceptionInfo>(4);
                 }
-                exceptionInfoList.add(new ExceptionInfo(pcOffset, info.exceptionEdge, info.state.bci));
+                exceptionInfoList.add(new ExceptionInfo(pcOffset, info.exceptionEdge(), info.state.bci));
             }
         }
     }
@@ -155,7 +155,7 @@
             assert lastSafepointPos < pcOffset;
             lastSafepointPos = pcOffset;
             targetMethod.recordSafepoint(pcOffset, info.debugInfo());
-            recordExceptionHandlers(pcOffset, info);
+            assert info.exceptionEdge() == null;
         }
     }
 
--- a/graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java	Tue May 31 15:19:30 2011 +0200
@@ -215,7 +215,7 @@
         public final LIRDebugInfo info;
 
         public DeoptimizationStub(FrameState state) {
-            info = new LIRDebugInfo(state, null);
+            info = new LIRDebugInfo(state);
         }
     }
 
@@ -387,7 +387,7 @@
             dims[i] = toXirArgument(x.dimension(i));
         }
 
-        XirSnippet snippet = xir.genNewMultiArray(site(x), dims, x.elementKind);
+        XirSnippet snippet = xir.genNewMultiArray(site(x), dims, x.elementType);
         emitXir(snippet, x, stateFor(x), null, true);
     }
 
@@ -476,6 +476,9 @@
         RiMethod target = x.target();
         LIRDebugInfo info = stateFor(x, stateBeforeInvokeWithArguments(x));
         LIRDebugInfo info2 = stateFor(x, stateBeforeInvokeReturn(x));
+        if (x.exceptionEdge() != null) {
+            info2.setExceptionEdge(getLIRBlock(x.exceptionEdge()));
+        }
 
         XirSnippet snippet = null;
 
@@ -879,20 +882,6 @@
     }
 
     @Override
-    public void visitThrow(Throw x) {
-        setNoResult(x);
-        CiValue exceptionOpr = load(x.exception());
-        LIRDebugInfo info = stateFor(x, x.stateBefore());
-
-        // move exception oop into fixed register
-        CiCallingConvention callingConvention = compilation.frameMap().getCallingConvention(new CiKind[]{CiKind.Object}, RuntimeCall);
-        CiValue argumentOperand = callingConvention.locations[0];
-        lir.move(exceptionOpr, argumentOperand);
-
-        lir.throwException(CiValue.IllegalValue, argumentOperand, info);
-    }
-
-    @Override
     public void visitDeoptimize(Deoptimize deoptimize) {
         DeoptimizationStub stub = new DeoptimizationStub(lastState);
         addDeoptimizationStub(stub);
@@ -1487,16 +1476,7 @@
         if (compilation.placeholderState != null) {
             state = compilation.placeholderState;
         }
-
-        assert state != null;
-        LIRBlock exceptionEdge = null;
-        if (x instanceof ExceptionEdgeInstruction) {
-            Instruction begin = ((ExceptionEdgeInstruction) x).exceptionEdge();
-            if (begin != null) {
-                exceptionEdge = getLIRBlock(begin);
-            }
-        }
-        return new LIRDebugInfo(state, exceptionEdge);
+        return new LIRDebugInfo(state);
     }
 
     List<CiValue> visitInvokeArguments(CiCallingConvention cc, Invoke x, List<CiValue> pointerSlots) {
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/CriticalEdgeFinder.java	Tue May 31 15:19:08 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2009, 2010, 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.c1x.graph;
-
-import java.util.*;
-
-import com.oracle.graal.graph.*;
-import com.sun.c1x.*;
-import com.sun.c1x.debug.*;
-import com.sun.c1x.ir.*;
-import com.sun.c1x.lir.*;
-
-/**
- * This class finds and splits "critical" edges in the control flow graph.
- * An edge between two blocks {@code A} and {@code B} is "critical" if {@code A}
- * has more than one successor and {@code B} has more than one predecessor. Such
- * edges are split by adding a block between the two blocks.
- */
-public class CriticalEdgeFinder {
-
-    private final List<LIRBlock> lirBlocks;
-    private final Graph graph;
-
-    /**
-     * The graph edges represented as a map from source to target nodes.
-     * Using a linked hash map makes compilation tracing more deterministic and thus eases debugging.
-     */
-    private Map<LIRBlock, List<LIRBlock>> edges = C1XOptions.DetailedAsserts ?
-                    new LinkedHashMap<LIRBlock, List<LIRBlock>>() :
-                    new HashMap<LIRBlock, List<LIRBlock>>();
-
-    public CriticalEdgeFinder(List<LIRBlock> lirBlocks, Graph graph) {
-        this.lirBlocks = lirBlocks;
-        this.graph = graph;
-        for (LIRBlock block : lirBlocks) {
-            apply(block);
-        }
-
-    }
-
-    private void apply(LIRBlock block) {
-        if (block.numberOfSux() >= 2) {
-            for (LIRBlock succ : block.blockSuccessors()) {
-                if (succ.numberOfPreds() >= 2) {
-                    // TODO: (tw) probably we don't have to make it a critical edge if succ only contains the _same_ predecessor multiple times.
-                    recordCriticalEdge(block, succ);
-                }
-            }
-        }
-    }
-
-    private void recordCriticalEdge(LIRBlock block, LIRBlock succ) {
-        if (!edges.containsKey(block)) {
-            edges.put(block, new ArrayList<LIRBlock>());
-        }
-
-        edges.get(block).add(succ);
-    }
-
-    public void splitCriticalEdges() {
-        for (Map.Entry<LIRBlock, List<LIRBlock>> entry : edges.entrySet()) {
-            LIRBlock from = entry.getKey();
-            for (LIRBlock to : entry.getValue()) {
-                LIRBlock split = splitEdge(from, to);
-                if (C1XOptions.PrintHIR) {
-                    TTY.println("Split edge between block %d and block %d, creating new block %d", from.blockID(), to.blockID(), split.blockID());
-                }
-            }
-        }
-    }
-
-
-    /**
-     * Creates and inserts a new block between this block and the specified successor,
-     * altering the successor and predecessor lists of involved blocks appropriately.
-     * @param source the source of the edge
-     * @param target the successor before which to insert a block
-     * @return the new block inserted
-     */
-    public LIRBlock splitEdge(LIRBlock source, LIRBlock target) {
-
-        // create new successor and mark it for special block order treatment
-        LIRBlock newSucc = new LIRBlock(lirBlocks.size());
-        lirBlocks.add(newSucc);
-
-        // This goto is not a safepoint.
-        Anchor e = new Anchor(null, graph);
-        Node sourceInstruction = source.lastInstruction();
-        Node targetInstruction = target.firstInstruction();
-        int sourceInstructionPredIndex = targetInstruction.predecessors().indexOf(sourceInstruction);
-        assert sourceInstructionPredIndex != -1 : "must find source instruction " + sourceInstruction + " in predecessor array of target instruction " + targetInstruction;
-        int replacedIndex = targetInstruction.predecessorsIndex().get(sourceInstructionPredIndex);
-        assert replacedIndex != -1 && sourceInstruction.successors().get(replacedIndex) != null;
-        e.successors().setAndClear(1, sourceInstruction, replacedIndex);
-        sourceInstruction.successors().set(replacedIndex, e);
-        newSucc.getInstructions().add(e);
-        assert e.defaultSuccessor() != null;
-        source.substituteSuccessor(target, newSucc);
-        target.substitutePredecessor(source, newSucc);
-        newSucc.blockPredecessors().add(source);
-        newSucc.blockSuccessors().add(target);
-        return newSucc;
-    }
-}
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java	Tue May 31 15:19:30 2011 +0200
@@ -338,11 +338,7 @@
         return handler.catchTypeCPI() == 0;
     }
 
-    private void handleException(Instruction x, int bci) {
-        if (!hasHandler()) {
-            return;
-        }
-
+    private Instruction handleException(Value exceptionObject, int bci) {
         assert bci == Instruction.SYNCHRONIZATION_ENTRY_BCI || bci == bci() : "invalid bci";
 
         RiExceptionHandler firstHandler = null;
@@ -389,19 +385,22 @@
 
             StateSplit entry = new Placeholder(graph);
             entry.setStateBefore(entryState);
-            ExceptionObject exception = new ExceptionObject(graph);
-            entry.setNext(exception);
-            FrameState stateWithException = entryState.duplicateModified(bci, CiKind.Void, exception);
+
+            Instruction currentNext = entry;
+            Value currentExceptionObject = exceptionObject;
+            if (currentExceptionObject == null) {
+                ExceptionObject exception = new ExceptionObject(graph);
+                entry.setNext(exception);
+                currentNext = exception;
+                currentExceptionObject = exception;
+            }
+            FrameState stateWithException = entryState.duplicateModified(bci, CiKind.Void, currentExceptionObject);
 
             Instruction successor = createTarget(dispatchBlock, stateWithException);
-            Anchor end = new Anchor(successor, graph);
-            exception.setNext(end);
-            if (x instanceof Invoke) {
-                ((Invoke) x).setExceptionEdge(entry);
-            } else {
-                ((Throw) x).setExceptionEdge(entry);
-            }
+            currentNext.setNext(successor);
+            return entry;
         }
+        return null;
     }
 
     private void genLoadConstant(int cpi) {
@@ -609,11 +608,13 @@
     }
 
     private void genThrow(int bci) {
-        FrameState stateBefore = frameState.create(bci);
-        Throw t = new Throw(frameState.apop(), graph);
-        t.setStateBefore(stateBefore);
-        appendWithBCI(t);
-        handleException(t, bci);
+        Value exception = frameState.apop();
+        append(new NullCheck(exception, graph));
+        Instruction entry = handleException(exception, bci);
+        if (entry == null) {
+            entry = new Unwind(exception, graph.end(), graph);
+        }
+        append(entry);
     }
 
     private void genCheckCast() {
@@ -832,7 +833,7 @@
         CiKind resultType = returnKind(target);
         Invoke invoke = new Invoke(bci(), opcode, resultType.stackKind(), args, target, target.signature().returnType(compilation.method.holder()), graph);
         Value result = appendWithBCI(invoke);
-        handleException(invoke, bci());
+        invoke.setExceptionEdge(handleException(null, bci()));
         frameState.pushReturn(resultType, result);
     }
 
@@ -1010,7 +1011,7 @@
     }
 
     private Value appendWithBCI(Instruction x) {
-        assert x.next() == null && x.predecessors().size() == 0 : "instruction should not have been appended yet";
+        assert x.predecessors().size() == 0 : "instruction should not have been appended yet";
         assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")";
         lastInstr.setNext(x);
 
@@ -1080,7 +1081,7 @@
 
         // Exit the monitor and unwind the stack.
         genMonitorExit(lock);
-        append(new Unwind(frameState.apop(), graph));
+        append(new Unwind(frameState.apop(), graph.end(), graph));
 
         // The sync handler is always the last thing to add => we can clear the frameState.
         frameState = null;
@@ -1149,7 +1150,7 @@
                 append(new MonitorExit(rootMethodSynchronizedObject, lockAddress, lockNumber, graph));
                 frameState.unlock();
             }
-            append(new Unwind(frameState.apop(), graph));
+            append(new Unwind(frameState.apop(), graph.end(), graph));
         } else {
             assert frameState.stackSize() == 1;
 
@@ -1494,12 +1495,4 @@
     private Block removeFromWorkList() {
         return workList.poll();
     }
-
-    /**
-     * Checks whether this graph has any handlers.
-     * @return {@code true} if there are any exception handlers
-     */
-    private boolean hasHandler() {
-        return Modifier.isSynchronized(compilation.method.accessFlags()) || (compilation.method.exceptionHandlers() != null && compilation.method.exceptionHandlers().length > 0);
-    }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java	Tue May 31 15:19:30 2011 +0200
@@ -82,13 +82,38 @@
         }
 
         new PhiSimplifier(this);
-        Schedule schedule = new Schedule(this.compilation.graph);
+
+//        Graph newGraph = new Graph();
+//        HashMap<Node, Node> replacement = new HashMap<Node, Node>();
+//        replacement.put(compilation.graph.start(), newGraph.start());
+//        replacement.put(compilation.graph.end(), newGraph.end());
+//        newGraph.addDuplicate(compilation.graph.getNodes(), replacement);
+//        compilation.graph = newGraph;
+
+        Graph graph = compilation.graph;
+
+        // Split critical edges.
+        List<Node> nodes = graph.getNodes();
+        for (int i = 0; i < nodes.size(); ++i) {
+            Node n = nodes.get(i);
+            if (Schedule.trueSuccessorCount(n) > 1) {
+                for (int j = 0; j < n.successors().size(); ++j) {
+                    Node succ = n.successors().get(j);
+                    if (Schedule.truePredecessorCount(succ) > 1) {
+                        Anchor a = new Anchor(null, graph);
+                        a.successors().setAndClear(1, n, j);
+                        n.successors().set(j, a);
+                    }
+                }
+            }
+        }
+
+        Schedule schedule = new Schedule(graph);
         List<Block> blocks = schedule.getBlocks();
         List<LIRBlock> lirBlocks = new ArrayList<LIRBlock>();
         Map<Block, LIRBlock> map = new HashMap<Block, LIRBlock>();
         for (Block b : blocks) {
             LIRBlock block = new LIRBlock(b.blockID());
-            block.setExceptionEntry(b.isExceptionEntry());
             map.put(b, block);
             block.setInstructions(b.getInstructions());
             block.setLinearScanNumber(b.blockID());
@@ -100,11 +125,7 @@
 
         for (Block b : blocks) {
             for (Block succ : b.getSuccessors()) {
-//                if (succ.isExceptionEntry()) {
-//                    map.get(b).getExceptionHandlerSuccessors().add(map.get(succ));
-//                } else {
-                    map.get(b).blockSuccessors().add(map.get(succ));
-//                }
+                map.get(b).blockSuccessors().add(map.get(succ));
             }
 
             for (Block pred : b.getPredecessors()) {
@@ -112,16 +133,7 @@
             }
         }
 
-
-     // TODO(tw): Schedule nodes within a block.
-
-
-        CriticalEdgeFinder finder = new CriticalEdgeFinder(lirBlocks, compilation.graph);
-        finder.splitCriticalEdges();
-
-
         orderedBlocks = lirBlocks;
-
         valueToBlock = new HashMap<Node, LIRBlock>();
         for (LIRBlock b : orderedBlocks) {
             for (Node i : b.getInstructions()) {
@@ -132,14 +144,6 @@
         assert startBlock != null;
         assert startBlock.blockPredecessors().size() == 0;
 
-/*        if (startBlock.blockPredecessors().size() > 0) {
-            LIRBlock oldStartBlock = startBlock;
-            startBlock = new LIRBlock(orderedBlocks.size());
-            startBlock.blockSuccessors().add(oldStartBlock);
-
-            orderedBlocks.add(startBlock);
-        }*/
-
         ComputeLinearScanOrder clso = new ComputeLinearScanOrder(lirBlocks.size(), startBlock);
         orderedBlocks = clso.linearScanOrder();
         this.compilation.stats.loopCount = clso.numLoops();
@@ -160,14 +164,6 @@
         // Graph builder must set the startBlock and the osrEntryBlock
         new GraphBuilder(compilation, this, compilation.graph).build();
 
-//        Graph newGraph = new Graph();
-//        HashMap<Node, Node> replacement = new HashMap<Node, Node>();
-//        replacement.put(compilation.graph.start(), newGraph.start());
-//        replacement.put(compilation.graph.end(), newGraph.end());
-//        newGraph.addDuplicate(compilation.graph.getNodes(), replacement);
-//
-//        compilation.graph = newGraph;
-
         verifyAndPrint("After graph building");
 
         if (C1XOptions.PrintCompilation) {
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/AccessField.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/AccessField.java	Tue May 31 15:19:30 2011 +0200
@@ -66,14 +66,12 @@
      * @param kind the result kind of the access
      * @param object the instruction producing the receiver object
      * @param field the compiler interface representation of the field
-     * @param stateBefore the state before the field access
      * @param inputCount
      * @param successorCount
      * @param graph
      */
     public AccessField(CiKind kind, Value object, RiField field, int inputCount, int successorCount, Graph graph) {
         super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
-//        assert object != null : "every field access must reference some object";
         this.field = field;
         setObject(object);
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/ComputeLinearScanOrder.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/ComputeLinearScanOrder.java	Tue May 31 15:19:30 2011 +0200
@@ -162,16 +162,6 @@
             cur.setBackwardBranchTarget(true);
             parent.setLinearScanLoopEnd();
 
-            // When a loop header is also the start of an exception handler, then the backward branch is
-            // an exception edge. Because such edges are usually critical edges which cannot be split, the
-            // loop must be excluded here from processing.
-            if (cur.isExceptionEntry()) {
-                // Make sure that dominators are correct in this weird situation
-                iterativeDominators = true;
-                return;
-            }
-//            assert parent.numberOfSux() == 1 && parent.suxAt(0) == cur : "loop end blocks must have one successor (critical edges are split)";
-
             loopEndBlocks.add(parent);
             return;
         }
@@ -374,10 +364,10 @@
 //        curBit--;
 
         // exceptions handlers are added as late as possible
-        if (!cur.isExceptionEntry()) {
-            weight |= 1 << curBit;
-        }
-        curBit--;
+//        if (!cur.isExceptionEntry()) {
+//            weight |= 1 << curBit;
+//        }
+//        curBit--;
 
         // guarantee that weight is > 0
         weight |= 1;
@@ -502,7 +492,6 @@
             for (LIRBlock cur : linearScanOrder) {
                 TTY.print(String.format("%4d: B%02d    loop: %2d  depth: %2d", cur.linearScanNumber(), cur.blockID(), cur.loopIndex(), cur.loopDepth()));
 
-                TTY.print(cur.isExceptionEntry() ? " ex" : "   ");
                 TTY.print(cur.isLinearScanLoopHeader() ? " lh" : "   ");
                 TTY.print(cur.isLinearScanLoopEnd() ? " le" : "   ");
 
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/If.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/If.java	Tue May 31 15:19:30 2011 +0200
@@ -77,15 +77,14 @@
     /**
      * Constructs a new If instruction.
      * @param x the instruction producing the first input to the instruction
-     * @param cond the condition (comparison operation)
+     * @param condition the condition (comparison operation)
      * @param y the instruction that produces the second input to this instruction
-     * @param stateAfter the state before the branch but after the input values have been popped
      * @param graph
      */
-    public If(Value x, Condition cond, Value y, Graph graph) {
+    public If(Value x, Condition condition, Value y, Graph graph) {
         super(CiKind.Illegal, 2, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         assert (x == null && y == null) || Util.archKindsEqual(x, y);
-        condition = cond;
+        this.condition = condition;
         setX(x);
         setY(y);
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/IfOp.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/IfOp.java	Tue May 31 15:19:30 2011 +0200
@@ -80,19 +80,20 @@
     /**
      * Constructs a new IfOp.
      * @param x the instruction producing the first value to be compared
-     * @param cond the condition of the comparison
+     * @param condition the condition of the comparison
      * @param y the instruction producing the second value to be compared
      * @param trueValue the value produced if the condition is true
      * @param falseValue the value produced if the condition is false
      */
-    public IfOp(Value x, Condition cond, Value y, Value trueValue, Value falseValue, Graph graph) {
+    public IfOp(Value x, Condition condition, Value y, Value trueValue, Value falseValue, Graph graph) {
         // TODO: return the appropriate bytecode IF_ICMPEQ, etc
         super(trueValue.kind.meet(falseValue.kind), Bytecodes.ILLEGAL, x, y, INPUT_COUNT, SUCCESSOR_COUNT, graph);
-        this.condition = cond;
+        this.condition = condition;
         setTrueValue(trueValue);
         setFalseValue(falseValue);
     }
 
+    // for copying
     private IfOp(CiKind kind, Condition cond, Graph graph) {
         super(kind, Bytecodes.ILLEGAL, null, null, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.condition = cond;
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/InstanceOf.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/InstanceOf.java	Tue May 31 15:19:30 2011 +0200
@@ -41,7 +41,6 @@
      * Constructs a new InstanceOf instruction.
      * @param targetClass the target class of the instanceof check
      * @param object the instruction producing the object input to this instruction
-     * @param stateBefore the state before this instruction
      * @param graph
      */
     public InstanceOf(RiType targetClass, Value targetClassInstruction, Value object, Graph graph) {
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Invoke.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Invoke.java	Tue May 31 15:19:30 2011 +0200
@@ -22,6 +22,8 @@
  */
 package com.sun.c1x.ir;
 
+import java.util.*;
+
 import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.util.*;
@@ -184,6 +186,15 @@
     }
 
     @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        properties.put("opcode", Bytecodes.nameOf(opcode));
+        properties.put("target", CiUtil.format("%H.%n(%p):%r", target, false));
+        properties.put("bci", bci);
+        return properties;
+    }
+
+    @Override
     public Node copy(Graph into) {
         Invoke x = new Invoke(bci, opcode, kind, new Value[argumentCount], target, returnType, into);
         x.setNonNull(isNonNull());
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/LoadIndexed.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/LoadIndexed.java	Tue May 31 15:19:30 2011 +0200
@@ -40,12 +40,11 @@
      * @param array the instruction producing the array
      * @param index the instruction producing the index
      * @param length the instruction producing the length
-     * @param elementType the element type
-     * @param stateAfter the after before executing this instruction
+     * @param elementKind the element type
      * @param graph
      */
-    public LoadIndexed(Value array, Value index, Value length, CiKind elementType, Graph graph) {
-        super(elementType.stackKind(), array, index, length, elementType, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    public LoadIndexed(Value array, Value index, Value length, CiKind elementKind, Graph graph) {
+        super(elementKind.stackKind(), array, index, length, elementKind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
     }
 
     /**
@@ -88,7 +87,7 @@
 
     @Override
     public Node copy(Graph into) {
-        LoadIndexed x = new LoadIndexed(null, null, null, kind, into);
+        LoadIndexed x = new LoadIndexed(null, null, null, elementKind(), into);
         x.setNonNull(isNonNull());
         return x;
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Local.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Local.java	Tue May 31 15:19:30 2011 +0200
@@ -43,7 +43,6 @@
     public Local(CiKind kind, int javaIndex, Graph graph) {
         super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.index = javaIndex;
-        this.inputs().set(0, graph.start());
     }
 
     /**
@@ -98,6 +97,4 @@
         x.setNonNull(isNonNull());
         return x;
     }
-
-
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/LogicOp.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/LogicOp.java	Tue May 31 15:19:30 2011 +0200
@@ -45,7 +45,8 @@
         super(x.kind, opcode, x, y, INPUT_COUNT, SUCCESSOR_COUNT, graph);
     }
 
-    public LogicOp(CiKind kind, int opcode, Graph graph) {
+    // for copying
+    private LogicOp(CiKind kind, int opcode, Graph graph) {
         super(kind, opcode, null, null, INPUT_COUNT, SUCCESSOR_COUNT, graph);
     }
 
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/MonitorEnter.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/MonitorEnter.java	Tue May 31 15:19:30 2011 +0200
@@ -45,7 +45,6 @@
      * @param object the instruction producing the object
      * @param lockAddress the address of the on-stack lock object or {@code null} if the runtime does not place locks on the stack
      * @param lockNumber the number of the lock
-     * @param stateAfter the state after
      * @param graph
      */
     public MonitorEnter(Value object, Value lockAddress, int lockNumber, Graph graph) {
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/MonitorExit.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/MonitorExit.java	Tue May 31 15:19:30 2011 +0200
@@ -39,7 +39,6 @@
      * @param object the instruction produces the object value
      * @param lockAddress the address of the on-stack lock object or {@code null} if the runtime does not place locks on the stack
      * @param lockNumber the number of the lock
-     * @param stateBefore the state after executing this instruction
      * @param graph
      */
     public MonitorExit(Value object, Value lockAddress, int lockNumber, Graph graph) {
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/NegateOp.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/NegateOp.java	Tue May 31 15:19:30 2011 +0200
@@ -69,6 +69,7 @@
         setX(x);
     }
 
+    // for copying
     private NegateOp(CiKind kind, Graph graph) {
         super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/NewMultiArray.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/NewMultiArray.java	Tue May 31 15:19:30 2011 +0200
@@ -67,23 +67,23 @@
         return dimensionCount;
     }
 
-    public final RiType elementKind;
+    public final RiType elementType;
     public final int cpi;
     public final RiConstantPool constantPool;
 
     /**
      * Constructs a new NewMultiArray instruction.
-     * @param elementKind the element type of the array
+     * @param elementType the element type of the array
      * @param dimensions the instructions which produce the dimensions for this array
      * @param stateBefore the state before this instruction
      * @param cpi the constant pool index for resolution
      * @param riConstantPool the constant pool for resolution
      * @param graph
      */
-    public NewMultiArray(RiType elementKind, Value[] dimensions, int cpi, RiConstantPool riConstantPool, Graph graph) {
+    public NewMultiArray(RiType elementType, Value[] dimensions, int cpi, RiConstantPool riConstantPool, Graph graph) {
         super(null, dimensions.length, SUCCESSOR_COUNT, graph);
         this.constantPool = riConstantPool;
-        this.elementKind = elementKind;
+        this.elementType = elementType;
         this.cpi = cpi;
 
         this.dimensionCount = dimensions.length;
@@ -102,7 +102,7 @@
      * @return the element type of the array
      */
     public RiType elementType() {
-        return elementKind;
+        return elementType;
     }
 
     @Override
@@ -114,12 +114,12 @@
           }
           out.print(dimension(i));
         }
-        out.print("] ").print(CiUtil.toJavaName(elementKind));
+        out.print("] ").print(CiUtil.toJavaName(elementType));
     }
 
     @Override
     public Node copy(Graph into) {
-        NewMultiArray x = new NewMultiArray(elementKind, new Value[dimensionCount], cpi, constantPool, into);
+        NewMultiArray x = new NewMultiArray(elementType, new Value[dimensionCount], cpi, constantPool, into);
         x.setNonNull(isNonNull());
         return x;
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/NewObjectArray.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/NewObjectArray.java	Tue May 31 15:19:30 2011 +0200
@@ -41,7 +41,6 @@
      * Constructs a new NewObjectArray instruction.
      * @param elementClass the class of elements in this array
      * @param length the instruction producing the length of the array
-     * @param stateBefore the state before the allocation
      * @param graph
      */
     public NewObjectArray(RiType elementClass, Value length, Graph graph) {
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/NullCheck.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/NullCheck.java	Tue May 31 15:19:30 2011 +0200
@@ -26,12 +26,13 @@
 import com.sun.c1x.debug.*;
 import com.sun.c1x.util.*;
 import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
 
 /**
  * The {@code NullCheck} class represents an explicit null check instruction.
  */
-public final class NullCheck extends Value {
+public final class NullCheck extends Instruction {
 
     private static final int INPUT_COUNT = 1;
     private static final int INPUT_OBJECT = 0;
@@ -71,6 +72,12 @@
         setObject(object);
     }
 
+    // for copying
+    private NullCheck(CiKind kind, Graph graph) {
+        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setNonNull(true);
+    }
+
     @Override
     public void accept(ValueVisitor v) {
         v.visitNullCheck(this);
@@ -109,7 +116,7 @@
 
     @Override
     public Node copy(Graph into) {
-        NullCheck x = new NullCheck(null, into);
+        NullCheck x = new NullCheck(kind, into);
         x.setNonNull(isNonNull());
         return x;
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Return.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Return.java	Tue May 31 15:19:30 2011 +0200
@@ -75,6 +75,11 @@
         successors().set(SUCCESSOR_END, graph.end());
     }
 
+    // for copying
+    private Return(CiKind kind, Graph graph) {
+        super(kind, 0, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
     @Override
     public void accept(ValueVisitor v) {
         v.visitReturn(this);
@@ -91,7 +96,7 @@
 
     @Override
     public Node copy(Graph into) {
-        Return x = new Return(null, into);
+        Return x = new Return(kind, into);
         x.setNonNull(isNonNull());
         return x;
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Throw.java	Tue May 31 15:19:08 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) 2009, 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.c1x.ir;
-
-import com.oracle.graal.graph.*;
-import com.sun.c1x.debug.*;
-import com.sun.c1x.value.*;
-import com.sun.cri.ci.*;
-
-/**
- * The {@code Throw} instruction represents a throw of an exception.
- */
-public final class Throw extends Instruction implements ExceptionEdgeInstruction {
-
-    private static final int INPUT_COUNT = 2;
-    private static final int INPUT_EXCEPTION = 0;
-    private static final int INPUT_STATE_BEFORE = 1;
-
-    private static final int SUCCESSOR_COUNT = 1;
-    private static final int SUCCESSOR_EXCEPTION_EDGE = 0;
-
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
-    }
-
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
-    /**
-     * The instruction which produces the exception to throw.
-     */
-     public Value exception() {
-        return (Value) inputs().get(super.inputCount() + INPUT_EXCEPTION);
-    }
-
-    public Value setException(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_EXCEPTION, n);
-    }
-
-    /**
-     * The state for this instruction.
-     */
-    public FrameState stateBefore() {
-        return (FrameState) inputs().get(super.inputCount() + INPUT_STATE_BEFORE);
-    }
-
-    public FrameState setStateBefore(FrameState n) {
-        return (FrameState) inputs().set(super.inputCount() + INPUT_STATE_BEFORE, n);
-    }
-
-    /**
-     * The entry to the exception dispatch chain for this throw.
-     * TODO ls: this needs more cleanup - throw should either unwind or jump to the exception dispatch chain
-     */
-    @Override
-    public Instruction exceptionEdge() {
-        return (Instruction) successors().get(super.successorCount() + SUCCESSOR_EXCEPTION_EDGE);
-    }
-
-    public Instruction setExceptionEdge(Instruction n) {
-        return (Instruction) successors().set(super.successorCount() + SUCCESSOR_EXCEPTION_EDGE, n);
-    }
-
-    /**
-     * Creates a new Throw instruction.
-     * @param exception the instruction that generates the exception to throw
-     * @param stateAfter the state before the exception is thrown but after the exception object has been popped
-     * @param graph
-     */
-    public Throw(Value exception, Graph graph) {
-        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
-        setException(exception);
-    }
-
-    @Override
-    public void accept(ValueVisitor v) {
-        v.visitThrow(this);
-    }
-
-    @Override
-    public void print(LogStream out) {
-        out.print("throw ").print(exception());
-    }
-
-    @Override
-    public Node copy(Graph into) {
-        Throw x = new Throw(null, into);
-        x.setNonNull(isNonNull());
-        return x;
-    }
-}
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Unwind.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Unwind.java	Tue May 31 15:19:30 2011 +0200
@@ -64,10 +64,10 @@
         return (Value) inputs().set(super.inputCount() + INPUT_EXCEPTION, n);
     }
 
-    public Unwind(Value exception, Graph graph) {
+    public Unwind(Value exception, Node successor, Graph graph) {
         super(CiKind.Object, 0, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         setException(exception);
-        successors().set(SUCCESSOR_END, graph.end());
+        successors().set(SUCCESSOR_END, successor);
     }
 
     @Override
@@ -82,7 +82,7 @@
 
     @Override
     public Node copy(Graph into) {
-        Unwind x = new Unwind(null, into);
+        Unwind x = new Unwind(null, null, into);
         x.setNonNull(isNonNull());
         return x;
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Value.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Value.java	Tue May 31 15:19:30 2011 +0200
@@ -22,6 +22,8 @@
  */
 package com.sun.c1x.ir;
 
+import java.util.*;
+
 import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.cri.ci.*;
@@ -213,4 +215,14 @@
 
     public abstract void print(LogStream out);
 
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        properties.put("kind", kind.toString());
+        properties.put("nonNull", isNonNull);
+        properties.put("operand", operand == null ? "null" : operand.toString());
+        return properties;
+    }
+
+
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java	Tue May 31 15:19:30 2011 +0200
@@ -66,7 +66,6 @@
     public abstract void visitStoreField(StoreField i);
     public abstract void visitStoreIndexed(StoreIndexed i);
     public abstract void visitTableSwitch(TableSwitch i);
-    public abstract void visitThrow(Throw i);
     public abstract void visitDeoptimize(Deoptimize deoptimize);
     public abstract void visitExceptionDispatch(ExceptionDispatch exceptionDispatch);
     public abstract void visitUnwind(Unwind unwind);
--- a/graal/GraalCompiler/src/com/sun/c1x/lir/LIRAssembler.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIRAssembler.java	Tue May 31 15:19:30 2011 +0200
@@ -311,10 +311,6 @@
                 emitLogicOp(op.code, op.operand1(), op.operand2(), op.result());
                 break;
 
-            case Throw:
-                emitThrow(op.operand1(), op.operand2(), op.info);
-                break;
-
             default:
                 throw Util.shouldNotReachHere();
         }
@@ -407,8 +403,6 @@
 
     protected abstract void emitVolatileMove(CiValue inOpr, CiValue result, CiKind kind, LIRDebugInfo info);
 
-    protected abstract void emitThrow(CiValue inOpr1, CiValue inOpr2, LIRDebugInfo info);
-
     protected abstract void emitLogicOp(LIROpcode code, CiValue inOpr1, CiValue inOpr2, CiValue dst);
 
     protected abstract void emitIntrinsicOp(LIROpcode code, CiValue inOpr1, CiValue inOpr2, CiValue dst, LIROp2 op);
--- a/graal/GraalCompiler/src/com/sun/c1x/lir/LIRBlock.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIRBlock.java	Tue May 31 15:19:30 2011 +0200
@@ -185,18 +185,8 @@
     private int linearScanNumber = -1;
     private boolean linearScanLoopEnd;
     private boolean linearScanLoopHeader;
-    private boolean exceptionEntry;
     private boolean backwardBranchTarget;
 
-
-    public void setExceptionEntry(boolean b) {
-        this.exceptionEntry = b;
-    }
-
-    public boolean isExceptionEntry() {
-        return exceptionEntry;
-    }
-
     public void setBackwardBranchTarget(boolean b) {
         this.backwardBranchTarget = b;
     }
@@ -247,24 +237,6 @@
         instructions = list;
     }
 
-    public void substituteSuccessor(LIRBlock target, LIRBlock newSucc) {
-        for (int i = 0; i < successors.size(); ++i) {
-            if (successors.get(i) == target) {
-                successors.set(i, newSucc);
-                break;
-            }
-        }
-    }
-
-    public void substitutePredecessor(LIRBlock source, LIRBlock newSucc) {
-        for (int i = 0; i < predecessors.size(); ++i) {
-            if (predecessors.get(i) == source) {
-                predecessors.set(i, newSucc);
-                break;
-            }
-        }
-    }
-
     public void setLastState(FrameState fs) {
         lastState = fs;
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/lir/LIRDebugInfo.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIRDebugInfo.java	Tue May 31 15:19:30 2011 +0200
@@ -37,12 +37,19 @@
     }
 
     public final FrameState state;
-    public final LIRBlock exceptionEdge;
+    private LIRBlock exceptionEdge;
     public CiDebugInfo debugInfo;
 
-    public LIRDebugInfo(FrameState state, LIRBlock exceptionEdge) {
+    public LIRDebugInfo(FrameState state) {
         assert state != null;
         this.state = state;
+    }
+
+    public LIRBlock exceptionEdge() {
+        return exceptionEdge;
+    }
+
+    public void setExceptionEdge(LIRBlock exceptionEdge) {
         this.exceptionEdge = exceptionEdge;
     }
 
--- a/graal/GraalCompiler/src/com/sun/c1x/lir/LIRInstruction.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIRInstruction.java	Tue May 31 15:19:30 2011 +0200
@@ -482,7 +482,7 @@
     }
 
     public final LIRBlock exceptionEdge() {
-        return (info == null) ? null : info.exceptionEdge;
+        return (info == null) ? null : info.exceptionEdge();
     }
 
     @Override
--- a/graal/GraalCompiler/src/com/sun/c1x/lir/LIRList.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIRList.java	Tue May 31 15:19:30 2011 +0200
@@ -172,10 +172,6 @@
         append(new LIROp1(LIROpcode.NullCheck, opr, info));
     }
 
-    public void throwException(CiValue exceptionPC, CiValue exceptionOop, LIRDebugInfo info) {
-        append(new LIROp2(LIROpcode.Throw, exceptionPC, exceptionOop, CiValue.IllegalValue, info, CiKind.Illegal, true));
-    }
-
     public void compareTo(CiValue left, CiValue right, CiValue dst) {
         append(new LIROp2(LIROpcode.CompareTo, left, right, dst));
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/lir/LIROpcode.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIROpcode.java	Tue May 31 15:19:30 2011 +0200
@@ -77,7 +77,6 @@
         Shl,
         Shr,
         Ushr,
-        Throw,
         CompareTo,
     EndOp2,
     BeginOp3,
--- a/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRAssembler.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRAssembler.java	Tue May 31 15:19:30 2011 +0200
@@ -1397,16 +1397,6 @@
         indirectCall(reg, null, null);
     }
 
-    @Override
-    protected void emitThrow(CiValue exceptionPC, CiValue exceptionOop, LIRDebugInfo info) {
-       // exception object is not added to oop map by LinearScan
-       // (LinearScan assumes that no oops are in fixed registers)
-       // info.addRegisterOop(exceptionOop);
-        directCall(CiRuntimeCall.HandleException, info);
-        // enough room for two byte trap
-        shouldNotReachHere();
-    }
-
     private void emitXIRShiftOp(LIROpcode code, CiValue left, CiValue count, CiValue dest) {
         if (count.isConstant()) {
             emitShiftOp(code, left, ((CiConstant) count).asInt(), dest);
--- a/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java	Tue May 31 15:19:30 2011 +0200
@@ -54,6 +54,7 @@
         if (!isStatic(method.accessFlags())) {
             // add the receiver and assume it is non null
             Local local = new Local(method.holder().kind(), javaIndex, graph);
+            local.inputs().set(0, graph.start());
             local.setNonNull(true);
             local.setDeclaredType(method.holder());
             storeLocal(javaIndex, local);
@@ -67,6 +68,7 @@
             RiType type = sig.argumentTypeAt(i, accessingClass);
             CiKind kind = type.kind().stackKind();
             Local local = new Local(kind, index, graph);
+            local.inputs().set(0, graph.start());
             if (type.isResolved()) {
                 local.setDeclaredType(type);
             }
--- a/graal/GraalGraph/src/com/oracle/graal/graph/Graph.java	Tue May 31 15:19:08 2011 +0200
+++ b/graal/GraalGraph/src/com/oracle/graal/graph/Graph.java	Tue May 31 15:19:30 2011 +0200
@@ -26,6 +26,7 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
@@ -42,8 +43,8 @@
         end = new EndNode(this);
     }
 
-    public Collection<Node> getNodes() {
-        return Collections.unmodifiableCollection(nodes);
+    public List<Node> getNodes() {
+        return Collections.unmodifiableList(nodes);
     }
 
     int register(Node node) {
@@ -74,22 +75,18 @@
 
     public void addDuplicate(Collection<Node> nodes, Map<Node, Node> replacements) {
         Map<Node, Node> newNodes = new HashMap<Node, Node>();
+        // create node duplicates
         for (Node node : nodes) {
             if (node != null && !replacements.containsKey(node)) {
-                newNodes.put(node, node.copy(this));
+                Node newNode = node.copy(this);
+                assert newNode.getClass() == node.getClass();
+                newNodes.put(node, newNode);
             }
         }
+        // re-wire inputs
         for (Entry<Node, Node> entry : newNodes.entrySet()) {
             Node oldNode = entry.getKey();
             Node node = entry.getValue();
-            for (int i = 0; i < oldNode.successors().size(); i++) {
-                Node succ = oldNode.successors().get(i);
-                Node target = replacements.get(succ);
-                if (target == null) {
-                    target = newNodes.get(succ);
-                }
-                node.successors().set(i, target);
-            }
             for (int i = 0; i < oldNode.inputs().size(); i++) {
                 Node input = oldNode.inputs().get(i);
                 Node target = replacements.get(input);
@@ -102,12 +99,6 @@
         for (Entry<Node, Node> entry : replacements.entrySet()) {
             Node oldNode = entry.getKey();
             Node node = entry.getValue();
-            for (int i = 0; i < oldNode.successors().size(); i++) {
-                Node succ = oldNode.successors().get(i);
-                if (newNodes.containsKey(succ)) {
-                    node.successors().set(i, newNodes.get(succ));
-                }
-            }
             for (int i = 0; i < oldNode.inputs().size(); i++) {
                 Node input = oldNode.inputs().get(i);
                 if (newNodes.containsKey(input)) {
@@ -115,5 +106,30 @@
                 }
             }
         }
+        // re-wire successors
+        for (Entry<Node, Node> entry : newNodes.entrySet()) {
+            Node oldNode = entry.getKey();
+            Node node = entry.getValue();
+            for (int i = 0; i < oldNode.predecessors().size(); i++) {
+                Node pred = oldNode.predecessors().get(i);
+                int predIndex = oldNode.predecessorsIndex().get(i);
+                Node source = replacements.get(pred);
+                if (source == null) {
+                    source = newNodes.get(pred);
+                }
+                source.successors().set(predIndex,  node);
+            }
+        }
+        for (Entry<Node, Node> entry : replacements.entrySet()) {
+            Node oldNode = entry.getKey();
+            Node node = entry.getValue();
+            for (int i = 0; i < oldNode.predecessors().size(); i++) {
+                Node pred = oldNode.predecessors().get(i);
+                int predIndex = oldNode.predecessorsIndex().get(i);
+                if (newNodes.containsKey(pred)) {
+                    newNodes.get(pred).successors().set(predIndex, node);
+                }
+            }
+        }
     }
 }
--- a/rundacapo.sh	Tue May 31 15:19:08 2011 +0200
+++ b/rundacapo.sh	Tue May 31 15:19:30 2011 +0200
@@ -15,4 +15,4 @@
   echo "DACAPO is not defined. It must point to a Dacapo benchmark directory."
   exit 1;
 fi
-${JDK7}/bin/java -client -d64 -graal -XX:-C1XBailoutIsFatal -XX:+PrintCompilation -C1X:+QuietBailout -Xms1g -Xmx2g -esa -classpath ${DACAPO}/dacapo-9.12-bach.jar Harness --preserve $*
+${JDK7}/bin/java -client -d64 -graal -XX:-C1XBailoutIsFatal -XX:+PrintCompilation -C1X:-QuietBailout -Xms1g -Xmx2g -esa -classpath ${DACAPO}/dacapo-9.12-bach.jar Harness --preserve $*