changeset 2885:693e4e92346b

merge
author Lukas Stadler <lukas.stadler@jku.at>
date Wed, 08 Jun 2011 13:06:45 +0200
parents adfc15cbcabc (current diff) 971b7dcf64dc (diff)
children d9ee2a573a55 80d27a8a022b 7eec76f3e39e
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/DeadCodeElimination.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/GraphBuilder.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/Inlining.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatDiv.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatMul.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatRem.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatSub.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerAdd.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerDiv.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerMul.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerRem.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerSub.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/opt/CanonicalizerPhase.java graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeArray.java
diffstat 31 files changed, 2244 insertions(+), 2131 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/C1XOptions.java	Wed Jun 08 13:04:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/C1XOptions.java	Wed Jun 08 13:06:45 2011 +0200
@@ -62,7 +62,6 @@
     public static String  PrintFilter                        = null;
 
     // printing settings
-    public static boolean PrintHIR                           = ____;
     public static boolean PrintLIR                           = ____;
     public static boolean PrintCFGToFile                     = ____;
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/DeadCodeElimination.java	Wed Jun 08 13:04:17 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.graph;
-
-import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.gen.*;
-import com.oracle.max.graal.compiler.ir.*;
-import com.oracle.max.graal.graph.*;
-
-
-public class DeadCodeElimination extends Phase {
-
-    private NodeBitMap alive;
-    private NodeWorklist worklist;
-    private Graph graph;
-
-    public int deletedNodeCount;
-
-    @Override
-    protected void run(Graph graph) {
-        this.graph = graph;
-        this.alive = graph.createNodeBitMap();
-        this.worklist = graph.createNodeWorklist();
-
-        worklist.add(graph.start());
-
-        iterateSuccessors();
-        disconnectCFGNodes();
-
-        iterateInputs();
-        disconnectNonCFGNodes();
-
-        deleteCFGNodes();
-        deleteNonCFGNodes();
-
-        new PhiSimplifier(graph);
-
-        if (C1XOptions.TraceDeadCodeElimination) {
-            System.out.printf("dead code elimination: deleted %d nodes\n", deletedNodeCount);
-        }
-    }
-
-    private static boolean isCFG(Node n) {
-        return n != null && ((n instanceof Instruction) || n == n.graph().start());
-    }
-
-    private void iterateSuccessors() {
-        for (Node current : worklist) {
-            for (Node successor : current.successors()) {
-                worklist.add(successor);
-            }
-        }
-    }
-
-    private void disconnectCFGNodes() {
-        for (Node node : graph.getNodes()) {
-            if (node != Node.Null && !worklist.isMarked(node) && isCFG(node)) {
-                // iterate backwards so that the predecessor indexes in removePhiPredecessor are correct
-                for (int i = node.successors().size() - 1; i >= 0; i--) {
-                    Node successor = node.successors().get(i);
-                    if (successor != Node.Null && worklist.isMarked(successor)) {
-                        if (successor instanceof Merge) {
-                            ((Merge) successor).removePhiPredecessor(node);
-                        }
-                    }
-                }
-                node.successors().clearAll();
-                node.inputs().clearAll();
-            }
-        }
-    }
-
-    private void deleteCFGNodes() {
-        for (Node node : graph.getNodes()) {
-            if (node != Node.Null && !worklist.isMarked(node) && isCFG(node)) {
-                node.delete();
-                deletedNodeCount++;
-            }
-        }
-    }
-
-    private void iterateInputs() {
-        for (Node node : graph.getNodes()) {
-            if (node != Node.Null && worklist.isMarked(node)) {
-                for (Node input : node.inputs()) {
-                    worklist.add(input);
-                }
-            }
-        }
-        for (Node current : worklist) {
-            for (Node input : current.inputs()) {
-                worklist.add(input);
-            }
-        }
-    }
-
-    private void disconnectNonCFGNodes() {
-        for (Node node : graph.getNodes()) {
-            if (node != Node.Null && !worklist.isMarked(node) && !isCFG(node)) {
-                node.inputs().clearAll();
-            }
-        }
-    }
-
-    private void deleteNonCFGNodes() {
-        for (Node node : graph.getNodes()) {
-            if (node != Node.Null && !worklist.isMarked(node) && !isCFG(node)) {
-                node.delete();
-                deletedNodeCount++;
-            }
-        }
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/GraphBuilder.java	Wed Jun 08 13:04:17 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1552 +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.oracle.max.graal.compiler.graph;
-
-import static com.sun.cri.bytecode.Bytecodes.*;
-import static java.lang.reflect.Modifier.*;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.debug.*;
-import com.oracle.max.graal.compiler.graph.BlockMap.*;
-import com.oracle.max.graal.compiler.graph.BlockMap.Block;
-import com.oracle.max.graal.compiler.ir.*;
-import com.oracle.max.graal.compiler.schedule.*;
-import com.oracle.max.graal.compiler.util.*;
-import com.oracle.max.graal.compiler.value.*;
-import com.oracle.max.graal.graph.*;
-import com.sun.cri.bytecode.*;
-import com.sun.cri.ci.*;
-import com.sun.cri.ri.*;
-import com.sun.cri.ri.RiType.*;
-
-/**
- * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph.
- * A number of optimizations may be performed during parsing of the bytecode, including value
- * numbering, inlining, constant folding, strength reduction, etc.
- */
-public final class GraphBuilder extends Phase {
-
-    /**
-     * The minimum value to which {@link C1XOptions#TraceBytecodeParserLevel} must be set to trace
-     * the bytecode instructions as they are parsed.
-     */
-    public static final int TRACELEVEL_INSTRUCTIONS = 1;
-
-    /**
-     * The minimum value to which {@link C1XOptions#TraceBytecodeParserLevel} must be set to trace
-     * the frame state before each bytecode instruction as it is parsed.
-     */
-    public static final int TRACELEVEL_STATE = 2;
-
-    private final C1XCompilation compilation;
-    private CompilerGraph graph;
-
-    private final CiStatistics stats;
-    private final RiRuntime runtime;
-    private final RiMethod method;
-    private final RiConstantPool constantPool;
-
-    private final BytecodeStream stream;           // the bytecode stream
-    private final LogStream log;
-    private FrameStateBuilder frameState;          // the current execution state
-
-    // bci-to-block mapping
-    private Block[] blockFromBci;
-    private ArrayList<Block> blockList;
-
-    private int nextBlockNumber;
-
-    private Value methodSynchronizedObject;
-    private CiExceptionHandler syncHandler;
-
-    private Block unwindBlock;
-    private Block returnBlock;
-
-    // the worklist of blocks, sorted by depth first number
-    private final PriorityQueue<Block> workList = new PriorityQueue<Block>(10, new Comparator<Block>() {
-        public int compare(Block o1, Block o2) {
-            return o1.blockID - o2.blockID;
-        }
-    });
-
-    private Instruction lastInstr;                 // the last instruction added
-
-    private final Set<Block> blocksOnWorklist = new HashSet<Block>();
-    private final Set<Block> blocksVisited = new HashSet<Block>();
-
-    private final boolean createUnwind;
-
-
-    /**
-     * Creates a new, initialized, {@code GraphBuilder} instance for a given compilation.
-     *
-     * @param compilation the compilation
-     * @param ir the IR to build the graph into
-     * @param graph
-     */
-    public GraphBuilder(C1XCompilation compilation, RiMethod method, boolean createUnwind) {
-        this.compilation = compilation;
-
-        this.runtime = compilation.runtime;
-        this.method = method;
-        this.stats = compilation.stats;
-        this.log = C1XOptions.TraceBytecodeParserLevel > 0 ? new LogStream(TTY.out()) : null;
-        this.stream = new BytecodeStream(method.code());
-
-        this.constantPool = runtime.getConstantPool(method);
-        this.createUnwind = createUnwind;
-    }
-
-    @Override
-    protected void run(Graph graph) {
-        assert graph != null;
-        this.graph = (CompilerGraph) graph;
-        this.frameState = new FrameStateBuilder(method, graph);
-        build();
-    }
-
-    /**
-     * Builds the graph for a the specified {@code IRScope}.
-     *
-     * @param createUnwind setting this to true will always generate an unwind block, even if there is no exception
-     *            handler and the method is not synchronized
-     */
-    private void build() {
-        if (log != null) {
-            log.println();
-            log.println("Compiling " + method);
-        }
-
-        // 2. compute the block map, setup exception handlers and get the entrypoint(s)
-        BlockMap blockMap = compilation.getBlockMap(method);
-
-        blockList = new ArrayList<Block>(blockMap.blocks);
-        blockFromBci = new Block[method.code().length];
-        for (int i = 0; i < blockList.size(); i++) {
-            int blockID = nextBlockNumber();
-            assert blockID == i;
-            Block block = blockList.get(i);
-            if (block.startBci >= 0) {
-                blockFromBci[block.startBci] = block;
-            }
-        }
-
-        // 1. create the start block
-        Block startBlock = nextBlock(Instruction.SYNCHRONIZATION_ENTRY_BCI);
-        markOnWorkList(startBlock);
-        lastInstr = createTarget(startBlock, frameState);
-        graph.start().setStart(lastInstr);
-
-        if (isSynchronized(method.accessFlags())) {
-            // 4A.1 add a monitor enter to the start block
-            methodSynchronizedObject = synchronizedObject(frameState, method);
-            genMonitorEnter(methodSynchronizedObject, Instruction.SYNCHRONIZATION_ENTRY_BCI);
-            // 4A.2 finish the start block
-            finishStartBlock(startBlock);
-
-            // 4A.3 setup an exception handler to unlock the root method synchronized object
-            syncHandler = new CiExceptionHandler(0, method.code().length, Instruction.SYNCHRONIZATION_ENTRY_BCI, 0, null);
-        } else {
-            // 4B.1 simply finish the start block
-            finishStartBlock(startBlock);
-
-            if (createUnwind) {
-                syncHandler = new CiExceptionHandler(0, method.code().length, Instruction.SYNCHRONIZATION_ENTRY_BCI, 0, null);
-            }
-        }
-
-        // 5. SKIPPED: look for intrinsics
-
-        // 6B.1 do the normal parsing
-        addToWorkList(blockFromBci[0]);
-        iterateAllBlocks();
-
-        // remove Placeholders
-        for (Node n : graph.getNodes()) {
-            if (n instanceof Placeholder) {
-                Placeholder p = (Placeholder) n;
-                assert p.blockPredecessors().size() == 1;
-                Node pred = p.blockPredecessors().get(0);
-                int predIndex = p.predecessorsIndex().get(0);
-                pred.successors().setAndClear(predIndex, p, 0);
-                p.delete();
-            }
-        }
-
-        // remove FrameStates
-        for (Node n : graph.getNodes()) {
-            if (n instanceof FrameState) {
-                boolean delete = false;
-                if (n.usages().size() == 0 && n.predecessors().size() == 0) {
-                    delete = true;
-                }
-                if (delete) {
-                    n.delete();
-                }
-            }
-        }
-    }
-
-    private int nextBlockNumber() {
-        stats.blockCount++;
-        return nextBlockNumber++;
-    }
-
-    private Block nextBlock(int bci) {
-        Block block = new Block();
-        block.startBci = bci;
-        block.endBci = bci;
-        block.blockID = nextBlockNumber();
-        return block;
-    }
-
-    private Block unwindBlock() {
-        if (unwindBlock == null) {
-            unwindBlock = new Block();
-            unwindBlock.startBci = Instruction.SYNCHRONIZATION_ENTRY_BCI;
-            unwindBlock.endBci = Instruction.SYNCHRONIZATION_ENTRY_BCI;
-            unwindBlock.blockID = nextBlockNumber();
-            addToWorkList(unwindBlock);
-        }
-        return unwindBlock;
-    }
-
-    private Block returnBlock() {
-        if (returnBlock == null) {
-            returnBlock = new Block();
-            returnBlock.startBci = Instruction.SYNCHRONIZATION_ENTRY_BCI;
-            returnBlock.endBci = Instruction.SYNCHRONIZATION_ENTRY_BCI;
-            returnBlock.blockID = nextBlockNumber();
-            addToWorkList(returnBlock);
-        }
-        return returnBlock;
-    }
-
-    private void markOnWorkList(Block block) {
-        blocksOnWorklist.add(block);
-    }
-
-    private boolean isOnWorkList(Block block) {
-        return blocksOnWorklist.contains(block);
-    }
-
-    private void markVisited(Block block) {
-        blocksVisited.add(block);
-    }
-
-    private boolean isVisited(Block block) {
-        return blocksVisited.contains(block);
-    }
-
-    private void finishStartBlock(Block startBlock) {
-        assert bci() == 0;
-        Instruction target = createTargetAt(0, frameState);
-        appendGoto(target);
-    }
-
-    public void mergeOrClone(Block target, FrameStateAccess newState) {
-        Instruction first = target.firstInstruction;
-        if (target.isLoopHeader && isVisited(target)) {
-            first = ((LoopBegin) first).loopEnd();
-        }
-        assert first instanceof StateSplit;
-
-        int bci = target.startBci;
-
-        FrameState existingState = ((StateSplit) first).stateBefore();
-
-        if (existingState == null) {
-            // copy state because it is modified
-            FrameState duplicate = newState.duplicate(bci);
-
-            // if the block is a loop header, insert all necessary phis
-            if (first instanceof LoopBegin && target.isLoopHeader) {
-                assert first instanceof Merge;
-                insertLoopPhis((Merge) first, duplicate);
-                ((Merge) first).setStateBefore(duplicate);
-            } else {
-                ((StateSplit) first).setStateBefore(duplicate);
-            }
-        } else {
-            if (!C1XOptions.AssumeVerifiedBytecode && !existingState.isCompatibleWith(newState)) {
-                // stacks or locks do not match--bytecodes would not verify
-                TTY.println(existingState.toString());
-                TTY.println(newState.duplicate(0).toString());
-                throw new CiBailout("stack or locks do not match");
-            }
-            assert existingState.localsSize() == newState.localsSize();
-            assert existingState.stackSize() == newState.stackSize();
-
-            if (first instanceof Placeholder) {
-                assert !target.isLoopHeader;
-                Merge merge = new Merge(graph);
-
-                Placeholder p = (Placeholder) first;
-                assert p.next() == null;
-                p.replace(merge);
-                target.firstInstruction = merge;
-                merge.setStateBefore(existingState);
-                first = merge;
-            }
-
-            existingState.merge((Merge) first, newState);
-        }
-
-        for (int j = 0; j < frameState.localsSize() + frameState.stackSize(); ++j) {
-            if (frameState.valueAt(j) != null) {
-                assert !frameState.valueAt(j).isDeleted();
-            }
-        }
-    }
-
-    private void insertLoopPhis(Merge merge, FrameState newState) {
-        int stackSize = newState.stackSize();
-        for (int i = 0; i < stackSize; i++) {
-            // always insert phis for the stack
-            Value x = newState.stackAt(i);
-            if (x != null) {
-                newState.setupPhiForStack(merge, i).addInput(x);
-            }
-        }
-        int localsSize = newState.localsSize();
-        for (int i = 0; i < localsSize; i++) {
-            Value x = newState.localAt(i);
-            if (x != null) {
-                newState.setupPhiForLocal(merge, i).addInput(x);
-            }
-        }
-    }
-
-    public BytecodeStream stream() {
-        return stream;
-    }
-
-    public int bci() {
-        return stream.currentBCI();
-    }
-
-    private void loadLocal(int index, CiKind kind) {
-        frameState.push(kind, frameState.loadLocal(index));
-    }
-
-    private void storeLocal(CiKind kind, int index) {
-        frameState.storeLocal(index, frameState.pop(kind));
-    }
-
-    public boolean covers(RiExceptionHandler handler, int bci) {
-        return handler.startBCI() <= bci && bci < handler.endBCI();
-    }
-
-    public boolean isCatchAll(RiExceptionHandler handler) {
-        return handler.catchTypeCPI() == 0;
-    }
-
-    private Instruction handleException(Value exceptionObject, int bci) {
-        assert bci == Instruction.SYNCHRONIZATION_ENTRY_BCI || bci == bci() : "invalid bci";
-
-        RiExceptionHandler firstHandler = null;
-        RiExceptionHandler[] exceptionHandlers = method.exceptionHandlers();
-        // join with all potential exception handlers
-        if (exceptionHandlers != null) {
-            for (RiExceptionHandler handler : exceptionHandlers) {
-                // if the handler covers this bytecode index, add it to the list
-                if (covers(handler, bci)) {
-                    firstHandler = handler;
-                    break;
-                }
-            }
-        }
-
-        if (firstHandler == null) {
-            firstHandler = syncHandler;
-        }
-
-        if (firstHandler != null) {
-            compilation.setHasExceptionHandlers();
-
-            Block dispatchBlock = null;
-            for (Block block : blockList) {
-                if (block instanceof ExceptionBlock) {
-                    ExceptionBlock excBlock = (ExceptionBlock) block;
-                    if (excBlock.handler == firstHandler) {
-                        dispatchBlock = block;
-                        break;
-                    }
-                }
-            }
-            // if there's no dispatch block then the catch block needs to be a catch all
-            if (dispatchBlock == null) {
-                assert isCatchAll(firstHandler);
-                int handlerBCI = firstHandler.handlerBCI();
-                if (handlerBCI == Instruction.SYNCHRONIZATION_ENTRY_BCI) {
-                    dispatchBlock = unwindBlock();
-                } else {
-                    dispatchBlock = blockFromBci[handlerBCI];
-                }
-            }
-            FrameState entryState = frameState.duplicateWithEmptyStack(bci);
-
-            StateSplit entry = new Placeholder(graph);
-            entry.setStateBefore(entryState);
-
-            Instruction currentNext = entry;
-            Value currentExceptionObject = exceptionObject;
-            if (currentExceptionObject == null) {
-                ExceptionObject exception = new ExceptionObject(graph);
-                entry.setNext(exception);
-                currentNext = exception;
-                currentExceptionObject = exception;
-            }
-            FrameState stateWithException = entryState.duplicateModified(bci, CiKind.Void, currentExceptionObject);
-
-            Instruction successor = createTarget(dispatchBlock, stateWithException);
-            currentNext.setNext(successor);
-            return entry;
-        }
-        return null;
-    }
-
-    private void genLoadConstant(int cpi) {
-        Object con = constantPool.lookupConstant(cpi);
-
-        if (con instanceof RiType) {
-            // this is a load of class constant which might be unresolved
-            RiType riType = (RiType) con;
-            if (!riType.isResolved()) {
-                append(new Deoptimize(graph));
-                frameState.push(CiKind.Object, append(Constant.forObject(null, graph)));
-            } else {
-                frameState.push(CiKind.Object, append(new Constant(riType.getEncoding(Representation.JavaClass), graph)));
-            }
-        } else if (con instanceof CiConstant) {
-            CiConstant constant = (CiConstant) con;
-            frameState.push(constant.kind.stackKind(), appendConstant(constant));
-        } else {
-            throw new Error("lookupConstant returned an object of incorrect type");
-        }
-    }
-
-    private void genLoadIndexed(CiKind kind) {
-        Value index = frameState.ipop();
-        Value array = frameState.apop();
-        Value length = append(new ArrayLength(array, graph));
-        Value v = append(new LoadIndexed(array, index, length, kind, graph));
-        frameState.push(kind.stackKind(), v);
-    }
-
-    private void genStoreIndexed(CiKind kind) {
-        Value value = frameState.pop(kind.stackKind());
-        Value index = frameState.ipop();
-        Value array = frameState.apop();
-        Value length = append(new ArrayLength(array, graph));
-        StoreIndexed result = new StoreIndexed(array, index, length, kind, value, graph);
-        append(result);
-    }
-
-    private void stackOp(int opcode) {
-        switch (opcode) {
-            case POP: {
-                frameState.xpop();
-                break;
-            }
-            case POP2: {
-                frameState.xpop();
-                frameState.xpop();
-                break;
-            }
-            case DUP: {
-                Value w = frameState.xpop();
-                frameState.xpush(w);
-                frameState.xpush(w);
-                break;
-            }
-            case DUP_X1: {
-                Value w1 = frameState.xpop();
-                Value w2 = frameState.xpop();
-                frameState.xpush(w1);
-                frameState.xpush(w2);
-                frameState.xpush(w1);
-                break;
-            }
-            case DUP_X2: {
-                Value w1 = frameState.xpop();
-                Value w2 = frameState.xpop();
-                Value w3 = frameState.xpop();
-                frameState.xpush(w1);
-                frameState.xpush(w3);
-                frameState.xpush(w2);
-                frameState.xpush(w1);
-                break;
-            }
-            case DUP2: {
-                Value w1 = frameState.xpop();
-                Value w2 = frameState.xpop();
-                frameState.xpush(w2);
-                frameState.xpush(w1);
-                frameState.xpush(w2);
-                frameState.xpush(w1);
-                break;
-            }
-            case DUP2_X1: {
-                Value w1 = frameState.xpop();
-                Value w2 = frameState.xpop();
-                Value w3 = frameState.xpop();
-                frameState.xpush(w2);
-                frameState.xpush(w1);
-                frameState.xpush(w3);
-                frameState.xpush(w2);
-                frameState.xpush(w1);
-                break;
-            }
-            case DUP2_X2: {
-                Value w1 = frameState.xpop();
-                Value w2 = frameState.xpop();
-                Value w3 = frameState.xpop();
-                Value w4 = frameState.xpop();
-                frameState.xpush(w2);
-                frameState.xpush(w1);
-                frameState.xpush(w4);
-                frameState.xpush(w3);
-                frameState.xpush(w2);
-                frameState.xpush(w1);
-                break;
-            }
-            case SWAP: {
-                Value w1 = frameState.xpop();
-                Value w2 = frameState.xpop();
-                frameState.xpush(w1);
-                frameState.xpush(w2);
-                break;
-            }
-            default:
-                throw Util.shouldNotReachHere();
-        }
-
-    }
-
-    private void genArithmeticOp(CiKind kind, int opcode) {
-        genArithmeticOp(kind, opcode, false);
-    }
-
-    private void genArithmeticOp(CiKind result, int opcode, boolean canTrap) {
-        Value y = frameState.pop(result);
-        Value x = frameState.pop(result);
-        boolean isStrictFP = isStrict(method.accessFlags());
-        Arithmetic v;
-        switch(opcode){
-            case IADD:
-            case LADD: v = new IntegerAdd(result, x, y, graph); break;
-            case FADD:
-            case DADD: v = new FloatAdd(result, x, y, isStrictFP, graph); break;
-            case ISUB:
-            case LSUB: v = new IntegerSub(result, x, y, graph); break;
-            case FSUB:
-            case DSUB: v = new FloatSub(result, x, y, isStrictFP, graph); break;
-            case IMUL:
-            case LMUL: v = new IntegerMul(result, x, y, graph); break;
-            case FMUL:
-            case DMUL: v = new FloatMul(result, x, y, isStrictFP, graph); break;
-            case IDIV:
-            case LDIV: v = new IntegerDiv(result, x, y, graph); break;
-            case FDIV:
-            case DDIV: v = new FloatDiv(result, x, y, isStrictFP, graph); break;
-            case IREM:
-            case LREM: v = new IntegerRem(result, x, y, graph); break;
-            case FREM:
-            case DREM: v = new FloatRem(result, x, y, isStrictFP, graph); break;
-            default:
-                throw new CiBailout("should not reach");
-        }
-        Value result1 = append(v);
-        if (canTrap) {
-            append(new ValueAnchor(result1, graph));
-        }
-        frameState.push(result, result1);
-    }
-
-    private void genNegateOp(CiKind kind) {
-        frameState.push(kind, append(new Negate(frameState.pop(kind), graph)));
-    }
-
-    private void genShiftOp(CiKind kind, int opcode) {
-        Value s = frameState.ipop();
-        Value x = frameState.pop(kind);
-        Shift v;
-        switch(opcode){
-            case ISHL:
-            case LSHL: v = new LeftShift(kind, x, s, graph); break;
-            case ISHR:
-            case LSHR: v = new RightShift(kind, x, s, graph); break;
-            case IUSHR:
-            case LUSHR: v = new UnsignedRightShift(kind, x, s, graph); break;
-            default:
-                throw new CiBailout("should not reach");
-        }
-        frameState.push(kind, append(v));
-    }
-
-    private void genLogicOp(CiKind kind, int opcode) {
-        Value y = frameState.pop(kind);
-        Value x = frameState.pop(kind);
-        Logic v;
-        switch(opcode){
-            case IAND:
-            case LAND: v = new And(kind, x, y, graph); break;
-            case IOR:
-            case LOR: v = new Or(kind, x, y, graph); break;
-            case IXOR:
-            case LXOR: v = new Xor(kind, x, y, graph); break;
-            default:
-                throw new CiBailout("should not reach");
-        }
-        frameState.push(kind, append(v));
-    }
-
-    private void genCompareOp(CiKind kind, int opcode, CiKind resultKind) {
-        Value y = frameState.pop(kind);
-        Value x = frameState.pop(kind);
-        Value value = append(new NormalizeCompare(opcode, resultKind, x, y, graph));
-        if (!resultKind.isVoid()) {
-            frameState.ipush(value);
-        }
-    }
-
-    private void genConvert(int opcode, CiKind from, CiKind to) {
-        CiKind tt = to.stackKind();
-        frameState.push(tt, append(new Convert(opcode, frameState.pop(from.stackKind()), tt, graph)));
-    }
-
-    private void genIncrement() {
-        int index = stream().readLocalIndex();
-        int delta = stream().readIncrement();
-        Value x = frameState.localAt(index);
-        Value y = append(Constant.forInt(delta, graph));
-        frameState.storeLocal(index, append(new IntegerAdd(CiKind.Int, x, y, graph)));
-    }
-
-    private void genGoto(int fromBCI, int toBCI) {
-        appendGoto(createTargetAt(toBCI, frameState));
-    }
-
-    private void ifNode(Value x, Condition cond, Value y) {
-        assert !x.isDeleted() && !y.isDeleted();
-        If ifNode = new If(new Compare(x, cond, y, graph), graph);
-        append(ifNode);
-        Instruction tsucc = createTargetAt(stream().readBranchDest(), frameState);
-        ifNode.setBlockSuccessor(0, tsucc);
-        Instruction fsucc = createTargetAt(stream().nextBCI(), frameState);
-        ifNode.setBlockSuccessor(1, fsucc);
-    }
-
-    private void genIfZero(Condition cond) {
-        Value y = appendConstant(CiConstant.INT_0);
-        Value x = frameState.ipop();
-        ifNode(x, cond, y);
-    }
-
-    private void genIfNull(Condition cond) {
-        Value y = appendConstant(CiConstant.NULL_OBJECT);
-        Value x = frameState.apop();
-        ifNode(x, cond, y);
-    }
-
-    private void genIfSame(CiKind kind, Condition cond) {
-        Value y = frameState.pop(kind);
-        Value x = frameState.pop(kind);
-        assert !x.isDeleted() && !y.isDeleted();
-        ifNode(x, cond, y);
-    }
-
-    private void genThrow(int bci) {
-        Value exception = frameState.apop();
-        append(new NullCheck(exception, graph));
-
-        Instruction entry = handleException(exception, bci);
-        if (entry != null) {
-            append(entry);
-        } else {
-            frameState.clearStack();
-            frameState.apush(exception);
-            appendGoto(createTarget(unwindBlock(), frameState));
-        }
-    }
-
-    private void genCheckCast() {
-        int cpi = stream().readCPI();
-        RiType type = constantPool.lookupType(cpi, CHECKCAST);
-        boolean isInitialized = type.isResolved();
-        Value typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, isInitialized, cpi);
-        Value object = frameState.apop();
-        if (typeInstruction != null) {
-            frameState.apush(append(new CheckCast(type, typeInstruction, object, graph)));
-        } else {
-            frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
-        }
-    }
-
-    private void genInstanceOf() {
-        int cpi = stream().readCPI();
-        RiType type = constantPool.lookupType(cpi, INSTANCEOF);
-        boolean isInitialized = type.isResolved();
-        Value typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, isInitialized, cpi);
-        Value object = frameState.apop();
-        if (typeInstruction != null) {
-            frameState.ipush(append(new InstanceOf(type, typeInstruction, object, graph)));
-        } else {
-            frameState.ipush(appendConstant(CiConstant.INT_0));
-        }
-    }
-
-    void genNewInstance(int cpi) {
-        RiType type = constantPool.lookupType(cpi, NEW);
-        if (type.isResolved()) {
-            NewInstance n = new NewInstance(type, cpi, constantPool, graph);
-            frameState.apush(append(n));
-        } else {
-            append(new Deoptimize(graph));
-            frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
-        }
-    }
-
-    private void genNewTypeArray(int typeCode) {
-        CiKind kind = CiKind.fromArrayTypeCode(typeCode);
-        RiType elementType = runtime.asRiType(kind);
-        NewTypeArray nta = new NewTypeArray(frameState.ipop(), elementType, graph);
-        frameState.apush(append(nta));
-    }
-
-    private void genNewObjectArray(int cpi) {
-        RiType type = constantPool.lookupType(cpi, ANEWARRAY);
-        Value length = frameState.ipop();
-        if (type.isResolved()) {
-            NewArray n = new NewObjectArray(type, length, graph);
-            frameState.apush(append(n));
-        } else {
-            append(new Deoptimize(graph));
-            frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
-        }
-
-    }
-
-    private void genNewMultiArray(int cpi) {
-        RiType type = constantPool.lookupType(cpi, MULTIANEWARRAY);
-        int rank = stream().readUByte(bci() + 3);
-        Value[] dims = new Value[rank];
-        for (int i = rank - 1; i >= 0; i--) {
-            dims[i] = frameState.ipop();
-        }
-        if (type.isResolved()) {
-            NewArray n = new NewMultiArray(type, dims, cpi, constantPool, graph);
-            frameState.apush(append(n));
-        } else {
-            append(new Deoptimize(graph));
-            frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
-        }
-    }
-
-    private void genGetField(int cpi, RiField field) {
-        CiKind kind = field.kind();
-        Value receiver = frameState.apop();
-        if (field.isResolved()) {
-            LoadField load = new LoadField(receiver, field, graph);
-            appendOptimizedLoadField(kind, load);
-        } else {
-            append(new Deoptimize(graph));
-            frameState.push(kind.stackKind(), append(Constant.defaultForKind(kind, graph)));
-        }
-    }
-
-    private void genPutField(int cpi, RiField field) {
-        Value value = frameState.pop(field.kind().stackKind());
-        Value receiver = frameState.apop();
-        if (field.isResolved()) {
-            StoreField store = new StoreField(receiver, field, value, graph);
-            appendOptimizedStoreField(store);
-        } else {
-            append(new Deoptimize(graph));
-        }
-    }
-
-    private void genGetStatic(int cpi, RiField field) {
-        RiType holder = field.holder();
-        boolean isInitialized = field.isResolved();
-        CiConstant constantValue = null;
-        if (isInitialized) {
-            constantValue = field.constantValue(null);
-        }
-        if (constantValue != null) {
-            frameState.push(constantValue.kind.stackKind(), appendConstant(constantValue));
-        } else {
-            Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized, cpi);
-            CiKind kind = field.kind();
-            if (container != null) {
-                LoadField load = new LoadField(container, field, graph);
-                appendOptimizedLoadField(kind, load);
-            } else {
-                append(new Deoptimize(graph));
-                frameState.push(kind.stackKind(), append(Constant.defaultForKind(kind, graph)));
-            }
-        }
-    }
-
-    private void genPutStatic(int cpi, RiField field) {
-        RiType holder = field.holder();
-        Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, field.isResolved(), cpi);
-        Value value = frameState.pop(field.kind().stackKind());
-        if (container != null) {
-            StoreField store = new StoreField(container, field, value, graph);
-            appendOptimizedStoreField(store);
-        } else {
-            append(new Deoptimize(graph));
-        }
-    }
-
-    private Value genTypeOrDeopt(RiType.Representation representation, RiType holder, boolean initialized, int cpi) {
-        if (initialized) {
-            return appendConstant(holder.getEncoding(representation));
-        } else {
-            append(new Deoptimize(graph));
-            return null;
-        }
-    }
-
-    private void appendOptimizedStoreField(StoreField store) {
-        append(store);
-    }
-
-    private void appendOptimizedLoadField(CiKind kind, LoadField load) {
-        // append the load to the instruction
-        Value optimized = append(load);
-        frameState.push(kind.stackKind(), optimized);
-    }
-
-    private void genInvokeStatic(RiMethod target, int cpi, RiConstantPool constantPool) {
-        RiType holder = target.holder();
-        boolean isInitialized = target.isResolved() && holder.isInitialized();
-        if (!isInitialized && C1XOptions.ResolveClassBeforeStaticInvoke) {
-            // Re-use the same resolution code as for accessing a static field. Even though
-            // the result of resolution is not used by the invocation (only the side effect
-            // of initialization is required), it can be commoned with static field accesses.
-            genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized, cpi);
-        }
-        Value[] args = frameState.popArguments(target.signature().argumentSlots(false));
-        appendInvoke(INVOKESTATIC, target, args, cpi, constantPool);
-    }
-
-    private void genInvokeInterface(RiMethod target, int cpi, RiConstantPool constantPool) {
-        Value[] args = frameState.popArguments(target.signature().argumentSlots(true));
-        genInvokeIndirect(INVOKEINTERFACE, target, args, cpi, constantPool);
-
-    }
-
-    private void genInvokeVirtual(RiMethod target, int cpi, RiConstantPool constantPool) {
-        Value[] args = frameState.popArguments(target.signature().argumentSlots(true));
-        genInvokeIndirect(INVOKEVIRTUAL, target, args, cpi, constantPool);
-
-    }
-
-    private void genInvokeSpecial(RiMethod target, RiType knownHolder, int cpi, RiConstantPool constantPool) {
-        Value[] args = frameState.popArguments(target.signature().argumentSlots(true));
-        invokeDirect(target, args, knownHolder, cpi, constantPool);
-
-    }
-
-    private void genInvokeIndirect(int opcode, RiMethod target, Value[] args, int cpi, RiConstantPool constantPool) {
-        Value receiver = args[0];
-        // attempt to devirtualize the call
-        if (target.isResolved()) {
-            RiType klass = target.holder();
-
-            // 0. check for trivial cases
-            if (target.canBeStaticallyBound() && !isAbstract(target.accessFlags())) {
-                // check for trivial cases (e.g. final methods, nonvirtual methods)
-                invokeDirect(target, args, target.holder(), cpi, constantPool);
-                return;
-            }
-            // 1. check if the exact type of the receiver can be determined
-            RiType exact = getExactType(klass, receiver);
-            if (exact != null && exact.isResolved()) {
-                // either the holder class is exact, or the receiver object has an exact type
-                invokeDirect(exact.resolveMethodImpl(target), args, exact, cpi, constantPool);
-                return;
-            }
-        }
-        // devirtualization failed, produce an actual invokevirtual
-        appendInvoke(opcode, target, args, cpi, constantPool);
-    }
-
-    private CiKind returnKind(RiMethod target) {
-        return target.signature().returnKind();
-    }
-
-    private void invokeDirect(RiMethod target, Value[] args, RiType knownHolder, int cpi, RiConstantPool constantPool) {
-        appendInvoke(INVOKESPECIAL, target, args, cpi, constantPool);
-    }
-
-    private void appendInvoke(int opcode, RiMethod target, Value[] args, int cpi, RiConstantPool constantPool) {
-        CiKind resultType = returnKind(target);
-        Invoke invoke = new Invoke(bci(), opcode, resultType.stackKind(), args, target, target.signature().returnType(method.holder()), graph);
-        Value result = appendWithBCI(invoke);
-        invoke.setExceptionEdge(handleException(null, bci()));
-        frameState.pushReturn(resultType, result);
-    }
-
-    private RiType getExactType(RiType staticType, Value receiver) {
-        RiType exact = staticType.exactType();
-        if (exact == null) {
-            exact = receiver.exactType();
-            if (exact == null) {
-                if (receiver.isConstant()) {
-                    exact = runtime.getTypeOf(receiver.asConstant());
-                }
-                if (exact == null) {
-                    RiType declared = receiver.declaredType();
-                    exact = declared == null || !declared.isResolved() ? null : declared.exactType();
-                }
-            }
-        }
-        return exact;
-    }
-
-    private void callRegisterFinalizer() {
-        Value receiver = frameState.loadLocal(0);
-        RiType declaredType = receiver.declaredType();
-        RiType receiverType = declaredType;
-        RiType exactType = receiver.exactType();
-        if (exactType == null && declaredType != null) {
-            exactType = declaredType.exactType();
-        }
-        if (exactType == null && receiver instanceof Local && ((Local) receiver).index() == 0) {
-            // the exact type isn't known, but the receiver is parameter 0 => use holder
-            receiverType = method.holder();
-            exactType = receiverType.exactType();
-        }
-        boolean needsCheck = true;
-        if (exactType != null) {
-            // we have an exact type
-            needsCheck = exactType.hasFinalizer();
-        } else {
-            // if either the declared type of receiver or the holder can be assumed to have no finalizers
-            if (declaredType != null && !declaredType.hasFinalizableSubclass()) {
-                if (compilation.recordNoFinalizableSubclassAssumption(declaredType)) {
-                    needsCheck = false;
-                }
-            }
-
-            if (receiverType != null && !receiverType.hasFinalizableSubclass()) {
-                if (compilation.recordNoFinalizableSubclassAssumption(receiverType)) {
-                    needsCheck = false;
-                }
-            }
-        }
-
-        if (needsCheck) {
-            // append a call to the finalizer registration
-            append(new RegisterFinalizer(frameState.loadLocal(0), frameState.create(bci()), graph));
-            C1XMetrics.InlinedFinalizerChecks++;
-        }
-    }
-
-    private void genReturn(Value x) {
-        frameState.clearStack();
-        if (x != null) {
-            frameState.push(x.kind, x);
-        }
-        appendGoto(createTarget(returnBlock(), frameState));
-    }
-
-    private void genMonitorEnter(Value x, int bci) {
-        int lockNumber = frameState.locksSize();
-        MonitorAddress lockAddress = null;
-        if (runtime.sizeOfBasicObjectLock() != 0) {
-            lockAddress = new MonitorAddress(lockNumber, graph);
-            append(lockAddress);
-        }
-        MonitorEnter monitorEnter = new MonitorEnter(x, lockAddress, lockNumber, graph);
-        appendWithBCI(monitorEnter);
-        frameState.lock(x);
-        if (bci == Instruction.SYNCHRONIZATION_ENTRY_BCI) {
-            monitorEnter.setStateAfter(frameState.create(0));
-        }
-    }
-
-    private void genMonitorExit(Value x) {
-        int lockNumber = frameState.locksSize() - 1;
-        if (lockNumber < 0) {
-            throw new CiBailout("monitor stack underflow");
-        }
-        MonitorAddress lockAddress = null;
-        if (runtime.sizeOfBasicObjectLock() != 0) {
-            lockAddress = new MonitorAddress(lockNumber, graph);
-            append(lockAddress);
-        }
-        appendWithBCI(new MonitorExit(x, lockAddress, lockNumber, graph));
-        frameState.unlock();
-    }
-
-    private void genJsr(int dest) {
-        throw new CiBailout("jsr/ret not supported");
-    }
-
-    private void genRet(int localIndex) {
-        throw new CiBailout("jsr/ret not supported");
-    }
-
-    private void genTableswitch() {
-        int bci = bci();
-        Value value = frameState.ipop();
-        BytecodeTableSwitch ts = new BytecodeTableSwitch(stream(), bci);
-        int max = ts.numberOfCases();
-        List<Instruction> list = new ArrayList<Instruction>(max + 1);
-        List<Integer> offsetList = new ArrayList<Integer>(max + 1);
-        for (int i = 0; i < max; i++) {
-            // add all successors to the successor list
-            int offset = ts.offsetAt(i);
-            list.add(null);
-            offsetList.add(offset);
-        }
-        int offset = ts.defaultOffset();
-        list.add(null);
-        offsetList.add(offset);
-        TableSwitch tableSwitch = new TableSwitch(value, list, ts.lowKey(), graph);
-        for (int i = 0; i < offsetList.size(); ++i) {
-            tableSwitch.setBlockSuccessor(i, createTargetAt(bci + offsetList.get(i), frameState));
-        }
-        append(tableSwitch);
-    }
-
-    private void genLookupswitch() {
-        int bci = bci();
-        Value value = frameState.ipop();
-        BytecodeLookupSwitch ls = new BytecodeLookupSwitch(stream(), bci);
-        int max = ls.numberOfCases();
-        List<Instruction> list = new ArrayList<Instruction>(max + 1);
-        List<Integer> offsetList = new ArrayList<Integer>(max + 1);
-        int[] keys = new int[max];
-        for (int i = 0; i < max; i++) {
-            // add all successors to the successor list
-            int offset = ls.offsetAt(i);
-            list.add(null);
-            offsetList.add(offset);
-            keys[i] = ls.keyAt(i);
-        }
-        int offset = ls.defaultOffset();
-        list.add(null);
-        offsetList.add(offset);
-        LookupSwitch lookupSwitch = new LookupSwitch(value, list, keys, graph);
-        for (int i = 0; i < offsetList.size(); ++i) {
-            lookupSwitch.setBlockSuccessor(i, createTargetAt(bci + offsetList.get(i), frameState));
-        }
-        append(lookupSwitch);
-    }
-
-    private Value appendConstant(CiConstant constant) {
-        return append(new Constant(constant, graph));
-    }
-
-    private Value append(Instruction x) {
-        return appendWithBCI(x);
-    }
-
-    private Value append(Value v) {
-        return v;
-    }
-
-    private Value appendWithBCI(Instruction x) {
-        assert x.predecessors().size() == 0 : "instruction should not have been appended yet";
-        assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")";
-        lastInstr.setNext(x);
-
-        lastInstr = x;
-        if (++stats.nodeCount >= C1XOptions.MaximumInstructionCount) {
-            // bailout if we've exceeded the maximum inlining size
-            throw new CiBailout("Method and/or inlining is too large");
-        }
-
-        return x;
-    }
-
-    private Instruction createTargetAt(int bci, FrameStateAccess stateAfter) {
-        return createTarget(blockFromBci[bci], stateAfter);
-    }
-
-    private Instruction createTarget(Block block, FrameStateAccess stateAfter) {
-        assert block != null && stateAfter != null;
-        assert block.isLoopHeader || block.firstInstruction == null || block.firstInstruction.next() == null : "non-loop block must be iterated after all its predecessors";
-
-        if (block.isExceptionEntry) {
-            assert stateAfter.stackSize() == 1;
-        }
-
-        if (block.firstInstruction == null) {
-            if (block.isLoopHeader) {
-//                block.firstInstruction = new Merge(block.startBci, graph);
-
-                LoopBegin loopBegin = new LoopBegin(graph);
-                LoopEnd loopEnd = new LoopEnd(graph);
-                loopEnd.setLoopBegin(loopBegin);
-                block.firstInstruction = loopBegin;
-            } else {
-                block.firstInstruction = new Placeholder(graph);
-            }
-        }
-        mergeOrClone(block, stateAfter);
-        addToWorkList(block);
-
-        if (block.firstInstruction instanceof LoopBegin && isVisited(block)) {
-            return ((LoopBegin) block.firstInstruction).loopEnd();
-        } else {
-            return block.firstInstruction;
-        }
-    }
-
-    private Value synchronizedObject(FrameStateAccess state, RiMethod target) {
-        if (isStatic(target.accessFlags())) {
-            Constant classConstant = new Constant(target.holder().getEncoding(Representation.JavaClass), graph);
-            return append(classConstant);
-        } else {
-            return state.localAt(0);
-        }
-    }
-
-    private void iterateAllBlocks() {
-        Block block;
-        while ((block = removeFromWorkList()) != null) {
-
-            // remove blocks that have no predecessors by the time it their bytecodes are parsed
-            if (block.firstInstruction == null) {
-                markVisited(block);
-                continue;
-            }
-
-            if (!isVisited(block)) {
-                markVisited(block);
-                // now parse the block
-                frameState.initializeFrom(((StateSplit) block.firstInstruction).stateBefore());
-                lastInstr = block.firstInstruction;
-                assert block.firstInstruction.next() == null : "instructions already appended at block " + block.blockID;
-
-                if (block == returnBlock) {
-                    createReturnBlock(block);
-                } else if (block == unwindBlock) {
-                    createUnwindBlock(block);
-                } else if (block instanceof ExceptionBlock) {
-                    createExceptionDispatch((ExceptionBlock) block);
-                } else {
-                    iterateBytecodesForBlock(block);
-                }
-            }
-        }
-        for (Block b : blocksVisited) {
-            if (b.isLoopHeader) {
-                LoopBegin begin = (LoopBegin) b.firstInstruction;
-                LoopEnd end = begin.loopEnd();
-
-//              This can happen with degenerated loops like this one:
-//                for (;;) {
-//                    try {
-//                        break;
-//                    } catch (UnresolvedException iioe) {
-//                    }
-//                }
-                if (end.stateBefore() != null) {
-                    begin.stateBefore().merge(begin, end.stateBefore());
-                } else {
-                    end.delete();
-                    Merge merge = new Merge(graph);
-                    merge.successors().setAndClear(merge.nextIndex(), begin, begin.nextIndex());
-                    begin.replace(merge);
-                }
-            }
-        }
-    }
-
-    private void createUnwindBlock(Block block) {
-        if (Modifier.isSynchronized(method.accessFlags())) {
-            genMonitorExit(methodSynchronizedObject);
-        }
-        append(graph.createUnwind(frameState.apop()));
-    }
-
-    private void createReturnBlock(Block block) {
-        if (method.isConstructor() && method.holder().superType() == null) {
-            callRegisterFinalizer();
-        }
-        CiKind returnKind = method.signature().returnKind().stackKind();
-        Value x = returnKind == CiKind.Void ? null : frameState.pop(returnKind);
-        assert frameState.stackSize() == 0;
-
-        if (Modifier.isSynchronized(method.accessFlags())) {
-            genMonitorExit(methodSynchronizedObject);
-        }
-        append(graph.createReturn(x));
-    }
-
-    private void createExceptionDispatch(ExceptionBlock block) {
-        if (block.handler == null) {
-            assert frameState.stackSize() == 1 : "only exception object expected on stack, actual size: " + frameState.stackSize();
-            createUnwindBlock(block);
-        } else {
-            assert frameState.stackSize() == 1;
-
-            Block nextBlock = block.next == null ? unwindBlock() : block.next;
-            if (block.handler.catchType().isResolved()) {
-                Instruction catchSuccessor = createTarget(blockFromBci[block.handler.handlerBCI()], frameState);
-                Instruction nextDispatch = createTarget(nextBlock, frameState);
-                append(new ExceptionDispatch(frameState.stackAt(0), catchSuccessor, nextDispatch, block.handler.catchType(), graph));
-            } else {
-                Deoptimize deopt = new Deoptimize(graph);
-                deopt.setMessage("unresolved " + block.handler.catchType().name());
-                append(deopt);
-                Instruction nextDispatch = createTarget(nextBlock, frameState);
-                appendGoto(nextDispatch);
-            }
-        }
-    }
-
-    private void appendGoto(Instruction target) {
-        lastInstr.setNext(target);
-    }
-
-    private void iterateBytecodesForBlock(Block block) {
-        assert frameState != null;
-
-        stream.setBCI(block.startBci);
-
-        int endBCI = stream.endBCI();
-        boolean blockStart = true;
-
-        int bci = block.startBci;
-        while (bci < endBCI) {
-            Block nextBlock = blockFromBci[bci];
-            if (nextBlock != null && nextBlock != block) {
-                assert !nextBlock.isExceptionEntry;
-                // we fell through to the next block, add a goto and break
-                appendGoto(createTarget(nextBlock, frameState));
-                break;
-            }
-            // read the opcode
-            int opcode = stream.currentBC();
-
-            traceState();
-            traceInstruction(bci, opcode, blockStart);
-            processBytecode(bci, opcode);
-
-            if (Schedule.isBlockEnd(lastInstr) || lastInstr.next() != null) {
-                break;
-            }
-
-            stream.next();
-            bci = stream.currentBCI();
-            if (lastInstr instanceof StateSplit) {
-                StateSplit stateSplit = (StateSplit) lastInstr;
-                if (stateSplit.stateAfter() == null && stateSplit.needsStateAfter()) {
-                    stateSplit.setStateAfter(frameState.create(bci));
-                }
-            }
-            blockStart = false;
-        }
-    }
-
-    private void traceState() {
-        if (C1XOptions.TraceBytecodeParserLevel >= TRACELEVEL_STATE && !TTY.isSuppressed()) {
-            log.println(String.format("|   state [nr locals = %d, stack depth = %d, method = %s]", frameState.localsSize(), frameState.stackSize(), method));
-            for (int i = 0; i < frameState.localsSize(); ++i) {
-                Value value = frameState.localAt(i);
-                log.println(String.format("|   local[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value));
-            }
-            for (int i = 0; i < frameState.stackSize(); ++i) {
-                Value value = frameState.stackAt(i);
-                log.println(String.format("|   stack[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value));
-            }
-            for (int i = 0; i < frameState.locksSize(); ++i) {
-                Value value = frameState.lockAt(i);
-                log.println(String.format("|   lock[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value));
-            }
-        }
-    }
-
-    private void processBytecode(int bci, int opcode) {
-        int cpi;
-
-        // Checkstyle: stop
-        switch (opcode) {
-            case NOP            : /* nothing to do */ break;
-            case ACONST_NULL    : frameState.apush(appendConstant(CiConstant.NULL_OBJECT)); break;
-            case ICONST_M1      : frameState.ipush(appendConstant(CiConstant.INT_MINUS_1)); break;
-            case ICONST_0       : frameState.ipush(appendConstant(CiConstant.INT_0)); break;
-            case ICONST_1       : frameState.ipush(appendConstant(CiConstant.INT_1)); break;
-            case ICONST_2       : frameState.ipush(appendConstant(CiConstant.INT_2)); break;
-            case ICONST_3       : frameState.ipush(appendConstant(CiConstant.INT_3)); break;
-            case ICONST_4       : frameState.ipush(appendConstant(CiConstant.INT_4)); break;
-            case ICONST_5       : frameState.ipush(appendConstant(CiConstant.INT_5)); break;
-            case LCONST_0       : frameState.lpush(appendConstant(CiConstant.LONG_0)); break;
-            case LCONST_1       : frameState.lpush(appendConstant(CiConstant.LONG_1)); break;
-            case FCONST_0       : frameState.fpush(appendConstant(CiConstant.FLOAT_0)); break;
-            case FCONST_1       : frameState.fpush(appendConstant(CiConstant.FLOAT_1)); break;
-            case FCONST_2       : frameState.fpush(appendConstant(CiConstant.FLOAT_2)); break;
-            case DCONST_0       : frameState.dpush(appendConstant(CiConstant.DOUBLE_0)); break;
-            case DCONST_1       : frameState.dpush(appendConstant(CiConstant.DOUBLE_1)); break;
-            case BIPUSH         : frameState.ipush(appendConstant(CiConstant.forInt(stream.readByte()))); break;
-            case SIPUSH         : frameState.ipush(appendConstant(CiConstant.forInt(stream.readShort()))); break;
-            case LDC            : // fall through
-            case LDC_W          : // fall through
-            case LDC2_W         : genLoadConstant(stream.readCPI()); break;
-            case ILOAD          : loadLocal(stream.readLocalIndex(), CiKind.Int); break;
-            case LLOAD          : loadLocal(stream.readLocalIndex(), CiKind.Long); break;
-            case FLOAD          : loadLocal(stream.readLocalIndex(), CiKind.Float); break;
-            case DLOAD          : loadLocal(stream.readLocalIndex(), CiKind.Double); break;
-            case ALOAD          : loadLocal(stream.readLocalIndex(), CiKind.Object); break;
-            case ILOAD_0        : // fall through
-            case ILOAD_1        : // fall through
-            case ILOAD_2        : // fall through
-            case ILOAD_3        : loadLocal(opcode - ILOAD_0, CiKind.Int); break;
-            case LLOAD_0        : // fall through
-            case LLOAD_1        : // fall through
-            case LLOAD_2        : // fall through
-            case LLOAD_3        : loadLocal(opcode - LLOAD_0, CiKind.Long); break;
-            case FLOAD_0        : // fall through
-            case FLOAD_1        : // fall through
-            case FLOAD_2        : // fall through
-            case FLOAD_3        : loadLocal(opcode - FLOAD_0, CiKind.Float); break;
-            case DLOAD_0        : // fall through
-            case DLOAD_1        : // fall through
-            case DLOAD_2        : // fall through
-            case DLOAD_3        : loadLocal(opcode - DLOAD_0, CiKind.Double); break;
-            case ALOAD_0        : // fall through
-            case ALOAD_1        : // fall through
-            case ALOAD_2        : // fall through
-            case ALOAD_3        : loadLocal(opcode - ALOAD_0, CiKind.Object); break;
-            case IALOAD         : genLoadIndexed(CiKind.Int   ); break;
-            case LALOAD         : genLoadIndexed(CiKind.Long  ); break;
-            case FALOAD         : genLoadIndexed(CiKind.Float ); break;
-            case DALOAD         : genLoadIndexed(CiKind.Double); break;
-            case AALOAD         : genLoadIndexed(CiKind.Object); break;
-            case BALOAD         : genLoadIndexed(CiKind.Byte  ); break;
-            case CALOAD         : genLoadIndexed(CiKind.Char  ); break;
-            case SALOAD         : genLoadIndexed(CiKind.Short ); break;
-            case ISTORE         : storeLocal(CiKind.Int, stream.readLocalIndex()); break;
-            case LSTORE         : storeLocal(CiKind.Long, stream.readLocalIndex()); break;
-            case FSTORE         : storeLocal(CiKind.Float, stream.readLocalIndex()); break;
-            case DSTORE         : storeLocal(CiKind.Double, stream.readLocalIndex()); break;
-            case ASTORE         : storeLocal(CiKind.Object, stream.readLocalIndex()); break;
-            case ISTORE_0       : // fall through
-            case ISTORE_1       : // fall through
-            case ISTORE_2       : // fall through
-            case ISTORE_3       : storeLocal(CiKind.Int, opcode - ISTORE_0); break;
-            case LSTORE_0       : // fall through
-            case LSTORE_1       : // fall through
-            case LSTORE_2       : // fall through
-            case LSTORE_3       : storeLocal(CiKind.Long, opcode - LSTORE_0); break;
-            case FSTORE_0       : // fall through
-            case FSTORE_1       : // fall through
-            case FSTORE_2       : // fall through
-            case FSTORE_3       : storeLocal(CiKind.Float, opcode - FSTORE_0); break;
-            case DSTORE_0       : // fall through
-            case DSTORE_1       : // fall through
-            case DSTORE_2       : // fall through
-            case DSTORE_3       : storeLocal(CiKind.Double, opcode - DSTORE_0); break;
-            case ASTORE_0       : // fall through
-            case ASTORE_1       : // fall through
-            case ASTORE_2       : // fall through
-            case ASTORE_3       : storeLocal(CiKind.Object, opcode - ASTORE_0); break;
-            case IASTORE        : genStoreIndexed(CiKind.Int   ); break;
-            case LASTORE        : genStoreIndexed(CiKind.Long  ); break;
-            case FASTORE        : genStoreIndexed(CiKind.Float ); break;
-            case DASTORE        : genStoreIndexed(CiKind.Double); break;
-            case AASTORE        : genStoreIndexed(CiKind.Object); break;
-            case BASTORE        : genStoreIndexed(CiKind.Byte  ); break;
-            case CASTORE        : genStoreIndexed(CiKind.Char  ); break;
-            case SASTORE        : genStoreIndexed(CiKind.Short ); break;
-            case POP            : // fall through
-            case POP2           : // fall through
-            case DUP            : // fall through
-            case DUP_X1         : // fall through
-            case DUP_X2         : // fall through
-            case DUP2           : // fall through
-            case DUP2_X1        : // fall through
-            case DUP2_X2        : // fall through
-            case SWAP           : stackOp(opcode); break;
-            case IADD           : // fall through
-            case ISUB           : // fall through
-            case IMUL           : genArithmeticOp(CiKind.Int, opcode); break;
-            case IDIV           : // fall through
-            case IREM           : genArithmeticOp(CiKind.Int, opcode, true); break;
-            case LADD           : // fall through
-            case LSUB           : // fall through
-            case LMUL           : genArithmeticOp(CiKind.Long, opcode); break;
-            case LDIV           : // fall through
-            case LREM           : genArithmeticOp(CiKind.Long, opcode, true); break;
-            case FADD           : // fall through
-            case FSUB           : // fall through
-            case FMUL           : // fall through
-            case FDIV           : // fall through
-            case FREM           : genArithmeticOp(CiKind.Float, opcode); break;
-            case DADD           : // fall through
-            case DSUB           : // fall through
-            case DMUL           : // fall through
-            case DDIV           : // fall through
-            case DREM           : genArithmeticOp(CiKind.Double, opcode); break;
-            case INEG           : genNegateOp(CiKind.Int); break;
-            case LNEG           : genNegateOp(CiKind.Long); break;
-            case FNEG           : genNegateOp(CiKind.Float); break;
-            case DNEG           : genNegateOp(CiKind.Double); break;
-            case ISHL           : // fall through
-            case ISHR           : // fall through
-            case IUSHR          : genShiftOp(CiKind.Int, opcode); break;
-            case IAND           : // fall through
-            case IOR            : // fall through
-            case IXOR           : genLogicOp(CiKind.Int, opcode); break;
-            case LSHL           : // fall through
-            case LSHR           : // fall through
-            case LUSHR          : genShiftOp(CiKind.Long, opcode); break;
-            case LAND           : // fall through
-            case LOR            : // fall through
-            case LXOR           : genLogicOp(CiKind.Long, opcode); break;
-            case IINC           : genIncrement(); break;
-            case I2L            : genConvert(opcode, CiKind.Int   , CiKind.Long  ); break;
-            case I2F            : genConvert(opcode, CiKind.Int   , CiKind.Float ); break;
-            case I2D            : genConvert(opcode, CiKind.Int   , CiKind.Double); break;
-            case L2I            : genConvert(opcode, CiKind.Long  , CiKind.Int   ); break;
-            case L2F            : genConvert(opcode, CiKind.Long  , CiKind.Float ); break;
-            case L2D            : genConvert(opcode, CiKind.Long  , CiKind.Double); break;
-            case F2I            : genConvert(opcode, CiKind.Float , CiKind.Int   ); break;
-            case F2L            : genConvert(opcode, CiKind.Float , CiKind.Long  ); break;
-            case F2D            : genConvert(opcode, CiKind.Float , CiKind.Double); break;
-            case D2I            : genConvert(opcode, CiKind.Double, CiKind.Int   ); break;
-            case D2L            : genConvert(opcode, CiKind.Double, CiKind.Long  ); break;
-            case D2F            : genConvert(opcode, CiKind.Double, CiKind.Float ); break;
-            case I2B            : genConvert(opcode, CiKind.Int   , CiKind.Byte  ); break;
-            case I2C            : genConvert(opcode, CiKind.Int   , CiKind.Char  ); break;
-            case I2S            : genConvert(opcode, CiKind.Int   , CiKind.Short ); break;
-            case LCMP           : genCompareOp(CiKind.Long, opcode, CiKind.Int); break;
-            case FCMPL          : genCompareOp(CiKind.Float, opcode, CiKind.Int); break;
-            case FCMPG          : genCompareOp(CiKind.Float, opcode, CiKind.Int); break;
-            case DCMPL          : genCompareOp(CiKind.Double, opcode, CiKind.Int); break;
-            case DCMPG          : genCompareOp(CiKind.Double, opcode, CiKind.Int); break;
-            case IFEQ           : genIfZero(Condition.EQ); break;
-            case IFNE           : genIfZero(Condition.NE); break;
-            case IFLT           : genIfZero(Condition.LT); break;
-            case IFGE           : genIfZero(Condition.GE); break;
-            case IFGT           : genIfZero(Condition.GT); break;
-            case IFLE           : genIfZero(Condition.LE); break;
-            case IF_ICMPEQ      : genIfSame(CiKind.Int, Condition.EQ); break;
-            case IF_ICMPNE      : genIfSame(CiKind.Int, Condition.NE); break;
-            case IF_ICMPLT      : genIfSame(CiKind.Int, Condition.LT); break;
-            case IF_ICMPGE      : genIfSame(CiKind.Int, Condition.GE); break;
-            case IF_ICMPGT      : genIfSame(CiKind.Int, Condition.GT); break;
-            case IF_ICMPLE      : genIfSame(CiKind.Int, Condition.LE); break;
-            case IF_ACMPEQ      : genIfSame(frameState.peekKind(), Condition.EQ); break;
-            case IF_ACMPNE      : genIfSame(frameState.peekKind(), Condition.NE); break;
-            case GOTO           : genGoto(stream.currentBCI(), stream.readBranchDest()); break;
-            case JSR            : genJsr(stream.readBranchDest()); break;
-            case RET            : genRet(stream.readLocalIndex()); break;
-            case TABLESWITCH    : genTableswitch(); break;
-            case LOOKUPSWITCH   : genLookupswitch(); break;
-            case IRETURN        : genReturn(frameState.ipop()); break;
-            case LRETURN        : genReturn(frameState.lpop()); break;
-            case FRETURN        : genReturn(frameState.fpop()); break;
-            case DRETURN        : genReturn(frameState.dpop()); break;
-            case ARETURN        : genReturn(frameState.apop()); break;
-            case RETURN         : genReturn(null  ); break;
-            case GETSTATIC      : cpi = stream.readCPI(); genGetStatic(cpi, constantPool.lookupField(cpi, opcode)); break;
-            case PUTSTATIC      : cpi = stream.readCPI(); genPutStatic(cpi, constantPool.lookupField(cpi, opcode)); break;
-            case GETFIELD       : cpi = stream.readCPI(); genGetField(cpi, constantPool.lookupField(cpi, opcode)); break;
-            case PUTFIELD       : cpi = stream.readCPI(); genPutField(cpi, constantPool.lookupField(cpi, opcode)); break;
-            case INVOKEVIRTUAL  : cpi = stream.readCPI(); genInvokeVirtual(constantPool.lookupMethod(cpi, opcode), cpi, constantPool); break;
-            case INVOKESPECIAL  : cpi = stream.readCPI(); genInvokeSpecial(constantPool.lookupMethod(cpi, opcode), null, cpi, constantPool); break;
-            case INVOKESTATIC   : cpi = stream.readCPI(); genInvokeStatic(constantPool.lookupMethod(cpi, opcode), cpi, constantPool); break;
-            case INVOKEINTERFACE: cpi = stream.readCPI(); genInvokeInterface(constantPool.lookupMethod(cpi, opcode), cpi, constantPool); break;
-            case NEW            : genNewInstance(stream.readCPI()); break;
-            case NEWARRAY       : genNewTypeArray(stream.readLocalIndex()); break;
-            case ANEWARRAY      : genNewObjectArray(stream.readCPI()); break;
-            case ARRAYLENGTH    : genArrayLength(); break;
-            case ATHROW         : genThrow(stream.currentBCI()); break;
-            case CHECKCAST      : genCheckCast(); break;
-            case INSTANCEOF     : genInstanceOf(); break;
-            case MONITORENTER   : genMonitorEnter(frameState.apop(), stream.currentBCI()); break;
-            case MONITOREXIT    : genMonitorExit(frameState.apop()); break;
-            case MULTIANEWARRAY : genNewMultiArray(stream.readCPI()); break;
-            case IFNULL         : genIfNull(Condition.EQ); break;
-            case IFNONNULL      : genIfNull(Condition.NE); break;
-            case GOTO_W         : genGoto(stream.currentBCI(), stream.readFarBranchDest()); break;
-            case JSR_W          : genJsr(stream.readFarBranchDest()); break;
-            case BREAKPOINT:
-                throw new CiBailout("concurrent setting of breakpoint");
-            default:
-                throw new CiBailout("Unsupported opcode " + opcode + " (" + nameOf(opcode) + ") [bci=" + bci + "]");
-        }
-        // Checkstyle: resume
-    }
-
-    private void traceInstruction(int bci, int opcode, boolean blockStart) {
-        if (C1XOptions.TraceBytecodeParserLevel >= TRACELEVEL_INSTRUCTIONS && !TTY.isSuppressed()) {
-            StringBuilder sb = new StringBuilder(40);
-            sb.append(blockStart ? '+' : '|');
-            if (bci < 10) {
-                sb.append("  ");
-            } else if (bci < 100) {
-                sb.append(' ');
-            }
-            sb.append(bci).append(": ").append(Bytecodes.nameOf(opcode));
-            for (int i = bci + 1; i < stream.nextBCI(); ++i) {
-                sb.append(' ').append(stream.readUByte(i));
-            }
-            log.println(sb.toString());
-        }
-    }
-
-    private void genArrayLength() {
-        frameState.ipush(append(new ArrayLength(frameState.apop(), graph)));
-    }
-
-    /**
-     * Adds a block to the worklist, if it is not already in the worklist.
-     * This method will keep the worklist topologically stored (i.e. the lower
-     * DFNs are earlier in the list).
-     * @param block the block to add to the work list
-     */
-    private void addToWorkList(Block block) {
-        if (!isOnWorkList(block)) {
-            markOnWorkList(block);
-            sortIntoWorkList(block);
-        }
-    }
-
-    private void sortIntoWorkList(Block top) {
-        workList.offer(top);
-    }
-
-    /**
-     * Removes the next block from the worklist. The list is sorted topologically, so the
-     * block with the lowest depth first number in the list will be removed and returned.
-     * @return the next block from the worklist; {@code null} if there are no blocks
-     * in the worklist
-     */
-    private Block removeFromWorkList() {
-        return workList.poll();
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Wed Jun 08 13:04:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Wed Jun 08 13:06:45 2011 +0200
@@ -29,7 +29,7 @@
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.observer.*;
-import com.oracle.max.graal.compiler.opt.*;
+import com.oracle.max.graal.compiler.phases.*;
 import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
@@ -84,24 +84,9 @@
 
         if (C1XOptions.OptCanonicalizer) {
             new CanonicalizerPhase().apply(graph);
-            verifyAndPrint("After canonicalization");
         }
 
-        // Split critical edges.
-        List<Node> nodes = graph.getNodes();
-        for (int i = 0; i < nodes.size(); ++i) {
-            Node n = nodes.get(i);
-            if (Schedule.trueSuccessorCount(n) > 1) {
-                for (int j = 0; j < n.successors().size(); ++j) {
-                    Node succ = n.successors().get(j);
-                    if (Schedule.truePredecessorCount(succ) > 1) {
-                        Anchor a = new Anchor(graph);
-                        a.successors().setAndClear(1, n, j);
-                        n.successors().set(j, a);
-                    }
-                }
-            }
-        }
+        new SplitCriticalEdgesPhase().apply(graph);
 
         Schedule schedule = new Schedule(graph);
         List<Block> blocks = schedule.getBlocks();
@@ -157,7 +142,7 @@
 
     private void buildGraph() {
         // Graph builder must set the startBlock and the osrEntryBlock
-        new GraphBuilder(compilation, compilation.method, false).apply(compilation.graph);
+        new GraphBuilderPhase(compilation, compilation.method, false).apply(compilation.graph);
 
 //        CompilerGraph duplicate = new CompilerGraph();
 //        Map<Node, Node> replacements = new HashMap<Node, Node>();
@@ -165,16 +150,16 @@
 //        duplicate.addDuplicate(compilation.graph.getNodes(), replacements);
 //        compilation.graph = duplicate;
 
-        verifyAndPrint("After graph building");
+        new DuplicationPhase().apply(compilation.graph);
 
-        DeadCodeElimination dce = new DeadCodeElimination();
+        DeadCodeEliminationPhase dce = new DeadCodeEliminationPhase();
         dce.apply(compilation.graph);
         if (dce.deletedNodeCount > 0) {
             verifyAndPrint("After dead code elimination");
         }
 
         if (C1XOptions.Inline) {
-            new Inlining(compilation, this).apply(compilation.graph);
+            new InliningPhase(compilation, this).apply(compilation.graph);
         }
 
         if (C1XOptions.PrintCompilation) {
@@ -190,36 +175,17 @@
         return orderedBlocks;
     }
 
-    private void print(boolean cfgOnly) {
-        if (!TTY.isSuppressed()) {
-            TTY.println("IR for " + compilation.method);
-            final InstructionPrinter ip = new InstructionPrinter(TTY.out());
-            final BlockPrinter bp = new BlockPrinter(this, ip, cfgOnly);
-            //getHIRStartBlock().iteratePreOrder(bp);
-        }
-    }
-
     /**
      * Verifies the IR and prints it out if the relevant options are set.
      * @param phase the name of the phase for printing
      */
     public void verifyAndPrint(String phase) {
-        if (C1XOptions.PrintHIR && !TTY.isSuppressed()) {
-            TTY.println(phase);
-            print(false);
-        }
-
         if (compilation.compiler.isObserved()) {
             compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, phase, compilation.graph, true, false));
         }
     }
 
     public void printGraph(String phase, Graph graph) {
-        if (C1XOptions.PrintHIR && !TTY.isSuppressed()) {
-            TTY.println(phase);
-            print(false);
-        }
-
         if (compilation.compiler.isObserved()) {
             compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, phase, graph, true, false));
         }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/Inlining.java	Wed Jun 08 13:04:17 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,288 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.graph;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.ir.*;
-import com.oracle.max.graal.compiler.value.*;
-import com.oracle.max.graal.graph.*;
-import com.sun.cri.ci.*;
-import com.sun.cri.ri.*;
-
-
-public class Inlining extends Phase {
-
-    private final C1XCompilation compilation;
-    private final IR ir;
-
-    private final Queue<Invoke> invokes = new ArrayDeque<Invoke>();
-    private final Queue<RiMethod> methods = new ArrayDeque<RiMethod>();
-    private int inliningSize;
-
-    public Inlining(C1XCompilation compilation, IR ir) {
-        this.compilation = compilation;
-        this.ir = ir;
-    }
-
-    private void addToQueue(Invoke invoke, RiMethod method) {
-        invokes.add(invoke);
-        methods.add(method);
-        inliningSize += method.code().length;
-    }
-
-    @Override
-    protected void run(Graph graph) {
-        if (!C1XOptions.Inline) {
-            return;
-        }
-
-        inliningSize = compilation.method.code().length;
-        int iterations = C1XOptions.MaximumRecursiveInlineLevel;
-        do {
-            for (Node node : graph.getNodes()) {
-                if (node instanceof Invoke) {
-                    Invoke invoke = (Invoke) node;
-                    RiMethod target = invoke.target;
-                    if (!checkInliningConditions(invoke) || !target.isResolved() || Modifier.isNative(target.accessFlags())) {
-                        continue;
-                    }
-                    if (target.canBeStaticallyBound()) {
-                        if (checkInliningConditions(invoke.target)) {
-                            addToQueue(invoke, invoke.target);
-                        }
-                    } else {
-                        RiMethod concrete = invoke.target.holder().uniqueConcreteMethod(invoke.target);
-                        if (concrete != null && concrete.isResolved() && !Modifier.isNative(concrete.accessFlags())) {
-                            if (checkInliningConditions(concrete)) {
-                                if (C1XOptions.TraceInlining) {
-                                    System.out.println("registering concrete method assumption...");
-                                }
-                                compilation.assumptions.recordConcreteMethod(invoke.target, concrete);
-                                addToQueue(invoke, concrete);
-                            }
-                        }
-                    }
-                    if (inliningSize > C1XOptions.MaximumInstructionCount) {
-                        break;
-                    }
-                }
-            }
-
-            assert invokes.size() == methods.size();
-            if (invokes.isEmpty()) {
-                break;
-            }
-
-            Invoke invoke;
-            while ((invoke = invokes.poll()) != null) {
-                RiMethod method = methods.remove();
-                inlineMethod(invoke, method);
-            }
-            DeadCodeElimination dce = new DeadCodeElimination();
-            dce.apply(graph);
-            if (dce.deletedNodeCount > 0) {
-                ir.verifyAndPrint("After dead code elimination");
-            }
-            ir.verifyAndPrint("After inlining iteration");
-
-            if (inliningSize > C1XOptions.MaximumInstructionCount) {
-                if (C1XOptions.TraceInlining) {
-                    System.out.println("inlining stopped: MaximumInstructionCount reached");
-                }
-                break;
-            }
-        } while(--iterations > 0);
-    }
-
-    private boolean checkInliningConditions(Invoke invoke) {
-        String name = invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", invoke.target, false);
-        if (invoke.predecessors().size() == 0) {
-            if (C1XOptions.TraceInlining) {
-                System.out.println("not inlining " + name + " because the invoke is dead code");
-            }
-            return false;
-        }
-        return true;
-    }
-
-    private boolean checkInliningConditions(RiMethod method) {
-        String name = null;
-        if (C1XOptions.TraceInlining) {
-            name = CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.code().length + " bytes)";
-        }
-        if (method.code().length > C1XOptions.MaximumInlineSize) {
-            if (C1XOptions.TraceInlining) {
-                System.out.println("not inlining " + name + " because of code size");
-            }
-            return false;
-        }
-        if (!method.holder().isInitialized()) {
-            if (C1XOptions.TraceInlining) {
-                System.out.println("not inlining " + name + " because of non-initialized class");
-            }
-            return false;
-        }
-        return true;
-    }
-
-    private void inlineMethod(Invoke invoke, RiMethod method) {
-        String name = invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.code().length + " bytes)";
-        FrameState stateAfter = invoke.stateAfter();
-        Instruction exceptionEdge = invoke.exceptionEdge();
-
-        if (C1XOptions.TraceInlining) {
-            System.out.printf("Building graph for %s, locals: %d, stack: %d\n", name, method.maxLocals(), method.maxStackSize());
-        }
-
-        CompilerGraph graph = new CompilerGraph();
-        new GraphBuilder(compilation, method, true).apply(graph);
-
-        boolean withReceiver = !Modifier.isStatic(method.accessFlags());
-
-        int argumentCount = method.signature().argumentCount(false);
-        Value[] parameters = new Value[argumentCount + (withReceiver ? 1 : 0)];
-        int slot = withReceiver ? 1 : 0;
-        int param = withReceiver ? 1 : 0;
-        for (int i = 0; i < argumentCount; i++) {
-            parameters[param++] = invoke.argument(slot);
-            slot += method.signature().argumentKindAt(i).sizeInSlots();
-        }
-        if (withReceiver) {
-            parameters[0] = invoke.argument(0);
-        }
-
-        HashMap<Node, Node> replacements = new HashMap<Node, Node>();
-        ArrayList<Node> nodes = new ArrayList<Node>();
-        ArrayList<Node> frameStates = new ArrayList<Node>();
-        Return returnNode = null;
-        Unwind unwindNode = null;
-        StartNode startNode = graph.start();
-        for (Node node : graph.getNodes()) {
-            if (node != null) {
-                if (node instanceof StartNode) {
-                    assert startNode == node;
-                } else if (node instanceof Local) {
-                    replacements.put(node, parameters[((Local) node).index()]);
-                } else {
-                    nodes.add(node);
-                    if (node instanceof Return) {
-                        returnNode = (Return) node;
-                    } else if (node instanceof Unwind) {
-                        unwindNode = (Unwind) node;
-                    } else if (node instanceof FrameState) {
-                        frameStates.add(node);
-                    }
-                }
-            }
-        }
-
-        if (C1XOptions.TraceInlining) {
-            ir.printGraph("Subgraph " + CiUtil.format("%H.%n(%p):%r", method, false), graph);
-            System.out.println("inlining " + name + ": " + frameStates.size() + " frame states, " + nodes.size() + " nodes");
-        }
-
-        assert invoke.predecessors().size() == 1 : "size: " + invoke.predecessors().size();
-        Instruction pred;
-        if (withReceiver) {
-            pred = new NullCheck(parameters[0], compilation.graph);
-        } else {
-            pred = new Merge(compilation.graph);
-        }
-        invoke.predecessors().get(0).successors().replace(invoke, pred);
-        replacements.put(startNode, pred);
-
-        Map<Node, Node> duplicates = compilation.graph.addDuplicate(nodes, replacements);
-
-        if (returnNode != null) {
-            List<Node> usages = new ArrayList<Node>(invoke.usages());
-            for (Node usage : usages) {
-                if (returnNode.result() instanceof Local) {
-                    usage.inputs().replace(invoke, replacements.get(returnNode.result()));
-                } else {
-                    usage.inputs().replace(invoke, duplicates.get(returnNode.result()));
-                }
-            }
-            Node returnDuplicate = duplicates.get(returnNode);
-            returnDuplicate.inputs().clearAll();
-
-            assert returnDuplicate.predecessors().size() == 1;
-            Node returnPred = returnDuplicate.predecessors().get(0);
-            int index = returnDuplicate.predecessorsIndex().get(0);
-            returnPred.successors().setAndClear(index, invoke, 0);
-            returnDuplicate.delete();
-        }
-
-//        if (invoke.next() instanceof Merge) {
-//            ((Merge) invoke.next()).removePhiPredecessor(invoke);
-//        }
-//        invoke.successors().clearAll();
-        invoke.inputs().clearAll();
-        invoke.setExceptionEdge(null);
-//        invoke.delete();
-
-
-        if (exceptionEdge != null) {
-            if (unwindNode != null) {
-                assert unwindNode.predecessors().size() == 1;
-                assert exceptionEdge.successors().size() == 1;
-                ExceptionObject obj = (ExceptionObject) exceptionEdge;
-
-                List<Node> usages = new ArrayList<Node>(obj.usages());
-                for (Node usage : usages) {
-                    if (replacements.containsKey(unwindNode.exception())) {
-                        usage.inputs().replace(obj, replacements.get(unwindNode.exception()));
-                    } else {
-                        usage.inputs().replace(obj, duplicates.get(unwindNode.exception()));
-                    }
-                }
-                Node unwindDuplicate = duplicates.get(unwindNode);
-                unwindDuplicate.inputs().clearAll();
-
-                assert unwindDuplicate.predecessors().size() == 1;
-                Node unwindPred = unwindDuplicate.predecessors().get(0);
-                int index = unwindDuplicate.predecessorsIndex().get(0);
-                unwindPred.successors().setAndClear(index, obj, 0);
-
-                obj.inputs().clearAll();
-                obj.delete();
-                unwindDuplicate.delete();
-
-            }
-        }
-
-        // adjust all frame states that were copied
-        if (frameStates.size() > 0) {
-            FrameState outerFrameState = stateAfter.duplicateModified(invoke.bci, invoke.kind);
-            for (Node frameState : frameStates) {
-                ((FrameState) duplicates.get(frameState)).setOuterFrameState(outerFrameState);
-            }
-        }
-
-        if (C1XOptions.TraceInlining) {
-            ir.verifyAndPrint("After inlining " + CiUtil.format("%H.%n(%p):%r", method, false));
-        }
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/package-info.java	Wed Jun 08 13:04:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/package-info.java	Wed Jun 08 13:06:45 2011 +0200
@@ -35,7 +35,7 @@
  *
  * {@code IR.buildGraph} creates an {@link com.oracle.max.graal.compiler.ir.IRScope topScope} object,
  * that represents a context for inlining, and then invokes the constructor for the
- * {@link com.oracle.max.graal.compiler.graph.GraphBuilder} class, passing the {@link com.oracle.max.graal.compiler.C1XCompilation}, and {@code IR}
+ * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase} class, passing the {@link com.oracle.max.graal.compiler.C1XCompilation}, and {@code IR}
  * instances, which are cached. The following support objects are created in the constructor:
  *
  * <ul>
@@ -44,7 +44,7 @@
  * <li>{@code canonicalizer}: an instance of {@link com.oracle.max.graal.compiler.opt.Canonicalizer}
  * </ul>
  *
- * Now the {@link com.oracle.max.graal.compiler.graph.GraphBuilder#build} is invoked with {@code topScope} as argument.
+ * Now the {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#build} is invoked with {@code topScope} as argument.
  *
  * <H3>{@code GraphBuilder.build}</H3>
  *
@@ -60,20 +60,20 @@
  * the statistics are updated.
  * </li>
  *
- * <li>Next the {@link com.oracle.max.graal.compiler.graph.GraphBuilder#pushRootScope} method is called, with the passed-in {@link com.oracle.max.graal.compiler.ir.IRScope}
+ * <li>Next the {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#pushRootScope} method is called, with the passed-in {@link com.oracle.max.graal.compiler.ir.IRScope}
  * object, the {@link com.oracle.max.graal.compiler.graph.BlockMap} returned by build and the {@code startBlock}. (Note: Unlike
- * {@link com.oracle.max.graal.compiler.graph.GraphBuilder#pushScope}, this method does not propagate the
+ * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#pushScope}, this method does not propagate the
  * {@link com.oracle.max.graal.compiler.graph.BlockMap#storesInLoops} field to the {@link com.oracle.max.graal.compiler.ir.IRScope} object, which means that
  * {@link com.oracle.max.graal.compiler.ir.BlockBegin#insertLoopPhis} will always get null for this value. Is this a bug?).
- * {@link com.oracle.max.graal.compiler.graph.GraphBuilder#pushRootScope} initializes the {@link com.oracle.max.graal.compiler.graph.GraphBuilder#scopeData} field with a
+ * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#pushRootScope} initializes the {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#scopeData} field with a
  * {@link com.oracle.max.graal.compiler.graph.ScopeData} instance, with null parent. The
- * {@link com.oracle.max.graal.compiler.graph.GraphBuilder#compilation} instance is called to get an {@link com.sun.cri.ri.RiConstantPool}
- * , which is C1X's interface to constant pool information. The {@link com.oracle.max.graal.compiler.graph.GraphBuilder#curBlock} field is
+ * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#compilation} instance is called to get an {@link com.sun.cri.ri.RiConstantPool}
+ * , which is C1X's interface to constant pool information. The {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#curBlock} field is
  * set to the {@code startBlock}.
  * <p>
  *
  * Now a {@link com.oracle.max.graal.compiler.value.FrameState initialState} object is created by
- * {@link com.oracle.max.graal.compiler.graph.GraphBuilder#stateAtEntry}. If the method is not static, then a {@link com.oracle.max.graal.compiler.ir.Local}
+ * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#stateAtEntry}. If the method is not static, then a {@link com.oracle.max.graal.compiler.ir.Local}
  * instance is created at index 0. Since the receiver cannot be {@code null}, the
  * {@link com.oracle.max.graal.compiler.ir.Value.Flag#NonNull} flag is set. Additional {@link com.oracle.max.graal.compiler.ir.Local} instances are created for the
  * arguments to the method. The index is incremented by the number of slots occupied by the
@@ -83,14 +83,14 @@
  * copy since {@code stateBefore} will be {@code null}.
  * </li>
  * <li>
- * This step sets up three instance fields: {@link com.oracle.max.graal.compiler.graph.GraphBuilder#curBlock} and
- * {@link com.oracle.max.graal.compiler.graph.GraphBuilder#lastInstr} to {@code startBlock} and
- * {@link com.oracle.max.graal.compiler.graph.GraphBuilder#curState} to {@code initialState}. (N.B. the setting of {@code curBlock} is
- * redundant as it is done in {@link com.oracle.max.graal.compiler.graph.GraphBuilder#pushRootScope}).
+ * This step sets up three instance fields: {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#curBlock} and
+ * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#lastInstr} to {@code startBlock} and
+ * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#curState} to {@code initialState}. (N.B. the setting of {@code curBlock} is
+ * redundant as it is done in {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#pushRootScope}).
  * </li>
  * <li>
  * Step 4 contains special handling for synchronized methods (TBD), otherwise it calls
- * {@link com.oracle.max.graal.compiler.graph.GraphBuilder#finishStartBlock} which adds a {@link com.oracle.max.graal.compiler.ir.Base} block as the end of
+ * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#finishStartBlock} which adds a {@link com.oracle.max.graal.compiler.ir.Base} block as the end of
  * the {@code startBlock}. The {@link com.oracle.max.graal.compiler.ir.Base} block has one successor set to the (entry) block with flag
  * {@link com.oracle.max.graal.compiler.ir.BlockBegin.BlockFlag#StandardEntry}, that was created by {@link com.oracle.max.graal.compiler.graph.BlockMap#build} (and possibly a
  * successor to an OSREntry block).
@@ -103,26 +103,26 @@
  * and {@link com.oracle.max.graal.compiler.C1XOptions#OptIntrinsify} is set, an attempt is made to inline it (TBD). Otherwise, or if the
  * intrinsification fails, normal processing continues by adding the entry block to the
  * {@link com.oracle.max.graal.compiler.graph.ScopeData} work list (kept topologically sorted) and calling
- * {@link com.oracle.max.graal.compiler.graph.GraphBuilder#iterateAllBlocks}.
+ * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#iterateAllBlocks}.
  * </li>
  * <li>
  * Finally there is some cleanup code for synchronized blocks and OSR compilations.
  * </li>
  * </ol>
  *
- * <H3>{@link com.oracle.max.graal.compiler.graph.GraphBuilder#iterateAllBlocks}</H3>
+ * <H3>{@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#iterateAllBlocks}</H3>
  * {@link com.oracle.max.graal.compiler.graph#iterateAllBlocks} repeatedly removes a block from the work list and, if not already visited, marks it so,
- * kills the current memory map, sets {@link com.oracle.max.graal.compiler.graph.GraphBuilder#curBlock}, {@link com.oracle.max.graal.compiler.graph.GraphBuilder#curState}
- * and {@link com.oracle.max.graal.compiler.graph.GraphBuilder#lastInstr} and then calls
- * {@link com.oracle.max.graal.compiler.graph.GraphBuilder#iterateBytecodesForBlock}.
+ * kills the current memory map, sets {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#curBlock}, {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#curState}
+ * and {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#lastInstr} and then calls
+ * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#iterateBytecodesForBlock}.
  *
  * This process continues until all the blocks have been visited (processed) after which control returns to {@code
  * build}.
  * <p>
 
- * <H3>{@link com.oracle.max.graal.compiler.graph.GraphBuilder#iterateBytecodesForBlock}</H3>
+ * <H3>{@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#iterateBytecodesForBlock}</H3>
  *
- * {@link com.oracle.max.graal.compiler.graph.GraphBuilder#iterateBytecodesForBlock} performs an abstract interpretation of the bytecodes in the block, appending new
+ * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#iterateBytecodesForBlock} performs an abstract interpretation of the bytecodes in the block, appending new
  * nodes as necessary, until the last added node is an instance of {@link com.oracle.max.graal.compiler.ir.BlockEnd}. (Note: It has an
  * explicit check for finding a new {@link com.oracle.max.graal.compiler.ir.BlockBegin} before a {@link com.oracle.max.graal.compiler.ir.BlockEnd} but
  * {@link com.oracle.max.graal.compiler.graph.BlockMap#moveSuccessorLists} has a similar check so this may be redundant). For example,
@@ -137,7 +137,7 @@
  * </pre>
  *
  * The {@code iconst_0} bytecode causes a {@link com.oracle.max.graal.compiler.ir.Constant} node representing zero to be pushed on the
- * {@link com.oracle.max.graal.compiler.graph.GraphBuilder#curState} stack and the node to be appended to the {@link com.oracle.max.graal.compiler.ir.BlockBegin} (entry) node associated with index 0.
+ * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#curState} stack and the node to be appended to the {@link com.oracle.max.graal.compiler.ir.BlockBegin} (entry) node associated with index 0.
  * The {@code istore_2} causes the node to be popped of the stack and stored in the local slot 2. No IR node is
  * generated for the {@code istore_2}. The {@code goto} creates a {@link com.oracle.max.graal.compiler.ir.Goto} node which is a subclass
  * of {@link com.oracle.max.graal.compiler.ir.BlockEnd}, so this terminates the iteration. As part of termination the {@link com.oracle.max.graal.compiler.ir.Goto} node is marked as the
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/And.java	Wed Jun 08 13:04:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/And.java	Wed Jun 08 13:06:45 2011 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.max.graal.compiler.ir;
 
-import com.oracle.max.graal.compiler.opt.CanonicalizerPhase.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.bytecode.*;
 import com.sun.cri.ci.*;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatDiv.java	Wed Jun 08 13:04:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatDiv.java	Wed Jun 08 13:06:45 2011 +0200
@@ -51,8 +51,7 @@
 
     @Override
     public Node copy(Graph into) {
-        FloatDiv x = new FloatDiv(kind, null, null, isStrictFP(), into);
-        return x;
+        return new FloatDiv(kind, null, null, isStrictFP(), into);
     }
 
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatMul.java	Wed Jun 08 13:04:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatMul.java	Wed Jun 08 13:06:45 2011 +0200
@@ -51,8 +51,7 @@
 
     @Override
     public Node copy(Graph into) {
-        FloatMul x = new FloatMul(kind, null, null, isStrictFP(), into);
-        return x;
+        return new FloatMul(kind, null, null, isStrictFP(), into);
     }
 
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatRem.java	Wed Jun 08 13:04:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatRem.java	Wed Jun 08 13:06:45 2011 +0200
@@ -51,8 +51,7 @@
 
     @Override
     public Node copy(Graph into) {
-        FloatRem x = new FloatRem(kind, null, null, isStrictFP(), into);
-        return x;
+        return new FloatRem(kind, null, null, isStrictFP(), into);
     }
 
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatSub.java	Wed Jun 08 13:04:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatSub.java	Wed Jun 08 13:06:45 2011 +0200
@@ -40,8 +40,7 @@
 
     @Override
     public Node copy(Graph into) {
-        FloatSub x = new FloatSub(kind, null, null, isStrictFP(), into);
-        return x;
+        return new FloatSub(kind, null, null, isStrictFP(), into);
     }
 
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java	Wed Jun 08 13:04:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java	Wed Jun 08 13:06:45 2011 +0200
@@ -114,6 +114,6 @@
 
     @Override
     public Node copy(Graph into) {
-        return new If(compare(), into);
+        return new If(null, into);
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerAdd.java	Wed Jun 08 13:04:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerAdd.java	Wed Jun 08 13:06:45 2011 +0200
@@ -35,8 +35,7 @@
 
     @Override
     public Node copy(Graph into) {
-        IntegerAdd x = new IntegerAdd(kind, null, null, into);
-        return x;
+        return new IntegerAdd(kind, null, null, into);
     }
 
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerDiv.java	Wed Jun 08 13:04:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerDiv.java	Wed Jun 08 13:06:45 2011 +0200
@@ -40,8 +40,7 @@
 
     @Override
     public Node copy(Graph into) {
-        IntegerDiv x = new IntegerDiv(kind, null, null, into);
-        return x;
+        return new IntegerDiv(kind, null, null, into);
     }
 
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerMul.java	Wed Jun 08 13:04:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerMul.java	Wed Jun 08 13:06:45 2011 +0200
@@ -40,8 +40,7 @@
 
     @Override
     public Node copy(Graph into) {
-        IntegerMul x = new IntegerMul(kind, null, null, into);
-        return x;
+        return new IntegerMul(kind, null, null, into);
     }
 
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerRem.java	Wed Jun 08 13:04:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerRem.java	Wed Jun 08 13:06:45 2011 +0200
@@ -40,8 +40,7 @@
 
     @Override
     public Node copy(Graph into) {
-        IntegerRem x = new IntegerRem(kind, null, null, into);
-        return x;
+        return new IntegerRem(kind, null, null, into);
     }
 
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerSub.java	Wed Jun 08 13:04:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerSub.java	Wed Jun 08 13:06:45 2011 +0200
@@ -35,8 +35,7 @@
 
     @Override
     public Node copy(Graph into) {
-        IntegerSub x = new IntegerSub(kind, null, null, into);
-        return x;
+        return new IntegerSub(kind, null, null, into);
     }
 
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Or.java	Wed Jun 08 13:04:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Or.java	Wed Jun 08 13:06:45 2011 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.max.graal.compiler.ir;
 
-import com.oracle.max.graal.compiler.opt.CanonicalizerPhase.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.bytecode.*;
 import com.sun.cri.ci.*;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Xor.java	Wed Jun 08 13:04:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Xor.java	Wed Jun 08 13:06:45 2011 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.max.graal.compiler.ir;
 
-import com.oracle.max.graal.compiler.opt.CanonicalizerPhase.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.bytecode.*;
 import com.sun.cri.ci.*;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/opt/CanonicalizerPhase.java	Wed Jun 08 13:04:17 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.opt;
-
-import java.util.*;
-
-import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.graph.*;
-
-public class CanonicalizerPhase extends Phase {
-
-
-    @Override
-    protected void run(Graph graph) {
-        NodeBitMap visited = graph.createNodeBitMap();
-        List<Node> nodes = new ArrayList<Node>(graph.getNodes());
-        for (Node n : nodes) {
-            if (n == null) {
-                continue;
-            }
-            if (!visited.isMarked(n)) {
-                this.canonicalize(n, visited);
-            }
-        }
-    }
-
-    private void canonicalize(Node n, NodeBitMap visited) {
-        visited.mark(n);
-        for (Node input : n.inputs()) {
-            if (input == null) {
-                continue;
-            }
-            if (!visited.isNew(input) && !visited.isMarked(input)) {
-                canonicalize(input, visited);
-            }
-        }
-
-        CanonicalizerOp op = n.lookup(CanonicalizerOp.class);
-        if (op != null) {
-            Node canonical = op.canonical(n);
-            if (canonical != n) {
-                n.replace(canonical);
-                C1XMetrics.NodesCanonicalized++;
-            }
-        }
-    }
-
-    public interface CanonicalizerOp extends Op {
-        Node canonical(Node node);
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/package-info.java	Wed Jun 08 13:04:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/package-info.java	Wed Jun 08 13:06:45 2011 +0200
@@ -86,7 +86,7 @@
  * the IR graph prevent many bugs due to the mutability of {@code FrameState}.</li>
  *
  * <li>
- * Move the {@code FrameState} class to an inner class, or combine entirely, with the {@link com.oracle.max.graal.compiler.graph.GraphBuilder} class. After
+ * Move the {@code FrameState} class to an inner class, or combine entirely, with the {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase} class. After
  * the introduction of the {@code FrameStateInfo} into HIR nodes, the mutable value stack should only need to be
  * accessed from the graph builder.</li>
  *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java	Wed Jun 08 13:06:45 2011 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.phases;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.graph.*;
+
+public class CanonicalizerPhase extends Phase {
+
+
+    @Override
+    protected void run(Graph graph) {
+        NodeBitMap visited = graph.createNodeBitMap();
+        List<Node> nodes = new ArrayList<Node>(graph.getNodes());
+        for (Node n : nodes) {
+            if (n == null) {
+                continue;
+            }
+            if (!visited.isMarked(n)) {
+                this.canonicalize(n, visited);
+            }
+        }
+    }
+
+    private void canonicalize(Node n, NodeBitMap visited) {
+        visited.mark(n);
+        for (Node input : n.inputs()) {
+            if (input == null) {
+                continue;
+            }
+            if (!visited.isNew(input) && !visited.isMarked(input)) {
+                canonicalize(input, visited);
+            }
+        }
+
+        CanonicalizerOp op = n.lookup(CanonicalizerOp.class);
+        if (op != null) {
+            Node canonical = op.canonical(n);
+            if (canonical != n) {
+                n.replace(canonical);
+                C1XMetrics.NodesCanonicalized++;
+            }
+        }
+    }
+
+    public interface CanonicalizerOp extends Op {
+        Node canonical(Node node);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Wed Jun 08 13:06:45 2011 +0200
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.phases;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+
+
+public class DeadCodeEliminationPhase extends Phase {
+
+    private NodeBitMap alive;
+    private NodeWorklist worklist;
+    private Graph graph;
+
+    public int deletedNodeCount;
+
+    @Override
+    protected void run(Graph graph) {
+        this.graph = graph;
+        this.alive = graph.createNodeBitMap();
+        this.worklist = graph.createNodeWorklist();
+
+        worklist.add(graph.start());
+
+        iterateSuccessors();
+        disconnectCFGNodes();
+
+        iterateInputs();
+        disconnectNonCFGNodes();
+
+        deleteCFGNodes();
+        deleteNonCFGNodes();
+
+        new PhiSimplifier(graph);
+
+        if (C1XOptions.TraceDeadCodeElimination) {
+            System.out.printf("dead code elimination: deleted %d nodes\n", deletedNodeCount);
+        }
+    }
+
+    private static boolean isCFG(Node n) {
+        return n != null && ((n instanceof Instruction) || n == n.graph().start());
+    }
+
+    private void iterateSuccessors() {
+        for (Node current : worklist) {
+            for (Node successor : current.successors()) {
+                worklist.add(successor);
+            }
+        }
+    }
+
+    private void disconnectCFGNodes() {
+        for (Node node : graph.getNodes()) {
+            if (node != Node.Null && !worklist.isMarked(node) && isCFG(node)) {
+                // iterate backwards so that the predecessor indexes in removePhiPredecessor are correct
+                for (int i = node.successors().size() - 1; i >= 0; i--) {
+                    Node successor = node.successors().get(i);
+                    if (successor != Node.Null && worklist.isMarked(successor)) {
+                        if (successor instanceof Merge) {
+                            ((Merge) successor).removePhiPredecessor(node);
+                        }
+                    }
+                }
+                node.successors().clearAll();
+                node.inputs().clearAll();
+            }
+        }
+    }
+
+    private void deleteCFGNodes() {
+        for (Node node : graph.getNodes()) {
+            if (node != Node.Null && !worklist.isMarked(node) && isCFG(node)) {
+                node.delete();
+                deletedNodeCount++;
+            }
+        }
+    }
+
+    private void iterateInputs() {
+        for (Node node : graph.getNodes()) {
+            if (node != Node.Null && worklist.isMarked(node)) {
+                for (Node input : node.inputs()) {
+                    worklist.add(input);
+                }
+            }
+        }
+        for (Node current : worklist) {
+            for (Node input : current.inputs()) {
+                worklist.add(input);
+            }
+        }
+    }
+
+    private void disconnectNonCFGNodes() {
+        for (Node node : graph.getNodes()) {
+            if (node != Node.Null && !worklist.isMarked(node) && !isCFG(node)) {
+                node.inputs().clearAll();
+            }
+        }
+    }
+
+    private void deleteNonCFGNodes() {
+        for (Node node : graph.getNodes()) {
+            if (node != Node.Null && !worklist.isMarked(node) && !isCFG(node)) {
+                node.delete();
+                deletedNodeCount++;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DuplicationPhase.java	Wed Jun 08 13:06:45 2011 +0200
@@ -0,0 +1,56 @@
+/*
+ * 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.oracle.max.graal.compiler.phases;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.graph.*;
+
+/**
+ * Duplicates every node in the graph to test the implementation of the {@link com.oracle.max.graal.graph.Node#copy()} method in node subclasses.
+ */
+public class DuplicationPhase extends Phase {
+
+    @Override
+    protected void run(Graph graph) {
+
+        // Create duplicate graph.
+        CompilerGraph duplicate = new CompilerGraph();
+        Map<Node, Node> replacements = new HashMap<Node, Node>();
+        replacements.put(graph.start(), duplicate.start());
+        duplicate.addDuplicate(graph.getNodes(), replacements);
+
+        // Delete nodes in original graph.
+        for (Node n : graph.getNodes()) {
+            if (n != null && n != graph.start()) {
+                n.forceDelete();
+            }
+        }
+
+        // Copy nodes from duplicate back to original graph.
+        replacements.clear();
+        replacements.put(duplicate.start(), graph.start());
+        graph.addDuplicate(duplicate.getNodes(), replacements);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Wed Jun 08 13:06:45 2011 +0200
@@ -0,0 +1,1553 @@
+/*
+ * 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.oracle.max.graal.compiler.phases;
+
+import static com.sun.cri.bytecode.Bytecodes.*;
+import static java.lang.reflect.Modifier.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.compiler.graph.BlockMap.*;
+import com.oracle.max.graal.compiler.graph.BlockMap.Block;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.schedule.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+import com.sun.cri.ri.RiType.*;
+
+/**
+ * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph.
+ * A number of optimizations may be performed during parsing of the bytecode, including value
+ * numbering, inlining, constant folding, strength reduction, etc.
+ */
+public final class GraphBuilderPhase extends Phase {
+
+    /**
+     * The minimum value to which {@link C1XOptions#TraceBytecodeParserLevel} must be set to trace
+     * the bytecode instructions as they are parsed.
+     */
+    public static final int TRACELEVEL_INSTRUCTIONS = 1;
+
+    /**
+     * The minimum value to which {@link C1XOptions#TraceBytecodeParserLevel} must be set to trace
+     * the frame state before each bytecode instruction as it is parsed.
+     */
+    public static final int TRACELEVEL_STATE = 2;
+
+    private final C1XCompilation compilation;
+    private CompilerGraph graph;
+
+    private final CiStatistics stats;
+    private final RiRuntime runtime;
+    private final RiMethod method;
+    private final RiConstantPool constantPool;
+
+    private final BytecodeStream stream;           // the bytecode stream
+    private final LogStream log;
+    private FrameStateBuilder frameState;          // the current execution state
+
+    // bci-to-block mapping
+    private Block[] blockFromBci;
+    private ArrayList<Block> blockList;
+
+    private int nextBlockNumber;
+
+    private Value methodSynchronizedObject;
+    private CiExceptionHandler syncHandler;
+
+    private Block unwindBlock;
+    private Block returnBlock;
+
+    // the worklist of blocks, sorted by depth first number
+    private final PriorityQueue<Block> workList = new PriorityQueue<Block>(10, new Comparator<Block>() {
+        public int compare(Block o1, Block o2) {
+            return o1.blockID - o2.blockID;
+        }
+    });
+
+    private Instruction lastInstr;                 // the last instruction added
+
+    private final Set<Block> blocksOnWorklist = new HashSet<Block>();
+    private final Set<Block> blocksVisited = new HashSet<Block>();
+
+    private final boolean createUnwind;
+
+
+    /**
+     * Creates a new, initialized, {@code GraphBuilder} instance for a given compilation.
+     *
+     * @param compilation the compilation
+     * @param ir the IR to build the graph into
+     * @param graph
+     */
+    public GraphBuilderPhase(C1XCompilation compilation, RiMethod method, boolean createUnwind) {
+        this.compilation = compilation;
+
+        this.runtime = compilation.runtime;
+        this.method = method;
+        this.stats = compilation.stats;
+        this.log = C1XOptions.TraceBytecodeParserLevel > 0 ? new LogStream(TTY.out()) : null;
+        this.stream = new BytecodeStream(method.code());
+
+        this.constantPool = runtime.getConstantPool(method);
+        this.createUnwind = createUnwind;
+    }
+
+    @Override
+    protected void run(Graph graph) {
+        assert graph != null;
+        this.graph = (CompilerGraph) graph;
+        this.frameState = new FrameStateBuilder(method, graph);
+        build();
+    }
+
+    /**
+     * Builds the graph for a the specified {@code IRScope}.
+     *
+     * @param createUnwind setting this to true will always generate an unwind block, even if there is no exception
+     *            handler and the method is not synchronized
+     */
+    private void build() {
+        if (log != null) {
+            log.println();
+            log.println("Compiling " + method);
+        }
+
+        // 2. compute the block map, setup exception handlers and get the entrypoint(s)
+        BlockMap blockMap = compilation.getBlockMap(method);
+
+        blockList = new ArrayList<Block>(blockMap.blocks);
+        blockFromBci = new Block[method.code().length];
+        for (int i = 0; i < blockList.size(); i++) {
+            int blockID = nextBlockNumber();
+            assert blockID == i;
+            Block block = blockList.get(i);
+            if (block.startBci >= 0) {
+                blockFromBci[block.startBci] = block;
+            }
+        }
+
+        // 1. create the start block
+        Block startBlock = nextBlock(Instruction.SYNCHRONIZATION_ENTRY_BCI);
+        markOnWorkList(startBlock);
+        lastInstr = createTarget(startBlock, frameState);
+        graph.start().setStart(lastInstr);
+
+        if (isSynchronized(method.accessFlags())) {
+            // 4A.1 add a monitor enter to the start block
+            methodSynchronizedObject = synchronizedObject(frameState, method);
+            genMonitorEnter(methodSynchronizedObject, Instruction.SYNCHRONIZATION_ENTRY_BCI);
+            // 4A.2 finish the start block
+            finishStartBlock(startBlock);
+
+            // 4A.3 setup an exception handler to unlock the root method synchronized object
+            syncHandler = new CiExceptionHandler(0, method.code().length, Instruction.SYNCHRONIZATION_ENTRY_BCI, 0, null);
+        } else {
+            // 4B.1 simply finish the start block
+            finishStartBlock(startBlock);
+
+            if (createUnwind) {
+                syncHandler = new CiExceptionHandler(0, method.code().length, Instruction.SYNCHRONIZATION_ENTRY_BCI, 0, null);
+            }
+        }
+
+        // 5. SKIPPED: look for intrinsics
+
+        // 6B.1 do the normal parsing
+        addToWorkList(blockFromBci[0]);
+        iterateAllBlocks();
+
+        // remove Placeholders
+        for (Node n : graph.getNodes()) {
+            if (n instanceof Placeholder) {
+                Placeholder p = (Placeholder) n;
+                assert p.blockPredecessors().size() == 1;
+                Node pred = p.blockPredecessors().get(0);
+                int predIndex = p.predecessorsIndex().get(0);
+                pred.successors().setAndClear(predIndex, p, 0);
+                p.delete();
+            }
+        }
+
+        // remove FrameStates
+        for (Node n : graph.getNodes()) {
+            if (n instanceof FrameState) {
+                boolean delete = false;
+                if (n.usages().size() == 0 && n.predecessors().size() == 0) {
+                    delete = true;
+                }
+                if (delete) {
+                    n.delete();
+                }
+            }
+        }
+    }
+
+    private int nextBlockNumber() {
+        stats.blockCount++;
+        return nextBlockNumber++;
+    }
+
+    private Block nextBlock(int bci) {
+        Block block = new Block();
+        block.startBci = bci;
+        block.endBci = bci;
+        block.blockID = nextBlockNumber();
+        return block;
+    }
+
+    private Block unwindBlock() {
+        if (unwindBlock == null) {
+            unwindBlock = new Block();
+            unwindBlock.startBci = Instruction.SYNCHRONIZATION_ENTRY_BCI;
+            unwindBlock.endBci = Instruction.SYNCHRONIZATION_ENTRY_BCI;
+            unwindBlock.blockID = nextBlockNumber();
+            addToWorkList(unwindBlock);
+        }
+        return unwindBlock;
+    }
+
+    private Block returnBlock() {
+        if (returnBlock == null) {
+            returnBlock = new Block();
+            returnBlock.startBci = Instruction.SYNCHRONIZATION_ENTRY_BCI;
+            returnBlock.endBci = Instruction.SYNCHRONIZATION_ENTRY_BCI;
+            returnBlock.blockID = nextBlockNumber();
+            addToWorkList(returnBlock);
+        }
+        return returnBlock;
+    }
+
+    private void markOnWorkList(Block block) {
+        blocksOnWorklist.add(block);
+    }
+
+    private boolean isOnWorkList(Block block) {
+        return blocksOnWorklist.contains(block);
+    }
+
+    private void markVisited(Block block) {
+        blocksVisited.add(block);
+    }
+
+    private boolean isVisited(Block block) {
+        return blocksVisited.contains(block);
+    }
+
+    private void finishStartBlock(Block startBlock) {
+        assert bci() == 0;
+        Instruction target = createTargetAt(0, frameState);
+        appendGoto(target);
+    }
+
+    public void mergeOrClone(Block target, FrameStateAccess newState) {
+        Instruction first = target.firstInstruction;
+        if (target.isLoopHeader && isVisited(target)) {
+            first = ((LoopBegin) first).loopEnd();
+        }
+        assert first instanceof StateSplit;
+
+        int bci = target.startBci;
+
+        FrameState existingState = ((StateSplit) first).stateBefore();
+
+        if (existingState == null) {
+            // copy state because it is modified
+            FrameState duplicate = newState.duplicate(bci);
+
+            // if the block is a loop header, insert all necessary phis
+            if (first instanceof LoopBegin && target.isLoopHeader) {
+                assert first instanceof Merge;
+                insertLoopPhis((Merge) first, duplicate);
+                ((Merge) first).setStateBefore(duplicate);
+            } else {
+                ((StateSplit) first).setStateBefore(duplicate);
+            }
+        } else {
+            if (!C1XOptions.AssumeVerifiedBytecode && !existingState.isCompatibleWith(newState)) {
+                // stacks or locks do not match--bytecodes would not verify
+                TTY.println(existingState.toString());
+                TTY.println(newState.duplicate(0).toString());
+                throw new CiBailout("stack or locks do not match");
+            }
+            assert existingState.localsSize() == newState.localsSize();
+            assert existingState.stackSize() == newState.stackSize();
+
+            if (first instanceof Placeholder) {
+                assert !target.isLoopHeader;
+                Merge merge = new Merge(graph);
+
+                Placeholder p = (Placeholder) first;
+                assert p.next() == null;
+                p.replace(merge);
+                target.firstInstruction = merge;
+                merge.setStateBefore(existingState);
+                first = merge;
+            }
+
+            existingState.merge((Merge) first, newState);
+        }
+
+        for (int j = 0; j < frameState.localsSize() + frameState.stackSize(); ++j) {
+            if (frameState.valueAt(j) != null) {
+                assert !frameState.valueAt(j).isDeleted();
+            }
+        }
+    }
+
+    private void insertLoopPhis(Merge merge, FrameState newState) {
+        int stackSize = newState.stackSize();
+        for (int i = 0; i < stackSize; i++) {
+            // always insert phis for the stack
+            Value x = newState.stackAt(i);
+            if (x != null) {
+                newState.setupPhiForStack(merge, i).addInput(x);
+            }
+        }
+        int localsSize = newState.localsSize();
+        for (int i = 0; i < localsSize; i++) {
+            Value x = newState.localAt(i);
+            if (x != null) {
+                newState.setupPhiForLocal(merge, i).addInput(x);
+            }
+        }
+    }
+
+    public BytecodeStream stream() {
+        return stream;
+    }
+
+    public int bci() {
+        return stream.currentBCI();
+    }
+
+    private void loadLocal(int index, CiKind kind) {
+        frameState.push(kind, frameState.loadLocal(index));
+    }
+
+    private void storeLocal(CiKind kind, int index) {
+        frameState.storeLocal(index, frameState.pop(kind));
+    }
+
+    public boolean covers(RiExceptionHandler handler, int bci) {
+        return handler.startBCI() <= bci && bci < handler.endBCI();
+    }
+
+    public boolean isCatchAll(RiExceptionHandler handler) {
+        return handler.catchTypeCPI() == 0;
+    }
+
+    private Instruction handleException(Value exceptionObject, int bci) {
+        assert bci == Instruction.SYNCHRONIZATION_ENTRY_BCI || bci == bci() : "invalid bci";
+
+        RiExceptionHandler firstHandler = null;
+        RiExceptionHandler[] exceptionHandlers = method.exceptionHandlers();
+        // join with all potential exception handlers
+        if (exceptionHandlers != null) {
+            for (RiExceptionHandler handler : exceptionHandlers) {
+                // if the handler covers this bytecode index, add it to the list
+                if (covers(handler, bci)) {
+                    firstHandler = handler;
+                    break;
+                }
+            }
+        }
+
+        if (firstHandler == null) {
+            firstHandler = syncHandler;
+        }
+
+        if (firstHandler != null) {
+            compilation.setHasExceptionHandlers();
+
+            Block dispatchBlock = null;
+            for (Block block : blockList) {
+                if (block instanceof ExceptionBlock) {
+                    ExceptionBlock excBlock = (ExceptionBlock) block;
+                    if (excBlock.handler == firstHandler) {
+                        dispatchBlock = block;
+                        break;
+                    }
+                }
+            }
+            // if there's no dispatch block then the catch block needs to be a catch all
+            if (dispatchBlock == null) {
+                assert isCatchAll(firstHandler);
+                int handlerBCI = firstHandler.handlerBCI();
+                if (handlerBCI == Instruction.SYNCHRONIZATION_ENTRY_BCI) {
+                    dispatchBlock = unwindBlock();
+                } else {
+                    dispatchBlock = blockFromBci[handlerBCI];
+                }
+            }
+            FrameState entryState = frameState.duplicateWithEmptyStack(bci);
+
+            StateSplit entry = new Placeholder(graph);
+            entry.setStateBefore(entryState);
+
+            Instruction currentNext = entry;
+            Value currentExceptionObject = exceptionObject;
+            if (currentExceptionObject == null) {
+                ExceptionObject exception = new ExceptionObject(graph);
+                entry.setNext(exception);
+                currentNext = exception;
+                currentExceptionObject = exception;
+            }
+            FrameState stateWithException = entryState.duplicateModified(bci, CiKind.Void, currentExceptionObject);
+
+            Instruction successor = createTarget(dispatchBlock, stateWithException);
+            currentNext.setNext(successor);
+            return entry;
+        }
+        return null;
+    }
+
+    private void genLoadConstant(int cpi) {
+        Object con = constantPool.lookupConstant(cpi);
+
+        if (con instanceof RiType) {
+            // this is a load of class constant which might be unresolved
+            RiType riType = (RiType) con;
+            if (!riType.isResolved()) {
+                append(new Deoptimize(graph));
+                frameState.push(CiKind.Object, append(Constant.forObject(null, graph)));
+            } else {
+                frameState.push(CiKind.Object, append(new Constant(riType.getEncoding(Representation.JavaClass), graph)));
+            }
+        } else if (con instanceof CiConstant) {
+            CiConstant constant = (CiConstant) con;
+            frameState.push(constant.kind.stackKind(), appendConstant(constant));
+        } else {
+            throw new Error("lookupConstant returned an object of incorrect type");
+        }
+    }
+
+    private void genLoadIndexed(CiKind kind) {
+        Value index = frameState.ipop();
+        Value array = frameState.apop();
+        Value length = append(new ArrayLength(array, graph));
+        Value v = append(new LoadIndexed(array, index, length, kind, graph));
+        frameState.push(kind.stackKind(), v);
+    }
+
+    private void genStoreIndexed(CiKind kind) {
+        Value value = frameState.pop(kind.stackKind());
+        Value index = frameState.ipop();
+        Value array = frameState.apop();
+        Value length = append(new ArrayLength(array, graph));
+        StoreIndexed result = new StoreIndexed(array, index, length, kind, value, graph);
+        append(result);
+    }
+
+    private void stackOp(int opcode) {
+        switch (opcode) {
+            case POP: {
+                frameState.xpop();
+                break;
+            }
+            case POP2: {
+                frameState.xpop();
+                frameState.xpop();
+                break;
+            }
+            case DUP: {
+                Value w = frameState.xpop();
+                frameState.xpush(w);
+                frameState.xpush(w);
+                break;
+            }
+            case DUP_X1: {
+                Value w1 = frameState.xpop();
+                Value w2 = frameState.xpop();
+                frameState.xpush(w1);
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                break;
+            }
+            case DUP_X2: {
+                Value w1 = frameState.xpop();
+                Value w2 = frameState.xpop();
+                Value w3 = frameState.xpop();
+                frameState.xpush(w1);
+                frameState.xpush(w3);
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                break;
+            }
+            case DUP2: {
+                Value w1 = frameState.xpop();
+                Value w2 = frameState.xpop();
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                break;
+            }
+            case DUP2_X1: {
+                Value w1 = frameState.xpop();
+                Value w2 = frameState.xpop();
+                Value w3 = frameState.xpop();
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                frameState.xpush(w3);
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                break;
+            }
+            case DUP2_X2: {
+                Value w1 = frameState.xpop();
+                Value w2 = frameState.xpop();
+                Value w3 = frameState.xpop();
+                Value w4 = frameState.xpop();
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                frameState.xpush(w4);
+                frameState.xpush(w3);
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                break;
+            }
+            case SWAP: {
+                Value w1 = frameState.xpop();
+                Value w2 = frameState.xpop();
+                frameState.xpush(w1);
+                frameState.xpush(w2);
+                break;
+            }
+            default:
+                throw Util.shouldNotReachHere();
+        }
+
+    }
+
+    private void genArithmeticOp(CiKind kind, int opcode) {
+        genArithmeticOp(kind, opcode, false);
+    }
+
+    private void genArithmeticOp(CiKind result, int opcode, boolean canTrap) {
+        Value y = frameState.pop(result);
+        Value x = frameState.pop(result);
+        boolean isStrictFP = isStrict(method.accessFlags());
+        Arithmetic v;
+        switch(opcode){
+            case IADD:
+            case LADD: v = new IntegerAdd(result, x, y, graph); break;
+            case FADD:
+            case DADD: v = new FloatAdd(result, x, y, isStrictFP, graph); break;
+            case ISUB:
+            case LSUB: v = new IntegerSub(result, x, y, graph); break;
+            case FSUB:
+            case DSUB: v = new FloatSub(result, x, y, isStrictFP, graph); break;
+            case IMUL:
+            case LMUL: v = new IntegerMul(result, x, y, graph); break;
+            case FMUL:
+            case DMUL: v = new FloatMul(result, x, y, isStrictFP, graph); break;
+            case IDIV:
+            case LDIV: v = new IntegerDiv(result, x, y, graph); break;
+            case FDIV:
+            case DDIV: v = new FloatDiv(result, x, y, isStrictFP, graph); break;
+            case IREM:
+            case LREM: v = new IntegerRem(result, x, y, graph); break;
+            case FREM:
+            case DREM: v = new FloatRem(result, x, y, isStrictFP, graph); break;
+            default:
+                throw new CiBailout("should not reach");
+        }
+        Value result1 = append(v);
+        if (canTrap) {
+            append(new ValueAnchor(result1, graph));
+        }
+        frameState.push(result, result1);
+    }
+
+    private void genNegateOp(CiKind kind) {
+        frameState.push(kind, append(new Negate(frameState.pop(kind), graph)));
+    }
+
+    private void genShiftOp(CiKind kind, int opcode) {
+        Value s = frameState.ipop();
+        Value x = frameState.pop(kind);
+        Shift v;
+        switch(opcode){
+            case ISHL:
+            case LSHL: v = new LeftShift(kind, x, s, graph); break;
+            case ISHR:
+            case LSHR: v = new RightShift(kind, x, s, graph); break;
+            case IUSHR:
+            case LUSHR: v = new UnsignedRightShift(kind, x, s, graph); break;
+            default:
+                throw new CiBailout("should not reach");
+        }
+        frameState.push(kind, append(v));
+    }
+
+    private void genLogicOp(CiKind kind, int opcode) {
+        Value y = frameState.pop(kind);
+        Value x = frameState.pop(kind);
+        Logic v;
+        switch(opcode){
+            case IAND:
+            case LAND: v = new And(kind, x, y, graph); break;
+            case IOR:
+            case LOR: v = new Or(kind, x, y, graph); break;
+            case IXOR:
+            case LXOR: v = new Xor(kind, x, y, graph); break;
+            default:
+                throw new CiBailout("should not reach");
+        }
+        frameState.push(kind, append(v));
+    }
+
+    private void genCompareOp(CiKind kind, int opcode, CiKind resultKind) {
+        Value y = frameState.pop(kind);
+        Value x = frameState.pop(kind);
+        Value value = append(new NormalizeCompare(opcode, resultKind, x, y, graph));
+        if (!resultKind.isVoid()) {
+            frameState.ipush(value);
+        }
+    }
+
+    private void genConvert(int opcode, CiKind from, CiKind to) {
+        CiKind tt = to.stackKind();
+        frameState.push(tt, append(new Convert(opcode, frameState.pop(from.stackKind()), tt, graph)));
+    }
+
+    private void genIncrement() {
+        int index = stream().readLocalIndex();
+        int delta = stream().readIncrement();
+        Value x = frameState.localAt(index);
+        Value y = append(Constant.forInt(delta, graph));
+        frameState.storeLocal(index, append(new IntegerAdd(CiKind.Int, x, y, graph)));
+    }
+
+    private void genGoto(int fromBCI, int toBCI) {
+        appendGoto(createTargetAt(toBCI, frameState));
+    }
+
+    private void ifNode(Value x, Condition cond, Value y) {
+        assert !x.isDeleted() && !y.isDeleted();
+        If ifNode = new If(new Compare(x, cond, y, graph), graph);
+        append(ifNode);
+        Instruction tsucc = createTargetAt(stream().readBranchDest(), frameState);
+        ifNode.setBlockSuccessor(0, tsucc);
+        Instruction fsucc = createTargetAt(stream().nextBCI(), frameState);
+        ifNode.setBlockSuccessor(1, fsucc);
+    }
+
+    private void genIfZero(Condition cond) {
+        Value y = appendConstant(CiConstant.INT_0);
+        Value x = frameState.ipop();
+        ifNode(x, cond, y);
+    }
+
+    private void genIfNull(Condition cond) {
+        Value y = appendConstant(CiConstant.NULL_OBJECT);
+        Value x = frameState.apop();
+        ifNode(x, cond, y);
+    }
+
+    private void genIfSame(CiKind kind, Condition cond) {
+        Value y = frameState.pop(kind);
+        Value x = frameState.pop(kind);
+        assert !x.isDeleted() && !y.isDeleted();
+        ifNode(x, cond, y);
+    }
+
+    private void genThrow(int bci) {
+        Value exception = frameState.apop();
+        append(new NullCheck(exception, graph));
+
+        Instruction entry = handleException(exception, bci);
+        if (entry != null) {
+            append(entry);
+        } else {
+            frameState.clearStack();
+            frameState.apush(exception);
+            appendGoto(createTarget(unwindBlock(), frameState));
+        }
+    }
+
+    private void genCheckCast() {
+        int cpi = stream().readCPI();
+        RiType type = constantPool.lookupType(cpi, CHECKCAST);
+        boolean isInitialized = type.isResolved();
+        Value typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, isInitialized, cpi);
+        Value object = frameState.apop();
+        if (typeInstruction != null) {
+            frameState.apush(append(new CheckCast(type, typeInstruction, object, graph)));
+        } else {
+            frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
+        }
+    }
+
+    private void genInstanceOf() {
+        int cpi = stream().readCPI();
+        RiType type = constantPool.lookupType(cpi, INSTANCEOF);
+        boolean isInitialized = type.isResolved();
+        Value typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, isInitialized, cpi);
+        Value object = frameState.apop();
+        if (typeInstruction != null) {
+            frameState.ipush(append(new InstanceOf(type, typeInstruction, object, graph)));
+        } else {
+            frameState.ipush(appendConstant(CiConstant.INT_0));
+        }
+    }
+
+    void genNewInstance(int cpi) {
+        RiType type = constantPool.lookupType(cpi, NEW);
+        if (type.isResolved()) {
+            NewInstance n = new NewInstance(type, cpi, constantPool, graph);
+            frameState.apush(append(n));
+        } else {
+            append(new Deoptimize(graph));
+            frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
+        }
+    }
+
+    private void genNewTypeArray(int typeCode) {
+        CiKind kind = CiKind.fromArrayTypeCode(typeCode);
+        RiType elementType = runtime.asRiType(kind);
+        NewTypeArray nta = new NewTypeArray(frameState.ipop(), elementType, graph);
+        frameState.apush(append(nta));
+    }
+
+    private void genNewObjectArray(int cpi) {
+        RiType type = constantPool.lookupType(cpi, ANEWARRAY);
+        Value length = frameState.ipop();
+        if (type.isResolved()) {
+            NewArray n = new NewObjectArray(type, length, graph);
+            frameState.apush(append(n));
+        } else {
+            append(new Deoptimize(graph));
+            frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
+        }
+
+    }
+
+    private void genNewMultiArray(int cpi) {
+        RiType type = constantPool.lookupType(cpi, MULTIANEWARRAY);
+        int rank = stream().readUByte(bci() + 3);
+        Value[] dims = new Value[rank];
+        for (int i = rank - 1; i >= 0; i--) {
+            dims[i] = frameState.ipop();
+        }
+        if (type.isResolved()) {
+            NewArray n = new NewMultiArray(type, dims, cpi, constantPool, graph);
+            frameState.apush(append(n));
+        } else {
+            append(new Deoptimize(graph));
+            frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
+        }
+    }
+
+    private void genGetField(int cpi, RiField field) {
+        CiKind kind = field.kind();
+        Value receiver = frameState.apop();
+        if (field.isResolved()) {
+            LoadField load = new LoadField(receiver, field, graph);
+            appendOptimizedLoadField(kind, load);
+        } else {
+            append(new Deoptimize(graph));
+            frameState.push(kind.stackKind(), append(Constant.defaultForKind(kind, graph)));
+        }
+    }
+
+    private void genPutField(int cpi, RiField field) {
+        Value value = frameState.pop(field.kind().stackKind());
+        Value receiver = frameState.apop();
+        if (field.isResolved()) {
+            StoreField store = new StoreField(receiver, field, value, graph);
+            appendOptimizedStoreField(store);
+        } else {
+            append(new Deoptimize(graph));
+        }
+    }
+
+    private void genGetStatic(int cpi, RiField field) {
+        RiType holder = field.holder();
+        boolean isInitialized = field.isResolved();
+        CiConstant constantValue = null;
+        if (isInitialized) {
+            constantValue = field.constantValue(null);
+        }
+        if (constantValue != null) {
+            frameState.push(constantValue.kind.stackKind(), appendConstant(constantValue));
+        } else {
+            Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized, cpi);
+            CiKind kind = field.kind();
+            if (container != null) {
+                LoadField load = new LoadField(container, field, graph);
+                appendOptimizedLoadField(kind, load);
+            } else {
+                append(new Deoptimize(graph));
+                frameState.push(kind.stackKind(), append(Constant.defaultForKind(kind, graph)));
+            }
+        }
+    }
+
+    private void genPutStatic(int cpi, RiField field) {
+        RiType holder = field.holder();
+        Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, field.isResolved(), cpi);
+        Value value = frameState.pop(field.kind().stackKind());
+        if (container != null) {
+            StoreField store = new StoreField(container, field, value, graph);
+            appendOptimizedStoreField(store);
+        } else {
+            append(new Deoptimize(graph));
+        }
+    }
+
+    private Value genTypeOrDeopt(RiType.Representation representation, RiType holder, boolean initialized, int cpi) {
+        if (initialized) {
+            return appendConstant(holder.getEncoding(representation));
+        } else {
+            append(new Deoptimize(graph));
+            return null;
+        }
+    }
+
+    private void appendOptimizedStoreField(StoreField store) {
+        append(store);
+    }
+
+    private void appendOptimizedLoadField(CiKind kind, LoadField load) {
+        // append the load to the instruction
+        Value optimized = append(load);
+        frameState.push(kind.stackKind(), optimized);
+    }
+
+    private void genInvokeStatic(RiMethod target, int cpi, RiConstantPool constantPool) {
+        RiType holder = target.holder();
+        boolean isInitialized = target.isResolved() && holder.isInitialized();
+        if (!isInitialized && C1XOptions.ResolveClassBeforeStaticInvoke) {
+            // Re-use the same resolution code as for accessing a static field. Even though
+            // the result of resolution is not used by the invocation (only the side effect
+            // of initialization is required), it can be commoned with static field accesses.
+            genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized, cpi);
+        }
+        Value[] args = frameState.popArguments(target.signature().argumentSlots(false));
+        appendInvoke(INVOKESTATIC, target, args, cpi, constantPool);
+    }
+
+    private void genInvokeInterface(RiMethod target, int cpi, RiConstantPool constantPool) {
+        Value[] args = frameState.popArguments(target.signature().argumentSlots(true));
+        genInvokeIndirect(INVOKEINTERFACE, target, args, cpi, constantPool);
+
+    }
+
+    private void genInvokeVirtual(RiMethod target, int cpi, RiConstantPool constantPool) {
+        Value[] args = frameState.popArguments(target.signature().argumentSlots(true));
+        genInvokeIndirect(INVOKEVIRTUAL, target, args, cpi, constantPool);
+
+    }
+
+    private void genInvokeSpecial(RiMethod target, RiType knownHolder, int cpi, RiConstantPool constantPool) {
+        Value[] args = frameState.popArguments(target.signature().argumentSlots(true));
+        invokeDirect(target, args, knownHolder, cpi, constantPool);
+
+    }
+
+    private void genInvokeIndirect(int opcode, RiMethod target, Value[] args, int cpi, RiConstantPool constantPool) {
+        Value receiver = args[0];
+        // attempt to devirtualize the call
+        if (target.isResolved()) {
+            RiType klass = target.holder();
+
+            // 0. check for trivial cases
+            if (target.canBeStaticallyBound() && !isAbstract(target.accessFlags())) {
+                // check for trivial cases (e.g. final methods, nonvirtual methods)
+                invokeDirect(target, args, target.holder(), cpi, constantPool);
+                return;
+            }
+            // 1. check if the exact type of the receiver can be determined
+            RiType exact = getExactType(klass, receiver);
+            if (exact != null && exact.isResolved()) {
+                // either the holder class is exact, or the receiver object has an exact type
+                invokeDirect(exact.resolveMethodImpl(target), args, exact, cpi, constantPool);
+                return;
+            }
+        }
+        // devirtualization failed, produce an actual invokevirtual
+        appendInvoke(opcode, target, args, cpi, constantPool);
+    }
+
+    private CiKind returnKind(RiMethod target) {
+        return target.signature().returnKind();
+    }
+
+    private void invokeDirect(RiMethod target, Value[] args, RiType knownHolder, int cpi, RiConstantPool constantPool) {
+        appendInvoke(INVOKESPECIAL, target, args, cpi, constantPool);
+    }
+
+    private void appendInvoke(int opcode, RiMethod target, Value[] args, int cpi, RiConstantPool constantPool) {
+        CiKind resultType = returnKind(target);
+        Invoke invoke = new Invoke(bci(), opcode, resultType.stackKind(), args, target, target.signature().returnType(method.holder()), graph);
+        Value result = appendWithBCI(invoke);
+        invoke.setExceptionEdge(handleException(null, bci()));
+        frameState.pushReturn(resultType, result);
+    }
+
+    private RiType getExactType(RiType staticType, Value receiver) {
+        RiType exact = staticType.exactType();
+        if (exact == null) {
+            exact = receiver.exactType();
+            if (exact == null) {
+                if (receiver.isConstant()) {
+                    exact = runtime.getTypeOf(receiver.asConstant());
+                }
+                if (exact == null) {
+                    RiType declared = receiver.declaredType();
+                    exact = declared == null || !declared.isResolved() ? null : declared.exactType();
+                }
+            }
+        }
+        return exact;
+    }
+
+    private void callRegisterFinalizer() {
+        Value receiver = frameState.loadLocal(0);
+        RiType declaredType = receiver.declaredType();
+        RiType receiverType = declaredType;
+        RiType exactType = receiver.exactType();
+        if (exactType == null && declaredType != null) {
+            exactType = declaredType.exactType();
+        }
+        if (exactType == null && receiver instanceof Local && ((Local) receiver).index() == 0) {
+            // the exact type isn't known, but the receiver is parameter 0 => use holder
+            receiverType = method.holder();
+            exactType = receiverType.exactType();
+        }
+        boolean needsCheck = true;
+        if (exactType != null) {
+            // we have an exact type
+            needsCheck = exactType.hasFinalizer();
+        } else {
+            // if either the declared type of receiver or the holder can be assumed to have no finalizers
+            if (declaredType != null && !declaredType.hasFinalizableSubclass()) {
+                if (compilation.recordNoFinalizableSubclassAssumption(declaredType)) {
+                    needsCheck = false;
+                }
+            }
+
+            if (receiverType != null && !receiverType.hasFinalizableSubclass()) {
+                if (compilation.recordNoFinalizableSubclassAssumption(receiverType)) {
+                    needsCheck = false;
+                }
+            }
+        }
+
+        if (needsCheck) {
+            // append a call to the finalizer registration
+            append(new RegisterFinalizer(frameState.loadLocal(0), frameState.create(bci()), graph));
+            C1XMetrics.InlinedFinalizerChecks++;
+        }
+    }
+
+    private void genReturn(Value x) {
+        frameState.clearStack();
+        if (x != null) {
+            frameState.push(x.kind, x);
+        }
+        appendGoto(createTarget(returnBlock(), frameState));
+    }
+
+    private void genMonitorEnter(Value x, int bci) {
+        int lockNumber = frameState.locksSize();
+        MonitorAddress lockAddress = null;
+        if (runtime.sizeOfBasicObjectLock() != 0) {
+            lockAddress = new MonitorAddress(lockNumber, graph);
+            append(lockAddress);
+        }
+        MonitorEnter monitorEnter = new MonitorEnter(x, lockAddress, lockNumber, graph);
+        appendWithBCI(monitorEnter);
+        frameState.lock(x);
+        if (bci == Instruction.SYNCHRONIZATION_ENTRY_BCI) {
+            monitorEnter.setStateAfter(frameState.create(0));
+        }
+    }
+
+    private void genMonitorExit(Value x) {
+        int lockNumber = frameState.locksSize() - 1;
+        if (lockNumber < 0) {
+            throw new CiBailout("monitor stack underflow");
+        }
+        MonitorAddress lockAddress = null;
+        if (runtime.sizeOfBasicObjectLock() != 0) {
+            lockAddress = new MonitorAddress(lockNumber, graph);
+            append(lockAddress);
+        }
+        appendWithBCI(new MonitorExit(x, lockAddress, lockNumber, graph));
+        frameState.unlock();
+    }
+
+    private void genJsr(int dest) {
+        throw new CiBailout("jsr/ret not supported");
+    }
+
+    private void genRet(int localIndex) {
+        throw new CiBailout("jsr/ret not supported");
+    }
+
+    private void genTableswitch() {
+        int bci = bci();
+        Value value = frameState.ipop();
+        BytecodeTableSwitch ts = new BytecodeTableSwitch(stream(), bci);
+        int max = ts.numberOfCases();
+        List<Instruction> list = new ArrayList<Instruction>(max + 1);
+        List<Integer> offsetList = new ArrayList<Integer>(max + 1);
+        for (int i = 0; i < max; i++) {
+            // add all successors to the successor list
+            int offset = ts.offsetAt(i);
+            list.add(null);
+            offsetList.add(offset);
+        }
+        int offset = ts.defaultOffset();
+        list.add(null);
+        offsetList.add(offset);
+        TableSwitch tableSwitch = new TableSwitch(value, list, ts.lowKey(), graph);
+        for (int i = 0; i < offsetList.size(); ++i) {
+            tableSwitch.setBlockSuccessor(i, createTargetAt(bci + offsetList.get(i), frameState));
+        }
+        append(tableSwitch);
+    }
+
+    private void genLookupswitch() {
+        int bci = bci();
+        Value value = frameState.ipop();
+        BytecodeLookupSwitch ls = new BytecodeLookupSwitch(stream(), bci);
+        int max = ls.numberOfCases();
+        List<Instruction> list = new ArrayList<Instruction>(max + 1);
+        List<Integer> offsetList = new ArrayList<Integer>(max + 1);
+        int[] keys = new int[max];
+        for (int i = 0; i < max; i++) {
+            // add all successors to the successor list
+            int offset = ls.offsetAt(i);
+            list.add(null);
+            offsetList.add(offset);
+            keys[i] = ls.keyAt(i);
+        }
+        int offset = ls.defaultOffset();
+        list.add(null);
+        offsetList.add(offset);
+        LookupSwitch lookupSwitch = new LookupSwitch(value, list, keys, graph);
+        for (int i = 0; i < offsetList.size(); ++i) {
+            lookupSwitch.setBlockSuccessor(i, createTargetAt(bci + offsetList.get(i), frameState));
+        }
+        append(lookupSwitch);
+    }
+
+    private Value appendConstant(CiConstant constant) {
+        return append(new Constant(constant, graph));
+    }
+
+    private Value append(Instruction x) {
+        return appendWithBCI(x);
+    }
+
+    private Value append(Value v) {
+        return v;
+    }
+
+    private Value appendWithBCI(Instruction x) {
+        assert x.predecessors().size() == 0 : "instruction should not have been appended yet";
+        assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")";
+        lastInstr.setNext(x);
+
+        lastInstr = x;
+        if (++stats.nodeCount >= C1XOptions.MaximumInstructionCount) {
+            // bailout if we've exceeded the maximum inlining size
+            throw new CiBailout("Method and/or inlining is too large");
+        }
+
+        return x;
+    }
+
+    private Instruction createTargetAt(int bci, FrameStateAccess stateAfter) {
+        return createTarget(blockFromBci[bci], stateAfter);
+    }
+
+    private Instruction createTarget(Block block, FrameStateAccess stateAfter) {
+        assert block != null && stateAfter != null;
+        assert block.isLoopHeader || block.firstInstruction == null || block.firstInstruction.next() == null : "non-loop block must be iterated after all its predecessors";
+
+        if (block.isExceptionEntry) {
+            assert stateAfter.stackSize() == 1;
+        }
+
+        if (block.firstInstruction == null) {
+            if (block.isLoopHeader) {
+//                block.firstInstruction = new Merge(block.startBci, graph);
+
+                LoopBegin loopBegin = new LoopBegin(graph);
+                LoopEnd loopEnd = new LoopEnd(graph);
+                loopEnd.setLoopBegin(loopBegin);
+                block.firstInstruction = loopBegin;
+            } else {
+                block.firstInstruction = new Placeholder(graph);
+            }
+        }
+        mergeOrClone(block, stateAfter);
+        addToWorkList(block);
+
+        if (block.firstInstruction instanceof LoopBegin && isVisited(block)) {
+            return ((LoopBegin) block.firstInstruction).loopEnd();
+        } else {
+            return block.firstInstruction;
+        }
+    }
+
+    private Value synchronizedObject(FrameStateAccess state, RiMethod target) {
+        if (isStatic(target.accessFlags())) {
+            Constant classConstant = new Constant(target.holder().getEncoding(Representation.JavaClass), graph);
+            return append(classConstant);
+        } else {
+            return state.localAt(0);
+        }
+    }
+
+    private void iterateAllBlocks() {
+        Block block;
+        while ((block = removeFromWorkList()) != null) {
+
+            // remove blocks that have no predecessors by the time it their bytecodes are parsed
+            if (block.firstInstruction == null) {
+                markVisited(block);
+                continue;
+            }
+
+            if (!isVisited(block)) {
+                markVisited(block);
+                // now parse the block
+                frameState.initializeFrom(((StateSplit) block.firstInstruction).stateBefore());
+                lastInstr = block.firstInstruction;
+                assert block.firstInstruction.next() == null : "instructions already appended at block " + block.blockID;
+
+                if (block == returnBlock) {
+                    createReturnBlock(block);
+                } else if (block == unwindBlock) {
+                    createUnwindBlock(block);
+                } else if (block instanceof ExceptionBlock) {
+                    createExceptionDispatch((ExceptionBlock) block);
+                } else {
+                    iterateBytecodesForBlock(block);
+                }
+            }
+        }
+        for (Block b : blocksVisited) {
+            if (b.isLoopHeader) {
+                LoopBegin begin = (LoopBegin) b.firstInstruction;
+                LoopEnd end = begin.loopEnd();
+
+//              This can happen with degenerated loops like this one:
+//                for (;;) {
+//                    try {
+//                        break;
+//                    } catch (UnresolvedException iioe) {
+//                    }
+//                }
+                if (end.stateBefore() != null) {
+                    begin.stateBefore().merge(begin, end.stateBefore());
+                } else {
+                    end.delete();
+                    Merge merge = new Merge(graph);
+                    merge.successors().setAndClear(merge.nextIndex(), begin, begin.nextIndex());
+                    begin.replace(merge);
+                }
+            }
+        }
+    }
+
+    private void createUnwindBlock(Block block) {
+        if (Modifier.isSynchronized(method.accessFlags())) {
+            genMonitorExit(methodSynchronizedObject);
+        }
+        append(graph.createUnwind(frameState.apop()));
+    }
+
+    private void createReturnBlock(Block block) {
+        if (method.isConstructor() && method.holder().superType() == null) {
+            callRegisterFinalizer();
+        }
+        CiKind returnKind = method.signature().returnKind().stackKind();
+        Value x = returnKind == CiKind.Void ? null : frameState.pop(returnKind);
+        assert frameState.stackSize() == 0;
+
+        if (Modifier.isSynchronized(method.accessFlags())) {
+            genMonitorExit(methodSynchronizedObject);
+        }
+        append(graph.createReturn(x));
+    }
+
+    private void createExceptionDispatch(ExceptionBlock block) {
+        if (block.handler == null) {
+            assert frameState.stackSize() == 1 : "only exception object expected on stack, actual size: " + frameState.stackSize();
+            createUnwindBlock(block);
+        } else {
+            assert frameState.stackSize() == 1;
+
+            Block nextBlock = block.next == null ? unwindBlock() : block.next;
+            if (block.handler.catchType().isResolved()) {
+                Instruction catchSuccessor = createTarget(blockFromBci[block.handler.handlerBCI()], frameState);
+                Instruction nextDispatch = createTarget(nextBlock, frameState);
+                append(new ExceptionDispatch(frameState.stackAt(0), catchSuccessor, nextDispatch, block.handler.catchType(), graph));
+            } else {
+                Deoptimize deopt = new Deoptimize(graph);
+                deopt.setMessage("unresolved " + block.handler.catchType().name());
+                append(deopt);
+                Instruction nextDispatch = createTarget(nextBlock, frameState);
+                appendGoto(nextDispatch);
+            }
+        }
+    }
+
+    private void appendGoto(Instruction target) {
+        lastInstr.setNext(target);
+    }
+
+    private void iterateBytecodesForBlock(Block block) {
+        assert frameState != null;
+
+        stream.setBCI(block.startBci);
+
+        int endBCI = stream.endBCI();
+        boolean blockStart = true;
+
+        int bci = block.startBci;
+        while (bci < endBCI) {
+            Block nextBlock = blockFromBci[bci];
+            if (nextBlock != null && nextBlock != block) {
+                assert !nextBlock.isExceptionEntry;
+                // we fell through to the next block, add a goto and break
+                appendGoto(createTarget(nextBlock, frameState));
+                break;
+            }
+            // read the opcode
+            int opcode = stream.currentBC();
+
+            traceState();
+            traceInstruction(bci, opcode, blockStart);
+            processBytecode(bci, opcode);
+
+            if (Schedule.isBlockEnd(lastInstr) || lastInstr.next() != null) {
+                break;
+            }
+
+            stream.next();
+            bci = stream.currentBCI();
+            if (lastInstr instanceof StateSplit) {
+                StateSplit stateSplit = (StateSplit) lastInstr;
+                if (stateSplit.stateAfter() == null && stateSplit.needsStateAfter()) {
+                    stateSplit.setStateAfter(frameState.create(bci));
+                }
+            }
+            blockStart = false;
+        }
+    }
+
+    private void traceState() {
+        if (C1XOptions.TraceBytecodeParserLevel >= TRACELEVEL_STATE && !TTY.isSuppressed()) {
+            log.println(String.format("|   state [nr locals = %d, stack depth = %d, method = %s]", frameState.localsSize(), frameState.stackSize(), method));
+            for (int i = 0; i < frameState.localsSize(); ++i) {
+                Value value = frameState.localAt(i);
+                log.println(String.format("|   local[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value));
+            }
+            for (int i = 0; i < frameState.stackSize(); ++i) {
+                Value value = frameState.stackAt(i);
+                log.println(String.format("|   stack[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value));
+            }
+            for (int i = 0; i < frameState.locksSize(); ++i) {
+                Value value = frameState.lockAt(i);
+                log.println(String.format("|   lock[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value));
+            }
+        }
+    }
+
+    private void processBytecode(int bci, int opcode) {
+        int cpi;
+
+        // Checkstyle: stop
+        switch (opcode) {
+            case NOP            : /* nothing to do */ break;
+            case ACONST_NULL    : frameState.apush(appendConstant(CiConstant.NULL_OBJECT)); break;
+            case ICONST_M1      : frameState.ipush(appendConstant(CiConstant.INT_MINUS_1)); break;
+            case ICONST_0       : frameState.ipush(appendConstant(CiConstant.INT_0)); break;
+            case ICONST_1       : frameState.ipush(appendConstant(CiConstant.INT_1)); break;
+            case ICONST_2       : frameState.ipush(appendConstant(CiConstant.INT_2)); break;
+            case ICONST_3       : frameState.ipush(appendConstant(CiConstant.INT_3)); break;
+            case ICONST_4       : frameState.ipush(appendConstant(CiConstant.INT_4)); break;
+            case ICONST_5       : frameState.ipush(appendConstant(CiConstant.INT_5)); break;
+            case LCONST_0       : frameState.lpush(appendConstant(CiConstant.LONG_0)); break;
+            case LCONST_1       : frameState.lpush(appendConstant(CiConstant.LONG_1)); break;
+            case FCONST_0       : frameState.fpush(appendConstant(CiConstant.FLOAT_0)); break;
+            case FCONST_1       : frameState.fpush(appendConstant(CiConstant.FLOAT_1)); break;
+            case FCONST_2       : frameState.fpush(appendConstant(CiConstant.FLOAT_2)); break;
+            case DCONST_0       : frameState.dpush(appendConstant(CiConstant.DOUBLE_0)); break;
+            case DCONST_1       : frameState.dpush(appendConstant(CiConstant.DOUBLE_1)); break;
+            case BIPUSH         : frameState.ipush(appendConstant(CiConstant.forInt(stream.readByte()))); break;
+            case SIPUSH         : frameState.ipush(appendConstant(CiConstant.forInt(stream.readShort()))); break;
+            case LDC            : // fall through
+            case LDC_W          : // fall through
+            case LDC2_W         : genLoadConstant(stream.readCPI()); break;
+            case ILOAD          : loadLocal(stream.readLocalIndex(), CiKind.Int); break;
+            case LLOAD          : loadLocal(stream.readLocalIndex(), CiKind.Long); break;
+            case FLOAD          : loadLocal(stream.readLocalIndex(), CiKind.Float); break;
+            case DLOAD          : loadLocal(stream.readLocalIndex(), CiKind.Double); break;
+            case ALOAD          : loadLocal(stream.readLocalIndex(), CiKind.Object); break;
+            case ILOAD_0        : // fall through
+            case ILOAD_1        : // fall through
+            case ILOAD_2        : // fall through
+            case ILOAD_3        : loadLocal(opcode - ILOAD_0, CiKind.Int); break;
+            case LLOAD_0        : // fall through
+            case LLOAD_1        : // fall through
+            case LLOAD_2        : // fall through
+            case LLOAD_3        : loadLocal(opcode - LLOAD_0, CiKind.Long); break;
+            case FLOAD_0        : // fall through
+            case FLOAD_1        : // fall through
+            case FLOAD_2        : // fall through
+            case FLOAD_3        : loadLocal(opcode - FLOAD_0, CiKind.Float); break;
+            case DLOAD_0        : // fall through
+            case DLOAD_1        : // fall through
+            case DLOAD_2        : // fall through
+            case DLOAD_3        : loadLocal(opcode - DLOAD_0, CiKind.Double); break;
+            case ALOAD_0        : // fall through
+            case ALOAD_1        : // fall through
+            case ALOAD_2        : // fall through
+            case ALOAD_3        : loadLocal(opcode - ALOAD_0, CiKind.Object); break;
+            case IALOAD         : genLoadIndexed(CiKind.Int   ); break;
+            case LALOAD         : genLoadIndexed(CiKind.Long  ); break;
+            case FALOAD         : genLoadIndexed(CiKind.Float ); break;
+            case DALOAD         : genLoadIndexed(CiKind.Double); break;
+            case AALOAD         : genLoadIndexed(CiKind.Object); break;
+            case BALOAD         : genLoadIndexed(CiKind.Byte  ); break;
+            case CALOAD         : genLoadIndexed(CiKind.Char  ); break;
+            case SALOAD         : genLoadIndexed(CiKind.Short ); break;
+            case ISTORE         : storeLocal(CiKind.Int, stream.readLocalIndex()); break;
+            case LSTORE         : storeLocal(CiKind.Long, stream.readLocalIndex()); break;
+            case FSTORE         : storeLocal(CiKind.Float, stream.readLocalIndex()); break;
+            case DSTORE         : storeLocal(CiKind.Double, stream.readLocalIndex()); break;
+            case ASTORE         : storeLocal(CiKind.Object, stream.readLocalIndex()); break;
+            case ISTORE_0       : // fall through
+            case ISTORE_1       : // fall through
+            case ISTORE_2       : // fall through
+            case ISTORE_3       : storeLocal(CiKind.Int, opcode - ISTORE_0); break;
+            case LSTORE_0       : // fall through
+            case LSTORE_1       : // fall through
+            case LSTORE_2       : // fall through
+            case LSTORE_3       : storeLocal(CiKind.Long, opcode - LSTORE_0); break;
+            case FSTORE_0       : // fall through
+            case FSTORE_1       : // fall through
+            case FSTORE_2       : // fall through
+            case FSTORE_3       : storeLocal(CiKind.Float, opcode - FSTORE_0); break;
+            case DSTORE_0       : // fall through
+            case DSTORE_1       : // fall through
+            case DSTORE_2       : // fall through
+            case DSTORE_3       : storeLocal(CiKind.Double, opcode - DSTORE_0); break;
+            case ASTORE_0       : // fall through
+            case ASTORE_1       : // fall through
+            case ASTORE_2       : // fall through
+            case ASTORE_3       : storeLocal(CiKind.Object, opcode - ASTORE_0); break;
+            case IASTORE        : genStoreIndexed(CiKind.Int   ); break;
+            case LASTORE        : genStoreIndexed(CiKind.Long  ); break;
+            case FASTORE        : genStoreIndexed(CiKind.Float ); break;
+            case DASTORE        : genStoreIndexed(CiKind.Double); break;
+            case AASTORE        : genStoreIndexed(CiKind.Object); break;
+            case BASTORE        : genStoreIndexed(CiKind.Byte  ); break;
+            case CASTORE        : genStoreIndexed(CiKind.Char  ); break;
+            case SASTORE        : genStoreIndexed(CiKind.Short ); break;
+            case POP            : // fall through
+            case POP2           : // fall through
+            case DUP            : // fall through
+            case DUP_X1         : // fall through
+            case DUP_X2         : // fall through
+            case DUP2           : // fall through
+            case DUP2_X1        : // fall through
+            case DUP2_X2        : // fall through
+            case SWAP           : stackOp(opcode); break;
+            case IADD           : // fall through
+            case ISUB           : // fall through
+            case IMUL           : genArithmeticOp(CiKind.Int, opcode); break;
+            case IDIV           : // fall through
+            case IREM           : genArithmeticOp(CiKind.Int, opcode, true); break;
+            case LADD           : // fall through
+            case LSUB           : // fall through
+            case LMUL           : genArithmeticOp(CiKind.Long, opcode); break;
+            case LDIV           : // fall through
+            case LREM           : genArithmeticOp(CiKind.Long, opcode, true); break;
+            case FADD           : // fall through
+            case FSUB           : // fall through
+            case FMUL           : // fall through
+            case FDIV           : // fall through
+            case FREM           : genArithmeticOp(CiKind.Float, opcode); break;
+            case DADD           : // fall through
+            case DSUB           : // fall through
+            case DMUL           : // fall through
+            case DDIV           : // fall through
+            case DREM           : genArithmeticOp(CiKind.Double, opcode); break;
+            case INEG           : genNegateOp(CiKind.Int); break;
+            case LNEG           : genNegateOp(CiKind.Long); break;
+            case FNEG           : genNegateOp(CiKind.Float); break;
+            case DNEG           : genNegateOp(CiKind.Double); break;
+            case ISHL           : // fall through
+            case ISHR           : // fall through
+            case IUSHR          : genShiftOp(CiKind.Int, opcode); break;
+            case IAND           : // fall through
+            case IOR            : // fall through
+            case IXOR           : genLogicOp(CiKind.Int, opcode); break;
+            case LSHL           : // fall through
+            case LSHR           : // fall through
+            case LUSHR          : genShiftOp(CiKind.Long, opcode); break;
+            case LAND           : // fall through
+            case LOR            : // fall through
+            case LXOR           : genLogicOp(CiKind.Long, opcode); break;
+            case IINC           : genIncrement(); break;
+            case I2L            : genConvert(opcode, CiKind.Int   , CiKind.Long  ); break;
+            case I2F            : genConvert(opcode, CiKind.Int   , CiKind.Float ); break;
+            case I2D            : genConvert(opcode, CiKind.Int   , CiKind.Double); break;
+            case L2I            : genConvert(opcode, CiKind.Long  , CiKind.Int   ); break;
+            case L2F            : genConvert(opcode, CiKind.Long  , CiKind.Float ); break;
+            case L2D            : genConvert(opcode, CiKind.Long  , CiKind.Double); break;
+            case F2I            : genConvert(opcode, CiKind.Float , CiKind.Int   ); break;
+            case F2L            : genConvert(opcode, CiKind.Float , CiKind.Long  ); break;
+            case F2D            : genConvert(opcode, CiKind.Float , CiKind.Double); break;
+            case D2I            : genConvert(opcode, CiKind.Double, CiKind.Int   ); break;
+            case D2L            : genConvert(opcode, CiKind.Double, CiKind.Long  ); break;
+            case D2F            : genConvert(opcode, CiKind.Double, CiKind.Float ); break;
+            case I2B            : genConvert(opcode, CiKind.Int   , CiKind.Byte  ); break;
+            case I2C            : genConvert(opcode, CiKind.Int   , CiKind.Char  ); break;
+            case I2S            : genConvert(opcode, CiKind.Int   , CiKind.Short ); break;
+            case LCMP           : genCompareOp(CiKind.Long, opcode, CiKind.Int); break;
+            case FCMPL          : genCompareOp(CiKind.Float, opcode, CiKind.Int); break;
+            case FCMPG          : genCompareOp(CiKind.Float, opcode, CiKind.Int); break;
+            case DCMPL          : genCompareOp(CiKind.Double, opcode, CiKind.Int); break;
+            case DCMPG          : genCompareOp(CiKind.Double, opcode, CiKind.Int); break;
+            case IFEQ           : genIfZero(Condition.EQ); break;
+            case IFNE           : genIfZero(Condition.NE); break;
+            case IFLT           : genIfZero(Condition.LT); break;
+            case IFGE           : genIfZero(Condition.GE); break;
+            case IFGT           : genIfZero(Condition.GT); break;
+            case IFLE           : genIfZero(Condition.LE); break;
+            case IF_ICMPEQ      : genIfSame(CiKind.Int, Condition.EQ); break;
+            case IF_ICMPNE      : genIfSame(CiKind.Int, Condition.NE); break;
+            case IF_ICMPLT      : genIfSame(CiKind.Int, Condition.LT); break;
+            case IF_ICMPGE      : genIfSame(CiKind.Int, Condition.GE); break;
+            case IF_ICMPGT      : genIfSame(CiKind.Int, Condition.GT); break;
+            case IF_ICMPLE      : genIfSame(CiKind.Int, Condition.LE); break;
+            case IF_ACMPEQ      : genIfSame(frameState.peekKind(), Condition.EQ); break;
+            case IF_ACMPNE      : genIfSame(frameState.peekKind(), Condition.NE); break;
+            case GOTO           : genGoto(stream.currentBCI(), stream.readBranchDest()); break;
+            case JSR            : genJsr(stream.readBranchDest()); break;
+            case RET            : genRet(stream.readLocalIndex()); break;
+            case TABLESWITCH    : genTableswitch(); break;
+            case LOOKUPSWITCH   : genLookupswitch(); break;
+            case IRETURN        : genReturn(frameState.ipop()); break;
+            case LRETURN        : genReturn(frameState.lpop()); break;
+            case FRETURN        : genReturn(frameState.fpop()); break;
+            case DRETURN        : genReturn(frameState.dpop()); break;
+            case ARETURN        : genReturn(frameState.apop()); break;
+            case RETURN         : genReturn(null  ); break;
+            case GETSTATIC      : cpi = stream.readCPI(); genGetStatic(cpi, constantPool.lookupField(cpi, opcode)); break;
+            case PUTSTATIC      : cpi = stream.readCPI(); genPutStatic(cpi, constantPool.lookupField(cpi, opcode)); break;
+            case GETFIELD       : cpi = stream.readCPI(); genGetField(cpi, constantPool.lookupField(cpi, opcode)); break;
+            case PUTFIELD       : cpi = stream.readCPI(); genPutField(cpi, constantPool.lookupField(cpi, opcode)); break;
+            case INVOKEVIRTUAL  : cpi = stream.readCPI(); genInvokeVirtual(constantPool.lookupMethod(cpi, opcode), cpi, constantPool); break;
+            case INVOKESPECIAL  : cpi = stream.readCPI(); genInvokeSpecial(constantPool.lookupMethod(cpi, opcode), null, cpi, constantPool); break;
+            case INVOKESTATIC   : cpi = stream.readCPI(); genInvokeStatic(constantPool.lookupMethod(cpi, opcode), cpi, constantPool); break;
+            case INVOKEINTERFACE: cpi = stream.readCPI(); genInvokeInterface(constantPool.lookupMethod(cpi, opcode), cpi, constantPool); break;
+            case NEW            : genNewInstance(stream.readCPI()); break;
+            case NEWARRAY       : genNewTypeArray(stream.readLocalIndex()); break;
+            case ANEWARRAY      : genNewObjectArray(stream.readCPI()); break;
+            case ARRAYLENGTH    : genArrayLength(); break;
+            case ATHROW         : genThrow(stream.currentBCI()); break;
+            case CHECKCAST      : genCheckCast(); break;
+            case INSTANCEOF     : genInstanceOf(); break;
+            case MONITORENTER   : genMonitorEnter(frameState.apop(), stream.currentBCI()); break;
+            case MONITOREXIT    : genMonitorExit(frameState.apop()); break;
+            case MULTIANEWARRAY : genNewMultiArray(stream.readCPI()); break;
+            case IFNULL         : genIfNull(Condition.EQ); break;
+            case IFNONNULL      : genIfNull(Condition.NE); break;
+            case GOTO_W         : genGoto(stream.currentBCI(), stream.readFarBranchDest()); break;
+            case JSR_W          : genJsr(stream.readFarBranchDest()); break;
+            case BREAKPOINT:
+                throw new CiBailout("concurrent setting of breakpoint");
+            default:
+                throw new CiBailout("Unsupported opcode " + opcode + " (" + nameOf(opcode) + ") [bci=" + bci + "]");
+        }
+        // Checkstyle: resume
+    }
+
+    private void traceInstruction(int bci, int opcode, boolean blockStart) {
+        if (C1XOptions.TraceBytecodeParserLevel >= TRACELEVEL_INSTRUCTIONS && !TTY.isSuppressed()) {
+            StringBuilder sb = new StringBuilder(40);
+            sb.append(blockStart ? '+' : '|');
+            if (bci < 10) {
+                sb.append("  ");
+            } else if (bci < 100) {
+                sb.append(' ');
+            }
+            sb.append(bci).append(": ").append(Bytecodes.nameOf(opcode));
+            for (int i = bci + 1; i < stream.nextBCI(); ++i) {
+                sb.append(' ').append(stream.readUByte(i));
+            }
+            log.println(sb.toString());
+        }
+    }
+
+    private void genArrayLength() {
+        frameState.ipush(append(new ArrayLength(frameState.apop(), graph)));
+    }
+
+    /**
+     * Adds a block to the worklist, if it is not already in the worklist.
+     * This method will keep the worklist topologically stored (i.e. the lower
+     * DFNs are earlier in the list).
+     * @param block the block to add to the work list
+     */
+    private void addToWorkList(Block block) {
+        if (!isOnWorkList(block)) {
+            markOnWorkList(block);
+            sortIntoWorkList(block);
+        }
+    }
+
+    private void sortIntoWorkList(Block top) {
+        workList.offer(top);
+    }
+
+    /**
+     * Removes the next block from the worklist. The list is sorted topologically, so the
+     * block with the lowest depth first number in the list will be removed and returned.
+     * @return the next block from the worklist; {@code null} if there are no blocks
+     * in the worklist
+     */
+    private Block removeFromWorkList() {
+        return workList.poll();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Wed Jun 08 13:06:45 2011 +0200
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.phases;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.value.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+
+public class InliningPhase extends Phase {
+
+    private final C1XCompilation compilation;
+    private final IR ir;
+
+    private final Queue<Invoke> invokes = new ArrayDeque<Invoke>();
+    private final Queue<RiMethod> methods = new ArrayDeque<RiMethod>();
+    private int inliningSize;
+
+    public InliningPhase(C1XCompilation compilation, IR ir) {
+        this.compilation = compilation;
+        this.ir = ir;
+    }
+
+    private void addToQueue(Invoke invoke, RiMethod method) {
+        invokes.add(invoke);
+        methods.add(method);
+        inliningSize += method.code().length;
+    }
+
+    @Override
+    protected void run(Graph graph) {
+        inliningSize = compilation.method.code().length;
+        int iterations = C1XOptions.MaximumRecursiveInlineLevel;
+        do {
+            for (Node node : graph.getNodes()) {
+                if (node instanceof Invoke) {
+                    Invoke invoke = (Invoke) node;
+                    RiMethod target = invoke.target;
+                    if (!checkInliningConditions(invoke) || !target.isResolved() || Modifier.isNative(target.accessFlags())) {
+                        continue;
+                    }
+                    if (target.canBeStaticallyBound()) {
+                        if (checkInliningConditions(invoke.target)) {
+                            addToQueue(invoke, invoke.target);
+                        }
+                    } else {
+                        RiMethod concrete = invoke.target.holder().uniqueConcreteMethod(invoke.target);
+                        if (concrete != null && concrete.isResolved() && !Modifier.isNative(concrete.accessFlags())) {
+                            if (checkInliningConditions(concrete)) {
+                                if (C1XOptions.TraceInlining) {
+                                    System.out.println("registering concrete method assumption...");
+                                }
+                                compilation.assumptions.recordConcreteMethod(invoke.target, concrete);
+                                addToQueue(invoke, concrete);
+                            }
+                        }
+                    }
+                    if (inliningSize > C1XOptions.MaximumInstructionCount) {
+                        break;
+                    }
+                }
+            }
+
+            assert invokes.size() == methods.size();
+            if (invokes.isEmpty()) {
+                break;
+            }
+
+            Invoke invoke;
+            while ((invoke = invokes.poll()) != null) {
+                RiMethod method = methods.remove();
+                inlineMethod(invoke, method);
+            }
+            DeadCodeEliminationPhase dce = new DeadCodeEliminationPhase();
+            dce.apply(graph);
+            if (dce.deletedNodeCount > 0) {
+                ir.verifyAndPrint("After dead code elimination");
+            }
+            ir.verifyAndPrint("After inlining iteration");
+
+            if (inliningSize > C1XOptions.MaximumInstructionCount) {
+                if (C1XOptions.TraceInlining) {
+                    System.out.println("inlining stopped: MaximumInstructionCount reached");
+                }
+                break;
+            }
+        } while(--iterations > 0);
+    }
+
+    private boolean checkInliningConditions(Invoke invoke) {
+        String name = invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", invoke.target, false);
+        if (invoke.predecessors().size() == 0) {
+            if (C1XOptions.TraceInlining) {
+                System.out.println("not inlining " + name + " because the invoke is dead code");
+            }
+            return false;
+        }
+        return true;
+    }
+
+    private boolean checkInliningConditions(RiMethod method) {
+        String name = null;
+        if (C1XOptions.TraceInlining) {
+            name = CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.code().length + " bytes)";
+        }
+        if (method.code().length > C1XOptions.MaximumInlineSize) {
+            if (C1XOptions.TraceInlining) {
+                System.out.println("not inlining " + name + " because of code size");
+            }
+            return false;
+        }
+        if (!method.holder().isInitialized()) {
+            if (C1XOptions.TraceInlining) {
+                System.out.println("not inlining " + name + " because of non-initialized class");
+            }
+            return false;
+        }
+        return true;
+    }
+
+    private void inlineMethod(Invoke invoke, RiMethod method) {
+        String name = invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.code().length + " bytes)";
+        FrameState stateAfter = invoke.stateAfter();
+        Instruction exceptionEdge = invoke.exceptionEdge();
+
+        if (C1XOptions.TraceInlining) {
+            System.out.printf("Building graph for %s, locals: %d, stack: %d\n", name, method.maxLocals(), method.maxStackSize());
+        }
+
+        CompilerGraph graph = new CompilerGraph();
+        new GraphBuilderPhase(compilation, method, true).apply(graph);
+
+        boolean withReceiver = !Modifier.isStatic(method.accessFlags());
+
+        int argumentCount = method.signature().argumentCount(false);
+        Value[] parameters = new Value[argumentCount + (withReceiver ? 1 : 0)];
+        int slot = withReceiver ? 1 : 0;
+        int param = withReceiver ? 1 : 0;
+        for (int i = 0; i < argumentCount; i++) {
+            parameters[param++] = invoke.argument(slot);
+            slot += method.signature().argumentKindAt(i).sizeInSlots();
+        }
+        if (withReceiver) {
+            parameters[0] = invoke.argument(0);
+        }
+
+        HashMap<Node, Node> replacements = new HashMap<Node, Node>();
+        ArrayList<Node> nodes = new ArrayList<Node>();
+        ArrayList<Node> frameStates = new ArrayList<Node>();
+        Return returnNode = null;
+        Unwind unwindNode = null;
+        StartNode startNode = graph.start();
+        for (Node node : graph.getNodes()) {
+            if (node != null) {
+                if (node instanceof StartNode) {
+                    assert startNode == node;
+                } else if (node instanceof Local) {
+                    replacements.put(node, parameters[((Local) node).index()]);
+                } else {
+                    nodes.add(node);
+                    if (node instanceof Return) {
+                        returnNode = (Return) node;
+                    } else if (node instanceof Unwind) {
+                        unwindNode = (Unwind) node;
+                    } else if (node instanceof FrameState) {
+                        frameStates.add(node);
+                    }
+                }
+            }
+        }
+
+        if (C1XOptions.TraceInlining) {
+            ir.printGraph("Subgraph " + CiUtil.format("%H.%n(%p):%r", method, false), graph);
+            System.out.println("inlining " + name + ": " + frameStates.size() + " frame states, " + nodes.size() + " nodes");
+        }
+
+        assert invoke.predecessors().size() == 1 : "size: " + invoke.predecessors().size();
+        Instruction pred;
+        if (withReceiver) {
+            pred = new NullCheck(parameters[0], compilation.graph);
+        } else {
+            pred = new Merge(compilation.graph);
+        }
+        invoke.predecessors().get(0).successors().replace(invoke, pred);
+        replacements.put(startNode, pred);
+
+        Map<Node, Node> duplicates = compilation.graph.addDuplicate(nodes, replacements);
+
+        if (returnNode != null) {
+            List<Node> usages = new ArrayList<Node>(invoke.usages());
+            for (Node usage : usages) {
+                if (returnNode.result() instanceof Local) {
+                    usage.inputs().replace(invoke, replacements.get(returnNode.result()));
+                } else {
+                    usage.inputs().replace(invoke, duplicates.get(returnNode.result()));
+                }
+            }
+            Node returnDuplicate = duplicates.get(returnNode);
+            returnDuplicate.inputs().clearAll();
+
+            assert returnDuplicate.predecessors().size() == 1;
+            Node returnPred = returnDuplicate.predecessors().get(0);
+            int index = returnDuplicate.predecessorsIndex().get(0);
+            returnPred.successors().setAndClear(index, invoke, 0);
+            returnDuplicate.delete();
+        }
+
+//        if (invoke.next() instanceof Merge) {
+//            ((Merge) invoke.next()).removePhiPredecessor(invoke);
+//        }
+//        invoke.successors().clearAll();
+        invoke.inputs().clearAll();
+        invoke.setExceptionEdge(null);
+//        invoke.delete();
+
+
+        if (exceptionEdge != null) {
+            if (unwindNode != null) {
+                assert unwindNode.predecessors().size() == 1;
+                assert exceptionEdge.successors().size() == 1;
+                ExceptionObject obj = (ExceptionObject) exceptionEdge;
+
+                List<Node> usages = new ArrayList<Node>(obj.usages());
+                for (Node usage : usages) {
+                    if (replacements.containsKey(unwindNode.exception())) {
+                        usage.inputs().replace(obj, replacements.get(unwindNode.exception()));
+                    } else {
+                        usage.inputs().replace(obj, duplicates.get(unwindNode.exception()));
+                    }
+                }
+                Node unwindDuplicate = duplicates.get(unwindNode);
+                unwindDuplicate.inputs().clearAll();
+
+                assert unwindDuplicate.predecessors().size() == 1;
+                Node unwindPred = unwindDuplicate.predecessors().get(0);
+                int index = unwindDuplicate.predecessorsIndex().get(0);
+                unwindPred.successors().setAndClear(index, obj, 0);
+
+                obj.inputs().clearAll();
+                obj.delete();
+                unwindDuplicate.delete();
+
+            }
+        }
+
+        // adjust all frame states that were copied
+        if (frameStates.size() > 0) {
+            FrameState outerFrameState = stateAfter.duplicateModified(invoke.bci, invoke.kind);
+            for (Node frameState : frameStates) {
+                ((FrameState) duplicates.get(frameState)).setOuterFrameState(outerFrameState);
+            }
+        }
+
+        if (C1XOptions.TraceInlining) {
+            ir.verifyAndPrint("After inlining " + CiUtil.format("%H.%n(%p):%r", method, false));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/SplitCriticalEdgesPhase.java	Wed Jun 08 13:06:45 2011 +0200
@@ -0,0 +1,51 @@
+/*
+ * 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.oracle.max.graal.compiler.phases;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.schedule.*;
+import com.oracle.max.graal.graph.*;
+
+
+public class SplitCriticalEdgesPhase extends Phase {
+
+    @Override
+    protected void run(Graph graph) {
+        List<Node> nodes = graph.getNodes();
+        for (int i = 0; i < nodes.size(); ++i) {
+            Node n = nodes.get(i);
+            if (Schedule.trueSuccessorCount(n) > 1) {
+                for (int j = 0; j < n.successors().size(); ++j) {
+                    Node succ = n.successors().get(j);
+                    if (Schedule.truePredecessorCount(succ) > 1) {
+                        Anchor a = new Anchor(graph);
+                        a.successors().setAndClear(1, n, j);
+                        n.successors().set(j, a);
+                    }
+                }
+            }
+        }
+    }
+}
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Graph.java	Wed Jun 08 13:04:17 2011 +0200
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Graph.java	Wed Jun 08 13:06:45 2011 +0200
@@ -84,6 +84,7 @@
         // create node duplicates
         for (Node node : nodes) {
             if (node != null && !replacements.containsKey(node)) {
+                assert node.graph != this;
                 Node newNode = node.copy(this);
                 assert newNode.getClass() == node.getClass();
                 newNodes.put(node, newNode);
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Node.java	Wed Jun 08 13:04:17 2011 +0200
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Node.java	Wed Jun 08 13:06:45 2011 +0200
@@ -115,6 +115,18 @@
     public boolean isDeleted() {
         return id == DeletedID;
     }
+    
+    public void forceDelete() {
+        for (Node n : usages) {
+            n.inputs.silentRemove(this);
+        }
+        for (Node n : predecessors) {
+            n.successors.silentRemove(this);
+        }
+        usages.clear();
+        predecessors.clear();
+        predecessorsIndex.clear();
+    }
 
     public void delete() {
         assert !isDeleted();
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeArray.java	Wed Jun 08 13:04:17 2011 +0200
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeArray.java	Wed Jun 08 13:06:45 2011 +0200
@@ -45,14 +45,20 @@
         return this.node;
     }
 
+    Node silentSet(int index, Node node) {
+        Node result = nodes[index];
+        nodes[index] = node;
+        return result;
+    }
+
     @Override
     public Node set(int index, Node node) {
-        assert node == Node.Null || node.graph == self().graph : "node is from different graph: (self=" + self() + ") and (node=" + node + ")";
+        assert node == Node.Null || node.graph == self().graph : "node is from different graph: (this=" + self() + ") and (node=" + node + ")";
         assert node == Node.Null || node.id() != Node.DeletedID : "inserted node must not be deleted";
         Node old = nodes[index];
 
         if (old != node) {
-            nodes[index] = node;
+            silentSet(index, node);
             if (self().inputs == this) {
                 if (old != null) {
                     old.usages.remove(self());
@@ -108,6 +114,10 @@
         return false;
     }
 
+    public int remove(Node n) {
+        return replace(n, null);
+    }
+
     public int replace(Node toReplace, Node replacement) {
         int result = 0;
         for (int i = 0; i < nodes.length; i++) {
@@ -118,6 +128,21 @@
         }
         return result;
     }
+    
+    int silentRemove(Node n) {
+        return silentReplace(n, null);
+    }
+
+    int silentReplace(Node toReplace, Node replacement) {
+        int result = 0;
+        for (int i = 0; i < nodes.length; i++) {
+            if (nodes[i] == toReplace) {
+                silentSet(i, replacement);
+                result++;
+            }
+        }
+        return result;
+    }
 
     public void setAndClear(int index, Node clearedNode, int clearedIndex) {
         assert self().successors == this;
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Phase.java	Wed Jun 08 13:04:17 2011 +0200
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Phase.java	Wed Jun 08 13:06:45 2011 +0200
@@ -23,11 +23,25 @@
 package com.oracle.max.graal.graph;
 
 public abstract class Phase {
+    
+    private final String name;
+    
+    public Phase() {
+        this.name = this.getClass().getSimpleName();
+    }
+    
+    public Phase(String name) {
+        this.name = name;
+    }
 
     public final void apply(Graph graph) {
         assert graph != null;
         run(graph);
     }
+    
+    public final String getName() {
+        return name;
+    }
 
     protected abstract void run(Graph graph);
 }