changeset 2710:0efd77a02ea9

Merge
author Gilles Duboscq <gilles.duboscq@oracle.com>
date Thu, 19 May 2011 11:43:30 +0200
parents 7b7dbe19fafb (current diff) 4272b7af2d17 (diff)
children fb4cc9812591
files graal/GraalCompiler/src/com/sun/c1x/alloc/ControlFlowOptimizer.java graal/GraalCompiler/src/com/sun/c1x/doc/IRInterpreter.txt graal/GraalCompiler/src/com/sun/c1x/doc/LoopPeeling.txt graal/GraalCompiler/src/com/sun/c1x/doc/backend_open_issues.txt graal/GraalCompiler/src/com/sun/c1x/doc/differences.txt graal/GraalCompiler/src/com/sun/c1x/doc/performance.txt graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java graal/GraalCompiler/src/com/sun/c1x/graph/BlockUtil.java graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java graal/GraalCompiler/src/com/sun/c1x/lir/LIRStackAllocate.java graal/GraalCompiler/src/com/sun/c1x/opt/InstructionSubstituter.java graal/GraalCompiler/src/com/sun/c1x/target/sparc/SPARC.java
diffstat 57 files changed, 923 insertions(+), 2113 deletions(-) [+]
line wrap: on
line diff
Binary file doc/design/graal_compiler.pdf has changed
--- a/graal/GraalCompiler/.classpath	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/.classpath	Thu May 19 11:43:30 2011 +0200
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
-	<classpathentry combineaccessrules="false" kind="src" path="/GraalGraph"/>
-	<classpathentry combineaccessrules="false" kind="src" path="/GraalGraphviz"/>
-	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.cri"/>
-	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.asm"/>
-	<classpathentry kind="output" path="bin"/>
-</classpath>
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/GraalGraph"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/GraalGraphviz"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.asm"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.cri"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- a/graal/GraalCompiler/src/com/sun/c1x/C1XCompilation.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/C1XCompilation.java	Thu May 19 11:43:30 2011 +0200
@@ -246,6 +246,7 @@
             initFrameMap(hir.maxLocks());
 
             lirGenerator = compiler.backend.newLIRGenerator(this);
+
             for (BlockBegin begin : hir.linearScanOrder()) {
                 lirGenerator.doBlock(begin);
             }
@@ -266,9 +267,6 @@
             // generate code for slow cases
             lirAssembler.emitLocalStubs();
 
-            // generate exception adapters
-            lirAssembler.emitExceptionEntries();
-
             // generate deoptimization stubs
             ArrayList<DeoptimizationStub> deoptimizationStubs = lirGenerator.deoptimizationStubs();
             if (deoptimizationStubs != null) {
--- a/graal/GraalCompiler/src/com/sun/c1x/C1XCompiler.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/C1XCompiler.java	Thu May 19 11:43:30 2011 +0200
@@ -131,8 +131,14 @@
         if (C1XOptions.PrintDOTGraphToPdf) {
             addCompilationObserver(new GraphvizPrinterObserver(true));
         }
-        if (C1XOptions.PrintIdealGraphToFile) {
-            addCompilationObserver(new IdealGraphPrinterObserver());
+        if (C1XOptions.PrintIdealGraphLevel != 0) {
+            CompilationObserver observer;
+            if (C1XOptions.PrintIdealGraphFile) {
+                observer = new IdealGraphPrinterObserver();
+            } else {
+                observer = new IdealGraphPrinterObserver(C1XOptions.PrintIdealGraphAddress, C1XOptions.PrintIdealGraphPort);
+            }
+            addCompilationObserver(observer);
         }
     }
 
--- a/graal/GraalCompiler/src/com/sun/c1x/C1XOptions.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/C1XOptions.java	Thu May 19 11:43:30 2011 +0200
@@ -69,7 +69,10 @@
     public static boolean PrintCFGToFile                     = ____;
     public static boolean PrintDOTGraphToFile                = ____;
     public static boolean PrintDOTGraphToPdf                 = ____;
-    public static boolean PrintIdealGraphToFile              = ____;
+    public static int     PrintIdealGraphLevel               = 0;
+    public static boolean PrintIdealGraphFile                = ____;
+    public static String  PrintIdealGraphAddress             = "127.0.0.1";
+    public static int     PrintIdealGraphPort                = 4444;
     public static boolean OmitDOTFrameStates                 = true;
     public static boolean PrintMetrics                       = ____;
     public static boolean PrintTimers                        = ____;
@@ -88,10 +91,6 @@
     public static boolean PrintAssumptions                   = ____;
     public static boolean QuietBailout                       = ____;
 
-    // all optimization settings
-    public static boolean OptBlockSkipping;
-    public static boolean OptControlFlow;
-
     // optimistic optimization settings
     public static boolean UseAssumptions                = true;
 
@@ -153,7 +152,6 @@
 
         // Level 1 optimizations
         PhiLoopStores                   = l;
-        OptControlFlow                  = l;
 
         // Level 2 optimizations
         OptInline                       = ll;
@@ -161,6 +159,5 @@
         // Level 3 optimizations
         UseStackMapTableLiveness        = lll;
         UseAssumptions                  = lll;
-        OptBlockSkipping                = lll;
     }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/alloc/ControlFlowOptimizer.java	Thu May 19 11:36:41 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,273 +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.alloc;
-
-import java.util.*;
-
-import com.sun.c1x.*;
-import com.sun.c1x.graph.*;
-import com.sun.c1x.ir.*;
-import com.sun.c1x.lir.*;
-import com.sun.c1x.util.*;
-import com.sun.cri.ci.*;
-
-/**
- * This class performs basic optimizations on the control flow graph after LIR generation.
- *
- * @author Thomas Wuerthinger
- */
-final class ControlFlowOptimizer {
-
-    /**
-     * Performs control flow optimizations on the given IR graph.
-     * @param ir the IR graph that should be optimized
-     */
-    public static void optimize(IR ir) {
-        ControlFlowOptimizer optimizer = new ControlFlowOptimizer(ir);
-        List<BlockBegin> code = ir.linearScanOrder();
-        optimizer.reorderShortLoops(code);
-        optimizer.deleteEmptyBlocks(code);
-        optimizer.deleteUnnecessaryJumps(code);
-        optimizer.deleteJumpsToReturn(code);
-    }
-
-    private final IR ir;
-
-    private ControlFlowOptimizer(IR ir) {
-        this.ir = ir;
-    }
-
-    private void reorderShortLoop(List<BlockBegin> code, BlockBegin headerBlock, int headerIdx) {
-        int i = headerIdx + 1;
-        int maxEnd = Math.min(headerIdx + C1XOptions.MaximumShortLoopSize, code.size());
-        while (i < maxEnd && code.get(i).loopDepth() >= headerBlock.loopDepth()) {
-            i++;
-        }
-
-        if (i == code.size() || code.get(i).loopDepth() < headerBlock.loopDepth()) {
-            int endIdx = i - 1;
-            BlockBegin endBlock = code.get(endIdx);
-
-            if (endBlock.numberOfSux() == 1 && endBlock.suxAt(0) == headerBlock) {
-                // short loop from headerIdx to endIdx found . reorder blocks such that
-                // the headerBlock is the last block instead of the first block of the loop
-
-                for (int j = headerIdx; j < endIdx; j++) {
-                    code.set(j, code.get(j + 1));
-                }
-                code.set(endIdx, headerBlock);
-
-                // correct the flags so that any loop alignment occurs in the right place.
-                assert code.get(endIdx).checkBlockFlag(BlockBegin.BlockFlag.BackwardBranchTarget) : "must be backward branch target";
-                code.get(endIdx).clearBlockFlag(BlockBegin.BlockFlag.BackwardBranchTarget);
-                code.get(headerIdx).setBlockFlag(BlockBegin.BlockFlag.BackwardBranchTarget);
-            }
-        }
-    }
-
-    private void reorderShortLoops(List<BlockBegin> code) {
-        for (int i = code.size() - 1; i >= 0; i--) {
-            BlockBegin block = code.get(i);
-
-            if (block.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader)) {
-                reorderShortLoop(code, block, i);
-            }
-        }
-
-        assert verify(code);
-    }
-
-    // only blocks with exactly one successor can be deleted. Such blocks
-    // must always end with an unconditional branch to this successor
-    private boolean canDeleteBlock(BlockBegin block) {
-        if (block.numberOfSux() != 1 ||
-            block.numberOfExceptionHandlers() != 0 ||
-            block == ir.startBlock ||
-            block.isExceptionEntry() ||
-            block.suxAt(0) == block) {
-            return false;
-        }
-
-        List<LIRInstruction> instructions = block.lir().instructionsList();
-
-        assert instructions.size() >= 2 : "block must have label and branch";
-        assert instructions.get(0).code == LIROpcode.Label : "first instruction must always be a label";
-        assert instructions.get(instructions.size() - 1) instanceof LIRBranch : "last instruction must always be a branch";
-        assert ((LIRBranch) instructions.get(instructions.size() - 1)).cond() == Condition.TRUE : "branch must be unconditional";
-        assert ((LIRBranch) instructions.get(instructions.size() - 1)).block() == block.suxAt(0) : "branch target must be the successor";
-
-        // block must have exactly one successor
-
-        return instructions.size() == 2 && instructions.get(instructions.size() - 1).info == null;
-    }
-
-    private void deleteEmptyBlocks(List<BlockBegin> code) {
-        int oldPos = 0;
-        int newPos = 0;
-        int numBlocks = code.size();
-
-        while (oldPos < numBlocks) {
-            BlockBegin block = code.get(oldPos);
-
-            if (canDeleteBlock(block)) {
-                BlockBegin newTarget = block.suxAt(0);
-
-                // propagate backward branch target flag for correct code alignment
-                if (block.checkBlockFlag(BlockBegin.BlockFlag.BackwardBranchTarget)) {
-                    newTarget.setBlockFlag(BlockBegin.BlockFlag.BackwardBranchTarget);
-                }
-
-                // update the block references in any branching LIR instructions
-                for (BlockEnd pred : block.blockPredecessors()) {
-                    for (LIRInstruction instr : pred.begin().lir().instructionsList()) {
-                        if (instr instanceof LIRBranch) {
-                            ((LIRBranch) instr).substitute(block, newTarget);
-                        } else if (instr instanceof LIRTableSwitch) {
-                            ((LIRTableSwitch) instr).substitute(block, newTarget);
-                        }
-                    }
-                }
-
-                // adjust successor and predecessor lists
-                ir.replaceBlock(block, newTarget);
-                C1XMetrics.BlocksDeleted++;
-            } else {
-                // adjust position of this block in the block list if blocks before
-                // have been deleted
-                if (newPos != oldPos) {
-                    code.set(newPos, code.get(oldPos));
-                }
-                newPos++;
-            }
-            oldPos++;
-        }
-        Util.truncate(code, newPos);
-
-        assert verify(code);
-    }
-
-    private void deleteUnnecessaryJumps(List<BlockBegin> code) {
-        // skip the last block because there a branch is always necessary
-        for (int i = code.size() - 2; i >= 0; i--) {
-            BlockBegin block = code.get(i);
-            List<LIRInstruction> instructions = block.lir().instructionsList();
-
-            LIRInstruction lastOp = instructions.get(instructions.size() - 1);
-            if (lastOp.code == LIROpcode.Branch) {
-                assert lastOp instanceof LIRBranch : "branch must be of type LIRBranch";
-                LIRBranch lastBranch = (LIRBranch) lastOp;
-
-                assert lastBranch.block() != null : "last branch must always have a block as target";
-                assert lastBranch.label() == lastBranch.block().label() : "must be equal";
-
-                if (lastBranch.info == null) {
-                    if (lastBranch.block() == code.get(i + 1)) {
-                        // delete last branch instruction
-                        Util.truncate(instructions, instructions.size() - 1);
-
-                    } else {
-                        LIRInstruction prevOp = instructions.get(instructions.size() - 2);
-                        if (prevOp.code == LIROpcode.Branch || prevOp.code == LIROpcode.CondFloatBranch) {
-                            assert prevOp instanceof LIRBranch : "branch must be of type LIRBranch";
-                            LIRBranch prevBranch = (LIRBranch) prevOp;
-
-                            if (prevBranch.block() == code.get(i + 1) && prevBranch.info == null) {
-                                // eliminate a conditional branch to the immediate successor
-                                prevBranch.changeBlock(lastBranch.block());
-                                prevBranch.negateCondition();
-                                Util.truncate(instructions, instructions.size() - 1);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        assert verify(code);
-    }
-
-    private void deleteJumpsToReturn(List<BlockBegin> code) {
-        for (int i = code.size() - 1; i >= 0; i--) {
-            BlockBegin block = code.get(i);
-            List<LIRInstruction> curInstructions = block.lir().instructionsList();
-            LIRInstruction curLastOp = curInstructions.get(curInstructions.size() - 1);
-
-            assert curInstructions.get(0).code == LIROpcode.Label : "first instruction must always be a label";
-            if (curInstructions.size() == 2 && curLastOp.code == LIROpcode.Return) {
-                // the block contains only a label and a return
-                // if a predecessor ends with an unconditional jump to this block, then the jump
-                // can be replaced with a return instruction
-                //
-                // Note: the original block with only a return statement cannot be deleted completely
-                // because the predecessors might have other (conditional) jumps to this block.
-                // this may lead to unnecesary return instructions in the final code
-
-                assert curLastOp.info == null : "return instructions do not have debug information";
-
-                assert curLastOp instanceof LIROp1 : "return must be LIROp1";
-                CiValue returnOpr = ((LIROp1) curLastOp).operand();
-
-                for (int j = block.numberOfPreds() - 1; j >= 0; j--) {
-                    BlockBegin pred = block.predAt(j).begin();
-                    List<LIRInstruction> predInstructions = pred.lir().instructionsList();
-                    LIRInstruction predLastOp = predInstructions.get(predInstructions.size() - 1);
-
-                    if (predLastOp.code == LIROpcode.Branch) {
-                        assert predLastOp instanceof LIRBranch : "branch must be LIRBranch";
-                        LIRBranch predLastBranch = (LIRBranch) predLastOp;
-
-                        if (predLastBranch.block() == block && predLastBranch.cond() == Condition.TRUE && predLastBranch.info == null) {
-                            // replace the jump to a return with a direct return
-                            // Note: currently the edge between the blocks is not deleted
-                            predInstructions.set(predInstructions.size() - 1, new LIROp1(LIROpcode.Return, returnOpr));
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    private boolean verify(List<BlockBegin> code) {
-        for (BlockBegin block : code) {
-            List<LIRInstruction> instructions = block.lir().instructionsList();
-
-            for (LIRInstruction instr : instructions) {
-                if (instr instanceof LIRBranch) {
-                    LIRBranch opBranch = (LIRBranch) instr;
-                    assert opBranch.block() == null || code.contains(opBranch.block()) : "missing successor branch from: " + block + " to: " + opBranch.block();
-                    assert opBranch.unorderedBlock() == null || code.contains(opBranch.unorderedBlock()) : "missing successor branch from: " + block + " to: " + opBranch.unorderedBlock();
-                }
-            }
-
-            for (BlockBegin sux : block.end().blockSuccessors()) {
-                assert code.contains(sux) : "missing successor from: " + block + "to: " + sux;
-            }
-
-            for (BlockEnd pred : block.blockPredecessors()) {
-                assert code.contains(pred.begin()) : "missing predecessor from: " + block + "to: " + pred.begin();
-            }
-        }
-
-        return true;
-    }
-}
--- a/graal/GraalCompiler/src/com/sun/c1x/alloc/EdgeMoveOptimizer.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/alloc/EdgeMoveOptimizer.java	Thu May 19 11:43:30 2011 +0200
@@ -66,7 +66,7 @@
         for (int i = blockList.size() - 1; i >= 1; i--) {
             BlockBegin block = blockList.get(i);
 
-            if (block.numberOfPreds() > 1 && !block.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry)) {
+            if (block.numberOfPreds() > 1) {
                 optimizer.optimizeMovesAtBlockEnd(block);
             }
             if (block.numberOfSux() == 2) {
@@ -122,11 +122,10 @@
 
         int numPreds = block.numberOfPreds();
         assert numPreds > 1 : "do not call otherwise";
-        assert !block.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry) : "exception handlers not allowed";
 
         // setup a list with the LIR instructions of all predecessors
         for (int i = 0; i < numPreds; i++) {
-            BlockBegin pred = block.predAt(i).begin();
+            BlockBegin pred = block.predAt(i).block();
             List<LIRInstruction> predInstructions = pred.lir().instructionsList();
 
             if (pred.numberOfSux() != 1) {
@@ -231,8 +230,7 @@
                 // the same blocks.
                 return;
             }
-            assert sux.predAt(0).begin() == block : "invalid control flow";
-            assert !sux.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry) : "exception handlers not allowed";
+            assert sux.predAt(0).block() == block : "invalid control flow";
 
             // ignore the label at the beginning of the block
             List<LIRInstruction> seq = suxInstructions.subList(1, suxInstructions.size());
--- a/graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScan.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScan.java	Thu May 19 11:43:30 2011 +0200
@@ -28,18 +28,18 @@
 import java.util.*;
 
 import com.sun.c1x.*;
-import com.sun.c1x.alloc.Interval.*;
+import com.sun.c1x.alloc.Interval.RegisterBinding;
+import com.sun.c1x.alloc.Interval.RegisterPriority;
+import com.sun.c1x.alloc.Interval.SpillState;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.gen.*;
 import com.sun.c1x.graph.*;
 import com.sun.c1x.ir.*;
-import com.sun.c1x.ir.BlockBegin.BlockFlag;
 import com.sun.c1x.lir.*;
 import com.sun.c1x.lir.LIRInstruction.OperandMode;
 import com.sun.c1x.observer.*;
 import com.sun.c1x.util.*;
 import com.sun.c1x.value.*;
-import com.sun.c1x.value.FrameState.PhiProcedure;
 import com.sun.c1x.value.FrameState.ValueProcedure;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
@@ -563,7 +563,7 @@
 
         for (int i = 0; i < numBlocks; i++) {
             BlockBegin block = blockAt(i);
-            block.setFirstLirInstructionId(opId);
+            block.lirBlock.setFirstLirInstructionId(opId);
             List<LIRInstruction> instructions = block.lir().instructionsList();
 
             int numInst = instructions.size();
@@ -578,7 +578,7 @@
                 index++;
                 opId += 2; // numbering of lirOps by two
             }
-            block.setLastLirInstructionId(opId - 2);
+            block.lirBlock.setLastLirInstructionId((opId - 2));
         }
         assert index == numInstructions : "must match";
         assert (index << 1) == opId : "must match: " + (index << 1);
@@ -599,17 +599,6 @@
             final CiBitMap liveGen = new CiBitMap(liveSize);
             final CiBitMap liveKill = new CiBitMap(liveSize);
 
-            if (block.isExceptionEntry()) {
-                // Phi functions at the begin of an exception handler are
-                // implicitly defined (= killed) at the beginning of the block.
-                block.stateBefore().forEachLivePhi(block, new PhiProcedure() {
-                    public boolean doPhi(Phi phi) {
-                        liveKill.set(operandNumber(phi.operand()));
-                        return true;
-                    }
-                });
-            }
-
             List<LIRInstruction> instructions = block.lir().instructionsList();
             int numInst = instructions.size();
 
@@ -773,8 +762,7 @@
 
                 // liveOut(block) is the union of liveIn(sux), for successors sux of block
                 int n = block.numberOfSux();
-                int e = block.numberOfExceptionHandlers();
-                if (n + e > 0) {
+                if (n > 0) {
                     // block has successors
                     if (n > 0) {
                         liveOut.setFrom(block.suxAt(0).lirBlock.liveIn);
@@ -784,9 +772,6 @@
                     } else {
                         liveOut.clearAll();
                     }
-                    for (int j = 0; j < e; j++) {
-                        liveOut.setUnion(block.exceptionHandlerAt(j).lirBlock.liveIn);
-                    }
 
                     if (!lirBlock.liveOut.isSame(liveOut)) {
                         // A change occurred. Swap the old and new live out sets to avoid copying.
@@ -1174,8 +1159,8 @@
         for (int i = blockCount() - 1; i >= 0; i--) {
             BlockBegin block = blockAt(i);
             List<LIRInstruction> instructions = block.lir().instructionsList();
-            final int blockFrom = block.firstLirInstructionId();
-            int blockTo = block.lastLirInstructionId();
+            final int blockFrom = block.lirBlock.firstLirInstructionId();
+            int blockTo = block.lirBlock.lastLirInstructionId();
 
             assert blockFrom == instructions.get(0).id;
             assert blockTo == instructions.get(instructions.size() - 1).id;
@@ -1282,19 +1267,19 @@
             } // end of instruction iteration
 
             // (tw) Make sure that no spill store optimization is applied for phi instructions that flow into exception handlers.
-            if (block.isExceptionEntry()) {
-                FrameState stateBefore = block.stateBefore();
-                stateBefore.forEachLivePhi(block, new PhiProcedure() {
-                    @Override
-                    public boolean doPhi(Phi phi) {
-                        Interval interval = intervalFor(phi.operand());
-                        if (interval != null) {
-                            interval.setSpillState(SpillState.NoOptimization);
-                        }
-                        return true;
-                    }
-                });
-            }
+//            if (block.isExceptionEntry()) {
+//                FrameState stateBefore = block.stateBefore();
+//                stateBefore.forEachLivePhi(block, new PhiProcedure() {
+//                    @Override
+//                    public boolean doPhi(Phi phi) {
+//                        Interval interval = intervalFor(phi.operand());
+//                        if (interval != null) {
+//                            interval.setSpillState(SpillState.NoOptimization);
+//                        }
+//                        return true;
+//                    }
+//                });
+//            }
 
         } // end of block iteration
 
@@ -1527,14 +1512,14 @@
         assert operand.isVariable() : "register number out of bounds";
         assert intervalFor(operand) != null : "no interval found";
 
-        return splitChildAtOpId(intervalFor(operand), block.firstLirInstructionId(), LIRInstruction.OperandMode.Output);
+        return splitChildAtOpId(intervalFor(operand), block.lirBlock.firstLirInstructionId(), LIRInstruction.OperandMode.Output);
     }
 
     Interval intervalAtBlockEnd(BlockBegin block, CiValue operand) {
         assert operand.isVariable() : "register number out of bounds";
         assert intervalFor(operand) != null : "no interval found";
 
-        return splitChildAtOpId(intervalFor(operand), block.lastLirInstructionId() + 1, LIRInstruction.OperandMode.Output);
+        return splitChildAtOpId(intervalFor(operand), block.lirBlock.lastLirInstructionId() + 1, LIRInstruction.OperandMode.Output);
     }
 
     Interval intervalAtOpId(CiValue operand, int opId) {
@@ -1596,7 +1581,7 @@
                 // may have be more than one predecessor but it will be guaranteed
                 // that all predecessors will be the same.
                 for (int i = 0; i < toBlock.numberOfPreds(); i++) {
-                    assert fromBlock == toBlock.predAt(i).begin() : "all critical edges must be broken";
+                    assert fromBlock == toBlock.predAt(i).block() : "all critical edges must be broken";
                 }
             }
 
@@ -1619,7 +1604,7 @@
             BlockBegin block = blockAt(i);
 
             // check if block has only one predecessor and only one successor
-            if (block.numberOfPreds() == 1 && block.numberOfSux() == 1 && block.numberOfExceptionHandlers() == 0 && !block.isExceptionEntry()) {
+            if (block.numberOfPreds() == 1 && block.numberOfSux() == 1) {
                 List<LIRInstruction> instructions = block.lir().instructionsList();
                 assert instructions.get(0).code == LIROpcode.Label : "block must start with label";
                 assert instructions.get(instructions.size() - 1).code == LIROpcode.Branch : "block with successors must end with branch";
@@ -1627,7 +1612,7 @@
 
                 // check if block is empty (only label and branch)
                 if (instructions.size() == 2) {
-                    BlockBegin pred = block.predAt(0).begin();
+                    BlockBegin pred = block.predAt(0).block();
                     BlockBegin sux = block.suxAt(0);
 
                     // prevent optimization of two consecutive blocks
@@ -1676,191 +1661,6 @@
         }
     }
 
-    void resolveExceptionEntry(BlockBegin block, CiValue operand, MoveResolver moveResolver) {
-        if (intervalFor(operand) == null) {
-            // if a phi function is never used, no interval is created . ignore this
-            return;
-        }
-
-        Interval interval = intervalAtBlockBegin(block, operand);
-        CiValue location = interval.location();
-
-        if (location.isRegister() && interval.alwaysInMemory()) {
-            // the interval is split to get a short range that is located on the stack
-            // in the following two cases:
-            // * the interval started in memory (e.g. method parameter), but is currently in a register
-            // this is an optimization for exception handling that reduces the number of moves that
-            // are necessary for resolving the states when an exception uses this exception handler
-            // * the interval would be on the fpu stack at the begin of the exception handler
-            // this is not allowed because of the complicated fpu stack handling on Intel
-
-            // range that will be spilled to memory
-            int fromOpId = block.firstLirInstructionId();
-            int toOpId = fromOpId + 1; // short live range of length 1
-            assert interval.from() <= fromOpId && interval.to() >= toOpId : "no split allowed between exception entry and first instruction";
-
-            if (interval.from() != fromOpId) {
-                // the part before fromOpId is unchanged
-                interval = interval.split(fromOpId, this);
-                interval.assignLocation(location);
-            }
-            assert interval.from() == fromOpId : "must be true now";
-
-            Interval spilledPart = interval;
-            if (interval.to() != toOpId) {
-                // the part after toOpId is unchanged
-                spilledPart = interval.splitFromStart(toOpId, this);
-                moveResolver.addMapping(spilledPart, interval);
-            }
-            assignSpillSlot(spilledPart);
-
-            assert spilledPart.from() == fromOpId && spilledPart.to() == toOpId : "just checking";
-        }
-    }
-
-    void resolveExceptionEntry(final BlockBegin block, final MoveResolver moveResolver) {
-        assert block.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry) : "should not call otherwise";
-        assert moveResolver.checkEmpty();
-
-        // visit all registers where the liveIn bit is set
-        for (int operandNum = block.lirBlock.liveIn.nextSetBit(0); operandNum >= 0; operandNum = block.lirBlock.liveIn.nextSetBit(operandNum + 1)) {
-            resolveExceptionEntry(block, operands.operandFor(operandNum), moveResolver);
-        }
-
-        // the liveIn bits are not set for phi functions of the xhandler entry, so iterate them separately
-        block.stateBefore().forEachLivePhi(block, new PhiProcedure() {
-            public boolean doPhi(Phi phi) {
-                resolveExceptionEntry(block, phi.operand(), moveResolver);
-                return true;
-            }
-        });
-
-        if (moveResolver.hasMappings()) {
-            // insert moves after first instruction
-            moveResolver.setInsertPosition(block.lir(), 0);
-            moveResolver.resolveAndAppendMoves();
-        }
-    }
-
-    void resolveExceptionEdge(ExceptionHandler handler, int throwingOpId, CiValue operand, Phi phi, MoveResolver moveResolver) {
-        if (intervalFor(operand) == null) {
-            // if a phi function is never used, no interval is created . ignore this
-            return;
-        }
-
-        // the computation of toInterval is equal to resolveCollectMappings,
-        // but fromInterval is more complicated because of phi functions
-        BlockBegin toBlock = handler.entryBlock();
-        Interval toInterval = intervalAtBlockBegin(toBlock, operand);
-
-        if (phi != null) {
-            // phi function of the exception entry block
-            // no moves are created for this phi function in the LIRGenerator, so the
-            // interval at the throwing instruction must be searched using the operands
-            // of the phi function
-            Value fromValue = phi.inputAt(handler.phiOperand());
-            Constant con = null;
-            if (fromValue instanceof Constant) {
-                con = (Constant) fromValue;
-            }
-            if (con != null && (con.operand().isIllegal() || con.operand().isConstant())) {
-                // unpinned constants may have no register, so add mapping from constant to interval
-                moveResolver.addMapping(con.asConstant(), toInterval);
-            } else {
-                // search split child at the throwing opId
-                Interval fromInterval = intervalAtOpId(fromValue.operand(), throwingOpId);
-                if (fromInterval != toInterval) {
-                    moveResolver.addMapping(fromInterval, toInterval);
-                    // with phi functions it can happen that the same fromValue is used in
-                    // multiple mappings, so notify move-resolver that this is allowed
-                    moveResolver.setMultipleReadsAllowed();
-                }
-            }
-        } else {
-            // no phi function, so use regNum also for fromInterval
-            // search split child at the throwing opId
-            Interval fromInterval = intervalAtOpId(operand, throwingOpId);
-            if (fromInterval != toInterval) {
-                // optimization to reduce number of moves: when toInterval is on stack and
-                // the stack slot is known to be always correct, then no move is necessary
-                if (!fromInterval.alwaysInMemory() || fromInterval.spillSlot() != toInterval.location()) {
-                    moveResolver.addMapping(fromInterval, toInterval);
-                }
-            }
-        }
-    }
-
-    void resolveExceptionEdge(final ExceptionHandler handler, final int throwingOpId, final MoveResolver moveResolver) {
-        if (C1XOptions.TraceLinearScanLevel >= 4) {
-            TTY.println("resolving exception handler B%d: throwingOpId=%d", handler.entryBlock().blockID, throwingOpId);
-        }
-
-        assert moveResolver.checkEmpty();
-        assert handler.lirOpId() == -1 : "already processed this xhandler";
-        handler.setLirOpId(throwingOpId);
-        assert handler.entryCode() == null : "code already present";
-
-        // visit all registers where the liveIn bit is set
-        BlockBegin block = handler.entryBlock();
-        for (int operandNum = block.lirBlock.liveIn.nextSetBit(0); operandNum >= 0; operandNum = block.lirBlock.liveIn.nextSetBit(operandNum + 1)) {
-            resolveExceptionEdge(handler, throwingOpId, operands.operandFor(operandNum), null, moveResolver);
-        }
-
-        // the liveIn bits are not set for phi functions of the xhandler entry, so iterate them separately
-        block.stateBefore().forEachLivePhi(block, new PhiProcedure() {
-            public boolean doPhi(Phi phi) {
-                resolveExceptionEdge(handler, throwingOpId, phi.operand(), phi, moveResolver);
-                return true;
-            }
-        });
-
-        if (moveResolver.hasMappings()) {
-            LIRList entryCode = new LIRList(gen);
-            moveResolver.setInsertPosition(entryCode, 0);
-            moveResolver.resolveAndAppendMoves();
-
-            entryCode.jump(handler.entryBlock());
-            handler.setEntryCode(entryCode);
-        }
-    }
-
-    void resolveExceptionHandlers() {
-        MoveResolver moveResolver = new MoveResolver(this);
-        //LIRVisitState visitor = new LIRVisitState();
-        int numBlocks = blockCount();
-
-        int i;
-        for (i = 0; i < numBlocks; i++) {
-            BlockBegin block = blockAt(i);
-            if (block.checkBlockFlag(BlockFlag.ExceptionEntry)) {
-                resolveExceptionEntry(block, moveResolver);
-            }
-        }
-
-        for (i = 0; i < numBlocks; i++) {
-            BlockBegin block = blockAt(i);
-            LIRList ops = block.lir();
-            int numOps = ops.length();
-
-            // iterate all instructions of the block. skip the first because it is always a label
-            assert !ops.at(0).hasOperands() : "first operation must always be a label";
-            for (int j = 1; j < numOps; j++) {
-                LIRInstruction op = ops.at(j);
-                int opId = op.id;
-
-                if (opId != -1 && op.info != null) {
-                    // visit operation to collect all operands
-                    for (ExceptionHandler handler : op.exceptionEdges()) {
-                        resolveExceptionEdge(handler, opId, moveResolver);
-                    }
-
-                } else if (C1XOptions.DetailedAsserts) {
-                    assert op.exceptionEdges().size() == 0 : "missed exception handler";
-                }
-            }
-        }
-    }
-
     // * Phase 7: assign register numbers back to LIR
     // (includes computation of debug information and oop maps)
 
@@ -1928,7 +1728,7 @@
         if (opId != -1) {
             if (C1XOptions.DetailedAsserts) {
                 BlockBegin block = blockForId(opId);
-                if (block.numberOfSux() <= 1 && opId == block.lastLirInstructionId()) {
+                if (block.numberOfSux() <= 1 && opId == block.lirBlock.lastLirInstructionId()) {
                     // check if spill moves could have been appended at the end of this block, but
                     // before the branch instruction. So the split child information for this branch would
                     // be incorrect.
@@ -2048,7 +1848,7 @@
             if (operand.isVariable()) {
                 OperandMode mode = OperandMode.Input;
                 BlockBegin block = blockForId(opId);
-                if (block.numberOfSux() == 1 && opId == block.lastLirInstructionId()) {
+                if (block.numberOfSux() == 1 && opId == block.lirBlock.lastLirInstructionId()) {
                     // generating debug information for the last instruction of a block.
                     // if this instruction is a branch, spill moves are inserted before this branch
                     // and so the wrong operand would be returned (spill moves at block boundaries are not
@@ -2057,7 +1857,7 @@
                     final LIRInstruction instr = block.lir().instructionsList().get(block.lir().instructionsList().size() - 1);
                     if (instr instanceof LIRBranch) {
                         if (block.lirBlock.liveOut.get(operandNumber(operand))) {
-                            opId = block.suxAt(0).firstLirInstructionId();
+                            opId = block.suxAt(0).lirBlock.firstLirInstructionId();
                             mode = OperandMode.Output;
                         }
                     }
@@ -2172,13 +1972,11 @@
 
             if (op.info != null) {
                 // exception handling
-                if (compilation.hasExceptionHandlers()) {
-                    for (ExceptionHandler handler : op.exceptionEdges()) {
-                        if (handler.entryCode() != null) {
-                            assignLocations(handler.entryCode().instructionsList(), null);
-                        }
-                    }
-                }
+//                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);
@@ -2252,9 +2050,6 @@
         }
 
         resolveDataFlow();
-        if (compilation.hasExceptionHandlers()) {
-            resolveExceptionHandlers();
-        }
 
         if (C1XOptions.PrintTimers) {
             C1XTimers.RESOLUTION.stop();
@@ -2288,12 +2083,7 @@
         }
 
         printLir("After register number assignment", true);
-
         EdgeMoveOptimizer.optimize(ir.linearScanOrder());
-        if (C1XOptions.OptControlFlow) {
-            ControlFlowOptimizer.optimize(ir);
-        }
-
         printLir("After control flow optimization", false);
     }
 
@@ -2313,7 +2103,7 @@
             TTY.println("--- Basic Blocks ---");
             for (i = 0; i < blockCount(); i++) {
                 BlockBegin block = blockAt(i);
-                TTY.print("B%d [%d, %d, %d, %d] ", block.blockID, block.firstLirInstructionId(), block.lastLirInstructionId(), block.loopIndex(), block.loopDepth());
+                TTY.print("B%d [%d, %d, %d, %d] ", block.blockID, block.lirBlock.firstLirInstructionId(), block.lirBlock.lastLirInstructionId(), block.loopIndex(), block.loopDepth());
             }
             TTY.println();
             TTY.println();
--- a/graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScanWalker.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScanWalker.java	Thu May 19 11:43:30 2011 +0200
@@ -262,9 +262,9 @@
 
         // Try to split at end of maxBlock. If this would be after
         // maxSplitPos, then use the begin of maxBlock
-        int optimalSplitPos = maxBlock.lastLirInstructionId() + 2;
+        int optimalSplitPos = maxBlock.lirBlock.lastLirInstructionId() + 2;
         if (optimalSplitPos > maxSplitPos) {
-            optimalSplitPos = maxBlock.firstLirInstructionId();
+            optimalSplitPos = maxBlock.lirBlock.firstLirInstructionId();
         }
 
         int minLoopDepth = maxBlock.loopDepth();
@@ -274,7 +274,7 @@
             if (cur.loopDepth() < minLoopDepth) {
                 // block with lower loop-depth found . split at the end of this block
                 minLoopDepth = cur.loopDepth();
-                optimalSplitPos = cur.lastLirInstructionId() + 2;
+                optimalSplitPos = cur.lirBlock.lastLirInstructionId() + 2;
             }
         }
         assert optimalSplitPos > allocator.maxOpId() || allocator.isBlockBegin(optimalSplitPos) : "algorithm must move split pos to block boundary";
@@ -334,7 +334,7 @@
                     if (doLoopOptimization) {
                         // Loop optimization: if a loop-end marker is found between min- and max-position :
                         // then split before this loop
-                        int loopEndPos = interval.nextUsageExact(RegisterPriority.LiveAtLoopEnd, minBlock.lastLirInstructionId() + 2);
+                        int loopEndPos = interval.nextUsageExact(RegisterPriority.LiveAtLoopEnd, minBlock.lirBlock.lastLirInstructionId() + 2);
                         if (C1XOptions.TraceLinearScanLevel >= 4) {
                             TTY.println("      loop optimization: loop end found at pos %d", loopEndPos);
                         }
@@ -353,8 +353,8 @@
                             }
                             assert loopBlock != minBlock : "loopBlock and minBlock must be different because block boundary is needed between";
 
-                            optimalSplitPos = findOptimalSplitPos(minBlock, loopBlock, loopBlock.lastLirInstructionId() + 2);
-                            if (optimalSplitPos == loopBlock.lastLirInstructionId() + 2) {
+                            optimalSplitPos = findOptimalSplitPos(minBlock, loopBlock, loopBlock.lirBlock.lastLirInstructionId() + 2);
+                            if (optimalSplitPos == loopBlock.lirBlock.lastLirInstructionId() + 2) {
                                 optimalSplitPos = -1;
                                 if (C1XOptions.TraceLinearScanLevel >= 4) {
                                     TTY.println("      loop optimization not necessary");
--- a/graal/GraalCompiler/src/com/sun/c1x/alloc/RegisterVerifier.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/alloc/RegisterVerifier.java	Thu May 19 11:43:30 2011 +0200
@@ -134,18 +134,18 @@
         }
     }
 
-    void processXhandler(ExceptionHandler xhandler, Interval[] inputState) {
+    void processXhandler(BlockBegin xhandler, Interval[] inputState) {
         if (C1XOptions.TraceLinearScanLevel >= 2) {
-            TTY.println("processXhandler B%d", xhandler.entryBlock().blockID);
+            TTY.println("processXhandler B%d", xhandler.blockID);
         }
 
         // must copy state because it is modified
         inputState = copy(inputState);
 
-        if (xhandler.entryCode() != null) {
-            processOperations(xhandler.entryCode(), inputState);
+        if (xhandler.lir() != null) {
+            processOperations(xhandler.lir(), inputState);
         }
-        processSuccessor(xhandler.entryBlock(), inputState);
+        processSuccessor(xhandler, inputState);
     }
 
     void processSuccessor(BlockBegin block, Interval[] inputState) {
@@ -260,10 +260,8 @@
             }
 
             // process xhandler before output and temp operands
-            List<ExceptionHandler> xhandlers = op.exceptionEdges();
-            n = xhandlers.size();
-            for (int k = 0; k < n; k++) {
-                processXhandler(xhandlers.get(k), inputState);
+            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)
--- a/graal/GraalCompiler/src/com/sun/c1x/asm/ExceptionInfo.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/asm/ExceptionInfo.java	Thu May 19 11:43:30 2011 +0200
@@ -22,8 +22,6 @@
  */
 package com.sun.c1x.asm;
 
-import java.util.*;
-
 import com.sun.c1x.ir.*;
 
 /**
@@ -33,12 +31,12 @@
 public class ExceptionInfo {
 
     public final int codeOffset;
-    public final List<ExceptionHandler> exceptionHandlers;
+    public final BlockBegin exceptionEdge;
     public final int bci;
 
-    public ExceptionInfo(int pcOffset, List<ExceptionHandler> exceptionHandlers, int bci) {
+    public ExceptionInfo(int pcOffset, BlockBegin exceptionEdge, int bci) {
         this.codeOffset = pcOffset;
-        this.exceptionHandlers = exceptionHandlers;
+        this.exceptionEdge = exceptionEdge;
         this.bci = bci;
     }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/asm/TargetMethodAssembler.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/asm/TargetMethodAssembler.java	Thu May 19 11:43:30 2011 +0200
@@ -27,7 +27,6 @@
 import com.oracle.max.asm.*;
 import com.sun.c1x.*;
 import com.sun.c1x.debug.*;
-import com.sun.c1x.ir.*;
 import com.sun.c1x.lir.*;
 import com.sun.c1x.util.*;
 import com.sun.cri.ci.*;
@@ -65,11 +64,7 @@
         if (exceptionInfoList != null) {
             for (ExceptionInfo ei : exceptionInfoList) {
                 int codeOffset = ei.codeOffset;
-                for (ExceptionHandler handler : ei.exceptionHandlers) {
-                    int entryOffset = handler.entryCodeOffset();
-                    RiType caughtType = handler.handler.catchType();
-                    targetMethod.recordExceptionHandler(codeOffset, ei.bci, 0, entryOffset, handler.handlerBCI(), caughtType);
-                }
+                targetMethod.recordExceptionHandler(codeOffset, -1, 0, ei.exceptionEdge.lirBlock.blockEntryPco, -1, null);
             }
         }
 
@@ -145,11 +140,11 @@
 
     public void recordExceptionHandlers(int pcOffset, LIRDebugInfo info) {
         if (info != null) {
-            if (info.exceptionHandlers != null) {
+            if (info.exceptionEdge != null) {
                 if (exceptionInfoList == null) {
                     exceptionInfoList = new ArrayList<ExceptionInfo>(4);
                 }
-                exceptionInfoList.add(new ExceptionInfo(pcOffset, info.exceptionHandlers, info.state.bci));
+                exceptionInfoList.add(new ExceptionInfo(pcOffset, info.exceptionEdge, info.state.bci));
             }
         }
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/debug/CFGPrinter.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/debug/CFGPrinter.java	Thu May 19 11:43:30 2011 +0200
@@ -124,7 +124,7 @@
      * @param printHIR if {@code true} the HIR for each instruction in the block will be printed
      * @param printLIR if {@code true} the LIR for each instruction in the block will be printed
      */
-    void printBlock(BlockBegin block, List<BlockBegin> successors, Iterable<BlockBegin> handlers, boolean printHIR, boolean printLIR) {
+    void printBlock(BlockBegin block, List<BlockBegin> successors, BlockBegin handler, boolean printHIR, boolean printLIR) {
         begin("block");
 
         out.print("name \"B").print(block.blockID).println('"');
@@ -132,8 +132,8 @@
         out.print("to_bci ").println(block.end() == null ? -1 : block.end().bci());
 
         out.print("predecessors ");
-        for (BlockEnd pred : block.blockPredecessors()) {
-            out.print("\"B").print(pred.begin().blockID).print("\" ");
+        for (Instruction pred : block.blockPredecessors()) {
+            out.print("\"B").print(pred.block().blockID).print("\" ");
         }
         out.println();
 
@@ -144,27 +144,12 @@
         out.println();
 
         out.print("xhandlers");
-        for (BlockBegin handler : handlers) {
+        if (handler != null) {
             out.print("\"B").print(handler.blockID).print("\" ");
         }
         out.println();
 
         out.print("flags ");
-        if (block.isExceptionEntry()) {
-            out.print("\"ex\" ");
-        }
-        if (block.isSubroutineEntry()) {
-            out.print("\"sr\" ");
-        }
-        if (block.isBackwardBranchTarget()) {
-            out.print("\"bb\" ");
-        }
-        if (block.isParserLoopHeader()) {
-            out.print("\"plh\" ");
-        }
-        if (block.isCriticalEdgeSplit()) {
-            out.print("\"ces\" ");
-        }
         if (block.isLinearScanLoopHeader()) {
             out.print("\"llh\" ");
         }
@@ -173,9 +158,6 @@
         }
         out.println();
 
-        if (block.dominator() != null) {
-            out.print("dominator \"B").print(block.dominator().blockID).println('"');
-        }
         if (block.loopIndex() != -1) {
             out.print("loop_index ").println(block.loopIndex());
             out.print("loop_depth ").println(block.loopDepth());
@@ -587,7 +569,7 @@
         startBlock.iteratePreOrder(new BlockClosure() {
             public void apply(BlockBegin block) {
                 List<BlockBegin> successors = block.end() != null ? block.end().blockSuccessors() : new ArrayList<BlockBegin>(0);
-                printBlock(block, successors, block.exceptionHandlerBlocks(), printHIR, printLIR);
+                printBlock(block, successors, block.exceptionEdge(), printHIR, printLIR);
             }
         });
         end("cfg");
--- a/graal/GraalCompiler/src/com/sun/c1x/debug/GraphvizPrinterObserver.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/debug/GraphvizPrinterObserver.java	Thu May 19 11:43:30 2011 +0200
@@ -23,6 +23,7 @@
 package com.sun.c1x.debug;
 
 import java.io.*;
+import java.util.regex.*;
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.vis.*;
@@ -38,6 +39,8 @@
  */
 public class GraphvizPrinterObserver implements CompilationObserver {
 
+    private static final Pattern INVALID_CHAR = Pattern.compile("[^A-Za-z0-9_.-]");
+
     private final boolean pdf;
     private int n;
 
@@ -59,11 +62,15 @@
             String name = event.getMethod().holder().name();
             name = name.substring(1, name.length() - 1).replace('/', '.');
             name = name + "." + event.getMethod().name();
+
             String filename = name + "_" + (n++) + "_" + event.getLabel();
+            filename = INVALID_CHAR.matcher(filename).replaceAll("_");
+
+            OutputStream out = null;
             try {
                 if (pdf) {
-                    ByteArrayOutputStream out = new ByteArrayOutputStream();
-                    GraphvizPrinter printer = new GraphvizPrinter(out);
+                    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+                    GraphvizPrinter printer = new GraphvizPrinter(buffer);
                     if (C1XOptions.OmitDOTFrameStates) {
                         printer.addOmittedClass(FrameState.class);
                     }
@@ -71,24 +78,28 @@
                     printer.print(graph, true);
                     printer.end();
 
-                    FileOutputStream output = new FileOutputStream(filename + ".pdf");
-                    GraphvizRunner.process(GraphvizRunner.DOT_LAYOUT, new ByteArrayInputStream(out.toByteArray()), output, "pdf");
-                    output.close();
+                    out = new FileOutputStream(filename + ".pdf");
+                    GraphvizRunner.process(GraphvizRunner.DOT_LAYOUT, new ByteArrayInputStream(buffer.toByteArray()), out, "pdf");
                 } else {
-                    final FileOutputStream stream = new FileOutputStream(filename + ".gv");
+                    out = new FileOutputStream(filename + ".gv");
 
-                    GraphvizPrinter printer = new GraphvizPrinter(stream);
+                    GraphvizPrinter printer = new GraphvizPrinter(out);
                     if (C1XOptions.OmitDOTFrameStates) {
                         printer.addOmittedClass(FrameState.class);
                     }
                     printer.begin(name);
                     printer.print(graph, true);
                     printer.end();
-
-                    stream.close();
                 }
             } catch (IOException e) {
                 e.printStackTrace();
+            } finally {
+                if (out != null) {
+                    try {
+                        out.close();
+                    } catch (IOException e) {
+                    }
+                }
             }
         }
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/debug/IdealGraphPrinter.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/debug/IdealGraphPrinter.java	Thu May 19 11:43:30 2011 +0200
@@ -63,21 +63,41 @@
     }
 
     /**
-     * Starts a new graph document containing a single group of graphs with the given name, short name and byte code
-     * index (BCI) as properties.
+     * Flushes any buffered output.
+     */
+    public void flush() {
+        stream.flush();
+    }
+
+    /**
+     * Starts a new graph document.
      */
-    public void begin(String name, String shortName, int bci) {
-        stream.println("<graphDocument><group>");
+    public void begin() {
+        stream.println("<graphDocument>");
+    }
+
+    /**
+     * Starts a new group of graphs with the given name, short name and method byte code index (BCI) as properties.
+     */
+    public void beginGroup(String name, String shortName, int bci) {
+        stream.println("<group>");
         stream.printf(" <properties><p name='name'>%s</p></properties>%n", escape(name));
         stream.printf(" <method name='%s' shortName='%s' bci='%d'/>%n", escape(name), escape(shortName), bci);
     }
 
     /**
-     * Finishes the graph document.
+     * Ends the current group.
+     */
+    public void endGroup() {
+        stream.println("</group>");
+    }
+
+    /**
+     * Finishes the graph document and flushes the output stream.
      */
     public void end() {
-        stream.println("</group></graphDocument>");
-        stream.flush();
+        stream.println("</graphDocument>");
+        flush();
     }
 
     /**
--- a/graal/GraalCompiler/src/com/sun/c1x/debug/IdealGraphPrinterObserver.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/debug/IdealGraphPrinterObserver.java	Thu May 19 11:43:30 2011 +0200
@@ -23,6 +23,8 @@
 package com.sun.c1x.debug;
 
 import java.io.*;
+import java.net.*;
+import java.util.regex.*;
 
 import com.oracle.graal.graph.*;
 import com.sun.c1x.*;
@@ -32,13 +34,34 @@
 /**
  * Observes compilation events and uses {@link IdealGraphPrinter} to generate a graph representation that can be
  * inspected with the <a href="http://kenai.com/projects/igv">Ideal Graph Visualizer</a>.
- * 
+ *
  * @author Peter Hofer
  */
 public class IdealGraphPrinterObserver implements CompilationObserver {
 
+    private static final Pattern INVALID_CHAR = Pattern.compile("[^A-Za-z0-9_.-]");
+
+    private final String host;
+    private final int port;
+
     private IdealGraphPrinter printer;
     private OutputStream stream;
+    private Socket socket;
+
+    /**
+     * Creates a new {@link IdealGraphPrinterObserver} that writes output to a file named after the compiled method.
+     */
+    public IdealGraphPrinterObserver() {
+        this(null, -1);
+    }
+
+    /**
+     * Creates a new {@link IdealGraphPrinterObserver} that sends output to a remove IdealGraphVisualizer instance.
+     */
+    public IdealGraphPrinterObserver(String host, int port) {
+        this.host = host;
+        this.port = port;
+    }
 
     @Override
     public void compilationStarted(CompilationEvent event) {
@@ -48,19 +71,70 @@
             String name = event.getMethod().holder().name();
             name = name.substring(1, name.length() - 1).replace('/', '.');
             name = name + "." + event.getMethod().name();
-            String filename = name + ".igv.xml";
-            try {
-                stream = new FileOutputStream(filename);
-                printer = new IdealGraphPrinter(stream);
+
+            if (host != null) {
+                openNetworkPrinter(name);
+            } else {
+                openFilePrinter(name);
+            }
+        }
+    }
+
+    private void openFilePrinter(String name) {
+        String filename = name + ".igv.xml";
+        filename = INVALID_CHAR.matcher(filename).replaceAll("_");
+
+        try {
+            stream = new FileOutputStream(filename);
+            printer = new IdealGraphPrinter(stream);
+            if (C1XOptions.OmitDOTFrameStates) {
+                printer.addOmittedClass(FrameState.class);
+            }
+            printer.begin();
+            printer.beginGroup(name, name, -1);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
 
-                if (C1XOptions.OmitDOTFrameStates) {
-                    printer.addOmittedClass(FrameState.class);
-                }
+    private void openNetworkPrinter(String name) {
+        try {
+            socket = new Socket(host, port);
+            if (socket.getInputStream().read() == 'y') {
+                stream = socket.getOutputStream();
+            } else {
+                // server currently does not accept any input
+                socket.close();
+                socket = null;
+                return;
+            }
 
-                printer.begin(name, name, -1);
-            } catch (IOException e) {
-                e.printStackTrace();
+            printer = new IdealGraphPrinter(stream);
+            if (C1XOptions.OmitDOTFrameStates) {
+                printer.addOmittedClass(FrameState.class);
             }
+            printer.begin();
+            printer.beginGroup(name, name, -1);
+            printer.flush();
+            if (socket.getInputStream().read() != 'y') {
+                // server declines input for this method
+                socket.close();
+                socket = null;
+                stream = null;
+                printer = null;
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+
+            if (socket != null) {
+                try {
+                    socket.close();
+                } catch (IOException ioe) {
+                }
+                socket = null;
+            }
+            stream = null;
+            printer = null;
         }
     }
 
@@ -76,13 +150,20 @@
     public void compilationFinished(CompilationEvent event) {
         if (printer != null) {
             try {
+                printer.endGroup();
                 printer.end();
-                stream.close();
+
+                if (socket != null) {
+                    socket.close(); // also closes stream
+                } else {
+                    stream.close();
+                }
             } catch (IOException e) {
                 e.printStackTrace();
             } finally {
                 printer = null;
                 stream = null;
+                socket = null;
             }
         }
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/doc/IRInterpreter.txt	Thu May 19 11:36:41 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-Current status and remaining issues in the IRInterpreter for HIR (September/18/09)
-=================================================================================
-
-Known Problems:
-With InterpretInvokedMethods disabled in C1XOptions:
-(2 fails)
-304: jtt/jvmni/JVM_GetClassContext01.java: (0) failed with false (expected true)
-557: jtt/reflect/Class_newInstance02.java: (0) failed with true (expected !java.lang.IllegalAccessException)
-
-The first problem is caused by the use of reflection in the IRInterpreter, and the calling stack is not as 
-expected by the JVM_GetClassContext01 test case. The second one is due to the private constructor of Class_newInstance01.
-Again, we are using reflection to call the newInstance() method to create an instance of class Class_newInstance01
-from the IRInterpreter class, which raises an IllegalAccessException.
-These are the only problems with all optimization levels.
-
-With InterpretInvokedMethods enabled in C1XOptions:
-(7 fails)
-245: jtt/except/Catch_StackOverflowError_03.java: (0) failed with !java.lang.InstantiationException (expected 0)
-304: jtt/jvmni/JVM_GetClassContext01.java: (0) failed with false (expected true)
-311: jtt/lang/Bridge_method01.java: (0) failed with unexpected com.sun.c1x.ci.CiBailout (expected 1)
-557: jtt/reflect/Class_newInstance02.java: (0) failed with true (expected !java.lang.IllegalAccessException)
-572: jtt/reflect/Invoke_virtual01.java: (1) failed with unexpected com.sun.c1x.ci.CiBailout (expected 55)
-575: jtt/reflect/Reflection_getCallerClass01.java: (1) failed with com.sun.c1x.debug.IRInterpreter$Evaluator (expected jtt.reflect.Reflection_getCallerClass01$Caller1)
-592: jtt/threads/Thread_isInterrupted04.java: (0) failed with false (expected true)
-
-Those are also due to reflection usage. The last problem has not been investigated.
\ No newline at end of file
--- a/graal/GraalCompiler/src/com/sun/c1x/doc/LoopPeeling.txt	Thu May 19 11:36:41 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-Remaining Issues in the Loop Peeling optimization (September/18/09)
-===================================================================
-
-Known Problems:
-Currently loop peeling is not working when the loop has exception
-blocks. The algorithm has to be updated to handle these cases.
-
-Limitations:
-The algorithm performs loop peeling only on innermost loops. However,
-this is not a limitation. If one wants to peel the outermost loop(s),
-after peeling the innermost loop, an additional pass is necessary
-to update the blocks of the outermost loop, since after peeling
-the innermost loop, newer blocks are added to the CFG.
-
-Current status as of 09/18/2009
-After running using hir configuration, with optimization level 3, the
-following test cases produce wrong results:
-(4 fails)
-233: jtt/except/Catch_Loop01.java: (4) failed with unexpected com.sun.c1x.ci.CiBailout (expected -170)
-234: jtt/except/Catch_Loop02.java: (4) failed with unexpected com.sun.c1x.ci.CiBailout (expected -170)
-245: jtt/except/Catch_StackOverflowError_03.java: (0) failed with unexpected com.sun.c1x.ci.CiBailout (expected 0)
-272: jtt/hotpath/HP_array04.java: (80) failed with unexpected java.lang.AssertionError (expected 15645)
-
-All of them are related the known problem aforementioned.
-All the tests have the innermost loops peeled, and produce right results.
-
-Future Work:
-1- Add more loop tests to jtt. New tests should run the loop 0, 1, 2 or more iterations.
-
-2- Peel loops with exception blocks. 
-
-3- Currently, all innermost loops are peeled. Should we add logic to filter out some loops from loop peeling?
-
-4- Improve the way instructions are cloned. Now the algorithm visits the blocks in BFS order, which
-might produce errors depending on the order the blocks are visited.
-
-5- After inserting new phi instructions at exit blocks, we need to iterate over the remaining CFG to update instructions
-that may use the new phi. The way it's done now might me inefficient if the block has more than one exit node, since
-we can iterate over the same block more than once. This needs to be improved.
-
-5- For performance reasons, improve the way loops are represented, for example, to use a bitmap to represent the loop blocks.
-
-
--- a/graal/GraalCompiler/src/com/sun/c1x/doc/backend_open_issues.txt	Thu May 19 11:36:41 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-Remaining Issues in the C1X backend (after the port July-Sep 09)
-======================================================================
-
-Maxine/Inspector Related Open Issues:
-   - Global stubs: Change calling convention (no longer write to callee stack as this makes stepping through the instructions for saving the parameters to global stubs impossible in the inspector)
-   - Reference maps: Corrently implement TargetMethod.prepareReferenceMap for C1XTargetMethod (checking for the need to stack walk a possible callee saved target method) and call it from Maxine
-   - Disassembler: The Maxine disassembler still does not correctly display every machine code instruction issued by C1X
-   - MaxRiRuntime and C1XTargetMethod have fixed dependencies on the X86 parts (instruction decoding, registers, calling convention), should be factored out
-
-Compile-Time Performance Improvements:
-   - Consider deleting the LIRItem class
-   - Make sure that LIROperand objects are not shared among LIR instructions and can therefore be directly modified by the LinearScan register allocator (no more need for the lazy creation of LIRAddress objects in the LIRInstruction class)
-   
-Run-Time Performance Improvements:
-   - Store mapping between machine code location and bytecode index in the target method (remove arguments from global stub calls), this decreases the number of necessary parameters especially for resolution instructions.
-   - Use Inline Cache on virtual method calls
-
-Better Portability:
-   - Integrate XIR; consider using CiLocation / CiConstant in XIR
-   - The JIT adapter frames should be a more general mechanism that receives two calling conventions (in form of an array of locations) and adapts between them automatically
-   - Have the possibility to register intrinsics by specifying XIR code
-   
\ No newline at end of file
--- a/graal/GraalCompiler/src/com/sun/c1x/doc/differences.txt	Thu May 19 11:36:41 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,154 +0,0 @@
-Differences between C1 and C1X, including upgrades and limitations
-(and some general information about C1)
-======================================================================
-
-StrictFP:
-   - C1X has removed the backend code to deal with the FPU stack, and therefore
-     requires SSE2 currently. StrictFP is still tracked in the front end.
-   - C1 will not inline methods with different strictfp-ness. C1X does not have this
-     limitation because it only targets SSE2 x86 processors.
-
-JSR/RET
-   - C1 will bail out if it encounters strange JSR/RET patterns
-       - recursive JSRs
-       - JSR regions that are shared with non-JSR code
-       - RET encountered out of JSR (would not verify)
-
-Exceptions
-   -  C1 will bailout if the code of an exception handler can be reached via normal
-      control flow.
-   => C1X might be extended to introduce a phi for the exception
-      object in this case.
-   -  C1 will bailout if an exception handler covers itself
-
-Verification
-   -  C1 does not rely on bytecode verification having been run. However, if it detects
-      type errors in its building the IR graph it will usually bail out.
-   -  C1 requires a bitmap of the bytecode, where a bit for
-      each byte of the bytecode indicates if the bytecode at that location starts a
-      basic block. It uses this to construct the basic block list in a single pass.
-   => Assertion failures and/or bugs in C1X that cause exceptions to be thrown bail out
-      the compilation instead of crashing the VM.
-   => C1X's BlockMap does not computes the basic block starts in one pass over the bytecode
-      and one pass over the successor lists.
-   => C1X computes the "stores in loops" only when loops are encountered in the CFG.
-      An option can select conservative mode (all locals stored in all loops) trades
-      faster parse speed for fewer optimization opportunities
-   => C1X includes an IRChecker that typechecks the entire IR and checks for CFG
-      consistency that can be run after each pass.
-
-Constants
-   => C1X allows unrestricted use of object constants throughout the code, including
-      folding reads of static final fields that reference objects.
-
-Pinning
-   => C1X pins fewer instructions than C1
-   ** C1X will eventually allow certain kinds of instructions to float outside the CFG
-      and be scheduled with a C2-lite scheduling pass.
-
-Synchronization
-   -  C1 will refuse to compile methods with unbalanced synchronization. This property is
-      computed by the bytecode verifier and supplied to C1.
-   ** C1X will not rely on the bytecode verifier to compute this but should do so itself.
-   => C1 relied on the backend to generate synchronization code for the root method's
-      synchronization operations. C1X inserts code into the start block and generates
-      and exception handler to do this explicitly.
-
-Optimizations
-   => C1X has many more options to turn on individual passes, parts of passes, approximations,
-      etc. It is designed to have three optimization levels:
-      0 = super-fast: essentially no optimization
-      1 = fast:       inlining, constant folding, and local optimizations
-      2 = optimized:  inlining, constant folding, local and global optimizations, including
-                      iterative versions of all algorithms
-   ** Planned optimizations for C1X that C1 does not have:
-      TypeCheckElimination:        remove redundant casts and devirtualize more call sites
-      ArrayBoundsCheckElimination: remove redundant array bounds checks and/or restructure
-                                   code to deoptimize when bounds checks within loops will fail
-      LoopPeeling:                 replicate the first iteration of a loop
-      LoopUnrolling:               replicate the body of certain shapes of loops
-      LoopInvariantCodeMotion:     move invariant code out of a loop
-      ProfileGuidedInlining:       use receiver method profiles to emit guarded inlines
-      ProfileGuidedBlockLayout:    use profiling information for code placement
-      Peephole:                    peephole optimize backend output
-
-Block Merging
-   ** C1X will replace branches to blocks with a single Goto with a branch to the
-      block's successor, if the blocks cannot be merged otherwise.
-
-Constant Folding / Strength reduction
-   -  C1 had some of its strength reduction logic built into the GraphBuilder because
-      the Canonicalizer could not return multiple instructions.
-   => C1X added this ability, moved the logic to Canonicalizer, and added a few new
-      strength reductions.
-   => C1X should have an interface for doing folding of @FOLD method calls
-   => C1X folds many intrinsic operations that don't have side effects
-   => C1X folds all the basic floating point operations
-   => C1X strength reduces (e >> C >> K) to (e >> (C + K)) when C and K are constant
-   => Multiplies of power-of-2 constants are reduced to shifts in the canonicalizer
-      (instead of the backend)
-   ** C1X will be able to run a global sparse conditional constant propagation phase
-      to catch any missed canonicalization opportunities after graph building.
-
-Switches
-   -  C1 did not detect back edges in tableswitch/lookupswitch default branches
-   => C1X does detect these back edges
-   => C1X moved the canonicalization code of 1 and 2 branch switches to canonicalizer,
-      where it belongs
-
-Inlining
-   -  C1 cannot inline:
-      -  native methods (or their stubs), except some intrinsics
-      -  methods whose class has not been initialized
-      -  methods with unbalanced monitors
-      -  methods with JSRs (this is probably technically possible now)
-
-   -  C1 will not inline:
-      -  methods with exception handlers (optional)
-      -  synchronized methods (optional)
-      -  if the maximum inline depth is reached (default = 9)
-      -  if the maximum recursive inline depth is reached (default = 1)
-      -  if the callee is larger than the maximum inline size (reduced to 90% at each level, starting at 35)
-      -  constructors for subclasses of Throwable
-      -  if the strictfp-ness of the callee is different than the caller (on x87)
-      -  abstract methods
-      -  synchronized intrinsics
-
-Load/store elimination
-   => C1X may eliminate loads of static fields, which C1 did not
-   => C1X distinguishes loads/stores to different fields in MemoryBuffer
-   => C1X assumes that RiField instances are unique when .isLoaded() is true
-
-Local/Global Value Numbering
-   => C1X improved local load elimination and no longer value numbers fields, reducing the
-      logic necessary in ValueMap, simplifying it and improving its performance.
-   => C1X reuses the same simplified ValueMap for GVN. Since heap accesses are no longer
-      value numbered, the logic to kill values is unnecessary, greatly simplifying
-      GVN.
-   ** A global version of load elimination will compensate for this loss in the future.
-   => C1X value numbers are always or'd with a high order bit when value numbering is possible
-      to prevent value numbering failing if the value number is accidentally 0.
-
-Nullcheck elimination
-   => A new flag, NonNull, indicates instructions that produce values that are guaranteed
-      to be non-null (e.g. NewXXX and Local 0, NullCheck). Instructions that require null
-      checks check this flag for their inputs in their constructors, eliminating most
-      redundant null checks immediately, without requiring the NullCheckEliminator to run.
-   => C1X uses a more efficient block ordering for null check elimination. The first pass is
-      optimistic and attempts to visit the blocks in reverse post-order. For acyclic graphs,
-      this almost always succeeds, requiring no iteration. Full iterative data flow analysis
-      can be enabled separately. Bitmaps used during the fixpoint calculation are much
-      smaller due to local numbering of instructions (as opposed to global IDs).
-   ** C1X will recognize If's that check against null and propagate the non-nullness across
-      the appropriate branches.
-
-BlockListBuilder
-   -  C1 had a vestigial loop map in BlockListBuilder which was not really used.
-   => C1X does not need to compute a complete loop map in order to do selective phi creation,
-      it builds the "storesInLoops" BitMap in BlockMap.
-
-Types
-   => C1X adds the declared type of method parameters to Local instructions, which
-      may help with devirtualization
-   => C1X makes local 0 of instance methods non-null at the start
-
--- a/graal/GraalCompiler/src/com/sun/c1x/doc/performance.txt	Thu May 19 11:36:41 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-Issues that can be addressed for improving performance in C1X
-----------------------------------------------------------------
-
-- indicates not done
-* indicates done
-
-Backend:
-	- better handling of constants, especially immediates
-	- (non XIR) checkcast, instanceof: use nullity
-	- (non XIR) checkcast, instanceof: emit fastpath direct compare
-	- use LEA instruction on x86
-	- recognize pointer arithmetic addressing modes
-	- recognize multiply by 3, 5, 9 and emit lea rk, [rs, rs*2], etc
-	- Maxine XIR: make direct runtime calls instead of through global stub
-	- Maxine XIR: implement inline allocation
-	- Maxine XIR: implement biased locking fastpath
-	- Maxine XIR: faster subtype checks for classes, leaves
-	- Maxine XIR: make use of XirSite nullity, range check information
-	- better handling of tableswitch bytecode
-	- better handling of two operand LIR form
-	- Make the following bytecode implementations inline:
-		- f2i f2l f2d d2i d2l d2f (SSE2)
-		* lrem ldiv (64 bit)
-		- fneg dneg
-	- Make the following bytecode implementations global stubs:
-		- frem drem
-	- Global stubs: use EAX for return value as normal instead of [rsp - 16]
-    - Emit direct call to runtime for new instance, monitorenter, monitorexit
-
-	* XIR: expose nullity, range checkness across XIR interface
-	- XIR: make use of CSE'd array length
-	- XIR: generate special if-instanceof XIR variant with label parameters
-    - Optimize special cases of bytecodes:
-        - (MIN_INT / -1) in IDIV,IREM
-        - (MIN_LONG / -1) in LDIV,LREM
-        - (-infinity, Nan, +infinity) in F2I, F2L, D2I, D2L
-
-
-Frontend:
-    - Remove redundant null check branches in NullCheckEliminator
-	- XIR: implement HIR -> HIR xir translation
-	- Refactor exception edges to allow removal, optimization
-	- Implement typecast elimination
-	- Implement constant propagation
-	- Implement GVN of memory loads / stores
-	- Implement memory reordering
-	- Implement loop invariant code motion
-	- Optimize endianness conversions and endian-writes
-	      (e.g. (x >> 24 & 0xff) | (....)) and a[0] = x >> 24 ...
-	- Finish loop peeling
-	- Implement loop unrolling
-	- Allow value numbering of constant loads
-	- Finish loop peeling
-	- Guarded and multiple inlining
-	- Maxine: speculative leaf class and leaf method assumption
-	- Maxine: adjust static / dynamic inlining heuristics
-		  (e.g. static: trivial methods only in cold spots)
-    - Aggressive optimization of array copy
-
-Compilation speed:
-    - Make special iterators for LIROperand input, temp, output
-    - Add analysisInfo field to Value and use in NullCheckEliminator
-	- Remove RiConstantPool, cpi from unresolved HIR instructions (move to RiField, RiMethod)
-	- Use BlockList instead of ArrayList<Block> where appropriate
-	- Use FrameState instead of ValueStack
-	- Remove exceptionHandlers, make DebugInfo hold FrameState, CiCodePos,
-		exception flags and exception handlers
-	- Clean up and simplify LIRInstruction constructor
-	- Create fewer LIRAddresses
-	- Simplify LIRGenerator logic (forcing of loading, etc)
-	- LIROperand: split into virtual register table?
-	- Cleanup assembler and remove dead code, useless assertions
-	- Chain assembler byte buffers and only assemble at the end
-	- Pick optimal initial assembler byte buffer size
-	- Pick good initial sizes for LinearScan data structures
-	- Remove unnecessary uses of ArrayList and replace with arrays or other list
-	- Use iteration over ArrayList instead of explicit loop
-	- Revisit manual editing / removal of items from ArrayList
-	- Remove non-XIR backend
-	- Pre-assemble XIR for backend
-
-	* Initialize compilation-unique instruction id's lazily with thread local compilation
-	* Remove dead LIROpcodes
-	* Remove dead code in LIRGenerator, X86LIRGenerator, LIRAssembler, X86LIRAssembler
-		(remove commented out code)
--- a/graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java	Thu May 19 11:43:30 2011 +0200
@@ -394,7 +394,6 @@
 
     @Override
     public void visitExceptionObject(ExceptionObject x) {
-        assert currentBlock.isExceptionEntry() : "ExceptionObject only allowed in exception handler block";
         assert currentBlock.next() == x : "ExceptionObject must be first instruction of block";
 
         // no moves are created for phi functions at the begin of exception
@@ -1446,7 +1445,7 @@
         }
 
         assert state != null;
-        return new LIRDebugInfo(state, x.exceptionHandlers());
+        return new LIRDebugInfo(state, x.exceptionEdge());
     }
 
     List<CiValue> visitInvokeArguments(CiCallingConvention cc, Invoke x, List<CiValue> pointerSlots) {
@@ -1611,4 +1610,15 @@
     public void visitFrameState(FrameState i) {
         // nothing to do for now
     }
+
+    @Override
+    public void visitUnwind(Unwind x) {
+        // TODO ls: this needs some thorough testing...
+        CiValue operand = resultOperandFor(x.kind);
+        CiValue result = force(x.exception(), operand);
+        ArrayList<CiValue> args = new ArrayList<CiValue>(1);
+        args.add(result);
+        lir.callRuntime(CiRuntimeCall.UnwindException, CiValue.IllegalValue, args, null);
+        setNoResult(x);
+    }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/BlockMap.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/BlockMap.java	Thu May 19 11:43:30 2011 +0200
@@ -615,42 +615,4 @@
 
         out.print("loop_depth ").println(Integer.bitCount(block.loops));
     }
-
-//
-//    private static StringBuilder append(StringBuilder sb, BlockBegin block) {
-//        return sb.append('B').append(block.blockID).append('@').append(block.bci());
-//    }
-//
-//    @Override
-//    public String toString() {
-//        StringBuilder sb = new StringBuilder();
-//        for (int bci = 0; bci < blockMap.length; ++bci) {
-//            BlockBegin block = blockMap[bci];
-//            if (block != null) {
-//                append(sb, block);
-//                if (loopBlocks != null && loopBlocks.contains(block)) {
-//                    sb.append("{loop-header}");
-//                }
-//                if (successorMap != null) {
-//                    BlockBegin[] succs = successorMap[bci];
-//                    if (succs != null && succs.length > 0) {
-//                        sb.append(" ->");
-//                        for (BlockBegin succ : succs) {
-//                            append(sb.append(' '), succ);
-//                        }
-//                    }
-//                }
-//                Collection<BlockBegin> handlers = getHandlers(block);
-//                if (!handlers.isEmpty()) {
-//                    sb.append(" xhandlers{");
-//                    for (BlockBegin h : handlers) {
-//                        append(sb, h).append(' ');
-//                    }
-//                    sb.append('}');
-//                }
-//                sb.append(String.format("%n"));
-//            }
-//        }
-//        return sb.toString();
-//    }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/BlockUtil.java	Thu May 19 11:36:41 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +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 com.sun.c1x.ir.*;
-
-/**
- * The {@code BlockUtil} class contains a number of utilities for manipulating a CFG of basic blocks.
- *
- * @author Ben L. Titzer
- */
-public class BlockUtil {
-
-    /**
-     * Disconnects the specified block from all other blocks.
-     * @param block the block to remove from the graph
-     */
-    public static void disconnectFromGraph(BlockBegin block) {
-        for (BlockEnd p : block.blockPredecessors()) {
-            p.blockSuccessors().remove(block);
-        }
-        for (BlockBegin s : block.end().blockSuccessors()) {
-            s.blockPredecessors().remove(block);
-        }
-    }
-}
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java	Thu May 19 11:43:30 2011 +0200
@@ -111,7 +111,7 @@
 
     private final Graph graph;
 
-    private final List<BlockBegin> newExceptionHandlers = new ArrayList<BlockBegin>();
+    private BlockBegin unwindBlock;
 
     /**
      * Creates a new, initialized, {@code GraphBuilder} instance for a given compilation.
@@ -147,11 +147,6 @@
             flags |= Flag.NoSafepoints.mask;
         }
 
-        // 1. create the start block
-        ir.startBlock = new BlockBegin(0, ir.nextBlockNumber(), graph);
-        BlockBegin startBlock = ir.startBlock;
-        graph.root().setStart(startBlock);
-
         // 2. compute the block map, setup exception handlers and get the entrypoint(s)
         BlockMap blockMap = compilation.getBlockMap(rootMethod);
 
@@ -159,9 +154,6 @@
         for (int i = 0; i < blockMap.blocks.size(); i++) {
             BlockMap.Block block = blockMap.blocks.get(i);
             BlockBegin blockBegin = new BlockBegin(block.startBci, ir.nextBlockNumber(), graph);
-            if (block.isExceptionEntry) {
-                blockBegin.setBlockFlag(BlockBegin.BlockFlag.ExceptionEntry);
-            }
             if (block.isLoopHeader) {
                 blockBegin.setBlockFlag(BlockBegin.BlockFlag.ParserLoopHeader);
             }
@@ -169,7 +161,11 @@
             blockList[block.startBci] = blockBegin;
         }
 
-        BlockBegin stdEntry = blockList[0];
+
+        // 1. create the start block
+        ir.startBlock = new BlockBegin(0, ir.nextBlockNumber(), graph);
+        BlockBegin startBlock = ir.startBlock;
+        graph.root().setStart(startBlock);
         curBlock = startBlock;
 
         RiExceptionHandler[] handlers = rootMethod.exceptionHandlers();
@@ -195,31 +191,30 @@
         lastInstr = startBlock;
         lastInstr.appendNext(null, -1);
 
+        BlockBegin entryBlock = blockList[0];
         if (isSynchronized(rootMethod.accessFlags())) {
             // 4A.1 add a monitor enter to the start block
             rootMethodSynchronizedObject = synchronizedObject(frameState, compilation.method);
             genMonitorEnter(rootMethodSynchronizedObject, Instruction.SYNCHRONIZATION_ENTRY_BCI);
             // 4A.2 finish the start block
-            finishStartBlock(startBlock, stdEntry);
+            finishStartBlock(startBlock, entryBlock);
 
             // 4A.3 setup an exception handler to unlock the root method synchronized object
             syncHandler = new BlockBegin(Instruction.SYNCHRONIZATION_ENTRY_BCI, ir.nextBlockNumber(), graph);
-            syncHandler.setExceptionEntry();
-            syncHandler.setBlockFlag(BlockBegin.BlockFlag.IsOnWorkList);
-            syncHandler.setBlockFlag(BlockBegin.BlockFlag.DefaultExceptionHandler);
+            markOnWorkList(syncHandler);
 
             ExceptionHandler h = new ExceptionHandler(new CiExceptionHandler(0, rootMethod.code().length, -1, 0, null));
             h.setEntryBlock(syncHandler);
             addExceptionHandler(h);
         } else {
             // 4B.1 simply finish the start block
-            finishStartBlock(startBlock, stdEntry);
+            finishStartBlock(startBlock, entryBlock);
         }
 
         // 5. SKIPPED: look for intrinsics
 
         // 6B.1 do the normal parsing
-        addToWorkList(stdEntry);
+        addToWorkList(entryBlock);
         iterateAllBlocks();
 
         if (syncHandler != null && syncHandler.stateBefore() != null) {
@@ -228,6 +223,26 @@
         }
     }
 
+    private Set<BlockBegin> blocksOnWorklist = new HashSet<BlockBegin>();
+
+    private void markOnWorkList(BlockBegin block) {
+        blocksOnWorklist.add(block);
+    }
+
+    private boolean isOnWorkList(BlockBegin block) {
+        return blocksOnWorklist.contains(block);
+    }
+
+    private Set<BlockBegin> blocksVisited = new HashSet<BlockBegin>();
+
+    private void markVisited(BlockBegin block) {
+        blocksVisited.add(block);
+    }
+
+    private boolean isVisited(BlockBegin block) {
+        return blocksVisited.contains(block);
+    }
+
     private void finishStartBlock(BlockBegin startBlock, BlockBegin stdEntry) {
         assert curBlock == startBlock;
         FrameState stateAfter = frameState.create(bci());
@@ -262,72 +277,151 @@
         frameState.storeLocal(index, frameState.pop(kind));
     }
 
-    List<ExceptionHandler> handleException(Instruction x, int bci) {
+    private void handleException(Instruction x, int bci) {
         if (!hasHandler()) {
-            return ExceptionHandler.ZERO_HANDLERS;
+            return;
         }
 
         ArrayList<ExceptionHandler> exceptionHandlers = new ArrayList<ExceptionHandler>();
 
-        FrameState state = frameState.create(bci);
         assert bci == Instruction.SYNCHRONIZATION_ENTRY_BCI || bci == bci() : "invalid bci";
 
         // join with all potential exception handlers
         if (this.exceptionHandlers != null) {
             for (ExceptionHandler handler : this.exceptionHandlers) {
+                // if the handler covers this bytecode index, add it to the list
                 if (handler.covers(bci)) {
-                    // if the handler covers this bytecode index, add it to the list
-                    if (addExceptionHandler(exceptionHandlers, handler, state)) {
-                        // if the handler was a default handler, we are done
-                        return exceptionHandlers;
+                    ExceptionHandler newHandler = addExceptionHandler(handler, frameState);
+                    exceptionHandlers.add(newHandler);
+
+                    // stop when reaching catch all
+                    if (handler.isCatchAll()) {
+                        break;
                     }
                 }
             }
         }
 
-        return exceptionHandlers;
+        if (!exceptionHandlers.isEmpty()) {
+            BlockBegin successor;
+
+            ArrayList<BlockBegin> newBlocks = new ArrayList<BlockBegin>();
+
+            int current = exceptionHandlers.size() - 1;
+            if (exceptionHandlers.get(current).isCatchAll()) {
+                successor = exceptionHandlers.get(current).entryBlock();
+                current--;
+            } else {
+                if (unwindBlock == null) {
+                    unwindBlock = new BlockBegin(bci, ir.nextBlockNumber(), graph);
+                    Unwind unwind = new Unwind(null, false, graph);
+                    unwindBlock.appendNext(unwind, bci);
+                    unwindBlock.setEnd(unwind);
+                }
+                successor = unwindBlock;
+            }
+
+            for (; current >= 0; current--) {
+                ExceptionHandler handler = exceptionHandlers.get(current);
+
+                BlockBegin newSucc = null;
+                for (Instruction pred : successor.blockPredecessors()) {
+                    if (pred instanceof ExceptionDispatch) {
+                        ExceptionDispatch dispatch = (ExceptionDispatch) pred;
+                        if (dispatch.handler().handler == handler.handler) {
+                            newSucc = dispatch.begin();
+                            break;
+                        }
+                    }
+                }
+                if (newSucc != null) {
+                    successor = newSucc;
+                } else {
+                    BlockBegin dispatchEntry = new BlockBegin(handler.handlerBCI(), ir.nextBlockNumber(), graph);
+                    if (handler.handler.catchType().isResolved()) {
+                        ExceptionDispatch end = new ExceptionDispatch(null, handler.entryBlock(), null, handler, null, false, graph);
+                        end.setBlockSuccessor(0, successor);
+                        dispatchEntry.appendNext(end, handler.handlerBCI());
+                        dispatchEntry.setEnd(end);
+                    } else {
+                        Deoptimize deopt = new Deoptimize(graph, null);
+                        dispatchEntry.appendNext(deopt, bci);
+                        Goto end = new Goto(successor, null, false, graph);
+                        deopt.appendNext(end, bci);
+                        dispatchEntry.setEnd(end);
+                    }
+                    newBlocks.add(dispatchEntry);
+                    successor = dispatchEntry;
+                }
+            }
+
+            FrameState entryState = frameState.duplicateWithEmptyStack(bci);
+
+            BlockBegin entry = new BlockBegin(bci, ir.nextBlockNumber(), graph);
+            entry.setStateBefore(entryState);
+            ExceptionObject exception = new ExceptionObject(graph);
+            entry.appendNext(exception, bci);
+            FrameState stateWithException = entryState.duplicateModified(bci, CiKind.Void, exception);
+            BlockEnd end = new Goto(successor, stateWithException, false, graph);
+            exception.appendNext(end, bci);
+            entry.setEnd(end);
+
+            if (x instanceof Invoke) {
+                ((Invoke) x).setExceptionEdge(entry);
+            } else {
+                ((Throw) x).setExceptionEdge(entry);
+            }
+
+            updateDispatchChain(end.blockSuccessor(0), stateWithException, bci);
+        }
+    }
+
+    private void updateDispatchChain(BlockBegin dispatchEntry, FrameStateAccess state, int bci) {
+        FrameState oldState = dispatchEntry.stateBefore();
+        if (oldState != null && dispatchEntry.predecessors().size() == 1) {
+            dispatchEntry.setStateBefore(null);
+            oldState.delete();
+        }
+        dispatchEntry.mergeOrClone(state, null);
+        FrameState mergedState = dispatchEntry.stateBefore();
+
+        if (dispatchEntry.next() instanceof ExceptionDispatch) {
+            // ordinary dispatch handler
+            ExceptionDispatch dispatch = (ExceptionDispatch) dispatchEntry.next();
+            dispatch.setStateAfter(mergedState.duplicate(bci));
+            dispatch.setException(mergedState.stackAt(0));
+            dispatch.catchSuccessor().setStateBefore(mergedState.duplicate(bci));
+            updateDispatchChain(dispatch.otherSuccessor(), mergedState, bci);
+        } else if (dispatchEntry.next() instanceof Deoptimize) {
+            // deoptimizing handler
+            Deoptimize deopt = (Deoptimize) dispatchEntry.next();
+            deopt.setStateBefore(mergedState.duplicate(bci));
+            dispatchEntry.end().setStateAfter(mergedState.duplicate(bci));
+            updateDispatchChain(dispatchEntry.end().blockSuccessor(0), mergedState, bci);
+        } else if (dispatchEntry.next() instanceof Unwind) {
+            // unwind handler
+            Unwind unwind = (Unwind) dispatchEntry.next();
+            unwind.setStateAfter(mergedState.duplicate(bci));
+            unwind.setException(mergedState.stackAt(0));
+        } else {
+            // synchronization or default exception handler, nothing to do
+        }
     }
 
     /**
      * Adds an exception handler to the {@linkplain BlockBegin#exceptionHandlerBlocks() list}
      * of exception handlers for the {@link #curBlock current block}.
-     *
-     * @param exceptionHandlers
-     * @param handler
-     * @param curScopeData
-     * @param curState the current state with empty stack
-     * @param scopeCount
-     * @return {@code true} if handler catches all exceptions (i.e. {@code handler.isCatchAll() == true})
      */
-    private boolean addExceptionHandler(ArrayList<ExceptionHandler> exceptionHandlers, ExceptionHandler handler, FrameState curState) {
+    private ExceptionHandler addExceptionHandler(ExceptionHandler handler, FrameStateAccess curState) {
         compilation.setHasExceptionHandlers();
 
         BlockBegin entry = handler.entryBlock();
-        FrameState entryState = entry.stateBefore();
-
-        assert entry.bci() == handler.handler.handlerBCI();
-        assert entryState == null || curState.locksSize() == entryState.locksSize() : "locks do not match : cur:" + curState.locksSize() + " entry:" + entryState.locksSize();
-
-        // exception handler starts with an empty expression stack
-        curState = curState.duplicateWithEmptyStack();
-
-        entry.mergeOrClone(curState, method());
-
-        // add current state for correct handling of phi functions
-        int phiOperand = entry.addExceptionState(curState);
-
-        // add entry to the list of exception handlers of this block
-        curBlock.addExceptionHandler(entry);
-
-        newExceptionHandlers.add(entry);
 
         // clone exception handler
         ExceptionHandler newHandler = new ExceptionHandler(handler);
-        newHandler.setPhiOperand(phiOperand);
-        exceptionHandlers.add(newHandler);
 
         // fill in exception handler subgraph lazily
-        if (!entry.wasVisited()) {
+        if (!isVisited(entry)) {
             addToWorkList(entry);
         } else {
             // This will occur for exception handlers that cover themselves. This code
@@ -336,9 +430,7 @@
             //
             //   http://www.cs.arizona.edu/projects/sumatra/hallofshame/java-async-race.html
         }
-
-        // stop when reaching catch all
-        return handler.isCatchAll();
+        return newHandler;
     }
 
     private void genLoadConstant(int cpi) {
@@ -977,7 +1069,7 @@
 
         if (x instanceof Invoke || x instanceof Throw) {
             // connect the instruction to any exception handlers
-            x.setExceptionHandlers(handleException(x, bci));
+            handleException(x, bci);
         }
 
         return x;
@@ -1015,7 +1107,6 @@
         frameState.initializeFrom(syncHandler.stateBefore());
 
         int bci = Instruction.SYNCHRONIZATION_ENTRY_BCI;
-        Value exception = appendWithoutOptimization(new ExceptionObject(graph), bci);
 
         assert lock != null;
         assert frameState.locksSize() > 0 && frameState.lockAt(frameState.locksSize() - 1) == lock;
@@ -1028,7 +1119,6 @@
         // exit the monitor
         genMonitorExit(lock, Instruction.SYNCHRONIZATION_ENTRY_BCI);
 
-        frameState.apush(exception);
         genThrow(bci);
         BlockEnd end = (BlockEnd) lastInstr;
         curBlock.setEnd(end);
@@ -1043,40 +1133,38 @@
     private void iterateAllBlocks() {
         BlockBegin b;
         while ((b = removeFromWorkList()) != null) {
-            if (!b.wasVisited()) {
-                b.setWasVisited(true);
+
+            // remove blocks that have no predecessors by the time it their bytecodes are parsed
+            if (b.blockPredecessors().size() == 0) {
+                markVisited(b);
+                continue;
+            }
+
+            if (!isVisited(b)) {
+                markVisited(b);
                 // now parse the block
                 curBlock = b;
                 frameState.initializeFrom(b.stateBefore());
                 lastInstr = b;
                 b.appendNext(null, -1);
 
-                iterateBytecodesForBlock(b.bci(), false);
+                iterateBytecodesForBlock(b.bci());
             }
         }
     }
 
-    private BlockEnd iterateBytecodesForBlock(int bci, boolean inliningIntoCurrentBlock) {
+    private BlockEnd iterateBytecodesForBlock(int bci) {
         assert frameState != null;
         stream.setBCI(bci);
 
         BlockBegin block = curBlock;
         BlockEnd end = null;
-        boolean pushException = block.isExceptionEntry() && block.next() == null;
         int prevBCI = bci;
         int endBCI = stream.endBCI();
         boolean blockStart = true;
 
         while (bci < endBCI) {
             BlockBegin nextBlock = blockAtOrNull(bci);
-            if (bci == 0 && inliningIntoCurrentBlock) {
-                if (!nextBlock.isParserLoopHeader()) {
-                    // Ignore the block boundary of the entry block of a method
-                    // being inlined unless the block is a loop header.
-                    nextBlock = null;
-                    blockStart = false;
-                }
-            }
             if (nextBlock != null && nextBlock != block) {
                 // we fell through to the next block, add a goto and break
                 end = new Goto(nextBlock, null, false, graph);
@@ -1086,12 +1174,6 @@
             // read the opcode
             int opcode = stream.currentBC();
 
-            // push an exception object onto the stack if we are parsing an exception handler
-            if (pushException) {
-                frameState.apush(append(new ExceptionObject(graph)));
-                pushException = false;
-            }
-
             traceState();
             traceInstruction(bci, stream, opcode, blockStart);
             processBytecode(bci, stream, opcode);
@@ -1125,14 +1207,6 @@
         end.setStateAfter(stateAtEnd);
         curBlock.setEnd(end);
 
-        for (BlockBegin entry : newExceptionHandlers) {
-            // add back-edge from exception handler entry to this block
-            if (!entry.blockPredecessors().contains(curBlock.end())) {
-                entry.addPredecessor(curBlock.end());
-            }
-        }
-        newExceptionHandlers.clear();
-
         // propagate the state
         for (BlockBegin succ : end.blockSuccessors()) {
             assert succ.blockPredecessors().contains(curBlock.end());
@@ -1417,8 +1491,8 @@
      * @param block the block to add to the work list
      */
     private void addToWorkList(BlockBegin block) {
-        if (!block.isOnWorkList()) {
-            block.setOnWorkList(true);
+        if (!isOnWorkList(block)) {
+            markOnWorkList(block);
             sortIntoWorkList(block);
         }
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java	Thu May 19 11:43:30 2011 +0200
@@ -89,7 +89,6 @@
     private void buildGraph() {
         // Graph builder must set the startBlock and the osrEntryBlock
         new GraphBuilder(compilation, this, compilation.graph).build();
-        assert startBlock != null;
         verifyAndPrint("After graph building");
 
         if (C1XOptions.PrintCompilation) {
@@ -168,8 +167,6 @@
         // create new successor and mark it for special block order treatment
         BlockBegin newSucc = new BlockBegin(bci, nextBlockNumber(), compilation.graph);
 
-        newSucc.setCriticalEdgeSplit(true);
-
         // This goto is not a safepoint.
         Goto e = new Goto(target, null, false, compilation.graph);
         newSucc.appendNext(e, bci);
@@ -185,55 +182,16 @@
         // link predecessor to new block
         source.end().substituteSuccessor(target, newSucc);
 
-        // The ordering needs to be the same, so remove the link that the
-        // set_end call above added and substitute the new_sux for this
-        // block.
-        target.removePredecessor(newSucc.end());
-
-        // the successor could be the target of a switch so it might have
-        // multiple copies of this predecessor, so substitute the new_sux
-        // for the first and delete the rest.
-        List<BlockEnd> list = target.blockPredecessors();
-        int x = list.indexOf(source.end());
-        list.set(x, newSucc.end());
-        newSucc.addPredecessor(source.end());
-        Iterator<BlockEnd> iterator = list.iterator();
-        while (iterator.hasNext()) {
-            if (iterator.next() == source.end()) {
-                iterator.remove();
-                newSucc.addPredecessor(source.end());
-            }
-        }
         return newSucc;
     }
 
     public void replaceBlock(BlockBegin oldBlock, BlockBegin newBlock) {
-        assert !oldBlock.isExceptionEntry() : "cannot replace exception handler blocks (yet)";
-        for (BlockBegin succ : oldBlock.end().blockSuccessors()) {
-            succ.removePredecessor(oldBlock.end());
-        }
-        for (BlockEnd pred : oldBlock.blockPredecessors()) {
+        List<Instruction> predecessors = new ArrayList<Instruction>(oldBlock.blockPredecessors());
+        for (Instruction pred : predecessors) {
             // substitute the new successor for this block in each predecessor
-            pred.substituteSuccessor(oldBlock, newBlock);
-            // and add each predecessor to the successor
-            newBlock.addPredecessor(pred);
+            pred.block().end().substituteSuccessor(oldBlock, newBlock);
         }
-        // this block is now disconnected; remove all its incoming and outgoing edges
-//        oldBlock.blockPredecessors().clear();
-//        oldBlock.end().successors().clear();
-    }
-
-    /**
-     * Disconnects the specified block from all other blocks.
-     * @param block the block to remove from the graph
-     */
-    public void disconnectFromGraph(BlockBegin block) {
-        for (BlockEnd p : block.blockPredecessors()) {
-            p.blockSuccessors().remove(block);
-        }
-        for (BlockBegin s : block.end().blockSuccessors()) {
-            s.blockPredecessors().remove(block);
-        }
+        oldBlock.end().clearSuccessors();
     }
 
     public int nextBlockNumber() {
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/BlockBegin.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/BlockBegin.java	Thu May 19 11:43:30 2011 +0200
@@ -71,19 +71,7 @@
 
     public void setEnd(BlockEnd end) {
         assert end != null;
-        BlockEnd old = this.end();
-        if (old != end) {
-            if (old != null) {
-                // disconnect this block from its current successors
-                for (BlockBegin s : old.blockSuccessors()) {
-                    s.blockPredecessors().remove(this.end());
-                }
-            }
-            successors().set(super.successorCount() + SUCCESSOR_END, end);
-            for (BlockBegin s : end.blockSuccessors()) {
-                s.addPredecessor(end);
-            }
-        }
+        successors().set(super.successorCount() + SUCCESSOR_END, end);
     }
 
     private static final List<BlockBegin> NO_HANDLERS = Collections.emptyList();
@@ -93,14 +81,8 @@
      */
     public enum BlockFlag {
         StandardEntry,
-        ExceptionEntry,
-        SubroutineEntry,
         BackwardBranchTarget,
-        IsOnWorkList,
-        WasVisited,
-        DefaultExceptionHandler,
         ParserLoopHeader,
-        CriticalEdgeSplit,
         LinearScanLoopHeader,
         LinearScanLoopEnd;
 
@@ -117,22 +99,13 @@
      */
     private int blockFlags;
 
-    /**
-     * The {@link BlockBegin} nodes for which this node is a successor.
-     */
-    private final List<BlockEnd> predecessors;
-
     private int depthFirstNumber;
     private int linearScanNumber;
-    private int loopDepth;
-    private int loopIndex;
 
     private BlockBegin dominator;
-    private List<BlockBegin> exceptionHandlerBlocks;
-    private List<FrameState> exceptionHandlerStates;
 
     // LIR block
-    public LIRBlock lirBlock;
+    public final LIRBlock lirBlock = new LIRBlock();
 
     /**
      * Constructs a new BlockBegin at the specified bytecode index.
@@ -145,8 +118,6 @@
         this.blockID = blockID;
         depthFirstNumber = -1;
         linearScanNumber = -1;
-        predecessors = new ArrayList<BlockEnd>(2);
-        loopIndex = -1;
         setBCI(bci);
     }
 
@@ -154,17 +125,13 @@
      * Gets the list of predecessors of this block.
      * @return the predecessor list
      */
-    public List<BlockEnd> blockPredecessors() {
-//      return Collections.unmodifiableList(predecessors);
-      return predecessors;
-    }
-
-    /**
-     * Gets the dominator of this block.
-     * @return the dominator block
-     */
-    public BlockBegin dominator() {
-        return dominator;
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public List<Instruction> blockPredecessors() {
+        if (predecessors().size() == 1 && predecessors().get(0) == graph().root()) {
+            return Collections.EMPTY_LIST;
+        } else {
+            return (List) Collections.unmodifiableList(predecessors());
+        }
     }
 
     /**
@@ -196,7 +163,7 @@
      * @return the loop depth
      */
     public int loopDepth() {
-        return loopDepth;
+        return lirBlock.loopDepth;
     }
 
     /**
@@ -204,20 +171,7 @@
      * @return the loop index
      */
     public int loopIndex() {
-        return loopIndex;
-    }
-
-    /**
-     * Gets the exception handlers that cover one or more instructions of this basic block.
-     *
-     * @return the exception handlers
-     */
-    public List<BlockBegin> exceptionHandlerBlocks() {
-        return exceptionHandlerBlocks == null ? NO_HANDLERS : exceptionHandlerBlocks;
-    }
-
-    public List<FrameState> exceptionHandlerStates() {
-        return exceptionHandlerStates;
+        return lirBlock.loopIndex;
     }
 
     public void setDepthFirstNumber(int depthFirstNumber) {
@@ -230,11 +184,11 @@
     }
 
     public void setLoopDepth(int loopDepth) {
-        this.loopDepth = loopDepth;
+        this.lirBlock.loopDepth = loopDepth;
     }
 
     public void setLoopIndex(int loopIndex) {
-        this.loopIndex = loopIndex;
+        this.lirBlock.loopIndex = loopIndex;
     }
 
     /**
@@ -288,10 +242,27 @@
         BlockBegin block;
         while ((block = queue.poll()) != null) {
             closure.apply(block);
-            queueBlocks(queue, block.exceptionHandlerBlocks(), mark);
+
+            Instruction inst = block;
+            ArrayList<BlockBegin> excBlocks = new ArrayList<BlockBegin>();
+            while (inst != null) {
+                if (inst instanceof Invoke) {
+                    excBlocks.add(((Invoke) inst).exceptionEdge());
+                } else if (inst instanceof Throw) {
+                    excBlocks.add(((Throw) inst).exceptionEdge());
+                }
+                inst = inst.next();
+            }
+            while (excBlocks.remove(null)) {
+                // nothing
+            }
+            if (excBlocks.size() > 0) {
+                queueBlocks(queue, excBlocks, mark);
+            }
+
             queueBlocks(queue, block.end().blockSuccessors(), mark);
             if (predecessors) {
-                queueBlockEnds(queue, block.predecessors, mark);
+                queueBlockEnds(queue, block.blockPredecessors(), mark);
             }
         }
     }
@@ -307,10 +278,10 @@
         }
     }
 
-    private void queueBlockEnds(LinkedList<BlockBegin> queue, List<BlockEnd> list, IdentityHashMap<BlockBegin, BlockBegin> mark) {
+    private void queueBlockEnds(LinkedList<BlockBegin> queue, List<Instruction> list, IdentityHashMap<BlockBegin, BlockBegin> mark) {
         if (list != null) {
-            for (BlockEnd end : list) {
-                BlockBegin b = end.begin();
+            for (Instruction end : list) {
+                BlockBegin b = end.block();
                 if (!mark.containsKey(b)) {
                     queue.offer(b);
                     mark.put(b, b);
@@ -324,9 +295,27 @@
             mark.put(this, this);
             closure.apply(this);
             BlockEnd e = end();
-            if (exceptionHandlerBlocks != null) {
-                iterateReverse(mark, closure, exceptionHandlerBlocks);
+
+            Instruction inst = this;
+            ArrayList<BlockBegin> excBlocks = new ArrayList<BlockBegin>();
+            while (inst != null) {
+                if (inst instanceof Invoke) {
+                    excBlocks.add(((Invoke) inst).exceptionEdge());
+                } else if (inst instanceof Throw) {
+                    excBlocks.add(((Throw) inst).exceptionEdge());
+                }
+                inst = inst.next();
             }
+            while (excBlocks.remove(null)) {
+                // nothing
+            }
+            if (excBlocks.size() > 0) {
+                iterateReverse(mark, closure, excBlocks);
+            }
+
+//            if (exceptionHandlerBlocks != null) {
+//                iterateReverse(mark, closure, exceptionHandlerBlocks);
+//            }
             assert e != null : "block must have block end";
             iterateReverse(mark, closure, e.blockSuccessors());
         }
@@ -338,58 +327,6 @@
         }
     }
 
-    /**
-     * Adds an exception handler that covers one or more instructions in this block.
-     *
-     * @param handler the entry block for the exception handler to add
-     */
-    public void addExceptionHandler(BlockBegin handler) {
-        assert handler != null && handler.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry);
-        if (exceptionHandlerBlocks == null) {
-            exceptionHandlerBlocks = new ArrayList<BlockBegin>(3);
-            exceptionHandlerBlocks.add(handler);
-        } else if (!exceptionHandlerBlocks.contains(handler)) {
-            exceptionHandlerBlocks.add(handler);
-        }
-    }
-
-    /**
-     * Adds a frame state that merges into the exception handler whose entry is this block.
-     *
-     * @param state the frame state at an instruction that raises an exception that can be caught by the exception
-     *            handler represented by this block
-     * @return the index of {@code state} in the list of frame states merging at this block (i.e. the frames states for
-     *         all instruction throwing an exception caught by this exception handler)
-     */
-    public int addExceptionState(FrameState state) {
-        assert checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry);
-        if (exceptionHandlerStates == null) {
-            exceptionHandlerStates = new ArrayList<FrameState>(4);
-        }
-        exceptionHandlerStates.add(state);
-        return exceptionHandlerStates.size() - 1;
-    }
-
-    /**
-     * Add a predecessor to this block.
-     * @param pred the predecessor to add
-     */
-    public void addPredecessor(BlockEnd pred) {
-        assert pred != null;
-        predecessors.add(pred);
-    }
-
-    /**
-     * Removes all occurrences of the specified block from the predecessor list of this block.
-     * @param pred the predecessor to remove
-     */
-    public void removePredecessor(BlockEnd pred) {
-        while (predecessors.remove(pred)) {
-            // the block may appear multiple times in the list
-            // XXX: this is not very efficient, consider Util.removeAllFromList
-        }
-    }
-
     @Override
     public void accept(ValueVisitor v) {
         v.visitBlockBegin(this);
@@ -399,17 +336,11 @@
         FrameState existingState = stateBefore();
 
         if (existingState == null) {
-            // this is the first state for the block
-            if (wasVisited()) {
-                // this can happen for complex jsr/ret patterns; just bail out
-                throw new CiBailout("jsr/ret too complex");
-            }
-
             // copy state because it is modified
             FrameState duplicate = newState.duplicate(bci());
             assert duplicate.bci == bci() : "duplicate.bci=" + duplicate.bci + " my bci=" + bci();
 
-            if (C1XOptions.UseStackMapTableLiveness) {
+            if (C1XOptions.UseStackMapTableLiveness && method != null) {
                 // if a liveness map is available, use it to invalidate dead locals
                 CiBitMap[] livenessMap = method.livenessMap();
                 if (livenessMap != null && bci() >= 0) {
@@ -436,10 +367,6 @@
             assert existingState.localsSize() == newState.localsSize();
             assert existingState.stackSize() == newState.stackSize();
 
-            if (wasVisited() && !isParserLoopHeader()) {
-                throw new CiBailout("jsr/ret too complicated");
-            }
-
             existingState.merge(this, newState);
         }
     }
@@ -473,54 +400,6 @@
         }
     }
 
-    public boolean isBackwardBranchTarget() {
-        return checkBlockFlag(BlockFlag.BackwardBranchTarget);
-    }
-
-    public void setBackwardBranchTarget(boolean value) {
-        setBlockFlag(BlockFlag.BackwardBranchTarget, value);
-    }
-
-    public boolean isCriticalEdgeSplit() {
-        return checkBlockFlag(BlockFlag.CriticalEdgeSplit);
-    }
-
-    public void setCriticalEdgeSplit(boolean value) {
-        setBlockFlag(BlockFlag.CriticalEdgeSplit, value);
-    }
-
-    public boolean isExceptionEntry() {
-        return checkBlockFlag(BlockFlag.ExceptionEntry);
-    }
-
-    public void setExceptionEntry() {
-        setBlockFlag(BlockFlag.ExceptionEntry);
-    }
-
-    public boolean isSubroutineEntry() {
-        return checkBlockFlag(BlockFlag.SubroutineEntry);
-    }
-
-    public void setSubroutineEntry() {
-        setBlockFlag(BlockFlag.SubroutineEntry);
-    }
-
-    public boolean isOnWorkList() {
-        return checkBlockFlag(BlockFlag.IsOnWorkList);
-    }
-
-    public void setOnWorkList(boolean value) {
-        setBlockFlag(BlockFlag.IsOnWorkList, value);
-    }
-
-    public boolean wasVisited() {
-        return checkBlockFlag(BlockFlag.WasVisited);
-    }
-
-    public void setWasVisited(boolean value) {
-        setBlockFlag(BlockFlag.WasVisited, value);
-    }
-
     public boolean isParserLoopHeader() {
         return checkBlockFlag(BlockFlag.ParserLoopHeader);
     }
@@ -533,18 +412,10 @@
         return checkBlockFlag(BlockFlag.LinearScanLoopHeader);
     }
 
-    public void setLinearScanLoopHeader(boolean value) {
-        setBlockFlag(BlockFlag.LinearScanLoopHeader, value);
-    }
-
     public boolean isLinearScanLoopEnd() {
         return checkBlockFlag(BlockFlag.LinearScanLoopEnd);
     }
 
-    public void setLinearScanLoopEnd(boolean value) {
-        setBlockFlag(BlockFlag.LinearScanLoopEnd, value);
-    }
-
     private void setBlockFlag(BlockFlag flag, boolean value) {
         if (value) {
             setBlockFlag(flag);
@@ -553,13 +424,6 @@
         }
     }
 
-    public void copyBlockFlags(BlockBegin other) {
-        copyBlockFlag(other, BlockBegin.BlockFlag.ParserLoopHeader);
-        copyBlockFlag(other, BlockBegin.BlockFlag.SubroutineEntry);
-        copyBlockFlag(other, BlockBegin.BlockFlag.ExceptionEntry);
-        copyBlockFlag(other, BlockBegin.BlockFlag.WasVisited);
-    }
-
     @Override
     public String toString() {
         StringBuilder builder = new StringBuilder();
@@ -619,8 +483,12 @@
      * @return the number of predecessors
      */
     public int numberOfPreds() {
-//        assert predecessors.size() == predecessors().size();
-        return predecessors.size();
+        // ignore the graph root
+        if (predecessors().size() == 1 && predecessors().get(0) == graph().root()) {
+            return 0;
+        } else {
+            return predecessors().size();
+        }
     }
 
     /**
@@ -639,52 +507,24 @@
     }
 
     public LIRBlock lirBlock() {
-        if (lirBlock == null) {
-            lirBlock = new LIRBlock();
-        }
         return lirBlock;
     }
 
-    public int exceptionHandlerPco() {
-        return lirBlock == null ? 0 : lirBlock.exceptionHandlerPCO;
+    public int blockEntryPco() {
+        return lirBlock == null ? 0 : lirBlock.blockEntryPco;
     }
 
-    public void setExceptionHandlerPco(int codeOffset) {
-        lirBlock().exceptionHandlerPCO = codeOffset;
-    }
-
-    public int numberOfExceptionHandlers() {
-        return exceptionHandlerBlocks == null ? 0 : exceptionHandlerBlocks.size();
-    }
-
-    public BlockBegin exceptionHandlerAt(int i) {
-        return exceptionHandlerBlocks.get(i);
+    public void setBlockEntryPco(int codeOffset) {
+        lirBlock().blockEntryPco = codeOffset;
     }
 
-    public BlockEnd predAt(int j) {
-//        assert predecessors.get(j) == predecessors().get(j);
-        return predecessors.get(j);
-    }
-
-    public int firstLirInstructionId() {
-        return lirBlock.firstLirInstructionID;
+    public Instruction predAt(int j) {
+        return (Instruction) predecessors().get(j);
     }
 
-    public void setFirstLirInstructionId(int firstLirInstructionId) {
-        lirBlock.firstLirInstructionID = firstLirInstructionId;
-    }
 
-    public int lastLirInstructionId() {
-        return lirBlock.lastLirInstructionID;
-    }
-
-    public void setLastLirInstructionId(int lastLirInstructionId) {
-        lirBlock.lastLirInstructionID = lastLirInstructionId;
-    }
-
-    public boolean isPredecessor(BlockEnd block) {
-//        assert predecessors.contains(block) == predecessors().contains(block);
-        return predecessors.contains(block);
+    public boolean isPredecessor(Instruction block) {
+        return predecessors().contains(block);
     }
 
     public void printWithoutPhis(LogStream out) {
@@ -694,21 +534,9 @@
 
         // print flags
         StringBuilder sb = new StringBuilder(8);
-        if (isExceptionEntry()) {
-            sb.append('E');
-        }
-        if (isSubroutineEntry()) {
-            sb.append('s');
-        }
         if (isParserLoopHeader()) {
             sb.append("LH");
         }
-        if (isBackwardBranchTarget()) {
-            sb.append('b');
-        }
-        if (wasVisited()) {
-            sb.append('V');
-        }
         if (sb.length() != 0) {
             out.print('(').print(sb.toString()).print(')');
         }
@@ -723,25 +551,12 @@
                 out.print(" B").print(successor.blockID);
             }
         }
-        // print exception handlers
-        if (!exceptionHandlers().isEmpty()) {
-            out.print(" (xhandlers");
-            for (BlockBegin handler : exceptionHandlerBlocks()) {
-                out.print(" B").print(handler.blockID);
-            }
-            out.print(')');
-        }
-
-        // print dominator block
-        if (dominator() != null) {
-            out.print(" dom B").print(dominator().blockID);
-        }
 
         // print predecessors
         if (!blockPredecessors().isEmpty()) {
             out.print(" pred:");
-            for (BlockEnd pred : blockPredecessors()) {
-                out.print(" B").print(pred.begin().blockID);
+            for (Instruction pred : blockPredecessors()) {
+                out.print(" B").print(pred.block().blockID);
             }
         }
     }
@@ -874,5 +689,34 @@
         return "BlockBegin #" + blockID;
     }
 
+    /**
+     * Iterates over all successors of this block: successors of the end node and exception handler.
+     */
+    public void allSuccessorsDo(boolean backwards, BlockClosure closure) {
+        if (backwards) {
+            for (int i = numberOfSux() - 1; i >= 0; i--) {
+                closure.apply(suxAt(i));
+            }
+        } else {
+            for (int i = 0; i < numberOfSux(); i++) {
+                closure.apply(suxAt(i));
+            }
+        }
+        for (Instruction x = next(); x != null; x = x.next()) {
+            if (x instanceof Invoke && ((Invoke) x).exceptionEdge() != null) {
+                closure.apply(((Invoke) x).exceptionEdge());
+            } else if (x instanceof Throw && ((Throw) x).exceptionEdge() != null) {
+                closure.apply(((Throw) x).exceptionEdge());
+            }
+        }
+    }
+
+    public void verifyPredecessors() {
+        for (int i = 0; i < numberOfPreds(); i++) {
+            predAt(i);
+        }
+
+    }
+
 
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/BlockEnd.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/BlockEnd.java	Thu May 19 11:43:30 2011 +0200
@@ -181,10 +181,16 @@
      * Gets this block end's list of successors.
      * @return the successor list
      */
-    @SuppressWarnings("unchecked")
+    @SuppressWarnings({ "unchecked", "rawtypes"})
     public List<BlockBegin> blockSuccessors() {
         List<BlockBegin> list = (List) successors().subList(super.successorCount() + SUCCESSOR_COUNT, super.successorCount() + blockSuccessorCount + SUCCESSOR_COUNT);
         return Collections.unmodifiableList(list);
     }
 
+    public void clearSuccessors() {
+        for (int i = 0; i < blockSuccessorCount(); i++) {
+            setBlockSuccessor(i, null);
+        }
+    }
+
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/ComputeLinearScanOrder.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/ComputeLinearScanOrder.java	Thu May 19 11:43:30 2011 +0200
@@ -126,7 +126,6 @@
         }
 
         computeOrder(startBlock);
-        computeDominators();
 
         printBlocks();
         assert verify();
@@ -140,11 +139,10 @@
      * 3. Number loop header blocks.
      * 4. Create a list with all loop end blocks.
      */
-    private void countEdges(BlockBegin cur, BlockBegin parent) {
+    private void countEdges(final BlockBegin cur, BlockBegin parent) {
         if (C1XOptions.TraceLinearScanLevel >= 3) {
             TTY.println("Counting edges for block B%d%s", cur.blockID, parent == null ? "" : " coming from B" + parent.blockID);
         }
-        assert cur.dominator() == null : "dominator already initialized";
 
         if (isActive(cur)) {
             if (C1XOptions.TraceLinearScanLevel >= 3) {
@@ -158,15 +156,6 @@
 
             parent.setBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd);
 
-            // 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.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry)) {
-                // Make sure that dominators are correct in this weird situation
-                iterativeDominators = true;
-                return;
-            }
-
             loopEndBlocks.add(parent);
             return;
         }
@@ -186,13 +175,11 @@
         setActive(cur);
 
         // recursive call for all successors
-        int i;
-        for (i = cur.numberOfSux() - 1; i >= 0; i--) {
-            countEdges(cur.suxAt(i), cur);
-        }
-        for (i = cur.numberOfExceptionHandlers() - 1; i >= 0; i--) {
-            countEdges(cur.exceptionHandlerAt(i), cur);
-        }
+        cur.allSuccessorsDo(true, new BlockClosure() {
+            public void apply(BlockBegin block) {
+                countEdges(block, cur);
+            }
+        });
 
         clearActive(cur);
 
@@ -231,8 +218,8 @@
             if (C1XOptions.TraceLinearScanLevel >= 3) {
                 TTY.println("Processing loop from B%d to B%d (loop %d):", loopStart.blockID, loopEnd.blockID, loopIdx);
             }
-            assert loopEnd.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd) : "loop end flag must be set";
-            assert loopStart.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader) : "loop header flag must be set";
+            assert loopEnd.isLinearScanLoopEnd() : "loop end flag must be set";
+            assert loopStart.isLinearScanLoopHeader() : "loop header flag must be set";
             assert loopIdx >= 0 && loopIdx < numLoops : "loop index not set";
             assert workList.isEmpty() : "work list must be empty before processing";
 
@@ -250,7 +237,7 @@
                 // recursive processing of all predecessors ends when start block of loop is reached
                 if (cur != loopStart) {
                     for (int j = cur.numberOfPreds() - 1; j >= 0; j--) {
-                        BlockBegin pred = cur.predAt(j).begin();
+                        BlockBegin pred = cur.predAt(j).block();
 
                         if (!isBlockInLoop(loopIdx, pred)) {
                             // this predecessor has not been processed yet, so add it to work list
@@ -319,55 +306,15 @@
                 cur.setLoopIndex(minLoopIdx);
 
                 // append all unvisited successors to work list
-                for (i = cur.numberOfSux() - 1; i >= 0; i--) {
-                    workList.add(cur.suxAt(i));
-                }
-                for (i = cur.numberOfExceptionHandlers() - 1; i >= 0; i--) {
-                    workList.add(cur.exceptionHandlerAt(i));
-                }
+                cur.allSuccessorsDo(true, new BlockClosure() {
+                    public void apply(BlockBegin block) {
+                        workList.add(block);
+                    }
+                });
             }
         } while (!workList.isEmpty());
     }
 
-    private BlockBegin commonDominator(BlockBegin a, BlockBegin b) {
-        assert a != null && b != null : "must have input blocks";
-
-        dominatorBlocks.clearAll();
-        while (a != null) {
-            dominatorBlocks.set(a.blockID);
-            assert a.dominator() != null || a == linearScanOrder.get(0) : "dominator must be initialized";
-            a = a.dominator();
-        }
-        while (b != null && !dominatorBlocks.get(b.blockID)) {
-            assert b.dominator() != null || b == linearScanOrder.get(0) : "dominator must be initialized";
-            b = b.dominator();
-        }
-
-        assert b != null : "could not find dominator";
-        return b;
-    }
-
-    private void computeDominator(BlockBegin cur, BlockBegin parent) {
-        if (cur.dominator() == null) {
-            if (C1XOptions.TraceLinearScanLevel >= 4) {
-                TTY.println("DOM: initializing dominator of B%d to B%d", cur.blockID, parent.blockID);
-            }
-            if (cur.isExceptionEntry()) {
-                assert parent.dominator() != null;
-                cur.setDominator(parent.dominator());
-            } else {
-                cur.setDominator(parent);
-            }
-
-        } else if (!(cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader) && parent.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd))) {
-            if (C1XOptions.TraceLinearScanLevel >= 4) {
-                TTY.println("DOM: computing dominator of B%d: common dominator of B%d and B%d is B%d", cur.blockID, parent.blockID, cur.dominator().blockID, commonDominator(cur.dominator(), parent).blockID);
-            }
-            assert cur.numberOfPreds() > 1 : "";
-            cur.setDominator(commonDominator(cur.dominator(), parent));
-        }
-    }
-
     private int computeWeight(BlockBegin cur) {
         BlockBegin singleSux = null;
         if (cur.numberOfSux() == 1) {
@@ -382,21 +329,14 @@
         // this is necessary for the (very rare) case that two successive blocks have
         // the same loop depth, but a different loop index (can happen for endless loops
         // with exception handlers)
-        if (!cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader)) {
+        if (!cur.isLinearScanLoopHeader()) {
             weight |= (1 << curBit);
         }
         curBit--;
 
         // loop end blocks (blocks that end with a backward branch) are added
         // after all other blocks of the loop.
-        if (!cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd)) {
-            weight |= (1 << curBit);
-        }
-        curBit--;
-
-        // critical edge split blocks are preferred because then they have a greater
-        // probability to be completely empty
-        if (cur.isCriticalEdgeSplit()) {
+        if (!cur.isLinearScanLoopEnd()) {
             weight |= (1 << curBit);
         }
         curBit--;
@@ -412,10 +352,10 @@
         }
         curBit--;
 
-        // exceptions handlers are added as late as possible
-        if (!cur.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry)) {
-            weight |= (1 << curBit);
-        }
+//        // exceptions handlers are added as late as possible
+//        if (!cur.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry)) {
+//            weight |= (1 << curBit);
+//        }
         curBit--;
 
         // guarantee that weight is > 0
@@ -505,85 +445,19 @@
         }
 
         do {
-            BlockBegin cur = workList.remove(workList.size() - 1);
+            final BlockBegin cur = workList.remove(workList.size() - 1);
             appendBlock(cur);
 
-            int i;
-            int numSux = cur.numberOfSux();
-            // changed loop order to get "intuitive" order of if- and else-blocks
-            for (i = 0; i < numSux; i++) {
-                BlockBegin sux = cur.suxAt(i);
-                computeDominator(sux, cur);
-                if (readyForProcessing(sux)) {
-                    sortIntoWorkList(sux);
+            cur.allSuccessorsDo(false, new BlockClosure() {
+                public void apply(BlockBegin block) {
+                    if (readyForProcessing(block)) {
+                        sortIntoWorkList(block);
+                    }
                 }
-            }
-            numSux = cur.numberOfExceptionHandlers();
-            for (i = 0; i < numSux; i++) {
-                BlockBegin sux = cur.exceptionHandlerAt(i);
-                computeDominator(sux, cur);
-                if (readyForProcessing(sux)) {
-                    sortIntoWorkList(sux);
-                }
-            }
+            });
         } while (workList.size() > 0);
     }
 
-    private boolean computeDominatorsIter() {
-        boolean changed = false;
-        int numBlocks = linearScanOrder.size();
-
-        assert linearScanOrder.get(0).dominator() == null : "must not have dominator";
-        assert linearScanOrder.get(0).numberOfPreds() == 0 : "must not have predecessors";
-        for (int i = 1; i < numBlocks; i++) {
-            BlockBegin block = linearScanOrder.get(i);
-
-            assert block.numberOfPreds() > 0;
-            BlockBegin dominator = block.predAt(0).begin();
-            if (block.isExceptionEntry()) {
-                dominator = dominator.dominator();
-            }
-
-            int numPreds = block.numberOfPreds();
-            for (int j = 1; j < numPreds; j++) {
-                BlockBegin curPred = block.predAt(j).begin();
-                if (block.isExceptionEntry()) {
-                    curPred = curPred.dominator();
-                }
-                dominator = commonDominator(dominator, curPred);
-            }
-
-            if (dominator != block.dominator()) {
-                if (C1XOptions.TraceLinearScanLevel >= 4) {
-                    TTY.println("DOM: updating dominator of B%d from B%d to B%d", block.blockID, block.dominator().blockID, dominator.blockID);
-                }
-                block.setDominator(dominator);
-                changed = true;
-            }
-        }
-        return changed;
-    }
-
-    private void computeDominators() {
-        if (C1XOptions.TraceLinearScanLevel >= 3) {
-            TTY.println("----- computing dominators (iterative computation required: %b)", iterativeDominators);
-        }
-
-        // iterative computation of dominators is only required for methods with non-natural loops
-        // and OSR-methods. For all other methods : the dominators computed when generating the
-        // linear scan block order are correct.
-        if (iterativeDominators) {
-            do {
-                if (C1XOptions.TraceLinearScanLevel >= 1) {
-                    TTY.println("DOM: next iteration of fix-point calculation");
-                }
-            } while (computeDominatorsIter());
-        }
-
-        // check that dominators are correct
-        assert !computeDominatorsIter() : "fix point not reached";
-    }
-
     public void printBlocks() {
         if (C1XOptions.TraceLinearScanLevel >= 2) {
             TTY.println("----- loop information:");
@@ -601,21 +475,13 @@
             for (BlockBegin 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.isCriticalEdgeSplit() ? " ce" : "   ");
-                TTY.print(cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader) ? " lh" : "   ");
-                TTY.print(cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd) ? " le" : "   ");
-
-                if (cur.dominator() != null) {
-                    TTY.print("    dom: B%d ", cur.dominator().blockID);
-                } else {
-                    TTY.print("    dom: null ");
-                }
+                TTY.print(cur.isLinearScanLoopHeader() ? " lh" : "   ");
+                TTY.print(cur.isLinearScanLoopEnd() ? " le" : "   ");
 
                 if (cur.numberOfPreds() > 0) {
                     TTY.print("    preds: ");
                     for (int j = 0; j < cur.numberOfPreds(); j++) {
-                        BlockBegin pred = cur.predAt(j).begin();
+                        BlockBegin pred = cur.predAt(j).block();
                         TTY.print("B%d ", pred.blockID);
                     }
                 }
@@ -626,13 +492,6 @@
                         TTY.print("B%d ", sux.blockID);
                     }
                 }
-                if (cur.numberOfExceptionHandlers() > 0) {
-                    TTY.print("    ex: ");
-                    for (int j = 0; j < cur.numberOfExceptionHandlers(); j++) {
-                        BlockBegin ex = cur.exceptionHandlerAt(j);
-                        TTY.print("B%d ", ex.blockID);
-                    }
-                }
                 TTY.println();
             }
         }
@@ -666,8 +525,8 @@
                 }
             }
 
-            for (BlockEnd pred : cur.blockPredecessors()) {
-                BlockBegin begin = pred.begin();
+            for (Instruction pred : cur.blockPredecessors()) {
+                BlockBegin begin = pred.block();
                 assert begin.linearScanNumber() >= 0 && begin.linearScanNumber() == linearScanOrder.indexOf(begin) : "incorrect linearScanNumber";
                 if (!cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader)) {
                     assert cur.linearScanNumber() > begin.linearScanNumber() : "invalid order";
@@ -675,17 +534,7 @@
                 if (cur.loopDepth() == begin.loopDepth()) {
                     assert cur.loopIndex() == begin.loopIndex() || cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader) : "successing blocks with same loop depth must have same loop index";
                 }
-
-                assert cur.dominator().linearScanNumber() <= begin.linearScanNumber() : "dominator must be before predecessors";
             }
-
-            // check dominator
-            if (i == 0) {
-                assert cur.dominator() == null : "first block has no dominator";
-            } else {
-                assert cur.dominator() != null : "all but first block must have dominator";
-            }
-            assert cur.numberOfPreds() != 1 || cur.dominator() == cur.predAt(0).begin() || cur.isExceptionEntry() : "Single predecessor must also be dominator";
         }
 
         // check that all loops are continuous
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/ExceptionDispatch.java	Thu May 19 11:43:30 2011 +0200
@@ -0,0 +1,143 @@
+/*
+ * 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.*;
+
+/**
+ * This instruction takes an exception object and has two successors:
+ * The catchSuccessor is called whenever the exception matches the given type, otherwise otherSuccessor is called.
+ */
+public final class ExceptionDispatch extends BlockEnd {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_EXCEPTION = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction producing the exception object.
+     */
+     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);
+    }
+
+    private final ExceptionHandler handler;
+
+    /**
+     * Constructs a new ExceptionDispatch instruction.
+     */
+    public ExceptionDispatch(Value exception, BlockBegin catchSuccessor, BlockBegin otherSuccessor, ExceptionHandler handler, FrameState stateAfter, boolean isSafepoint, Graph graph) {
+        super(CiKind.Int, stateAfter, isSafepoint, 2, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setException(exception);
+        setBlockSuccessor(0, otherSuccessor);
+        setBlockSuccessor(1, catchSuccessor);
+        this.handler = handler;
+    }
+
+    public ExceptionHandler handler() {
+        return handler;
+    }
+
+    /**
+     * Gets the block corresponding to the catch block.
+     * @return the true successor
+     */
+    public BlockBegin catchSuccessor() {
+        return blockSuccessor(1);
+    }
+
+    /**
+     * Gets the block corresponding to the rest of the dispatch chain.
+     * @return the false successor
+     */
+    public BlockBegin otherSuccessor() {
+        return blockSuccessor(0);
+    }
+
+    /**
+     * Gets the block corresponding to the specified outcome of the branch.
+     * @param istrue {@code true} if the true successor is requested, {@code false} otherwise
+     * @return the corresponding successor
+     */
+    public BlockBegin successor(boolean istrue) {
+        return blockSuccessor(istrue ? 1 : 0);
+    }
+
+    /**
+     * Swaps the successor blocks to this if and negates the condition (e.g. == goes to !=)
+     * @see Condition#negate()
+     */
+    public void swapSuccessors() {
+        BlockBegin t = blockSuccessor(0);
+        BlockBegin f = blockSuccessor(1);
+        setBlockSuccessor(0, f);
+        setBlockSuccessor(1, t);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitExceptionDispatch(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("exception_dispatch ").
+        print(exception()).
+        print(' ').
+        print("instanceof").
+        print(' ').
+        print(handler.handler.catchType().name()).
+        print(" then B").
+        print(blockSuccessors().get(1).blockID).
+        print(" else B").
+        print(blockSuccessors().get(0).blockID);
+        if (isSafepoint()) {
+            out.print(" (safepoint)");
+        }
+    }
+
+    @Override
+    public String shortName() {
+        return "Dispatch " + handler.handler.catchType().name();
+    }
+
+
+}
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Instruction.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Instruction.java	Thu May 19 11:43:30 2011 +0200
@@ -79,11 +79,6 @@
      */
     private int bci;
 
-    /**
-     * List of associated exception handlers.
-     */
-    private List<ExceptionHandler> exceptionHandlers = ExceptionHandler.ZERO_HANDLERS;
-
     private boolean isAppended = false;
 
     /**
@@ -185,22 +180,6 @@
     }
 
     /**
-     * Gets the list of exception handlers associated with this instruction.
-     * @return the list of exception handlers for this instruction
-     */
-    public final List<ExceptionHandler> exceptionHandlers() {
-        return exceptionHandlers;
-    }
-
-    /**
-     * Sets the list of exception handlers for this instruction.
-     * @param exceptionHandlers the exception handlers
-     */
-    public final void setExceptionHandlers(List<ExceptionHandler> exceptionHandlers) {
-        this.exceptionHandlers = exceptionHandlers;
-    }
-
-    /**
      * Compute the value number of this Instruction. Local and global value numbering
      * optimizations use a hash map, and the value number provides a hash code.
      * If the instruction cannot be value numbered, then this method should return
@@ -247,4 +226,8 @@
     public FrameState stateAfter() {
         return null;
     }
+
+    public BlockBegin exceptionEdge() {
+        return null;
+    }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Invoke.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Invoke.java	Thu May 19 11:43:30 2011 +0200
@@ -36,7 +36,8 @@
 
     private final int argumentCount;
 
-    private static final int SUCCESSOR_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 1;
+    private static final int SUCCESSOR_EXCEPTION_EDGE = 0;
 
     @Override
     protected int inputCount() {
@@ -65,6 +66,18 @@
         return argumentCount;
     }
 
+    /**
+     * The entry to the exception dispatch chain for this invoke.
+     */
+    @Override
+    public BlockBegin exceptionEdge() {
+        return (BlockBegin) successors().get(super.successorCount() + SUCCESSOR_EXCEPTION_EDGE);
+    }
+
+    public BlockBegin setExceptionEdge(BlockBegin n) {
+        return (BlockBegin) successors().set(super.successorCount() + SUCCESSOR_EXCEPTION_EDGE, n);
+    }
+
     public final int opcode;
     public final RiMethod target;
     public final RiType returnType;
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java	Thu May 19 11:43:30 2011 +0200
@@ -116,13 +116,7 @@
      * @return the instruction that produced the value in the i'th predecessor
      */
     public Value inputAt(int i) {
-        FrameState state;
-        if (block().isExceptionEntry()) {
-            state = block().exceptionHandlerStates().get(i);
-        } else {
-            state = block().blockPredecessors().get(i).stateAfter();
-        }
-        return inputIn(state);
+        return inputIn(block().blockPredecessors().get(i).stateAfter());
     }
 
     /**
@@ -143,11 +137,7 @@
      * @return the number of inputs in this phi
      */
     public int phiInputCount() {
-        if (block().isExceptionEntry()) {
-            return block().exceptionHandlerStates().size();
-        } else {
-            return block().blockPredecessors().size();
-        }
+        return block().blockPredecessors().size();
     }
 
     @Override
@@ -170,7 +160,7 @@
 
     @Override
     public String shortName() {
-        return "Phi: " + index;
+        return "Phi: " + index + " (" + phiInputCount() + ")";
     }
 
 
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/StateSplit.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/StateSplit.java	Thu May 19 11:43:30 2011 +0200
@@ -32,11 +32,11 @@
  */
 public abstract class StateSplit extends Instruction {
 
-    private static final int INPUT_COUNT = 2;
-    private static final int INPUT_STATE_AFTER = 0;
-    private static final int INPUT_STATE_BEFORE = 1;
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_STATE_BEFORE = 0;
 
-    private static final int SUCCESSOR_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 1;
+    private static final int SUCCESSOR_STATE_AFTER = 0;
 
     @Override
     protected int inputCount() {
@@ -51,22 +51,6 @@
     /**
      * The state for this instruction.
      */
-     @Override
-    public FrameState stateAfter() {
-        return (FrameState) inputs().get(super.inputCount() + INPUT_STATE_AFTER);
-    }
-
-    public FrameState setStateAfter(FrameState n) {
-        if (n != null && this instanceof BlockBegin) {
-            Exception e = new Exception();
-            e.printStackTrace();
-        }
-        return (FrameState) inputs().set(super.inputCount() + INPUT_STATE_AFTER, n);
-    }
-
-    /**
-     * The state for this instruction.
-     */
     public FrameState stateBefore() {
         return (FrameState) inputs().get(super.inputCount() + INPUT_STATE_BEFORE);
     }
@@ -76,6 +60,18 @@
     }
 
     /**
+     * The state for this instruction.
+     */
+     @Override
+    public FrameState stateAfter() {
+        return (FrameState) successors().get(super.successorCount() + SUCCESSOR_STATE_AFTER);
+    }
+
+    public FrameState setStateAfter(FrameState n) {
+        return (FrameState) successors().set(super.successorCount() + SUCCESSOR_STATE_AFTER, n);
+    }
+
+    /**
      * Creates a new state split with the specified value type.
      * @param kind the type of the value that this instruction produces
      * @param inputCount
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Throw.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Throw.java	Thu May 19 11:43:30 2011 +0200
@@ -36,7 +36,8 @@
     private static final int INPUT_EXCEPTION = 0;
     private static final int INPUT_STATE_BEFORE = 1;
 
-    private static final int SUCCESSOR_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 1;
+    private static final int SUCCESSOR_EXCEPTION_EDGE = 0;
 
     @Override
     protected int inputCount() {
@@ -71,6 +72,19 @@
     }
 
     /**
+     * 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 BlockBegin exceptionEdge() {
+        return (BlockBegin) successors().get(super.successorCount() + SUCCESSOR_EXCEPTION_EDGE);
+    }
+
+    public BlockBegin setExceptionEdge(BlockBegin n) {
+        return (BlockBegin) 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Unwind.java	Thu May 19 11:43:30 2011 +0200
@@ -0,0 +1,75 @@
+/*
+ * 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.c1x.ir;
+
+import com.oracle.graal.graph.*;
+import com.sun.c1x.debug.*;
+import com.sun.cri.ci.*;
+
+/**
+ * Unwind takes an exception object, destroys the current stack frame and passes the exception object to the system's exception dispatch code.
+ */
+public final class Unwind extends BlockEnd {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_EXCEPTION = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction that produces the exception object.
+     */
+     public Value exception() {
+        return (Value) inputs().get(super.inputCount() + INPUT_EXCEPTION);
+    }
+
+    public Value setException(Value n) {
+        assert n == null || n.kind == CiKind.Object;
+        return (Value) inputs().set(super.inputCount() + INPUT_EXCEPTION, n);
+    }
+
+    public Unwind(Value exception, boolean isSafepoint, Graph graph) {
+        super(CiKind.Object, null, isSafepoint, 0, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setException(exception);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitUnwind(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(kind.typeChar).print("unwind ").print(exception());
+    }
+}
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Value.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Value.java	Thu May 19 11:43:30 2011 +0200
@@ -24,7 +24,6 @@
 
 import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
-import com.sun.c1x.opt.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
 
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java	Thu May 19 11:43:30 2011 +0200
@@ -68,4 +68,6 @@
     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	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIRAssembler.java	Thu May 19 11:43:30 2011 +0200
@@ -96,35 +96,6 @@
 
     public abstract void emitTraps();
 
-    public void emitExceptionEntries() {
-        if (tasm.exceptionInfoList == null) {
-            return;
-        }
-        for (ExceptionInfo ilist : tasm.exceptionInfoList) {
-            List<ExceptionHandler> handlers = ilist.exceptionHandlers;
-
-            for (ExceptionHandler handler : handlers) {
-                assert handler.lirOpId() != -1 : "handler not processed by LinearScan";
-                assert handler.entryCode() == null || handler.entryCode().instructionsList().get(handler.entryCode().instructionsList().size() - 1).code == LIROpcode.Branch : "last operation must be branch";
-
-                if (handler.entryCodeOffset() == -1) {
-                    // entry code not emitted yet
-                    if (handler.entryCode() != null && handler.entryCode().instructionsList().size() > 1) {
-                        handler.setEntryCodeOffset(codePos());
-                        if (C1XOptions.CommentedAssembly) {
-                            tasm.blockComment("Exception adapter block");
-                        }
-                        emitLirList(handler.entryCode());
-                    } else {
-                        handler.setEntryCodeOffset(handler.entryBlock().exceptionHandlerPco());
-                    }
-
-                    assert handler.entryCodeOffset() != -1 : "must be set now";
-                }
-            }
-        }
-    }
-
     public void emitCode(List<BlockBegin> hir) {
         if (C1XOptions.PrintLIR && !TTY.isSuppressed()) {
             LIRList.printLIR(hir);
@@ -138,16 +109,8 @@
     }
 
     void emitBlock(BlockBegin block) {
-        if (block.checkBlockFlag(BlockBegin.BlockFlag.BackwardBranchTarget)) {
-            emitAlignment();
-        }
 
-        // if this block is the start of an exception handler, record the
-        // PC offset of the first instruction for later construction of
-        // the ExceptionHandlerTable
-        if (block.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry)) {
-            block.setExceptionHandlerPco(codePos());
-        }
+        block.setBlockEntryPco(codePos());
 
         if (C1XOptions.PrintLIRWithAssembly) {
             block.printWithoutPhis(TTY.out());
@@ -290,18 +253,6 @@
         switch (op.code) {
             case Label:
                 throw Util.shouldNotReachHere();
-            case OsrEntry:
-                emitOsrEntry();
-                break;
-            case Here:
-                emitHere(op.result(), op.info, false);
-                break;
-            case Info:
-                emitHere(op.result(), op.info, true);
-                break;
-            case Pause:
-                emitPause();
-                break;
             case Breakpoint:
                 emitBreakpoint();
                 break;
@@ -446,12 +397,8 @@
 
     protected abstract void emitNegate(LIRNegate negate);
 
-    protected abstract void emitHere(CiValue dst, LIRDebugInfo info, boolean infoOnly);
-
     protected abstract void emitMonitorAddress(int monitor, CiValue dst);
 
-    protected abstract void emitPause();
-
     protected abstract void emitStackAllocate(StackBlock src, CiValue dst);
 
     protected abstract void emitReturn(CiValue inOpr);
@@ -504,8 +451,6 @@
 
     protected abstract void emitMemoryBarriers(int barriers);
 
-    protected abstract void emitOsrEntry();
-
     protected abstract void reg2stack(CiValue src, CiValue dest, CiKind kind);
 
     protected abstract void reg2mem(CiValue src, CiValue dest, CiKind kind, LIRDebugInfo info, boolean unaligned);
--- a/graal/GraalCompiler/src/com/sun/c1x/lir/LIRBlock.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIRBlock.java	Thu May 19 11:43:30 2011 +0200
@@ -28,12 +28,11 @@
 
 /**
  * The {@code LIRBlock} class definition.
- *
- * @author Ben L. Titzer
  */
 public final class LIRBlock {
 
     public LIRBlock() {
+        loopIndex = -1;
     }
 
     public final Label label = new Label();
@@ -68,9 +67,28 @@
      */
     public CiBitMap liveKill;
 
-    public int firstLirInstructionID;
-    public int lastLirInstructionID;
-    public int exceptionHandlerPCO;
+    private int firstLirInstructionID;
+    private int lastLirInstructionID;
+    public int blockEntryPco;
+
+    public int firstLirInstructionId() {
+        return firstLirInstructionID;
+    }
+
+    public void setFirstLirInstructionId(int firstLirInstructionId) {
+        this.firstLirInstructionID = firstLirInstructionId;
+    }
+
+    public int lastLirInstructionId() {
+        return lastLirInstructionID;
+    }
+
+    public void setLastLirInstructionId(int lastLirInstructionId) {
+        this.lastLirInstructionID = lastLirInstructionId;
+    }
+
+    public int loopDepth;
+    public int loopIndex;
 
     public LIRList lir() {
         return lir;
--- a/graal/GraalCompiler/src/com/sun/c1x/lir/LIRDebugInfo.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIRDebugInfo.java	Thu May 19 11:43:30 2011 +0200
@@ -31,10 +31,6 @@
 
 /**
  * This class represents debugging and deoptimization information attached to a LIR instruction.
- *
- * @author Marcelo Cintra
- * @author Thomas Wuerthinger
- * @author Ben L. Titzer
  */
 public class LIRDebugInfo {
 
@@ -43,27 +39,18 @@
     }
 
     public final FrameState state;
-    public final List<ExceptionHandler> exceptionHandlers;
+    public final BlockBegin exceptionEdge;
     public CiDebugInfo debugInfo;
 
-    public LIRDebugInfo(FrameState state, List<ExceptionHandler> exceptionHandlers) {
+    public LIRDebugInfo(FrameState state, BlockBegin exceptionEdge) {
         assert state != null;
         this.state = state;
-        this.exceptionHandlers = exceptionHandlers;
+        this.exceptionEdge = exceptionEdge;
     }
 
     private LIRDebugInfo(LIRDebugInfo info) {
         this.state = info.state;
-
-        // deep copy of exception handlers
-        if (info.exceptionHandlers != null) {
-            this.exceptionHandlers = new ArrayList<ExceptionHandler>(info.exceptionHandlers.size());
-            for (ExceptionHandler h : info.exceptionHandlers) {
-                this.exceptionHandlers.add(new ExceptionHandler(h));
-            }
-        } else {
-            this.exceptionHandlers = null;
-        }
+        this.exceptionEdge = info.exceptionEdge;
     }
 
     public LIRDebugInfo copy() {
--- a/graal/GraalCompiler/src/com/sun/c1x/lir/LIRInstruction.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIRInstruction.java	Thu May 19 11:43:30 2011 +0200
@@ -483,12 +483,8 @@
         }
     }
 
-    public final List<ExceptionHandler> exceptionEdges() {
-        if (info != null && info.exceptionHandlers != null) {
-            return info.exceptionHandlers;
-        }
-
-        return Collections.emptyList();
+    public final BlockBegin exceptionEdge() {
+        return info.exceptionEdge;
     }
 
     @Override
--- a/graal/GraalCompiler/src/com/sun/c1x/lir/LIRList.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIRList.java	Thu May 19 11:43:30 2011 +0200
@@ -31,7 +31,6 @@
 import com.sun.c1x.gen.*;
 import com.sun.c1x.globalstub.*;
 import com.sun.c1x.ir.*;
-import com.sun.c1x.lir.FrameMap.StackBlock;
 import com.sun.cri.ci.*;
 import com.sun.cri.ci.CiTargetMethod.Mark;
 import com.sun.cri.ri.*;
@@ -101,10 +100,6 @@
         append(new LIRMemoryBarrier(barriers));
     }
 
-    public void osrEntry(CiValue osrPointer) {
-        append(new LIROp0(LIROpcode.OsrEntry, osrPointer));
-    }
-
     public void branchDestination(Label lbl) {
         append(new LIRLabel(lbl));
     }
@@ -155,14 +150,6 @@
         append(new LIRMonitorAddress(dst, monitor));
     }
 
-    public void infopoint(LIROpcode opcode, CiValue dst, LIRDebugInfo info) {
-        append(new LIROp0(opcode, dst, info));
-    }
-
-    public void alloca(StackBlock stackBlock, CiValue dst) {
-        append(new LIRStackAllocate(dst, stackBlock));
-    }
-
     public void convert(int code, CiValue left, CiValue dst, GlobalStub globalStub) {
         LIRConvert op = new LIRConvert(code, left, dst);
         op.globalStub = globalStub;
@@ -303,10 +290,6 @@
         append(new LIRCall(runtimeCallOp, rtCall, result, arguments, info, null, false, null));
     }
 
-    public void pause() {
-        append(new LIROp0(LIROpcode.Pause));
-    }
-
     public void breakpoint() {
         append(new LIROp0(LIROpcode.Breakpoint));
     }
@@ -411,19 +394,10 @@
         TTY.print("B%d ", x.blockID);
 
         // print flags
-        if (x.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry)) {
-            TTY.print("ex ");
-        }
-        if (x.checkBlockFlag(BlockBegin.BlockFlag.SubroutineEntry)) {
-            TTY.print("jsr ");
-        }
-        if (x.checkBlockFlag(BlockBegin.BlockFlag.BackwardBranchTarget)) {
-            TTY.print("bb ");
-        }
-        if (x.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader)) {
+        if (x.isLinearScanLoopHeader()) {
             TTY.print("lh ");
         }
-        if (x.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd)) {
+        if (x.isLinearScanLoopEnd()) {
             TTY.print("le ");
         }
 
@@ -434,7 +408,7 @@
         if (x.numberOfPreds() > 0) {
             TTY.print("preds: ");
             for (int i = 0; i < x.numberOfPreds(); i++) {
-                TTY.print("B%d ", x.predAt(i).begin().blockID);
+                TTY.print("B%d ", x.predAt(i).block().blockID);
             }
         }
 
@@ -445,14 +419,6 @@
             }
         }
 
-        // print exception handlers
-        if (x.numberOfExceptionHandlers() > 0) {
-            TTY.print("xhandler: ");
-            for (int i = 0; i < x.numberOfExceptionHandlers(); i++) {
-                TTY.print("B%d ", x.exceptionHandlerAt(i).blockID);
-            }
-        }
-
         TTY.println();
     }
 
--- a/graal/GraalCompiler/src/com/sun/c1x/lir/LIROpcode.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIROpcode.java	Thu May 19 11:43:30 2011 +0200
@@ -33,12 +33,7 @@
     // @formatter:off
     BeginOp0,
         Label,
-        OsrEntry,
-        Here,
-        Info,
-        Alloca,
         Breakpoint,
-        Pause,
         RuntimeCall,
         Membar,
         Branch,
--- a/graal/GraalCompiler/src/com/sun/c1x/lir/LIRStackAllocate.java	Thu May 19 11:36:41 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2010, 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.lir;
-
-import com.sun.c1x.lir.FrameMap.*;
-import com.sun.cri.bytecode.*;
-import com.sun.cri.ci.*;
-
-/**
- * LIR instruction used in translating {@link Bytecodes#ALLOCA}.
- *
- * @author Doug Simon
- */
-public class LIRStackAllocate extends LIRInstruction {
-
-    public final StackBlock stackBlock;
-
-    /**
-     * Creates an LIR instruction modelling a stack block allocation.
-     * @param result
-     */
-    public LIRStackAllocate(CiValue result, StackBlock stackBlock) {
-        super(LIROpcode.Alloca, result, null, false);
-        this.stackBlock = stackBlock;
-    }
-
-    @Override
-    public void emitCode(LIRAssembler masm) {
-        masm.emitStackAllocate(stackBlock, this.result());
-    }
-}
--- a/graal/GraalCompiler/src/com/sun/c1x/opt/InstructionSubstituter.java	Thu May 19 11:36:41 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +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.opt;
-
-import com.sun.c1x.ir.*;
-import com.sun.c1x.value.*;
-import com.sun.c1x.graph.IR;
-
-/**
- * This class allows instructions to be substituted within an IR graph. It allows
- * registering substitutions and iterates over the instructions of a program and replaces
- * the occurrence of each instruction with its substitution, if it has one.
- */
-public final class InstructionSubstituter implements BlockClosure, ValueClosure {
-
-    final IR ir;
-    boolean hasSubstitution;
-
-    public InstructionSubstituter(IR ir) {
-        this.ir = ir;
-    }
-
-    public void apply(BlockBegin block) {
-        Instruction last = null;
-        if (block.exceptionHandlerStates() != null) {
-            for (FrameState s : block.exceptionHandlerStates()) {
-                s.inputValuesDo(this);
-            }
-        }
-        for (Instruction n = block; n != null; n = last.next()) {
-            n.allValuesDo(this);
-            if (n.subst != null && last != null) {
-                // this instruction has a substitution, skip it
-                last.resetNext(n.next());
-            } else {
-                last = n;
-            }
-        }
-    }
-
-    public void finish() {
-        if (hasSubstitution) {
-            ir.startBlock.iterateAnyOrder(this, false);
-        }
-    }
-
-    public boolean hasSubst(Value i) {
-        return i.subst != null;
-    }
-
-    public void setSubst(Value i, Value n) {
-        if (i == n) {
-            i.subst = null;
-        } else {
-            hasSubstitution = true;
-            i.subst = n;
-        }
-    }
-
-    public Value getSubst(Value i) {
-        Value p = i;
-        while (true) {
-            if (p.subst == null) {
-                break;
-            }
-            p = p.subst;
-        }
-        return p;
-    }
-
-    public Value apply(Value i) {
-        if (i instanceof FrameState) {
-            FrameState state = (FrameState) i;
-            state.inputValuesDo(this);
-        }
-        if (i != null) {
-            return getSubst(i);
-        }
-        return i;
-    }
-}
--- a/graal/GraalCompiler/src/com/sun/c1x/opt/PhiSimplifier.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/opt/PhiSimplifier.java	Thu May 19 11:43:30 2011 +0200
@@ -34,13 +34,10 @@
 public final class PhiSimplifier implements BlockClosure {
 
     final IR ir;
-    final InstructionSubstituter subst;
 
     public PhiSimplifier(IR ir) {
         this.ir = ir;
-        this.subst = new InstructionSubstituter(ir);
         ir.startBlock.iterateAnyOrder(this, false);
-        subst.finish();
     }
 
     /**
@@ -62,10 +59,7 @@
             return x;
         }
         Phi phi = (Phi) x;
-        if (phi.hasSubst()) {
-            // already substituted, but the subst could be a phi itself, so simplify
-            return simplify(subst.getSubst(phi));
-        } else if (phi.checkFlag(Value.Flag.PhiCannotSimplify)) {
+        if (phi.checkFlag(Value.Flag.PhiCannotSimplify)) {
             // already tried, cannot simplify this phi
             return phi;
         } else if (phi.checkFlag(Value.Flag.PhiVisited)) {
@@ -121,7 +115,6 @@
             // successfully simplified the phi
             assert phiSubst != null : "illegal phi function";
             phi.clearFlag(Value.Flag.PhiVisited);
-            subst.setSubst(phi, phiSubst);
             return phiSubst;
         }
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRAssembler.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRAssembler.java	Thu May 19 11:43:30 2011 +0200
@@ -81,11 +81,6 @@
     }
 
     @Override
-    protected void emitOsrEntry() {
-        throw Util.unimplemented();
-    }
-
-    @Override
     protected int initialFrameSizeInBytes() {
         return frameMap.frameSize();
     }
@@ -97,26 +92,12 @@
     }
 
     @Override
-    protected void emitHere(CiValue dst, LIRDebugInfo info, boolean infoOnly) {
-        tasm.recordSafepoint(codePos(), info);
-        if (!infoOnly) {
-            masm.codeBuffer.putMark();
-            masm.leaq(dst.asRegister(), new CiAddress(CiKind.Word, InstructionRelative.asValue(), 0));
-        }
-    }
-
-    @Override
     protected void emitMonitorAddress(int monitor, CiValue dst) {
         CiStackSlot slot = frameMap.toMonitorBaseStackAddress(monitor);
         masm.leaq(dst.asRegister(), new CiAddress(slot.kind, AMD64.rsp.asValue(), slot.index() * target.arch.wordSize));
     }
 
     @Override
-    protected void emitPause() {
-        masm.pause();
-    }
-
-    @Override
     protected void emitBreakpoint() {
         masm.int3();
     }
@@ -1336,7 +1317,7 @@
             } else if (left.kind.isDouble()) {
                 masm.cmpsd2int(asXmmDoubleReg(left), asXmmDoubleReg(right), dst.asRegister(), code == LIROpcode.Ucmpfd2i);
             } else {
-                throw Util.unimplemented("no fpu stack");
+                assert false : "no fpu stack";
             }
         } else {
             assert code == LIROpcode.Cmpl2i;
@@ -2062,7 +2043,7 @@
                     break;
                 }
                 default:
-                    throw Util.unimplemented("XIR operation " + inst.op);
+                    assert false : "Unknown XIR operation " + inst.op;
             }
         }
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java	Thu May 19 11:43:30 2011 +0200
@@ -33,6 +33,9 @@
 import com.sun.c1x.util.*;
 import com.sun.cri.bytecode.*;
 import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+import com.sun.cri.ri.RiType.*;
+import com.sun.cri.xir.*;
 
 /**
  * This class implements the X86-specific portion of the LIR generator.
@@ -437,7 +440,7 @@
             CiValue reg = createResultVariable(x);
             lir.lcmp2int(left.result(), right.result(), reg);
         } else {
-            Util.unimplemented();
+            assert false;
         }
     }
 
@@ -518,4 +521,23 @@
         assert x.defaultSuccessor() == x.falseSuccessor() : "wrong destination above";
         lir.jump(x.defaultSuccessor());
     }
+
+    @Override
+    public void visitExceptionDispatch(ExceptionDispatch x) {
+        // TODO ls: this needs some more work...
+
+        RiType riType = x.handler().handler.catchType();
+        assert riType.isResolved();
+
+        XirArgument obj = toXirArgument(x.exception());
+        XirArgument clazz = toXirArgument(riType.getEncoding(Representation.ObjectHub));
+        XirSnippet snippet = xir.genInstanceOf(site(x), obj, clazz, riType);
+        CiValue result = emitXir(snippet, x, stateFor(x), null, true);
+
+        lir.cmp(Condition.EQ, result, CiConstant.TRUE);
+        lir.branch(Condition.EQ, CiKind.Boolean, x.catchSuccessor());
+
+        lir.jump(x.otherSuccessor());
+    }
+
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64XirAssembler.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64XirAssembler.java	Thu May 19 11:43:30 2011 +0200
@@ -27,7 +27,6 @@
 import java.util.*;
 
 import com.oracle.max.asm.target.amd64.*;
-import com.sun.c1x.util.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.xir.*;
 
@@ -194,7 +193,7 @@
                 case ShouldNotReachHere:
                     break;
                 default:
-                    throw Util.unimplemented("XIR operation " + i.op);
+                    assert false : "Unknown XIR operation " + i.op;
             }
             if (!appended) {
                 currentList.add(i);
--- a/graal/GraalCompiler/src/com/sun/c1x/target/sparc/SPARC.java	Thu May 19 11:36:41 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +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.target.sparc;
-
-import static com.sun.cri.bytecode.Bytecodes.MemoryBarriers.*;
-import static com.sun.cri.ci.CiRegister.RegisterFlag.*;
-
-import com.sun.cri.ci.*;
-
-/**
- * Represents the SPARC architecture.
- *
- * @author Thomas Wuerthinger
- */
-public class SPARC extends CiArchitecture {
-
-    // General purpose CPU registers
-    public static final CiRegister g0 = new CiRegister(0,  0,  8, "g0", CPU);
-    public static final CiRegister g1 = new CiRegister(1,  1,  8, "g1", CPU);
-    public static final CiRegister g2 = new CiRegister(2,  2,  8, "g2", CPU);
-    public static final CiRegister g3 = new CiRegister(3,  3,  8, "g3", CPU);
-    public static final CiRegister g4 = new CiRegister(4,  4,  8, "g4", CPU);
-    public static final CiRegister g5 = new CiRegister(5,  5,  8, "g5", CPU);
-    public static final CiRegister g6 = new CiRegister(6,  6,  8, "g6", CPU);
-    public static final CiRegister g7 = new CiRegister(7,  7,  8, "g7", CPU);
-
-    public static final CiRegister o0 = new CiRegister(8,  8,  8, "o0", CPU);
-    public static final CiRegister o1 = new CiRegister(9,  9,  8, "o1", CPU);
-    public static final CiRegister o2 = new CiRegister(10, 10, 8, "o2", CPU);
-    public static final CiRegister o3 = new CiRegister(11, 11, 8, "o3", CPU);
-    public static final CiRegister o4 = new CiRegister(12, 12, 8, "o4", CPU);
-    public static final CiRegister o5 = new CiRegister(13, 13, 8, "o5", CPU);
-    public static final CiRegister o6 = new CiRegister(14, 14, 8, "o6", CPU);
-    public static final CiRegister o7 = new CiRegister(15, 15, 8, "o7", CPU);
-
-    public static final CiRegister l0 = new CiRegister(16, 16, 8, "l0", CPU);
-    public static final CiRegister l1 = new CiRegister(17, 17, 8, "l1", CPU);
-    public static final CiRegister l2 = new CiRegister(18, 18, 8, "l2", CPU);
-    public static final CiRegister l3 = new CiRegister(19, 19, 8, "l3", CPU);
-    public static final CiRegister l4 = new CiRegister(20, 20, 8, "l4", CPU);
-    public static final CiRegister l5 = new CiRegister(21, 21, 8, "l5", CPU);
-    public static final CiRegister l6 = new CiRegister(22, 22, 8, "l6", CPU);
-    public static final CiRegister l7 = new CiRegister(23, 23, 8, "l7", CPU);
-
-    public static final CiRegister i0 = new CiRegister(24, 24, 8, "i0", CPU);
-    public static final CiRegister i1 = new CiRegister(25, 25, 8, "i1", CPU);
-    public static final CiRegister i2 = new CiRegister(26, 26, 8, "i2", CPU);
-    public static final CiRegister i3 = new CiRegister(27, 27, 8, "i3", CPU);
-    public static final CiRegister i4 = new CiRegister(28, 28, 8, "i4", CPU);
-    public static final CiRegister i5 = new CiRegister(29, 29, 8, "i5", CPU);
-    public static final CiRegister i6 = new CiRegister(30, 30, 8, "i6", CPU);
-    public static final CiRegister i7 = new CiRegister(31, 31, 8, "i7", CPU);
-
-    public static final CiRegister[] cpuRegisters = {
-        g0, g1, g2, g3, g4, g5, g6, g7,
-        o0, o1, o2, o3, o4, o5, o6, o7,
-        l0, l1, l2, l3, l4, l5, l6, l7,
-        i0, i1, i2, i3, i4, i5, i6, i7
-    };
-
-    protected SPARC(int wordSize, CiRegister[] registers) {
-        super("SPARC",
-              wordSize,
-              ByteOrder.BigEndian,
-              registers,
-              LOAD_LOAD | LOAD_STORE | STORE_STORE,
-              0,
-              i7.encoding + 1,
-              0);
-    }
-
-    @Override
-    public boolean isSPARC() {
-        return true;
-    }
-
-}
--- a/graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java	Thu May 19 11:43:30 2011 +0200
@@ -105,7 +105,8 @@
     /**
      * Gets a copy of this frame state without the stack.
      */
-    public FrameState duplicateWithEmptyStack() {
+    @Override
+    public FrameState duplicateWithEmptyStack(int bci) {
         FrameState other = new FrameState(bci, localsSize, 0, locksSize(), graph());
         for (int i = 0; i < localsSize; i++) {
             other.inputs().set(i, localAt(i));
--- a/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateAccess.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateAccess.java	Thu May 19 11:43:30 2011 +0200
@@ -42,4 +42,6 @@
 
     Value stackAt(int i);
 
+    FrameState duplicateWithEmptyStack(int bci);
+
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java	Thu May 19 11:43:30 2011 +0200
@@ -95,6 +95,11 @@
         return new FrameState(bci, locals, stack, stackIndex, locks, graph);
     }
 
+    @Override
+    public FrameState duplicateWithEmptyStack(int bci) {
+        return new FrameState(bci, locals, new Value[0], 0, locks, graph);
+    }
+
     /**
      * Pushes an instruction onto the stack with the expected type.
      * @param kind the type expected for this instruction
--- a/graal/GraalGraphviz/src/com/oracle/graal/graph/vis/GraphvizPrinter.java	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalGraphviz/src/com/oracle/graal/graph/vis/GraphvizPrinter.java	Thu May 19 11:43:30 2011 +0200
@@ -129,49 +129,54 @@
     }
 
     private void printNode(String name, String label, int ninputs, int nsuccessors) {
+        int minWidth = Math.min(label.length() / 3, 10);
+        minWidth = Math.max(minWidth, Math.max(ninputs + 1, nsuccessors + 1));
         out.println(name + "  [shape=plaintext,");
-        out.println("   label=< <TABLE BORDER=\"0\" CELLSPACING=\"0\"><TR><TD CELLPADDING=\"0\">");
-        out.println("    <TABLE BORDER=\"0\" CELLSPACING=\"2\" CELLPADDING=\"0\"><TR>");
-        out.println("    <TD WIDTH=\"15\" HEIGHT=\"5\" PORT=\"predecessors\" BGCOLOR=\"rosybrown1\"></TD></TR></TABLE>");
-        out.println("    </TD><TD COLSPAN=\"2\" CELLPADDING=\"0\" ALIGN=\"RIGHT\"><TABLE BORDER=\"0\" CELLSPACING=\"2\" CELLPADDING=\"0\"><TR>");
+        out.println("   label=< <TABLE BORDER=\"0\" CELLSPACING=\"0\"><TR>");
 
-        if ((ninputs == 1 && nsuccessors == 1) || (ninputs == 0 && nsuccessors == 0)) {
-            out.println("    <TD WIDTH=\"15\" HEIGHT=\"5\"></TD>");
-        }
+        printPort("predecessors", "rosybrown1");
 
-        for (int i = 0; i < nsuccessors - ninputs; i++) {
-            out.println("    <TD WIDTH=\"15\" HEIGHT=\"5\"></TD>");
+        for (int i = 1; i < minWidth - ninputs; i++) {
+            printEmptyPort();
         }
 
         for (int i = 0; i < ninputs; i++) {
-            out.println("    <TD WIDTH=\"15\" HEIGHT=\"5\" PORT=\"in" + i + "\" BGCOLOR=\"lightgrey\"></TD>");
+            printPort("in" + i, "lightgrey");
         }
 
         label = label.replace("&", "&amp;");
         label = label.replace("<", "&lt;");
         label = label.replace(">", "&gt;");
         label = label.replace("\"", "&quot;");
-        out.println("    </TR></TABLE></TD></TR><TR><TD BORDER=\"1\" COLSPAN=\"3\" BGCOLOR=\"" + NODE_BGCOLOR_STRING + "\">" + label + "</TD></TR>");
-        out.println("    <TR><TD COLSPAN=\"2\" CELLPADDING=\"0\" ALIGN=\"RIGHT\"><TABLE BORDER=\"0\" CELLSPACING=\"2\" CELLPADDING=\"0\"><TR>");
+        out.println("    </TR><TR><TD BORDER=\"1\" COLSPAN=\"" + minWidth + "\" BGCOLOR=\"" + NODE_BGCOLOR_STRING + "\">" + label + "</TD></TR><TR>");
 
         for (int i = 0; i < nsuccessors; i++) {
-            out.println("    <TD WIDTH=\"15\" HEIGHT=\"5\" PORT=\"succ" + i + "\" BGCOLOR=\"rosybrown1\"></TD>");
+            printPort("succ" + i, "rosybrown1");
+        }
+
+        for (int i = 1; i < minWidth - nsuccessors; i++) {
+            printEmptyPort();
         }
 
-        for (int i = 0; i < ninputs - nsuccessors; i++) {
-            out.println("    <TD WIDTH=\"15\" HEIGHT=\"5\"></TD>");
-        }
+        printPort("usages", "lightgrey");
+
+        out.println("    </TR></TABLE>>]; ");
+    }
 
-        if ((ninputs == 1 && nsuccessors == 1) || (ninputs == 0 && nsuccessors == 0)) {
-            out.println("    <TD WIDTH=\"15\" HEIGHT=\"5\"></TD>");
-        }
+    private void printPort(String name, String color) {
+        out.print("    <TD CELLPADDING=\"0\" WIDTH=\"15\"><TABLE BORDER=\"0\" CELLSPACING=\"2\" CELLPADDING=\"0\"><TR><TD WIDTH=\"15\" HEIGHT=\"5\" PORT=\"");
+        out.print(name);
+        out.print("\" BGCOLOR=\"");
+        out.print(color);
+        out.println("\"></TD></TR></TABLE></TD>");
+    }
 
-        out.println("    </TR></TABLE></TD><TD CELLPADDING=\"0\"><TABLE BORDER=\"0\" CELLSPACING=\"2\" CELLPADDING=\"0\"><TR>");
-        out.println("    <TD WIDTH=\"15\" HEIGHT=\"5\" PORT=\"usages\" BGCOLOR=\"lightgrey\"></TD></TR></TABLE></TD></TR></TABLE>>]; ");
+    private void printEmptyPort() {
+        out.print("    <TD CELLPADDING=\"0\" WIDTH=\"15\"><TABLE BORDER=\"0\" CELLSPACING=\"2\" CELLPADDING=\"0\"><TR><TD WIDTH=\"15\" HEIGHT=\"5\"></TD></TR></TABLE></TD>");
     }
 
     private void printControlEdge(int from, int fromPort, int to) {
-        out.println("n" + from + ":succ" + fromPort + " -> n" + to + ":predecessors:n [color=red, weight=10];");
+        out.println("n" + from + ":succ" + fromPort + " -> n" + to + ":predecessors:n [color=red, weight=2];");
     }
 
     private void printDataEdge(int from, int fromPort, int to) {
--- a/graal/GraalRuntime/.classpath	Thu May 19 11:36:41 2011 +0200
+++ b/graal/GraalRuntime/.classpath	Thu May 19 11:43:30 2011 +0200
@@ -1,11 +1,11 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
-	<classpathentry combineaccessrules="false" kind="src" path="/GraalCompiler"/>
-	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.base"/>
-	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.cri"/>
-	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.asm"/>
-	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.asmdis"/>
-	<classpathentry kind="output" path="bin"/>
-</classpath>
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/GraalCompiler"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.asm"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.base"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.asmdis"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.oracle.max.cri"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- a/runtests.sh	Thu May 19 11:36:41 2011 +0200
+++ b/runtests.sh	Thu May 19 11:43:30 2011 +0200
@@ -11,4 +11,5 @@
   echo "GRAAL is not defined. It must point to a maxine repository directory."
   exit 1;
 fi
-${JDK7}/bin/java -client -d64 -graal -ea -esa -Xcomp -XX:+PrintCompilation -XX:CompileOnly=jtt -Xbootclasspath/p:"${MAXINE}/com.oracle.max.vm/bin" -Xbootclasspath/p:"${MAXINE}/com.oracle.max.base/bin" $1 test.com.sun.max.vm.compiler.JavaTester -verbose=1 -gen-run-scheme=false -run-scheme-package=all ${MAXINE}/com.oracle.max.vm/test/jtt/bytecode ${MAXINE}/com.oracle.max.vm/test/jtt/except ${MAXINE}/com.oracle.max.vm/test/jtt/hotpath ${MAXINE}/com.oracle.max.vm/test/jtt/jdk ${MAXINE}/com.oracle.max.vm/test/jtt/lang ${MAXINE}/com.oracle.max.vm/test/jtt/loop ${MAXINE}/com.oracle.max.vm/test/jtt/micro ${MAXINE}/com.oracle.max.vm/test/jtt/optimize ${MAXINE}/com.oracle.max.vm/test/jtt/reflect ${MAXINE}/com.oracle.max.vm/test/jtt/threads
+TESTDIR=${MAXINE}/com.oracle.max.vm/test
+${JDK7}/bin/java -client -d64 -graal -ea -esa -Xcomp -XX:+PrintCompilation -XX:CompileOnly=jtt -Xbootclasspath/p:"${MAXINE}/com.oracle.max.vm/bin" -Xbootclasspath/p:"${MAXINE}/com.oracle.max.base/bin" $1 test.com.sun.max.vm.compiler.JavaTester -verbose=1 -gen-run-scheme=false -run-scheme-package=all ${TESTDIR}/jtt/bytecode ${TESTDIR}/jtt/except ${TESTDIR}/jtt/hotpath ${TESTDIR}/jtt/jdk ${TESTDIR}/jtt/lang ${TESTDIR}/jtt/loop ${TESTDIR}/jtt/micro ${TESTDIR}/jtt/optimize ${TESTDIR}/jtt/reflect ${TESTDIR}/jtt/threads