changeset 14795:9f8b3c49fb42

merge
author Josef Eisl <josef.eisl@jku.at>
date Thu, 13 Mar 2014 11:43:08 +0100
parents 63b0a6af67b7 (diff) 2a4d3ceb7ed3 (current diff)
children f5b3292b4ded
files graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java mx/projects
diffstat 32 files changed, 1043 insertions(+), 114 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java	Thu Mar 13 11:43:08 2014 +0100
@@ -23,37 +23,29 @@
 package com.oracle.graal.baseline;
 
 import static com.oracle.graal.api.code.TypeCheckHints.*;
-import static com.oracle.graal.api.meta.DeoptimizationAction.*;
-import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.bytecode.Bytecodes.*;
 import static com.oracle.graal.phases.GraalOptions.*;
 import static java.lang.reflect.Modifier.*;
 
-import java.lang.reflect.*;
-import java.util.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.api.meta.ResolvedJavaType.Representation;
 import com.oracle.graal.bytecode.*;
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.java.BciBlockMapping.Block;
 import com.oracle.graal.java.BciBlockMapping.ExceptionDispatchBlock;
-import com.oracle.graal.java.GraphBuilderPhase.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert;
-import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.tiers.*;
 
 /**
  * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph.
@@ -90,7 +82,8 @@
         return method;
     }
 
-    public LIR generate(ResolvedJavaMethod method, int entryBCI) {
+    public CompilationResult generate(ResolvedJavaMethod method, int entryBCI, Backend backend, CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner,
+                    CompilationResultBuilderFactory factory) {
         this.method = method;
         this.entryBCI = entryBCI;
         profilingInfo = method.getProfilingInfo();
@@ -100,12 +93,21 @@
         unwindBlock = null;
         methodSynchronizedObject = null;
         TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method);
+
+        // build blocks
         try {
             build();
         } finally {
             filter.remove();
         }
-        return null;
+        // emitLIR
+        LIRBlock b = new LIRBlock();
+        LIRGenerator lirGen = null;
+        // emitCode
+        Assumptions assumptions = new Assumptions(OptAssumptions.getValue());
+        GraalCompiler.emitCode(backend, new long[0], assumptions, lirGen, compilationResult, installedCodeOwner, factory);
+
+        return compilationResult;
     }
 
     protected void build() {
@@ -131,9 +133,9 @@
             throw GraalInternalError.unimplemented("Handle start block as loop header");
         }
 
-        for (Block block : blockMap.blocks) {
-            processBlock(block);
-        }
+        /*
+         * for (Block block : blockMap.blocks) { processBlock(block); }
+         */
 
         indent.outdent();
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRBlock.java	Thu Mar 13 11:43:08 2014 +0100
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2014, 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.graal.baseline;
+
+import java.util.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.*;
+
+public class LIRBlock implements com.oracle.graal.nodes.cfg.AbstractBlock<LIRBlock> {
+
+    public int getId() {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented("Auto-generated method stub");
+    }
+
+    public AbstractBeginNode getBeginNode() {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented("Auto-generated method stub");
+    }
+
+    public Loop getLoop() {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented("Auto-generated method stub");
+    }
+
+    public int getLoopDepth() {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented("Auto-generated method stub");
+    }
+
+    public boolean isLoopHeader() {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented("Auto-generated method stub");
+    }
+
+    public boolean isLoopEnd() {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented("Auto-generated method stub");
+    }
+
+    public boolean isExceptionEntry() {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented("Auto-generated method stub");
+    }
+
+    public List<LIRBlock> getPredecessors() {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented("Auto-generated method stub");
+    }
+
+    public int getPredecessorCount() {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented("Auto-generated method stub");
+    }
+
+    public List<LIRBlock> getSuccessors() {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented("Auto-generated method stub");
+    }
+
+    public int getSuccessorCount() {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented("Auto-generated method stub");
+    }
+
+    public int getLinearScanNumber() {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented("Auto-generated method stub");
+    }
+
+    public void setLinearScanNumber(int linearScanNumber) {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented("Auto-generated method stub");
+    }
+
+    public boolean isAligned() {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented("Auto-generated method stub");
+    }
+
+    public void setAlign(boolean align) {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented("Auto-generated method stub");
+    }
+
+    public LIRBlock getDominator() {
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented("Auto-generated method stub");
+    }
+
+}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Thu Mar 13 11:43:08 2014 +0100
@@ -500,8 +500,7 @@
     private CompilationResult compileBaseline(ResolvedJavaMethod javaMethod) {
         try (Scope bds = Debug.scope("compileBaseline")) {
             BaselineCompiler baselineCompiler = new BaselineCompiler(GraphBuilderConfiguration.getDefault(), providers.getMetaAccess());
-            baselineCompiler.generate(javaMethod, -1);
-            return null;
+            return baselineCompiler.generate(javaMethod, -1, getBackend(), new CompilationResult(), javaMethod, CompilationResultBuilderFactory.Default);
         } catch (Throwable e) {
             throw Debug.handle(e);
         }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Thu Mar 13 11:43:08 2014 +0100
@@ -73,7 +73,7 @@
         public RegisterStats(LIR lir) {
             this.lir = lir;
 
-            for (Block block : lir.codeEmittingOrder()) {
+            for (AbstractBlock<?> block : lir.codeEmittingOrder()) {
                 for (LIRInstruction instr : lir.lir(block)) {
                     collectStats(instr);
                 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu Mar 13 11:43:08 2014 +0100
@@ -239,11 +239,13 @@
         assert startBlock.getPredecessorCount() == 0;
 
         LIR lir = null;
+        List<Block> codeEmittingOrder = null;
+        List<Block> linearScanOrder = null;
         try (Scope ds = Debug.scope("MidEnd")) {
             try (Scope s = Debug.scope("ComputeLinearScanOrder")) {
                 NodesToDoubles nodeProbabilities = new ComputeProbabilityClosure(graph).apply();
-                List<Block> codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock, nodeProbabilities);
-                List<Block> linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock, nodeProbabilities);
+                codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock, nodeProbabilities);
+                linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock, nodeProbabilities);
 
                 lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder);
                 Debug.dump(lir, "After linear scan order");
@@ -258,7 +260,7 @@
             LIRGenerator lirGen = backend.newLIRGenerator(graph, stub, frameMap, cc, lir);
 
             try (Scope s = Debug.scope("LIRGen", lirGen)) {
-                for (Block b : lir.linearScanOrder()) {
+                for (Block b : linearScanOrder) {
                     emitBlock(lirGen, b, graph, schedule.getBlockToNodesMap());
                 }
                 lirGen.beforeRegisterAllocation();
@@ -278,7 +280,7 @@
 
             try (Scope s = Debug.scope("ControlFlowOptimizations")) {
                 EdgeMoveOptimizer.optimize(lir);
-                ControlFlowOptimizer.optimize(lir);
+                ControlFlowOptimizer.optimize(lir, codeEmittingOrder);
                 if (lirGen.canEliminateRedundantMoves()) {
                     RedundantMoveElimination.optimize(lir, frameMap);
                 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Thu Mar 13 11:43:08 2014 +0100
@@ -135,9 +135,9 @@
     LIRInstruction[] opIdToInstructionMap;
 
     /**
-     * Map from an instruction {@linkplain LIRInstruction#id id} to the {@linkplain Block block}
-     * containing the instruction. Entries should be retrieved with {@link #blockForId(int)} as the
-     * id is not simply an index into this array.
+     * Map from an instruction {@linkplain LIRInstruction#id id} to the {@linkplain AbstractBlock
+     * block} containing the instruction. Entries should be retrieved with {@link #blockForId(int)}
+     * as the id is not simply an index into this array.
      */
     AbstractBlock<?>[] opIdToBlockMap;
 
@@ -629,7 +629,7 @@
 
         // initialize with correct length
         opIdToInstructionMap = new LIRInstruction[numInstructions];
-        opIdToBlockMap = new Block[numInstructions];
+        opIdToBlockMap = new AbstractBlock<?>[numInstructions];
 
         int opId = 0;
         int index = 0;
@@ -869,7 +869,7 @@
         }
 
         // check that the liveIn set of the first block is empty
-        Block startBlock = ir.getControlFlowGraph().getStartBlock();
+        AbstractBlock<?> startBlock = ir.getControlFlowGraph().getStartBlock();
         if (blockData.get(startBlock).liveIn.cardinality() != 0) {
             if (DetailedAsserts.getValue()) {
                 reportFailure(numBlocks);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Thu Mar 13 11:43:08 2014 +0100
@@ -341,7 +341,8 @@
     }
 
     public LabelRef getLIRBlock(FixedNode b) {
-        Block result = lir.getControlFlowGraph().blockFor(b);
+        assert lir.getControlFlowGraph() instanceof ControlFlowGraph;
+        Block result = ((ControlFlowGraph) lir.getControlFlowGraph()).blockFor(b);
         int suxIndex = currentBlock.getSuccessors().indexOf(result);
         assert suxIndex != -1 : "Block not in successor list of current block";
 
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Thu Mar 13 11:43:08 2014 +0100
@@ -423,7 +423,7 @@
 
         RegisterAnalysis registerAnalysis = new RegisterAnalysis();
 
-        for (Block b : lir.codeEmittingOrder()) {
+        for (AbstractBlock<?> b : lir.codeEmittingOrder()) {
             for (LIRInstruction op : lir.lir(b)) {
                 if (op instanceof LabelOp) {
                     // Don't consider this as a definition
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Thu Mar 13 11:43:08 2014 +0100
@@ -244,7 +244,7 @@
             append(new WriteNode(buf, nullWord, location, BarrierType.NONE, false, false));
         }
 
-        FrameStateBuilder fsb = new FrameStateBuilder(method, getGraph(), true);
+        HIRFrameStateBuilder fsb = new HIRFrameStateBuilder(method, getGraph(), true);
         FrameState fs = fsb.create(0);
         getGraph().start().setStateAfter(fs);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Thu Mar 13 11:43:08 2014 +0100
@@ -121,7 +121,7 @@
                 return value;
             }
         };
-        for (Block block : lir.codeEmittingOrder()) {
+        for (AbstractBlock<?> block : lir.codeEmittingOrder()) {
             for (LIRInstruction op : lir.lir(block)) {
                 if (op instanceof LabelOp) {
                     // Don't consider this as a definition
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java	Thu Mar 13 11:43:08 2014 +0100
@@ -520,7 +520,7 @@
             // mirroring the calculations in c1_GraphBuilder.cpp (setup_osr_entry_block)
             int localsOffset = (graph.method().getMaxLocals() - 1) * 8;
             for (OSRLocalNode osrLocal : graph.getNodes(OSRLocalNode.class)) {
-                int size = FrameStateBuilder.stackSlots(osrLocal.kind());
+                int size = HIRFrameStateBuilder.stackSlots(osrLocal.kind());
                 int offset = localsOffset - (osrLocal.index() + size - 1) * 8;
                 IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, osrLocal.kind(), offset, ConstantNode.forLong(0, graph), graph, 1);
                 ReadNode load = graph.add(new ReadNode(buffer, location, osrLocal.stamp(), BarrierType.NONE, false));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java	Thu Mar 13 11:43:08 2014 +0100
@@ -122,7 +122,7 @@
     public int getParameterSlots(boolean withReceiver) {
         int argSlots = 0;
         for (int i = 0; i < getParameterCount(false); i++) {
-            argSlots += FrameStateBuilder.stackSlots(getParameterKind(i));
+            argSlots += HIRFrameStateBuilder.stackSlots(getParameterKind(i));
         }
         return argSlots + (withReceiver ? 1 : 0);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Thu Mar 13 11:43:08 2014 +0100
@@ -67,7 +67,7 @@
         JavaType[] signature = MetaUtil.signatureToTypes(method.getSignature(), isStatic ? null : method.getDeclaringClass());
         CallingConvention cc = gen.frameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, signature, gen.target(), false);
         List<ValueNode> parameters = new ArrayList<>();
-        for (int i = 0, slot = 0; i < cc.getArgumentCount(); i++, slot += FrameStateBuilder.stackSlots(frameState.localAt(slot).kind())) {
+        for (int i = 0, slot = 0; i < cc.getArgumentCount(); i++, slot += HIRFrameStateBuilder.stackSlots(frameState.localAt(slot).kind())) {
             parameters.add(frameState.localAt(slot));
         }
         Value[] args = gen.visitInvokeArguments(cc, parameters);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractFrameStateBuilder.java	Thu Mar 13 11:43:08 2014 +0100
@@ -0,0 +1,202 @@
+package com.oracle.graal.java;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+
+public abstract class AbstractFrameStateBuilder<T> {
+
+    protected final ResolvedJavaMethod method;
+    protected final StructuredGraph graph;
+    protected int stackSize;
+
+    public AbstractFrameStateBuilder(ResolvedJavaMethod method, StructuredGraph graph) {
+        assert graph != null;
+        this.method = method;
+        this.graph = graph;
+    }
+
+    protected AbstractFrameStateBuilder(AbstractFrameStateBuilder other) {
+        assert other.graph != null;
+        this.method = other.method;
+        this.graph = other.graph;
+    }
+
+    /**
+     * Returns the size of the local variables.
+     * 
+     * @return the size of the local variables
+     */
+    public abstract int localsSize();
+
+    /**
+     * Gets the current size (height) of the stack.
+     */
+    public int stackSize() {
+        return stackSize;
+    }
+
+    /**
+     * Gets the value in the local variables at the specified index, without any sanity checking.
+     * 
+     * @param i the index into the locals
+     * @return the instruction that produced the value for the specified local
+     */
+    public abstract T localAt(int i);
+
+    /**
+     * Get the value on the stack at the specified stack index.
+     * 
+     * @param i the index into the stack, with {@code 0} being the bottom of the stack
+     * @return the instruction at the specified position in the stack
+     */
+    public abstract T stackAt(int i);
+
+    /**
+     * Loads the local variable at the specified index, checking that the returned value is non-null
+     * and that two-stack values are properly handled.
+     * 
+     * @param i the index of the local variable to load
+     * @return the instruction that produced the specified local
+     */
+    public abstract T loadLocal(int i);
+
+    /**
+     * Stores a given local variable at the specified index. If the value occupies
+     * {@linkplain HIRFrameStateBuilder#isTwoSlot(Kind) two slots}, then the next local variable index
+     * is also overwritten.
+     * 
+     * @param i the index at which to store
+     * @param x the instruction which produces the value for the local
+     */
+    public abstract void storeLocal(int i, T x);
+
+    public abstract void storeStack(int i, T x);
+
+    /**
+     * Pushes an instruction onto the stack with the expected type.
+     * 
+     * @param kind the type expected for this instruction
+     * @param x the instruction to push onto the stack
+     */
+    public abstract void push(Kind kind, T x);
+
+    /**
+     * Pushes a value onto the stack without checking the type.
+     * 
+     * @param x the instruction to push onto the stack
+     */
+    public abstract void xpush(T x);
+
+    /**
+     * Pushes a value onto the stack and checks that it is an int.
+     * 
+     * @param x the instruction to push onto the stack
+     */
+    public abstract void ipush(T x);
+
+    /**
+     * Pushes a value onto the stack and checks that it is a float.
+     * 
+     * @param x the instruction to push onto the stack
+     */
+    public abstract void fpush(T x);
+
+    /**
+     * Pushes a value onto the stack and checks that it is an object.
+     * 
+     * @param x the instruction to push onto the stack
+     */
+    public abstract void apush(T x);
+
+    /**
+     * Pushes a value onto the stack and checks that it is a long.
+     * 
+     * @param x the instruction to push onto the stack
+     */
+    public abstract void lpush(T x);
+
+    /**
+     * Pushes a value onto the stack and checks that it is a double.
+     * 
+     * @param x the instruction to push onto the stack
+     */
+    public abstract void dpush(T x);
+
+    public abstract void pushReturn(Kind kind, T x);
+
+    /**
+     * Pops an instruction off the stack with the expected type.
+     * 
+     * @param kind the expected type
+     * @return the instruction on the top of the stack
+     */
+    public abstract T pop(Kind kind);
+
+    /**
+     * Pops a value off of the stack without checking the type.
+     * 
+     * @return x the instruction popped off the stack
+     */
+    public abstract T xpop();
+
+    /**
+     * Pops a value off of the stack and checks that it is an int.
+     * 
+     * @return x the instruction popped off the stack
+     */
+    public abstract T ipop();
+
+    /**
+     * Pops a value off of the stack and checks that it is a float.
+     * 
+     * @return x the instruction popped off the stack
+     */
+    public abstract T fpop();
+
+    /**
+     * Pops a value off of the stack and checks that it is an object.
+     * 
+     * @return x the instruction popped off the stack
+     */
+    public abstract T apop();
+
+    /**
+     * Pops a value off of the stack and checks that it is a long.
+     * 
+     * @return x the instruction popped off the stack
+     */
+    public abstract T lpop();
+
+    /**
+     * Pops a value off of the stack and checks that it is a double.
+     * 
+     * @return x the instruction popped off the stack
+     */
+    public abstract T dpop();
+
+    /**
+     * Pop the specified number of slots off of this stack and return them as an array of
+     * instructions.
+     * 
+     * @return an array containing the arguments off of the stack
+     */
+    public abstract T[] popArguments(int slotSize, int argSize);
+
+    /**
+     * Peeks an element from the operand stack.
+     * 
+     * @param argumentNumber The number of the argument, relative from the top of the stack (0 =
+     *            top). Long and double arguments only count as one argument, i.e., null-slots are
+     *            ignored.
+     * @return The peeked argument.
+     */
+    public abstract T peek(int argumentNumber);
+
+    /**
+     * Clears all values on this stack.
+     */
+    public void clearStack() {
+        stackSize = 0;
+    }
+
+}
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Thu Mar 13 11:43:08 2014 +0100
@@ -83,7 +83,7 @@
         public int blockID;
 
         public FixedWithNextNode firstInstruction;
-        public FrameStateBuilder entryState;
+        public HIRFrameStateBuilder entryState;
 
         public ArrayList<Block> successors = new ArrayList<>(2);
         public long exits;
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Mar 13 11:43:08 2014 +0100
@@ -116,7 +116,7 @@
 
         private BytecodeStream stream;           // the bytecode stream
 
-        protected FrameStateBuilder frameState;          // the current execution state
+        protected HIRFrameStateBuilder frameState;          // the current execution state
         private Block currentBlock;
 
         private ValueNode methodSynchronizedObject;
@@ -163,7 +163,7 @@
         /**
          * Gets the current frame state being processed by this builder.
          */
-        protected FrameStateBuilder getCurrentFrameState() {
+        protected HIRFrameStateBuilder getCurrentFrameState() {
             return frameState;
         }
 
@@ -200,7 +200,7 @@
             unwindBlock = null;
             methodSynchronizedObject = null;
             this.currentGraph = graph;
-            this.frameState = new FrameStateBuilder(method, graph, graphBuilderConfig.eagerResolving());
+            this.frameState = new HIRFrameStateBuilder(method, graph, graphBuilderConfig.eagerResolving());
             TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method);
             try {
                 build();
@@ -435,7 +435,7 @@
                 dispatchBlock = unwindBlock(bci);
             }
 
-            FrameStateBuilder dispatchState = frameState.copy();
+            HIRFrameStateBuilder dispatchState = frameState.copy();
             dispatchState.clearStack();
 
             DispatchBeginNode dispatchBegin;
@@ -1455,15 +1455,15 @@
         private static class Target {
 
             FixedNode fixed;
-            FrameStateBuilder state;
+            HIRFrameStateBuilder state;
 
-            public Target(FixedNode fixed, FrameStateBuilder state) {
+            public Target(FixedNode fixed, HIRFrameStateBuilder state) {
                 this.fixed = fixed;
                 this.state = state;
             }
         }
 
-        private Target checkLoopExit(FixedNode target, Block targetBlock, FrameStateBuilder state) {
+        private Target checkLoopExit(FixedNode target, Block targetBlock, HIRFrameStateBuilder state) {
             if (currentBlock != null) {
                 long exits = currentBlock.loops & ~targetBlock.loops;
                 if (exits != 0) {
@@ -1493,7 +1493,7 @@
                     if (targetBlock instanceof ExceptionDispatchBlock) {
                         bci = ((ExceptionDispatchBlock) targetBlock).deoptBci;
                     }
-                    FrameStateBuilder newState = state.copy();
+                    HIRFrameStateBuilder newState = state.copy();
                     for (Block loop : exitLoops) {
                         LoopBeginNode loopBegin = (LoopBeginNode) loop.firstInstruction;
                         LoopExitNode loopExit = currentGraph.add(new LoopExitNode(loopBegin));
@@ -1516,7 +1516,7 @@
             return new Target(target, state);
         }
 
-        private FixedNode createTarget(double probability, Block block, FrameStateBuilder stateAfter) {
+        private FixedNode createTarget(double probability, Block block, HIRFrameStateBuilder stateAfter) {
             assert probability >= 0 && probability <= 1.01 : probability;
             if (isNeverExecutedCode(probability)) {
                 return currentGraph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode));
@@ -1530,7 +1530,7 @@
             return probability == 0 && optimisticOpts.removeNeverExecutedCode() && entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI;
         }
 
-        private FixedNode createTarget(Block block, FrameStateBuilder state) {
+        private FixedNode createTarget(Block block, HIRFrameStateBuilder state) {
             assert block != null && state != null;
             assert !block.isExceptionEntry || state.stackSize() == 1;
 
@@ -1610,7 +1610,7 @@
          * Returns a block begin node with the specified state. If the specified probability is 0,
          * the block deoptimizes immediately.
          */
-        private AbstractBeginNode createBlockTarget(double probability, Block block, FrameStateBuilder stateAfter) {
+        private AbstractBeginNode createBlockTarget(double probability, Block block, HIRFrameStateBuilder stateAfter) {
             FixedNode target = createTarget(probability, block, stateAfter);
             AbstractBeginNode begin = AbstractBeginNode.begin(target);
 
@@ -1619,7 +1619,7 @@
             return begin;
         }
 
-        private ValueNode synchronizedObject(FrameStateBuilder state, ResolvedJavaMethod target) {
+        private ValueNode synchronizedObject(HIRFrameStateBuilder state, ResolvedJavaMethod target) {
             if (isStatic(target.getModifiers())) {
                 return appendConstant(target.getDeclaringClass().getEncoding(Representation.JavaClass));
             } else {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java	Thu Mar 13 11:43:08 2014 +0100
@@ -0,0 +1,572 @@
+/*
+ * Copyright (c) 2012, 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.graal.java;
+
+import static com.oracle.graal.graph.iterators.NodePredicates.*;
+import static com.oracle.graal.nodes.ValueNodeUtil.*;
+import static java.lang.reflect.Modifier.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.Node.Verbosity;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
+
+public class HIRFrameStateBuilder extends AbstractFrameStateBuilder<ValueNode> {
+
+    private static final ValueNode[] EMPTY_ARRAY = new ValueNode[0];
+    private static final MonitorIdNode[] EMPTY_MONITOR_ARRAY = new MonitorIdNode[0];
+
+    private final ValueNode[] locals;
+    private final ValueNode[] stack;
+    private ValueNode[] lockedObjects;
+    private MonitorIdNode[] monitorIds;
+
+    /**
+     * @see BytecodeFrame#rethrowException
+     */
+    private boolean rethrowException;
+
+    public HIRFrameStateBuilder(ResolvedJavaMethod method, StructuredGraph graph, boolean eagerResolve) {
+        super(method, graph);
+
+        this.locals = new ValueNode[method.getMaxLocals()];
+        // we always need at least one stack slot (for exceptions)
+        this.stack = new ValueNode[Math.max(1, method.getMaxStackSize())];
+        this.lockedObjects = EMPTY_ARRAY;
+        this.monitorIds = EMPTY_MONITOR_ARRAY;
+
+        int javaIndex = 0;
+        int index = 0;
+        if (!isStatic(method.getModifiers())) {
+            // add the receiver
+            ParameterNode receiver = graph.unique(new ParameterNode(javaIndex, StampFactory.declaredNonNull(method.getDeclaringClass())));
+            storeLocal(javaIndex, receiver);
+            javaIndex = 1;
+            index = 1;
+        }
+        Signature sig = method.getSignature();
+        int max = sig.getParameterCount(false);
+        ResolvedJavaType accessingClass = method.getDeclaringClass();
+        for (int i = 0; i < max; i++) {
+            JavaType type = sig.getParameterType(i, accessingClass);
+            if (eagerResolve) {
+                type = type.resolve(accessingClass);
+            }
+            Kind kind = type.getKind().getStackKind();
+            Stamp stamp;
+            if (kind == Kind.Object && type instanceof ResolvedJavaType) {
+                stamp = StampFactory.declared((ResolvedJavaType) type);
+            } else {
+                stamp = StampFactory.forKind(kind);
+            }
+            ParameterNode param = graph.unique(new ParameterNode(index, stamp));
+            storeLocal(javaIndex, param);
+            javaIndex += stackSlots(kind);
+            index++;
+        }
+    }
+
+    private HIRFrameStateBuilder(HIRFrameStateBuilder other) {
+        super(other);
+        locals = other.locals.clone();
+        stack = other.stack.clone();
+        lockedObjects = other.lockedObjects == EMPTY_ARRAY ? EMPTY_ARRAY : other.lockedObjects.clone();
+        monitorIds = other.monitorIds == EMPTY_MONITOR_ARRAY ? EMPTY_MONITOR_ARRAY : other.monitorIds.clone();
+        stackSize = other.stackSize;
+        rethrowException = other.rethrowException;
+
+        assert locals.length == method.getMaxLocals();
+        assert stack.length == Math.max(1, method.getMaxStackSize());
+        assert lockedObjects.length == monitorIds.length;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("[locals: [");
+        for (int i = 0; i < locals.length; i++) {
+            sb.append(i == 0 ? "" : ",").append(locals[i] == null ? "_" : locals[i].toString(Verbosity.Id));
+        }
+        sb.append("] stack: [");
+        for (int i = 0; i < stackSize; i++) {
+            sb.append(i == 0 ? "" : ",").append(stack[i] == null ? "_" : stack[i].toString(Verbosity.Id));
+        }
+        sb.append("] locks: [");
+        for (int i = 0; i < lockedObjects.length; i++) {
+            sb.append(i == 0 ? "" : ",").append(lockedObjects[i].toString(Verbosity.Id)).append(" / ").append(monitorIds[i].toString(Verbosity.Id));
+        }
+        sb.append("]");
+        if (rethrowException) {
+            sb.append(" rethrowException");
+        }
+        sb.append("]");
+        return sb.toString();
+    }
+
+    public FrameState create(int bci) {
+        return graph.add(new FrameState(method, bci, locals, Arrays.asList(stack).subList(0, stackSize), lockedObjects, monitorIds, rethrowException, false));
+    }
+
+    public HIRFrameStateBuilder copy() {
+        return new HIRFrameStateBuilder(this);
+    }
+
+    public boolean isCompatibleWith(HIRFrameStateBuilder other) {
+        assert method == other.method && graph == other.graph && localsSize() == other.localsSize() : "Can only compare frame states of the same method";
+        assert lockedObjects.length == monitorIds.length && other.lockedObjects.length == other.monitorIds.length : "mismatch between lockedObjects and monitorIds";
+
+        if (stackSize() != other.stackSize()) {
+            return false;
+        }
+        for (int i = 0; i < stackSize(); i++) {
+            ValueNode x = stackAt(i);
+            ValueNode y = other.stackAt(i);
+            if (x != y && (x == null || x.isDeleted() || y == null || y.isDeleted() || x.kind() != y.kind())) {
+                return false;
+            }
+        }
+        if (lockedObjects.length != other.lockedObjects.length) {
+            return false;
+        }
+        for (int i = 0; i < lockedObjects.length; i++) {
+            if (GraphUtil.originalValue(lockedObjects[i]) != GraphUtil.originalValue(other.lockedObjects[i]) || monitorIds[i] != other.monitorIds[i]) {
+                throw new BailoutException("unbalanced monitors");
+            }
+        }
+        return true;
+    }
+
+    public void merge(MergeNode block, HIRFrameStateBuilder other) {
+        assert isCompatibleWith(other);
+
+        for (int i = 0; i < localsSize(); i++) {
+            storeLocal(i, merge(localAt(i), other.localAt(i), block));
+        }
+        for (int i = 0; i < stackSize(); i++) {
+            storeStack(i, merge(stackAt(i), other.stackAt(i), block));
+        }
+        for (int i = 0; i < lockedObjects.length; i++) {
+            lockedObjects[i] = merge(lockedObjects[i], other.lockedObjects[i], block);
+            assert monitorIds[i] == other.monitorIds[i];
+        }
+    }
+
+    private ValueNode merge(ValueNode currentValue, ValueNode otherValue, MergeNode block) {
+        if (currentValue == null || currentValue.isDeleted()) {
+            return null;
+
+        } else if (block.isPhiAtMerge(currentValue)) {
+            if (otherValue == null || otherValue.isDeleted() || currentValue.kind() != otherValue.kind()) {
+                propagateDelete((PhiNode) currentValue);
+                return null;
+            }
+            ((PhiNode) currentValue).addInput(otherValue);
+            return currentValue;
+
+        } else if (currentValue != otherValue) {
+            assert !(block instanceof LoopBeginNode) : "Phi functions for loop headers are create eagerly for all locals and stack slots";
+            if (otherValue == null || otherValue.isDeleted() || currentValue.kind() != otherValue.kind()) {
+                return null;
+            }
+
+            PhiNode phi = graph.addWithoutUnique(new PhiNode(currentValue.kind(), block));
+            for (int i = 0; i < block.phiPredecessorCount(); i++) {
+                phi.addInput(currentValue);
+            }
+            phi.addInput(otherValue);
+            assert phi.valueCount() == block.phiPredecessorCount() + 1 : "valueCount=" + phi.valueCount() + " predSize= " + block.phiPredecessorCount();
+            return phi;
+
+        } else {
+            return currentValue;
+        }
+    }
+
+    private void propagateDelete(FloatingNode node) {
+        assert node instanceof PhiNode || node instanceof ProxyNode;
+        if (node.isDeleted()) {
+            return;
+        }
+        // Collect all phi functions that use this phi so that we can delete them recursively (after
+        // we delete ourselves to avoid circles).
+        List<FloatingNode> propagateUsages = node.usages().filter(FloatingNode.class).filter(isA(PhiNode.class).or(ProxyNode.class)).snapshot();
+
+        // Remove the phi function from all FrameStates where it is used and then delete it.
+        assert node.usages().filter(isNotA(FrameState.class).nor(PhiNode.class).nor(ProxyNode.class)).isEmpty() : "phi function that gets deletes must only be used in frame states";
+        node.replaceAtUsages(null);
+        node.safeDelete();
+
+        for (FloatingNode phiUsage : propagateUsages) {
+            propagateDelete(phiUsage);
+        }
+    }
+
+    public void insertLoopPhis(LoopBeginNode loopBegin) {
+        for (int i = 0; i < localsSize(); i++) {
+            storeLocal(i, createLoopPhi(loopBegin, localAt(i)));
+        }
+        for (int i = 0; i < stackSize(); i++) {
+            storeStack(i, createLoopPhi(loopBegin, stackAt(i)));
+        }
+        for (int i = 0; i < lockedObjects.length; i++) {
+            lockedObjects[i] = createLoopPhi(loopBegin, lockedObjects[i]);
+        }
+    }
+
+    public void insertLoopProxies(LoopExitNode loopExit, HIRFrameStateBuilder loopEntryState) {
+        for (int i = 0; i < localsSize(); i++) {
+            ValueNode value = localAt(i);
+            if (value != null && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) {
+                Debug.log(" inserting proxy for %s", value);
+                storeLocal(i, ProxyNode.forValue(value, loopExit, graph));
+            }
+        }
+        for (int i = 0; i < stackSize(); i++) {
+            ValueNode value = stackAt(i);
+            if (value != null && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) {
+                Debug.log(" inserting proxy for %s", value);
+                storeStack(i, ProxyNode.forValue(value, loopExit, graph));
+            }
+        }
+        for (int i = 0; i < lockedObjects.length; i++) {
+            ValueNode value = lockedObjects[i];
+            if (value != null && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) {
+                Debug.log(" inserting proxy for %s", value);
+                lockedObjects[i] = ProxyNode.forValue(value, loopExit, graph);
+            }
+        }
+    }
+
+    public void insertProxies(AbstractBeginNode begin) {
+        for (int i = 0; i < localsSize(); i++) {
+            ValueNode value = localAt(i);
+            if (value != null) {
+                Debug.log(" inserting proxy for %s", value);
+                storeLocal(i, ProxyNode.forValue(value, begin, graph));
+            }
+        }
+        for (int i = 0; i < stackSize(); i++) {
+            ValueNode value = stackAt(i);
+            if (value != null) {
+                Debug.log(" inserting proxy for %s", value);
+                storeStack(i, ProxyNode.forValue(value, begin, graph));
+            }
+        }
+        for (int i = 0; i < lockedObjects.length; i++) {
+            ValueNode value = lockedObjects[i];
+            if (value != null) {
+                Debug.log(" inserting proxy for %s", value);
+                lockedObjects[i] = ProxyNode.forValue(value, begin, graph);
+            }
+        }
+    }
+
+    private PhiNode createLoopPhi(MergeNode block, ValueNode value) {
+        if (value == null) {
+            return null;
+        }
+        assert !block.isPhiAtMerge(value) : "phi function for this block already created";
+
+        PhiNode phi = graph.addWithoutUnique(new PhiNode(value.kind(), block));
+        phi.addInput(value);
+        return phi;
+    }
+
+    public void cleanupDeletedPhis() {
+        for (int i = 0; i < localsSize(); i++) {
+            if (localAt(i) != null && localAt(i).isDeleted()) {
+                assert localAt(i) instanceof PhiNode || localAt(i) instanceof ProxyNode : "Only phi and value proxies can be deleted during parsing: " + localAt(i);
+                storeLocal(i, null);
+            }
+        }
+    }
+
+    public void clearNonLiveLocals(BitSet liveness) {
+        if (liveness == null) {
+            return;
+        }
+        for (int i = 0; i < locals.length; i++) {
+            if (!liveness.get(i)) {
+                locals[i] = null;
+            }
+        }
+    }
+
+    /**
+     * @see BytecodeFrame#rethrowException
+     */
+    public boolean rethrowException() {
+        return rethrowException;
+    }
+
+    /**
+     * @see BytecodeFrame#rethrowException
+     */
+    public void setRethrowException(boolean b) {
+        rethrowException = b;
+    }
+
+    @Override
+    public int localsSize() {
+        return locals.length;
+    }
+
+    @Override
+    public ValueNode localAt(int i) {
+        return locals[i];
+    }
+
+    @Override
+    public ValueNode stackAt(int i) {
+        return stack[i];
+    }
+
+    /**
+     * Adds a locked monitor to this frame state.
+     * 
+     * @param object the object whose monitor will be locked.
+     */
+    public void pushLock(ValueNode object, MonitorIdNode monitorId) {
+        assert object.isAlive() && object.kind() == Kind.Object : "unexpected value: " + object;
+        lockedObjects = Arrays.copyOf(lockedObjects, lockedObjects.length + 1);
+        monitorIds = Arrays.copyOf(monitorIds, monitorIds.length + 1);
+        lockedObjects[lockedObjects.length - 1] = object;
+        monitorIds[monitorIds.length - 1] = monitorId;
+        assert lockedObjects.length == monitorIds.length;
+    }
+
+    /**
+     * Removes a locked monitor from this frame state.
+     * 
+     * @return the object whose monitor was removed from the locks list.
+     */
+    public ValueNode popLock() {
+        try {
+            return lockedObjects[lockedObjects.length - 1];
+        } finally {
+            lockedObjects = lockedObjects.length == 1 ? EMPTY_ARRAY : Arrays.copyOf(lockedObjects, lockedObjects.length - 1);
+            monitorIds = monitorIds.length == 1 ? EMPTY_MONITOR_ARRAY : Arrays.copyOf(monitorIds, monitorIds.length - 1);
+        }
+    }
+
+    public MonitorIdNode peekMonitorId() {
+        return monitorIds[monitorIds.length - 1];
+    }
+
+    /**
+     * @return the current lock depth
+     */
+    public int lockDepth() {
+        assert lockedObjects.length == monitorIds.length;
+        return lockedObjects.length;
+    }
+
+    @Override
+    public ValueNode loadLocal(int i) {
+        ValueNode x = locals[i];
+        assert !x.isDeleted();
+        assert !isTwoSlot(x.kind()) || locals[i + 1] == null;
+        assert i == 0 || locals[i - 1] == null || !isTwoSlot(locals[i - 1].kind());
+        return x;
+    }
+
+    @Override
+    public void storeLocal(int i, ValueNode x) {
+        assert x == null || x.isAlive() && x.kind() != Kind.Void && x.kind() != Kind.Illegal : "unexpected value: " + x;
+        locals[i] = x;
+        if (x != null && isTwoSlot(x.kind())) {
+            // if this is a double word, then kill i+1
+            locals[i + 1] = null;
+        }
+        if (x != null && i > 0) {
+            ValueNode p = locals[i - 1];
+            if (p != null && isTwoSlot(p.kind())) {
+                // if there was a double word at i - 1, then kill it
+                locals[i - 1] = null;
+            }
+        }
+    }
+
+    @Override
+    public void storeStack(int i, ValueNode x) {
+        assert x == null || x.isAlive() && (stack[i] == null || x.kind() == stack[i].kind()) : "Method does not handle changes from one-slot to two-slot values or non-alive values";
+        stack[i] = x;
+    }
+
+    @Override
+    public void push(Kind kind, ValueNode x) {
+        assert x.isAlive() && x.kind() != Kind.Void && x.kind() != Kind.Illegal;
+        xpush(assertKind(kind, x));
+        if (isTwoSlot(kind)) {
+            xpush(null);
+        }
+    }
+
+    @Override
+    public void xpush(ValueNode x) {
+        assert x == null || (x.isAlive() && x.kind() != Kind.Void && x.kind() != Kind.Illegal);
+        stack[stackSize++] = x;
+    }
+
+    @Override
+    public void ipush(ValueNode x) {
+        xpush(assertInt(x));
+    }
+
+    @Override
+    public void fpush(ValueNode x) {
+        xpush(assertFloat(x));
+    }
+
+    @Override
+    public void apush(ValueNode x) {
+        xpush(assertObject(x));
+    }
+
+    @Override
+    public void lpush(ValueNode x) {
+        xpush(assertLong(x));
+        xpush(null);
+    }
+
+    @Override
+    public void dpush(ValueNode x) {
+        xpush(assertDouble(x));
+        xpush(null);
+    }
+
+    @Override
+    public void pushReturn(Kind kind, ValueNode x) {
+        if (kind != Kind.Void) {
+            push(kind.getStackKind(), x);
+        }
+    }
+
+    @Override
+    public ValueNode pop(Kind kind) {
+        assert kind != Kind.Void;
+        if (isTwoSlot(kind)) {
+            xpop();
+        }
+        return assertKind(kind, xpop());
+    }
+
+    @Override
+    public ValueNode xpop() {
+        ValueNode result = stack[--stackSize];
+        assert result == null || !result.isDeleted();
+        return result;
+    }
+
+    @Override
+    public ValueNode ipop() {
+        return assertInt(xpop());
+    }
+
+    @Override
+    public ValueNode fpop() {
+        return assertFloat(xpop());
+    }
+
+    @Override
+    public ValueNode apop() {
+        return assertObject(xpop());
+    }
+
+    @Override
+    public ValueNode lpop() {
+        assertHigh(xpop());
+        return assertLong(xpop());
+    }
+
+    @Override
+    public ValueNode dpop() {
+        assertHigh(xpop());
+        return assertDouble(xpop());
+    }
+
+    @Override
+    public ValueNode[] popArguments(int slotSize, int argSize) {
+        int base = stackSize - slotSize;
+        ValueNode[] r = new ValueNode[argSize];
+        int argIndex = 0;
+        int stackindex = 0;
+        while (stackindex < slotSize) {
+            ValueNode element = stack[base + stackindex];
+            assert element != null;
+            r[argIndex++] = element;
+            stackindex += stackSlots(element.kind());
+        }
+        stackSize = base;
+        return r;
+    }
+
+    @Override
+    public ValueNode peek(int argumentNumber) {
+        int idx = stackSize() - 1;
+        for (int i = 0; i < argumentNumber; i++) {
+            if (stackAt(idx) == null) {
+                idx--;
+                assert isTwoSlot(stackAt(idx).kind());
+            }
+            idx--;
+        }
+        return stackAt(idx);
+    }
+
+    public static int stackSlots(Kind kind) {
+        return isTwoSlot(kind) ? 2 : 1;
+    }
+
+    public static boolean isTwoSlot(Kind kind) {
+        assert kind != Kind.Void && kind != Kind.Illegal;
+        return kind == Kind.Long || kind == Kind.Double;
+    }
+
+    public boolean contains(ValueNode value) {
+        for (int i = 0; i < localsSize(); i++) {
+            if (localAt(i) == value) {
+                return true;
+            }
+        }
+        for (int i = 0; i < stackSize(); i++) {
+            if (stackAt(i) == value) {
+                return true;
+            }
+        }
+        assert lockedObjects.length == monitorIds.length;
+        for (int i = 0; i < lockedObjects.length; i++) {
+            if (lockedObjects[i] == value || monitorIds[i] == value) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java	Thu Mar 13 11:43:08 2014 +0100
@@ -37,9 +37,8 @@
     /**
      * Performs control flow optimizations on the given LIR graph.
      */
-    public static void optimize(LIR lir) {
-        List<Block> blocks = lir.codeEmittingOrder();
-        ControlFlowOptimizer.deleteEmptyBlocks(lir, blocks);
+    public static <T extends AbstractBlock<T>> void optimize(LIR lir, List<T> codeEmittingOrder) {
+        ControlFlowOptimizer.deleteEmptyBlocks(lir, codeEmittingOrder);
     }
 
     private ControlFlowOptimizer() {
@@ -54,8 +53,8 @@
      * @param block the block checked for deletion
      * @return whether the block can be deleted
      */
-    private static boolean canDeleteBlock(LIR lir, Block block) {
-        if (block.getSuccessorCount() != 1 || block.getPredecessorCount() == 0 || block.getFirstSuccessor() == block) {
+    private static boolean canDeleteBlock(LIR lir, AbstractBlock<?> block) {
+        if (block.getSuccessorCount() != 1 || block.getPredecessorCount() == 0 || block.getSuccessors().iterator().next() == block) {
             return false;
         }
 
@@ -64,13 +63,13 @@
         assert instructions.size() >= 2 : "block must have label and branch";
         assert instructions.get(0) instanceof StandardOp.LabelOp : "first instruction must always be a label";
         assert instructions.get(instructions.size() - 1) instanceof StandardOp.JumpOp : "last instruction must always be a branch";
-        assert ((StandardOp.JumpOp) instructions.get(instructions.size() - 1)).destination().label() == ((StandardOp.LabelOp) lir.lir(block.getFirstSuccessor()).get(0)).getLabel() : "branch target must be the successor";
+        assert ((StandardOp.JumpOp) instructions.get(instructions.size() - 1)).destination().label() == ((StandardOp.LabelOp) lir.lir(block.getSuccessors().iterator().next()).get(0)).getLabel() : "branch target must be the successor";
 
         // Block must have exactly one successor.
         return instructions.size() == 2 && !instructions.get(instructions.size() - 1).hasState() && !block.isExceptionEntry();
     }
 
-    private static void alignBlock(LIR lir, Block block) {
+    private static void alignBlock(LIR lir, AbstractBlock<?> block) {
         if (!block.isAligned()) {
             block.setAlign(true);
             List<LIRInstruction> instructions = lir.lir(block);
@@ -80,15 +79,15 @@
         }
     }
 
-    private static void deleteEmptyBlocks(LIR lir, List<Block> blocks) {
+    private static <T extends AbstractBlock<T>> void deleteEmptyBlocks(LIR lir, List<T> blocks) {
         assert verifyBlocks(lir, blocks);
-        Iterator<Block> iterator = blocks.iterator();
+        Iterator<T> iterator = blocks.iterator();
         while (iterator.hasNext()) {
-            Block block = iterator.next();
+            T block = iterator.next();
             if (canDeleteBlock(lir, block)) {
                 // adjust successor and predecessor lists
-                Block other = block.getFirstSuccessor();
-                for (Block pred : block.getPredecessors()) {
+                T other = block.getSuccessors().iterator().next();
+                for (AbstractBlock<T> pred : block.getPredecessors()) {
                     Collections.replaceAll(pred.getSuccessors(), block, other);
                 }
                 for (int i = 0; i < other.getPredecessorCount(); i++) {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java	Thu Mar 13 11:43:08 2014 +0100
@@ -53,10 +53,10 @@
     public static void optimize(LIR ir) {
         EdgeMoveOptimizer optimizer = new EdgeMoveOptimizer(ir);
 
-        List<Block> blockList = ir.linearScanOrder();
+        List<? extends AbstractBlock<?>> blockList = ir.linearScanOrder();
         // ignore the first block in the list (index 0 is not processed)
         for (int i = blockList.size() - 1; i >= 1; i--) {
-            Block block = blockList.get(i);
+            AbstractBlock<?> block = blockList.get(i);
 
             if (block.getPredecessorCount() > 1) {
                 optimizer.optimizeMovesAtBlockEnd(block);
@@ -103,8 +103,8 @@
      * Moves the longest {@linkplain #same common} subsequence at the end all predecessors of
      * {@code block} to the start of {@code block}.
      */
-    private void optimizeMovesAtBlockEnd(Block block) {
-        for (Block pred : block.getPredecessors()) {
+    private void optimizeMovesAtBlockEnd(AbstractBlock<?> block) {
+        for (AbstractBlock<?> pred : block.getPredecessors()) {
             if (pred == block) {
                 // currently we can't handle this correctly.
                 return;
@@ -118,7 +118,7 @@
         assert numPreds > 1 : "do not call otherwise";
 
         // setup a list with the LIR instructions of all predecessors
-        for (Block pred : block.getPredecessors()) {
+        for (AbstractBlock<?> pred : block.getPredecessors()) {
             assert pred != null;
             assert ir.lir(pred) != null;
             List<LIRInstruction> predInstructions = ir.lir(pred);
@@ -129,7 +129,7 @@
                 return;
             }
 
-            assert pred.getFirstSuccessor() == block : "invalid control flow";
+            assert pred.getSuccessors().iterator().next() == block : "invalid control flow";
             assert predInstructions.get(predInstructions.size() - 1) instanceof StandardOp.JumpOp : "block must end with unconditional jump";
 
             if (predInstructions.get(predInstructions.size() - 1).hasState()) {
@@ -173,7 +173,7 @@
      * {@code block} to the end of {@code block} just prior to the branch instruction ending
      * {@code block}.
      */
-    private void optimizeMovesAtBlockBegin(Block block) {
+    private void optimizeMovesAtBlockBegin(AbstractBlock<?> block) {
 
         edgeInstructionSeqences.clear();
         int numSux = block.getSuccessorCount();
@@ -203,7 +203,7 @@
         int insertIdx = instructions.size() - 1;
 
         // setup a list with the lir-instructions of all successors
-        for (Block sux : block.getSuccessors()) {
+        for (AbstractBlock<?> sux : block.getSuccessors()) {
             List<LIRInstruction> suxInstructions = ir.lir(sux);
 
             assert suxInstructions.get(0) instanceof StandardOp.LabelOp : "block must start with label";
@@ -213,7 +213,7 @@
                 // the same blocks.
                 return;
             }
-            assert sux.getFirstPredecessor() == block : "invalid control flow";
+            assert sux.getPredecessors().iterator().next() == block : "invalid control flow";
 
             // ignore the label at the beginning of the block
             List<LIRInstruction> seq = suxInstructions.subList(1, suxInstructions.size());
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Thu Mar 13 11:43:08 2014 +0100
@@ -35,17 +35,17 @@
  */
 public class LIR {
 
-    private final ControlFlowGraph cfg;
+    private final AbstractControlFlowGraph<?> cfg;
 
     /**
      * The linear-scan ordered list of blocks.
      */
-    private final List<Block> linearScanOrder;
+    private final List<? extends AbstractBlock<?>> linearScanOrder;
 
     /**
      * The order in which the code is emitted.
      */
-    private final List<Block> codeEmittingOrder;
+    private final List<? extends AbstractBlock<?>> codeEmittingOrder;
 
     private int firstVariableNumber;
 
@@ -65,14 +65,14 @@
     /**
      * Creates a new LIR instance for the specified compilation.
      */
-    public LIR(ControlFlowGraph cfg, List<Block> linearScanOrder, List<Block> codeEmittingOrder) {
+    public LIR(AbstractControlFlowGraph<?> cfg, List<? extends AbstractBlock<?>> linearScanOrder, List<? extends AbstractBlock<?>> codeEmittingOrder) {
         this.cfg = cfg;
         this.codeEmittingOrder = codeEmittingOrder;
         this.linearScanOrder = linearScanOrder;
         this.lirInstructions = new BlockMap<>(cfg);
     }
 
-    public ControlFlowGraph getControlFlowGraph() {
+    public AbstractControlFlowGraph<?> getControlFlowGraph() {
         return cfg;
     }
 
@@ -80,7 +80,7 @@
      * Determines if any instruction in the LIR has debug info associated with it.
      */
     public boolean hasDebugInfo() {
-        for (Block b : linearScanOrder()) {
+        for (AbstractBlock<?> b : linearScanOrder()) {
             for (LIRInstruction op : lir(b)) {
                 if (op.hasState()) {
                     return true;
@@ -108,11 +108,11 @@
      * 
      * @return the blocks in linear scan order
      */
-    public List<Block> linearScanOrder() {
+    public List<? extends AbstractBlock<?>> linearScanOrder() {
         return linearScanOrder;
     }
 
-    public List<Block> codeEmittingOrder() {
+    public List<? extends AbstractBlock<?>> codeEmittingOrder() {
         return codeEmittingOrder;
     }
 
@@ -169,7 +169,7 @@
      */
     public static final int MAX_EXCEPTION_EDGE_OP_DISTANCE_FROM_END = 3;
 
-    public static boolean verifyBlock(LIR lir, Block block) {
+    public static boolean verifyBlock(LIR lir, AbstractBlock<?> block) {
         List<LIRInstruction> ops = lir.lir(block);
         if (ops.size() == 0) {
             return false;
@@ -193,12 +193,12 @@
         return true;
     }
 
-    public static boolean verifyBlocks(LIR lir, List<Block> blocks) {
-        for (Block block : blocks) {
-            for (Block sux : block.getSuccessors()) {
+    public static boolean verifyBlocks(LIR lir, List<? extends AbstractBlock<?>> blocks) {
+        for (AbstractBlock<?> block : blocks) {
+            for (AbstractBlock<?> sux : block.getSuccessors()) {
                 assert blocks.contains(sux) : "missing successor from: " + block + "to: " + sux;
             }
-            for (Block pred : block.getPredecessors()) {
+            for (AbstractBlock<?> pred : block.getPredecessors()) {
                 assert blocks.contains(pred) : "missing predecessor from: " + block + "to: " + pred;
             }
             if (!verifyBlock(lir, block)) {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Thu Mar 13 11:43:08 2014 +0100
@@ -46,11 +46,11 @@
     private final BitSet[] blockLiveOut;
     private final Object[] variableDefinitions;
 
-    private BitSet liveOutFor(Block block) {
+    private BitSet liveOutFor(AbstractBlock<?> block) {
         return blockLiveOut[block.getId()];
     }
 
-    private void setLiveOutFor(Block block, BitSet liveOut) {
+    private void setLiveOutFor(AbstractBlock<?> block, BitSet liveOut) {
         blockLiveOut[block.getId()] = liveOut;
     }
 
@@ -98,7 +98,7 @@
     private BitSet curVariablesLive;
     private Value[] curRegistersLive;
 
-    private Block curBlock;
+    private AbstractBlock<?> curBlock;
     private Object curInstruction;
     private BitSet curRegistersDefined;
 
@@ -120,7 +120,7 @@
 
         int maxRegisterNum = maxRegisterNum();
         curRegistersDefined = new BitSet();
-        for (Block block : lir.linearScanOrder()) {
+        for (AbstractBlock<?> block : lir.linearScanOrder()) {
             curBlock = block;
             curVariablesLive = new BitSet();
             curRegistersLive = new Value[maxRegisterNum];
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java	Thu Mar 13 11:43:08 2014 +0100
@@ -31,15 +31,15 @@
 public final class NullCheckOptimizer {
 
     public static void optimize(LIR ir, int implicitNullCheckLimit) {
-        List<Block> blocks = ir.codeEmittingOrder();
+        List<? extends AbstractBlock<?>> blocks = ir.codeEmittingOrder();
         NullCheckOptimizer.foldNullChecks(ir, blocks, implicitNullCheckLimit);
     }
 
     private NullCheckOptimizer() {
     }
 
-    private static void foldNullChecks(LIR ir, List<Block> blocks, int implicitNullCheckLimit) {
-        for (Block block : blocks) {
+    private static void foldNullChecks(LIR ir, List<? extends AbstractBlock<?>> blocks, int implicitNullCheckLimit) {
+        for (AbstractBlock<?> block : blocks) {
             List<LIRInstruction> list = ir.lir(block);
 
             if (!list.isEmpty()) {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java	Thu Mar 13 11:43:08 2014 +0100
@@ -79,7 +79,7 @@
         int entryValueNum;
     }
 
-    Map<Block, BlockData> blockData = new HashMap<>();
+    Map<AbstractBlock<?>, BlockData> blockData = new HashMap<>();
 
     Register[] callerSaveRegs;
 
@@ -134,7 +134,7 @@
 
     private void initBlockData(LIR lir) {
 
-        List<Block> blocks = lir.linearScanOrder();
+        List<? extends AbstractBlock<?>> blocks = lir.linearScanOrder();
         numRegs = 0;
 
         int maxStackLocations = COMPLEXITY_LIMIT / blocks.size();
@@ -143,7 +143,7 @@
          * Search for relevant locations which can be optimized. These are register or stack slots
          * which occur as destinations of move instructions.
          */
-        for (Block block : blocks) {
+        for (AbstractBlock<?> block : blocks) {
             List<LIRInstruction> instructions = lir.lir(block);
             for (LIRInstruction op : instructions) {
                 if (isEligibleMove(op)) {
@@ -168,7 +168,7 @@
          */
         int numLocations = numRegs + stackIndices.size();
         Debug.log("num locations = %d (regs = %d, stack = %d)", numLocations, numRegs, stackIndices.size());
-        for (Block block : blocks) {
+        for (AbstractBlock<?> block : blocks) {
             BlockData data = new BlockData(numLocations);
             blockData.put(block, data);
         }
@@ -183,7 +183,7 @@
 
         Indent indent = Debug.logAndIndent("solve data flow");
 
-        List<Block> blocks = lir.linearScanOrder();
+        List<? extends AbstractBlock<?>> blocks = lir.linearScanOrder();
 
         int numIter = 0;
 
@@ -197,7 +197,7 @@
             changed = false;
             Indent indent2 = indent.logAndIndent("new iteration");
 
-            for (Block block : blocks) {
+            for (AbstractBlock<?> block : blocks) {
 
                 BlockData data = blockData.get(block);
                 /*
@@ -226,7 +226,7 @@
                     /*
                      * Merge the states of predecessor blocks
                      */
-                    for (Block predecessor : block.getPredecessors()) {
+                    for (AbstractBlock<?> predecessor : block.getPredecessors()) {
                         BlockData predData = blockData.get(predecessor);
                         newState |= mergeState(data.entryState, predData.exitState, valueNum);
                     }
@@ -281,9 +281,9 @@
 
         Indent indent = Debug.logAndIndent("eliminate moves");
 
-        List<Block> blocks = lir.linearScanOrder();
+        List<? extends AbstractBlock<?>> blocks = lir.linearScanOrder();
 
-        for (Block block : blocks) {
+        for (AbstractBlock<?> block : blocks) {
 
             Indent indent2 = indent.logAndIndent("eliminate moves in block %d", block.getId());
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Thu Mar 13 11:43:08 2014 +0100
@@ -298,7 +298,7 @@
      */
     public boolean isSuccessorEdge(LabelRef edge) {
         assert lir != null;
-        List<Block> order = lir.codeEmittingOrder();
+        List<? extends AbstractBlock<?>> order = lir.codeEmittingOrder();
         assert order.get(currentBlockIndex) == edge.getSourceBlock();
         return currentBlockIndex < order.size() - 1 && order.get(currentBlockIndex + 1) == edge.getTargetBlock();
     }
@@ -312,7 +312,7 @@
         this.lir = lir;
         this.currentBlockIndex = 0;
         frameContext.enter(this);
-        for (Block b : lir.codeEmittingOrder()) {
+        for (AbstractBlock<?> b : lir.codeEmittingOrder()) {
             emitBlock(b);
             currentBlockIndex++;
         }
@@ -320,7 +320,7 @@
         this.currentBlockIndex = 0;
     }
 
-    private void emitBlock(Block block) {
+    private void emitBlock(AbstractBlock<?> block) {
         if (Debug.isDumpEnabled()) {
             blockComment(String.format("block B%d %s", block.getId(), block.getLoop()));
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractBlock.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractBlock.java	Thu Mar 13 11:43:08 2014 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes.cfg;
 
+import java.util.*;
+
 import com.oracle.graal.nodes.*;
 
 public interface AbstractBlock<T extends AbstractBlock<?>> {
@@ -40,11 +42,11 @@
 
     boolean isExceptionEntry();
 
-    Iterable<T> getPredecessors();
+    List<T> getPredecessors();
 
     int getPredecessorCount();
 
-    Iterable<T> getSuccessors();
+    List<T> getSuccessors();
 
     int getSuccessorCount();
 
@@ -55,4 +57,6 @@
     boolean isAligned();
 
     void setAlign(boolean align);
+
+    T getDominator();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractControlFlowGraph.java	Thu Mar 13 11:43:08 2014 +0100
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, 2014, 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.graal.nodes.cfg;
+
+public interface AbstractControlFlowGraph<T extends AbstractBlock<T>> {
+
+    T[] getBlocks();
+
+    Loop[] getLoops();
+
+    Block getStartBlock();
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/BlockMap.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/BlockMap.java	Thu Mar 13 11:43:08 2014 +0100
@@ -27,7 +27,7 @@
     private final T[] data;
 
     @SuppressWarnings("unchecked")
-    public BlockMap(ControlFlowGraph cfg) {
+    public BlockMap(AbstractControlFlowGraph<?> cfg) {
         data = (T[]) new Object[cfg.getBlocks().length];
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Thu Mar 13 11:43:08 2014 +0100
@@ -28,7 +28,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 
-public class ControlFlowGraph {
+public class ControlFlowGraph implements AbstractControlFlowGraph<Block> {
 
     public final StructuredGraph graph;
 
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Thu Mar 13 11:43:08 2014 +0100
@@ -127,10 +127,11 @@
      * @param label A label describing the compilation phase that produced the control flow graph.
      * @param blocks The list of blocks to be printed.
      */
-    public void printCFG(String label, List<Block> blocks, boolean printNodes) {
+    public void printCFG(String label, List<? extends AbstractBlock<?>> blocks, boolean printNodes) {
         if (lir == null) {
             latestScheduling = new NodeMap<>(cfg.getNodeToBlock());
-            for (Block block : blocks) {
+            for (AbstractBlock<?> abstractBlock : blocks) {
+                Block block = (Block) abstractBlock;
                 Node cur = block.getBeginNode();
                 while (true) {
                     assert inFixedSchedule(cur) && latestScheduling.get(cur) == block;
@@ -148,7 +149,8 @@
 
         begin("cfg");
         out.print("name \"").print(label).println('"');
-        for (Block block : blocks) {
+        for (AbstractBlock<?> abstractBlock : blocks) {
+            Block block = (Block) abstractBlock;
             printBlock(block, printNodes);
         }
         end("cfg");
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Thu Mar 13 11:43:08 2014 +0100
@@ -141,7 +141,8 @@
             cfgPrinter.target = cfgPrinter.lirGenerator.target();
         }
         if (cfgPrinter.lir != null) {
-            cfgPrinter.cfg = cfgPrinter.lir.getControlFlowGraph();
+            assert cfgPrinter.lir.getControlFlowGraph() instanceof ControlFlowGraph;
+            cfgPrinter.cfg = (ControlFlowGraph) cfgPrinter.lir.getControlFlowGraph();
         }
 
         CodeCacheProvider codeCache = Debug.contextLookup(CodeCacheProvider.class);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java	Thu Mar 13 11:17:20 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java	Thu Mar 13 11:43:08 2014 +0100
@@ -106,7 +106,7 @@
      * @param name the name of the invoked method
      * @param args the arguments to the invocation
      */
-    public InvokeNode createInvoke(Class<?> declaringClass, String name, InvokeKind invokeKind, FrameStateBuilder frameStateBuilder, int bci, ValueNode... args) {
+    public InvokeNode createInvoke(Class<?> declaringClass, String name, InvokeKind invokeKind, HIRFrameStateBuilder frameStateBuilder, int bci, ValueNode... args) {
         boolean isStatic = invokeKind == InvokeKind.Static;
         ResolvedJavaMethod method = null;
         for (Method m : declaringClass.getDeclaredMethods()) {
@@ -123,7 +123,7 @@
      * Creates and appends an {@link InvokeNode} for a call to a given method with a given set of
      * arguments.
      */
-    public InvokeNode createInvoke(ResolvedJavaMethod method, InvokeKind invokeKind, FrameStateBuilder frameStateBuilder, int bci, ValueNode... args) {
+    public InvokeNode createInvoke(ResolvedJavaMethod method, InvokeKind invokeKind, HIRFrameStateBuilder frameStateBuilder, int bci, ValueNode... args) {
         assert Modifier.isStatic(method.getModifiers()) == (invokeKind == InvokeKind.Static);
         Signature signature = method.getSignature();
         JavaType returnType = signature.getReturnType(null);
--- a/mx/projects	Thu Mar 13 11:17:20 2014 +0100
+++ b/mx/projects	Thu Mar 13 11:43:08 2014 +0100
@@ -482,7 +482,7 @@
 # graal.baseline
 project@com.oracle.graal.baseline@subDir=graal
 project@com.oracle.graal.baseline@sourceDirs=src
-project@com.oracle.graal.baseline@dependencies=com.oracle.graal.java,com.oracle.graal.lir
+project@com.oracle.graal.baseline@dependencies=com.oracle.graal.java,com.oracle.graal.lir,com.oracle.graal.compiler
 project@com.oracle.graal.baseline@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.baseline@javaCompliance=1.7
 project@com.oracle.graal.baseline@workingSets=Graal,Java