changeset 14856:0d158f22f14c

Merge.
author Josef Eisl <josef.eisl@jku.at>
date Thu, 27 Mar 2014 17:31:20 +0100
parents 3a855006bf28 (diff) 66ac13a2c7a1 (current diff)
children 9c089e418bc9
files
diffstat 200 files changed, 5085 insertions(+), 3023 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java	Thu Mar 27 17:31:20 2014 +0100
@@ -26,7 +26,6 @@
 import java.util.*;
 
 import com.oracle.graal.nodes.cfg.*;
-import com.oracle.graal.nodes.util.*;
 
 /**
  * Computes an ordering of the block that can be used by the linear scan register allocator and the
@@ -67,11 +66,11 @@
      * 
      * @return sorted list of blocks
      */
-    public static <T extends AbstractBlock<T>> List<T> computeLinearScanOrder(int blockCount, T startBlock, NodesToDoubles nodeProbabilities) {
+    public static <T extends AbstractBlock<T>> List<T> computeLinearScanOrder(int blockCount, T startBlock, BlocksToDoubles blockProbabilities) {
         List<T> order = new ArrayList<>();
         BitSet visitedBlocks = new BitSet(blockCount);
-        PriorityQueue<T> worklist = initializeWorklist(startBlock, visitedBlocks, nodeProbabilities);
-        computeLinearScanOrder(order, worklist, visitedBlocks, nodeProbabilities);
+        PriorityQueue<T> worklist = initializeWorklist(startBlock, visitedBlocks, blockProbabilities);
+        computeLinearScanOrder(order, worklist, visitedBlocks, blockProbabilities);
         assert checkOrder(order, blockCount);
         return order;
     }
@@ -81,11 +80,11 @@
      * 
      * @return sorted list of blocks
      */
-    public static <T extends AbstractBlock<T>> List<T> computeCodeEmittingOrder(int blockCount, T startBlock, NodesToDoubles nodeProbabilities) {
+    public static <T extends AbstractBlock<T>> List<T> computeCodeEmittingOrder(int blockCount, T startBlock, BlocksToDoubles blockProbabilities) {
         List<T> order = new ArrayList<>();
         BitSet visitedBlocks = new BitSet(blockCount);
-        PriorityQueue<T> worklist = initializeWorklist(startBlock, visitedBlocks, nodeProbabilities);
-        computeCodeEmittingOrder(order, worklist, visitedBlocks, nodeProbabilities);
+        PriorityQueue<T> worklist = initializeWorklist(startBlock, visitedBlocks, blockProbabilities);
+        computeCodeEmittingOrder(order, worklist, visitedBlocks, blockProbabilities);
         assert checkOrder(order, blockCount);
         return order;
     }
@@ -93,28 +92,28 @@
     /**
      * Iteratively adds paths to the code emission block order.
      */
-    private static <T extends AbstractBlock<T>> void computeCodeEmittingOrder(List<T> order, PriorityQueue<T> worklist, BitSet visitedBlocks, NodesToDoubles nodeProbabilities) {
+    private static <T extends AbstractBlock<T>> void computeCodeEmittingOrder(List<T> order, PriorityQueue<T> worklist, BitSet visitedBlocks, BlocksToDoubles blockProbabilities) {
         while (!worklist.isEmpty()) {
             T nextImportantPath = worklist.poll();
-            addPathToCodeEmittingOrder(nextImportantPath, order, worklist, visitedBlocks, nodeProbabilities);
+            addPathToCodeEmittingOrder(nextImportantPath, order, worklist, visitedBlocks, blockProbabilities);
         }
     }
 
     /**
      * Iteratively adds paths to the linear scan block order.
      */
-    private static <T extends AbstractBlock<T>> void computeLinearScanOrder(List<T> order, PriorityQueue<T> worklist, BitSet visitedBlocks, NodesToDoubles nodeProbabilities) {
+    private static <T extends AbstractBlock<T>> void computeLinearScanOrder(List<T> order, PriorityQueue<T> worklist, BitSet visitedBlocks, BlocksToDoubles blockProbabilities) {
         while (!worklist.isEmpty()) {
             T nextImportantPath = worklist.poll();
-            addPathToLinearScanOrder(nextImportantPath, order, worklist, visitedBlocks, nodeProbabilities);
+            addPathToLinearScanOrder(nextImportantPath, order, worklist, visitedBlocks, blockProbabilities);
         }
     }
 
     /**
      * Initializes the priority queue used for the work list of blocks and adds the start block.
      */
-    private static <T extends AbstractBlock<T>> PriorityQueue<T> initializeWorklist(T startBlock, BitSet visitedBlocks, NodesToDoubles nodeProbabilities) {
-        PriorityQueue<T> result = new PriorityQueue<>(INITIAL_WORKLIST_CAPACITY, new BlockOrderComparator<T>(nodeProbabilities));
+    private static <T extends AbstractBlock<T>> PriorityQueue<T> initializeWorklist(T startBlock, BitSet visitedBlocks, BlocksToDoubles blockProbabilities) {
+        PriorityQueue<T> result = new PriorityQueue<>(INITIAL_WORKLIST_CAPACITY, new BlockOrderComparator<T>(blockProbabilities));
         result.add(startBlock);
         visitedBlocks.set(startBlock.getId());
         return result;
@@ -123,10 +122,10 @@
     /**
      * Add a linear path to the linear scan order greedily following the most likely successor.
      */
-    private static <T extends AbstractBlock<T>> void addPathToLinearScanOrder(T block, List<T> order, PriorityQueue<T> worklist, BitSet visitedBlocks, NodesToDoubles nodeProbabilities) {
+    private static <T extends AbstractBlock<T>> void addPathToLinearScanOrder(T block, List<T> order, PriorityQueue<T> worklist, BitSet visitedBlocks, BlocksToDoubles blockProbabilities) {
         block.setLinearScanNumber(order.size());
         order.add(block);
-        T mostLikelySuccessor = findAndMarkMostLikelySuccessor(block, visitedBlocks, nodeProbabilities);
+        T mostLikelySuccessor = findAndMarkMostLikelySuccessor(block, visitedBlocks, blockProbabilities);
         enqueueSuccessors(block, worklist, visitedBlocks);
         if (mostLikelySuccessor != null) {
             if (!mostLikelySuccessor.isLoopHeader() && mostLikelySuccessor.getPredecessorCount() > 1) {
@@ -135,17 +134,17 @@
                 double unscheduledSum = 0.0;
                 for (T pred : mostLikelySuccessor.getPredecessors()) {
                     if (pred.getLinearScanNumber() == -1) {
-                        unscheduledSum += nodeProbabilities.get(pred.getBeginNode());
+                        unscheduledSum += blockProbabilities.get(pred);
                     }
                 }
 
-                if (unscheduledSum > nodeProbabilities.get(block.getBeginNode()) / PENALTY_VERSUS_UNSCHEDULED) {
+                if (unscheduledSum > blockProbabilities.get(block) / PENALTY_VERSUS_UNSCHEDULED) {
                     // Add this merge only after at least one additional predecessor gets scheduled.
                     visitedBlocks.clear(mostLikelySuccessor.getId());
                     return;
                 }
             }
-            addPathToLinearScanOrder(mostLikelySuccessor, order, worklist, visitedBlocks, nodeProbabilities);
+            addPathToLinearScanOrder(mostLikelySuccessor, order, worklist, visitedBlocks, blockProbabilities);
         }
     }
 
@@ -153,7 +152,7 @@
      * Add a linear path to the code emission order greedily following the most likely successor.
      */
     @SuppressWarnings("unchecked")
-    private static <T extends AbstractBlock<T>> void addPathToCodeEmittingOrder(T initialBlock, List<T> order, PriorityQueue<T> worklist, BitSet visitedBlocks, NodesToDoubles nodeProbabilities) {
+    private static <T extends AbstractBlock<T>> void addPathToCodeEmittingOrder(T initialBlock, List<T> order, PriorityQueue<T> worklist, BitSet visitedBlocks, BlocksToDoubles blockProbabilities) {
         T block = initialBlock;
         while (block != null) {
             // Skip loop headers if there is only a single loop end block to
@@ -184,7 +183,7 @@
                 }
             }
 
-            T mostLikelySuccessor = findAndMarkMostLikelySuccessor(block, visitedBlocks, nodeProbabilities);
+            T mostLikelySuccessor = findAndMarkMostLikelySuccessor(block, visitedBlocks, blockProbabilities);
             enqueueSuccessors(block, worklist, visitedBlocks);
             block = mostLikelySuccessor;
         }
@@ -201,12 +200,11 @@
     /**
      * Find the highest likely unvisited successor block of a given block.
      */
-    private static <T extends AbstractBlock<T>> T findAndMarkMostLikelySuccessor(T block, BitSet visitedBlocks, NodesToDoubles nodeProbabilities) {
+    private static <T extends AbstractBlock<T>> T findAndMarkMostLikelySuccessor(T block, BitSet visitedBlocks, BlocksToDoubles blockProbabilities) {
         T result = null;
         for (T successor : block.getSuccessors()) {
-            assert nodeProbabilities.get(successor.getBeginNode()) >= 0.0 : "Probabilities must be positive";
-            if (!visitedBlocks.get(successor.getId()) && successor.getLoopDepth() >= block.getLoopDepth() &&
-                            (result == null || nodeProbabilities.get(successor.getBeginNode()) >= nodeProbabilities.get(result.getBeginNode()))) {
+            assert blockProbabilities.get(successor) >= 0.0 : "Probabilities must be positive";
+            if (!visitedBlocks.get(successor.getId()) && successor.getLoopDepth() >= block.getLoopDepth() && (result == null || blockProbabilities.get(successor) >= blockProbabilities.get(result))) {
                 result = successor;
             }
         }
@@ -249,9 +247,9 @@
      */
     private static class BlockOrderComparator<T extends AbstractBlock<T>> implements Comparator<T> {
 
-        private final NodesToDoubles probabilities;
+        private final BlocksToDoubles probabilities;
 
-        public BlockOrderComparator(NodesToDoubles probabilities) {
+        public BlockOrderComparator(BlocksToDoubles probabilities) {
             this.probabilities = probabilities;
         }
 
@@ -264,7 +262,7 @@
             }
 
             // Blocks with high probability before blocks with low probability.
-            if (probabilities.get(a.getBeginNode()) > probabilities.get(b.getBeginNode())) {
+            if (probabilities.get(a) > probabilities.get(b)) {
                 return -1;
             } else {
                 return 1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/KindInterface.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,30 @@
+/*
+ * 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.api.meta;
+
+public interface KindInterface {
+
+    Kind getKind();
+
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java	Thu Mar 27 17:31:20 2014 +0100
@@ -28,7 +28,7 @@
  * Abstract base class for values manipulated by the compiler. All values have a {@linkplain Kind
  * kind} and are immutable.
  */
-public abstract class Value implements Serializable {
+public abstract class Value implements Serializable, KindInterface {
 
     private static final long serialVersionUID = -6909397188697766469L;
 
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java	Thu Mar 27 17:31:20 2014 +0100
@@ -23,43 +23,41 @@
 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.alloc.*;
 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.alloc.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.java.*;
-import com.oracle.graal.java.BciBlockMapping.Block;
+import com.oracle.graal.java.BciBlockMapping.BciBlock;
 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.*;
+import com.oracle.graal.nodes.cfg.*;
 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.*;
+import com.oracle.graal.nodes.java.*;
 
 /**
  * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph.
  */
 @SuppressWarnings("all")
-public class BaselineCompiler {
+public class BaselineCompiler implements BytecodeParser<BciBlock> {
 
     public BaselineCompiler(GraphBuilderConfiguration graphBuilderConfig, MetaAccessProvider metaAccess) {
         this.graphBuilderConfig = graphBuilderConfig;
@@ -73,13 +71,19 @@
     private ProfilingInfo profilingInfo;
     private BytecodeStream stream;           // the bytecode stream
 
-    private Block currentBlock;
+    private Backend backend;
+    private LIRGenerator lirGen;
+    private LIRFrameStateBuilder frameState;
+    private LIRGenerationResult lirGenRes;
+
+    private BciBlock currentBlock;
 
     private ValueNode methodSynchronizedObject;
     private ExceptionDispatchBlock unwindBlock;
 
     private final GraphBuilderConfiguration graphBuilderConfig;
-    private Block[] loopHeaders;
+    private BciBlock[] loopHeaders;
+    private BytecodeParseHelper<Value> parserHelper;
 
     /**
      * Meters the number of actual bytecodes parsed.
@@ -90,9 +94,11 @@
         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;
+        this.backend = backend;
         profilingInfo = method.getProfilingInfo();
         assert method.getCode() != null : "method must contain bytecodes: " + method;
         this.stream = new BytecodeStream(method.getCode());
@@ -100,12 +106,22 @@
         unwindBlock = null;
         methodSynchronizedObject = null;
         TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method);
+
+        frameState = new LIRFrameStateBuilder(method);
+        parserHelper = new BytecodeParseHelper<>(frameState);
+
+        // build blocks and LIR instructions
         try {
             build();
         } finally {
             filter.remove();
         }
-        return null;
+
+        // emitCode
+        Assumptions assumptions = new Assumptions(OptAssumptions.getValue());
+        GraalCompiler.emitCode(backend, assumptions, lirGenRes, compilationResult, installedCodeOwner, factory);
+
+        return compilationResult;
     }
 
     protected void build() {
@@ -114,12 +130,19 @@
             TTY.println(MetaUtil.indent(MetaUtil.profileToString(profilingInfo, method, CodeUtil.NEW_LINE), "  "));
         }
 
-        Indent indent = Debug.logAndIndent("build graph for %s", method);
+        // Indent indent = Debug.logAndIndent("build graph for %s", method);
 
         // compute the block map, setup exception handlers and get the entrypoint(s)
         BciBlockMapping blockMap = BciBlockMapping.create(method);
         loopHeaders = blockMap.loopHeaders;
 
+        // add predecessors
+        for (BciBlock block : blockMap.blocks) {
+            for (BciBlock successor : block.getSuccessors()) {
+                successor.getPredecessors().add(block);
+            }
+        }
+
         if (isSynchronized(method.getModifiers())) {
             throw GraalInternalError.unimplemented("Handle synchronized methods");
         }
@@ -131,11 +154,56 @@
             throw GraalInternalError.unimplemented("Handle start block as loop header");
         }
 
-        for (Block block : blockMap.blocks) {
-            processBlock(block);
+        // add loops ? how do we add looks when we haven't parsed the bytecode?
+
+        // create the control flow graph
+        LIRControlFlowGraph cfg = new LIRControlFlowGraph(blockMap.blocks.toArray(new BciBlock[0]), new Loop[0]);
+
+        BlocksToDoubles blockProbabilities = new BlocksToDoubles(blockMap.blocks.size());
+        for (BciBlock b : blockMap.blocks) {
+            blockProbabilities.put(b, 1);
         }
 
-        indent.outdent();
+        // create the LIR
+        List<? extends AbstractBlock<?>> linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blockMap.blocks.size(), blockMap.startBlock, blockProbabilities);
+        List<? extends AbstractBlock<?>> codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blockMap.blocks.size(), blockMap.startBlock, blockProbabilities);
+        LIR lir = new LIR(cfg, linearScanOrder, codeEmittingOrder);
+
+        FrameMap frameMap = backend.newFrameMap();
+        TargetDescription target = backend.getTarget();
+        CallingConvention cc = CodeUtil.getCallingConvention(backend.getProviders().getCodeCache(), CallingConvention.Type.JavaCallee, method, false);
+        this.lirGenRes = backend.newLIRGenerationResult(lir, frameMap, null);
+        this.lirGen = backend.newLIRGenerator(cc, lirGenRes);
+
+        try (Scope ds = Debug.scope("BackEnd", lir)) {
+            try (Scope s = Debug.scope("LIRGen", lirGen)) {
+
+                // possibly add all the arguments to slots in the local variable array
+
+                for (BciBlock block : blockMap.blocks) {
+
+                    // lirGen.doBlock(block, method, this);
+                }
+                // indent.outdent();
+
+                lirGen.beforeRegisterAllocation();
+                Debug.dump(lir, "After LIR generation");
+            } catch (Throwable e) {
+                throw Debug.handle(e);
+            }
+
+            // try (Scope s = Debug.scope("Allocator", nodeLirGen)) {
+            try (Scope s = Debug.scope("Allocator")) {
+
+                if (backend.shouldAllocateRegisters()) {
+                    new LinearScan(target, lir, frameMap).allocate();
+                }
+            } catch (Throwable e) {
+                throw Debug.handle(e);
+            }
+        } catch (Throwable e) {
+            throw Debug.handle(e);
+        }
     }
 
     public BytecodeStream stream() {
@@ -147,11 +215,11 @@
     }
 
     private void loadLocal(int index, Kind kind) {
-        throw GraalInternalError.unimplemented();
+        parserHelper.loadLocal(index, kind);
     }
 
     private void storeLocal(Kind kind, int index) {
-        throw GraalInternalError.unimplemented();
+        parserHelper.storeLocal(kind, index);
     }
 
     /**
@@ -250,7 +318,10 @@
     }
 
     private void genArithmeticOp(Kind result, int opcode) {
-        throw GraalInternalError.unimplemented();
+        Value a = frameState.ipop();
+        Value b = frameState.ipop();
+        Value r = lirGen.emitAdd(a, b);
+        frameState.ipush(r);
     }
 
     private void genIntegerDivOp(Kind result, int opcode) {
@@ -434,7 +505,7 @@
         throw GraalInternalError.unimplemented();
     }
 
-    private void processBlock(Block block) {
+    public void processBlock(BciBlock block) {
         Indent indent = Debug.logAndIndent("Parsing block %s  firstInstruction: %s  loopHeader: %b", block, block.firstInstruction, block.isLoopHeader);
         currentBlock = block;
         iterateBytecodesForBlock(block);
@@ -445,7 +516,7 @@
         throw GraalInternalError.unimplemented();
     }
 
-    private void iterateBytecodesForBlock(Block block) {
+    private void iterateBytecodesForBlock(BciBlock block) {
 
         int endBCI = stream.endBCI();
 
@@ -646,12 +717,12 @@
             case RET            : genRet(stream.readLocalIndex()); break;
             case TABLESWITCH    : genSwitch(new BytecodeTableSwitch(stream(), bci())); break;
             case LOOKUPSWITCH   : genSwitch(new BytecodeLookupSwitch(stream(), bci())); 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 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(lookupField(cpi, opcode)); break;
             case PUTSTATIC      : cpi = stream.readCPI(); genPutStatic(lookupField(cpi, opcode)); break;
             case GETFIELD       : cpi = stream.readCPI(); genGetField(lookupField(cpi, opcode)); break;
@@ -700,11 +771,31 @@
             if (!currentBlock.jsrScope.isEmpty()) {
                 sb.append(' ').append(currentBlock.jsrScope);
             }
-            Debug.log(sb.toString());
+            Debug.log("%s", sb);
         }
     }
 
     private void genArrayLength() {
         throw GraalInternalError.unimplemented();
     }
+
+    private void genReturn(Value x) {
+        // frameState.setRethrowException(false);
+        frameState.clearStack();
+// if (graphBuilderConfig.eagerInfopointMode()) {
+// append(new InfopointNode(InfopointReason.METHOD_END, frameState.create(bci())));
+// }
+
+// synchronizedEpilogue(FrameState.AFTER_BCI, x);
+// if (frameState.lockDepth() != 0) {
+// throw new BailoutException("unbalanced monitors");
+// }
+
+        // lirGen.visitReturn(x);
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void setParameter(int i, Variable emitMove) {
+        frameState.storeLocal(i, emitMove);
+    }
 }
--- /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 27 17:31:20 2014 +0100
@@ -0,0 +1,62 @@
+/*
+ * 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.nodes.cfg.*;
+
+public class LIRBlock extends AbstractBlockBase<LIRBlock> {
+
+    public LIRBlock(int id) {
+        this.id = id;
+        predecessors = Collections.emptyList();
+        successors = Collections.emptyList();
+    }
+
+    public Loop getLoop() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public int getLoopDepth() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public boolean isLoopEnd() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public boolean isLoopHeader() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public boolean isExceptionEntry() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRControlFlowGraph.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,53 @@
+/*
+ * 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.baseline;
+
+import com.oracle.graal.java.BciBlockMapping.BciBlock;
+import com.oracle.graal.nodes.cfg.*;
+
+public class LIRControlFlowGraph implements AbstractControlFlowGraph<BciBlock> {
+
+    private BciBlock[] blocks;
+    private Loop[] loops;
+
+    public LIRControlFlowGraph(BciBlock[] blocks, Loop[] loops) {
+        this.blocks = blocks;
+        this.loops = loops;
+    }
+
+    public BciBlock[] getBlocks() {
+        return blocks;
+    }
+
+    public Loop[] getLoops() {
+        return loops;
+    }
+
+    public BciBlock getStartBlock() {
+        if (blocks.length > 0) {
+            return blocks[0];
+        }
+        return null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRFrameStateBuilder.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,249 @@
+/*
+ * 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.baseline;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.java.*;
+
+public class LIRFrameStateBuilder extends AbstractFrameStateBuilder<Value> {
+
+    private final Value[] locals;
+    private final Value[] stack;
+    private Value[] lockedObjects;
+
+    public LIRFrameStateBuilder(ResolvedJavaMethod method) {
+        super(method);
+
+        this.locals = new Value[method.getMaxLocals()];
+        // we always need at least one stack slot (for exceptions)
+        this.stack = new Value[Math.max(1, method.getMaxStackSize())];
+    }
+
+    protected LIRFrameStateBuilder(LIRFrameStateBuilder other) {
+        super(other);
+        // TODO Auto-generated constructor stub
+        locals = other.locals;
+        stack = other.stack;
+        lockedObjects = other.lockedObjects;
+    }
+
+    @Override
+    public int localsSize() {
+        return locals.length;
+    }
+
+    @Override
+    public Value localAt(int i) {
+        return locals[i];
+    }
+
+    @Override
+    public Value stackAt(int i) {
+        return stack[i];
+    }
+
+    @Override
+    public Value loadLocal(int i) {
+        Value x = locals[i];
+        assert !isTwoSlot(x.getKind()) || locals[i + 1] == null;
+        assert i == 0 || locals[i - 1] == null || !isTwoSlot(locals[i - 1].getKind());
+        return x;
+    }
+
+    @Override
+    public void storeLocal(int i, Value x) {
+        assert x == null || x.getKind() != Kind.Void && x.getKind() != Kind.Illegal : "unexpected value: " + x;
+        locals[i] = x;
+        if (x != null && isTwoSlot(x.getKind())) {
+            // if this is a double word, then kill i+1
+            locals[i + 1] = null;
+        }
+        if (x != null && i > 0) {
+            Value p = locals[i - 1];
+            if (p != null && isTwoSlot(p.getKind())) {
+                // if there was a double word at i - 1, then kill it
+                locals[i - 1] = null;
+            }
+        }
+    }
+
+    @Override
+    public void storeStack(int i, Value x) {
+        assert x == null || (stack[i] == null || x.getKind() == stack[i].getKind()) : "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, Value x) {
+        assert x.getKind() != Kind.Void && x.getKind() != Kind.Illegal;
+        xpush(assertKind(kind, x));
+        if (isTwoSlot(kind)) {
+            xpush(null);
+        }
+    }
+
+    @Override
+    public void xpush(Value x) {
+        assert x == null || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal);
+        stack[stackSize++] = x;
+    }
+
+    @Override
+    public void ipush(Value x) {
+        xpush(assertInt(x));
+    }
+
+    @Override
+    public void fpush(Value x) {
+        xpush(assertFloat(x));
+    }
+
+    @Override
+    public void apush(Value x) {
+        xpush(assertObject(x));
+    }
+
+    @Override
+    public void lpush(Value x) {
+        xpush(assertLong(x));
+    }
+
+    @Override
+    public void dpush(Value x) {
+        xpush(assertDouble(x));
+
+    }
+
+    @Override
+    public void pushReturn(Kind kind, Value x) {
+        if (kind != Kind.Void) {
+            push(kind.getStackKind(), x);
+        }
+    }
+
+    @Override
+    public Value pop(Kind kind) {
+        assert kind != Kind.Void;
+        if (isTwoSlot(kind)) {
+            xpop();
+        }
+        return assertKind(kind, xpop());
+    }
+
+    @Override
+    public Value xpop() {
+        Value result = stack[--stackSize];
+        return result;
+    }
+
+    @Override
+    public Value ipop() {
+        return assertInt(xpop());
+    }
+
+    @Override
+    public Value fpop() {
+        return assertFloat(xpop());
+    }
+
+    @Override
+    public Value apop() {
+        return assertObject(xpop());
+    }
+
+    @Override
+    public Value lpop() {
+        assertHigh(xpop());
+        return assertLong(xpop());
+    }
+
+    @Override
+    public Value dpop() {
+        assertHigh(xpop());
+        return assertDouble(xpop());
+    }
+
+    @Override
+    public Value[] popArguments(int slotSize, int argSize) {
+        int base = stackSize - slotSize;
+        Value[] r = new Value[argSize];
+        int argIndex = 0;
+        int stackindex = 0;
+        while (stackindex < slotSize) {
+            Value element = stack[base + stackindex];
+            assert element != null;
+            r[argIndex++] = element;
+            stackindex += stackSlots(element.getKind());
+        }
+        stackSize = base;
+        return r;
+    }
+
+    @Override
+    public Value peek(int argumentNumber) {
+        int idx = stackSize() - 1;
+        for (int i = 0; i < argumentNumber; i++) {
+            if (stackAt(idx) == null) {
+                idx--;
+                assert isTwoSlot(stackAt(idx).getKind());
+            }
+            idx--;
+        }
+        return stackAt(idx);
+    }
+
+    private static Value assertKind(Kind kind, Value x) {
+        assert x != null && x.getKind() == kind : "kind=" + kind + ", value=" + x + ((x == null) ? "" : ", value.kind=" + x.getKind());
+        return x;
+    }
+
+    private static Value assertLong(Value x) {
+        assert x != null && (x.getKind() == Kind.Long);
+        return x;
+    }
+
+    private static Value assertInt(Value x) {
+        assert x != null && (x.getKind() == Kind.Int);
+        return x;
+    }
+
+    private static Value assertFloat(Value x) {
+        assert x != null && (x.getKind() == Kind.Float);
+        return x;
+    }
+
+    private static Value assertObject(Value x) {
+        assert x != null && (x.getKind() == Kind.Object);
+        return x;
+    }
+
+    private static Value assertDouble(Value x) {
+        assert x != null && (x.getKind() == Kind.Double);
+        return x;
+    }
+
+    private static void assertHigh(Value x) {
+        assert x == null;
+    }
+}
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Thu Mar 27 17:31:20 2014 +0100
@@ -60,9 +60,8 @@
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.ReturnOp;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.StrategySwitchOp;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.TableSwitchOp;
-import com.oracle.graal.lir.amd64.AMD64Move.LeaDataOp;
 import com.oracle.graal.lir.amd64.AMD64Move.LeaOp;
-import com.oracle.graal.lir.amd64.AMD64Move.ZeroExtendLoadOp;
+import com.oracle.graal.lir.amd64.AMD64Move.LoadOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MembarOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp;
@@ -70,7 +69,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert;
-import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.util.*;
 
@@ -93,9 +91,9 @@
         }
     }
 
-    public AMD64LIRGenerator(StructuredGraph graph, Providers providers, FrameMap frameMap, CallingConvention cc, LIR lir) {
-        super(graph, providers, frameMap, cc, lir);
-        lir.setSpillMoveFactory(new AMD64SpillMoveFactory());
+    public AMD64LIRGenerator(Providers providers, CallingConvention cc, LIRGenerationResult lirGenRes) {
+        super(providers, cc, lirGenRes);
+        lirGenRes.getLIR().setSpillMoveFactory(new AMD64SpillMoveFactory());
     }
 
     @Override
@@ -159,10 +157,6 @@
         append(createMove(dst, src));
     }
 
-    public void emitData(AllocatableValue dst, byte[] data) {
-        append(new LeaDataOp(dst, data));
-    }
-
     @Override
     public AMD64AddressValue emitAddress(Value base, long displacement, Value index, int scale) {
         AllocatableValue baseRegister;
@@ -225,7 +219,7 @@
         return new AMD64AddressValue(target().wordKind, baseRegister, indexRegister, scaleEnum, displacementInt);
     }
 
-    protected AMD64AddressValue asAddressValue(Value address) {
+    public AMD64AddressValue asAddressValue(Value address) {
         if (address instanceof AMD64AddressValue) {
             return (AMD64AddressValue) address;
         } else {
@@ -266,13 +260,6 @@
     }
 
     @Override
-    protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        AllocatableValue targetAddress = AMD64.rax.asValue();
-        emitMove(targetAddress, operand(callTarget.computedAddress()));
-        append(new AMD64Call.IndirectCallOp(callTarget.target(), result, parameters, temps, targetAddress, callState));
-    }
-
-    @Override
     public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability) {
         append(new BranchOp(ConditionFlag.Overflow, overflow, noOverflow, overflowProbability));
     }
@@ -383,7 +370,7 @@
     /**
      * This method emits the compare instruction, and may reorder the operands. It returns true if
      * it did so.
-     * 
+     *
      * @param a the left operand of the comparison
      * @param b the right operand of the comparison
      * @return true if the left and right operands were switched, false otherwise
@@ -406,12 +393,6 @@
     }
 
     @Override
-    public void emitNullCheck(ValueNode v, DeoptimizingNode deopt) {
-        assert v.getKind() == Kind.Object : v + " - " + v.stamp() + " @ " + deopt;
-        append(new AMD64Move.NullCheckOp(load(operand(v)), state(deopt)));
-    }
-
-    @Override
     public Variable emitNegate(Value inputVal) {
         AllocatableValue input = asAllocatable(inputVal);
         Variable result = newVariable(input.getKind());
@@ -551,44 +532,6 @@
         }
     }
 
-    @Override
-    protected boolean peephole(ValueNode valueNode) {
-        if ((valueNode instanceof IntegerDivNode) || (valueNode instanceof IntegerRemNode)) {
-            FixedBinaryNode divRem = (FixedBinaryNode) valueNode;
-            FixedNode node = divRem.next();
-            while (node instanceof FixedWithNextNode) {
-                FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) node;
-                if (((fixedWithNextNode instanceof IntegerDivNode) || (fixedWithNextNode instanceof IntegerRemNode)) && fixedWithNextNode.getClass() != divRem.getClass()) {
-                    FixedBinaryNode otherDivRem = (FixedBinaryNode) fixedWithNextNode;
-                    if (otherDivRem.x() == divRem.x() && otherDivRem.y() == divRem.y() && !hasOperand(otherDivRem)) {
-                        Value[] results = emitIntegerDivRem(operand(divRem.x()), operand(divRem.y()), (DeoptimizingNode) valueNode);
-                        if (divRem instanceof IntegerDivNode) {
-                            setResult(divRem, results[0]);
-                            setResult(otherDivRem, results[1]);
-                        } else {
-                            setResult(divRem, results[1]);
-                            setResult(otherDivRem, results[0]);
-                        }
-                        return true;
-                    }
-                }
-                node = fixedWithNextNode.next();
-            }
-        }
-        return false;
-    }
-
-    protected MemoryArithmeticLIRLowerer memoryPeephole;
-
-    @Override
-    protected MemoryArithmeticLIRLowerer getMemoryLowerer() {
-        if (memoryPeephole == null) {
-            // Use the generic one
-            memoryPeephole = new AMD64MemoryPeephole(this);
-        }
-        return memoryPeephole;
-    }
-
     protected Value emitBinaryMemory(AMD64Arithmetic op, Kind kind, AllocatableValue a, AMD64AddressValue location, LIRFrameState state) {
         Variable result = newVariable(a.getKind());
         append(new BinaryMemory(op, kind, result, a, location, state));
@@ -602,10 +545,11 @@
     }
 
     protected Value emitZeroExtendMemory(Kind memoryKind, int resultBits, AMD64AddressValue address, LIRFrameState state) {
+        assert memoryKind.isUnsigned();
         // Issue a zero extending load of the proper bit size and set the result to
         // the proper kind.
         Variable result = newVariable(resultBits == 32 ? Kind.Int : Kind.Long);
-        append(new ZeroExtendLoadOp(memoryKind, result, address, state));
+        append(new LoadOp(memoryKind, result, address, state));
         return result;
     }
 
@@ -1036,7 +980,7 @@
     }
 
     @Override
-    protected void emitReturn(Value input) {
+    public void emitReturn(Value input) {
         append(new ReturnOp(input));
     }
 
@@ -1052,19 +996,4 @@
         append(new TableSwitchOp(lowKey, defaultTarget, targets, key, newVariable(target().wordKind), newVariable(key.getPlatformKind())));
     }
 
-    @Override
-    public void visitBreakpointNode(BreakpointNode node) {
-        JavaType[] sig = new JavaType[node.arguments().size()];
-        for (int i = 0; i < sig.length; i++) {
-            sig[i] = node.arguments().get(i).stamp().javaType(getMetaAccess());
-        }
-
-        Value[] parameters = visitInvokeArguments(frameMap.registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, sig, target(), false), node.arguments());
-        append(new AMD64BreakpointOp(parameters));
-    }
-
-    @Override
-    public void visitInfopointNode(InfopointNode i) {
-        append(new InfopointOp(stateFor(i.getState()), i.reason));
-    }
 }
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64MemoryPeephole.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64MemoryPeephole.java	Thu Mar 27 17:31:20 2014 +0100
@@ -45,10 +45,10 @@
 import com.oracle.graal.nodes.type.*;
 
 public class AMD64MemoryPeephole implements MemoryArithmeticLIRLowerer {
-    protected final AMD64LIRGenerator gen;
+    protected final AMD64NodeLIRGenerator gen;
     protected List<ValueNode> deferredNodes;
 
-    protected AMD64MemoryPeephole(AMD64LIRGenerator gen) {
+    protected AMD64MemoryPeephole(AMD64NodeLIRGenerator gen) {
         this.gen = gen;
     }
 
@@ -71,7 +71,7 @@
 
     protected LIRFrameState getState(Access access) {
         if (access instanceof DeoptimizingNode) {
-            return gen.state((DeoptimizingNode) access);
+            return gen.getLIRGenerator().state((DeoptimizingNode) access);
         }
         return null;
     }
@@ -90,7 +90,7 @@
             }
         }
         ensureEvaluated(other);
-        return gen.emitBinaryMemory(op, access.nullCheckLocation().getValueKind(), gen.asAllocatable(gen.operand(other)), makeAddress(access), getState(access));
+        return gen.getLIRGenerator().emitBinaryMemory(op, access.nullCheckLocation().getValueKind(), gen.getLIRGeneratorTool().asAllocatable(gen.operand(other)), makeAddress(access), getState(access));
     }
 
     /**
@@ -124,7 +124,7 @@
         AMD64AddressValue address = makeAddress(access);
         LIRFrameState state = getState(access);
         evaluateDeferred();
-        return gen.emitConvert2MemoryOp(kind, op, address, state);
+        return gen.getLIRGenerator().emitConvert2MemoryOp(kind, op, address, state);
     }
 
     @Override
@@ -248,7 +248,7 @@
 
     @Override
     public Value emitReinterpretMemory(Stamp stamp, Access access) {
-        PlatformKind to = gen.getPlatformKind(stamp);
+        PlatformKind to = gen.getLIRGenerator().getPlatformKind(stamp);
         Kind from = access.nullCheckLocation().getValueKind();
         assert to != from : "should have been eliminated";
 
@@ -366,7 +366,7 @@
             memoryKind = Kind.Char;
         }
         evaluateDeferred();
-        return gen.emitZeroExtendMemory(memoryKind, resultBits, makeAddress(access), getState(access));
+        return gen.getLIRGenerator().emitZeroExtendMemory(memoryKind, resultBits, makeAddress(access), getState(access));
     }
 
     public boolean emitIfMemory(IfNode x, Access access) {
@@ -446,7 +446,7 @@
                 return false;
             }
             ensureEvaluated(other);
-            gen.emitCompareMemoryConOp(kind, makeAddress(access), constant, getState(access));
+            gen.getLIRGenerator().emitCompareMemoryConOp(kind, makeAddress(access), constant, getState(access));
             mirrored = right == access;
         } else {
             if (kind != kind.getStackKind()) {
@@ -460,7 +460,7 @@
             }
 
             evaluateDeferred();
-            gen.emitCompareRegMemoryOp(kind, gen.operand(other), makeAddress(access), getState(access));
+            gen.getLIRGenerator().emitCompareRegMemoryOp(kind, gen.operand(other), makeAddress(access), getState(access));
             mirrored = left == access;
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRGenerator.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2009, 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.compiler.amd64;
+
+import com.oracle.graal.amd64.*;
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
+
+public abstract class AMD64NodeLIRGenerator extends NodeLIRGenerator {
+
+    public AMD64NodeLIRGenerator(StructuredGraph graph, LIRGenerationResult res, LIRGenerator gen) {
+        super(graph, res, gen);
+    }
+
+    protected MemoryArithmeticLIRLowerer memoryPeephole;
+
+    @Override
+    public MemoryArithmeticLIRLowerer getMemoryLowerer() {
+        if (memoryPeephole == null) {
+            // Use the generic one
+            memoryPeephole = new AMD64MemoryPeephole(this);
+        }
+        return memoryPeephole;
+    }
+
+    @Override
+    protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
+        AllocatableValue targetAddress = AMD64.rax.asValue();
+        gen.emitMove(targetAddress, operand(callTarget.computedAddress()));
+        append(new AMD64Call.IndirectCallOp(callTarget.target(), result, parameters, temps, targetAddress, callState));
+    }
+
+    @Override
+    public void emitNullCheck(ValueNode v, DeoptimizingNode deopt) {
+        assert v.getKind() == Kind.Object : v + " - " + v.stamp() + " @ " + deopt;
+        append(new AMD64Move.NullCheckOp(gen.load(operand(v)), gen.state(deopt)));
+    }
+
+    @Override
+    protected boolean peephole(ValueNode valueNode) {
+        if ((valueNode instanceof IntegerDivNode) || (valueNode instanceof IntegerRemNode)) {
+            FixedBinaryNode divRem = (FixedBinaryNode) valueNode;
+            FixedNode node = divRem.next();
+            while (node instanceof FixedWithNextNode) {
+                FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) node;
+                if (((fixedWithNextNode instanceof IntegerDivNode) || (fixedWithNextNode instanceof IntegerRemNode)) && fixedWithNextNode.getClass() != divRem.getClass()) {
+                    FixedBinaryNode otherDivRem = (FixedBinaryNode) fixedWithNextNode;
+                    if (otherDivRem.x() == divRem.x() && otherDivRem.y() == divRem.y() && operand(otherDivRem) == null) {
+                        Value[] results = ((AMD64LIRGenerator) gen).emitIntegerDivRem(operand(divRem.x()), operand(divRem.y()), (DeoptimizingNode) valueNode);
+                        if (divRem instanceof IntegerDivNode) {
+                            setResult(divRem, results[0]);
+                            setResult(otherDivRem, results[1]);
+                        } else {
+                            setResult(divRem, results[1]);
+                            setResult(otherDivRem, results[0]);
+                        }
+                        return true;
+                    }
+                }
+                node = fixedWithNextNode.next();
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public void visitBreakpointNode(BreakpointNode node) {
+        JavaType[] sig = new JavaType[node.arguments().size()];
+        for (int i = 0; i < sig.length; i++) {
+            sig[i] = node.arguments().get(i).stamp().javaType(gen.getMetaAccess());
+        }
+
+        Value[] parameters = visitInvokeArguments(res.getFrameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, sig, gen.target(), false), node.arguments());
+        append(new AMD64BreakpointOp(parameters));
+    }
+
+    @Override
+    public void visitInfopointNode(InfopointNode i) {
+        append(new InfopointOp(gen.stateFor(i.getState()), i.reason));
+    }
+
+    @Override
+    public AMD64LIRGenerator getLIRGenerator() {
+        return (AMD64LIRGenerator) gen;
+    }
+}
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Thu Mar 27 17:31:20 2014 +0100
@@ -32,7 +32,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.JumpOp;
@@ -54,7 +53,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.util.*;
 
 /**
@@ -76,9 +74,9 @@
         }
     }
 
-    public HSAILLIRGenerator(StructuredGraph graph, Providers providers, FrameMap frameMap, CallingConvention cc, LIR lir) {
-        super(graph, providers, frameMap, cc, lir);
-        lir.setSpillMoveFactory(new HSAILSpillMoveFactory());
+    public HSAILLIRGenerator(Providers providers, CallingConvention cc, LIRGenerationResult lirGenRes) {
+        super(providers, cc, lirGenRes);
+        lirGenRes.getLIR().setSpillMoveFactory(new HSAILSpillMoveFactory());
     }
 
     @Override
@@ -119,7 +117,7 @@
         throw GraalInternalError.unimplemented();
     }
 
-    protected HSAILAddressValue asAddressValue(Value address) {
+    public HSAILAddressValue asAddressValue(Value address) {
         if (address instanceof HSAILAddressValue) {
             return (HSAILAddressValue) address;
         } else {
@@ -177,7 +175,7 @@
         append(new JumpOp(label));
     }
 
-    protected static HSAILCompare mapKindToCompareOp(Kind kind) {
+    public static HSAILCompare mapKindToCompareOp(Kind kind) {
         switch (kind) {
             case Int:
                 return ICMP;
@@ -416,12 +414,6 @@
     }
 
     @Override
-    protected boolean peephole(ValueNode valueNode) {
-        // No peephole optimizations for now.
-        return false;
-    }
-
-    @Override
     public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) {
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
@@ -701,16 +693,6 @@
     }
 
     @Override
-    protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        throw GraalInternalError.unimplemented();
-    }
-
-    @Override
-    protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        throw GraalInternalError.unimplemented();
-    }
-
-    @Override
     public void emitBitCount(Variable result, Value value) {
         if (value.getKind().getStackKind() == Kind.Int) {
             append(new HSAILBitManipulationOp(IPOPCNT, result, value));
@@ -823,7 +805,7 @@
     }
 
     @Override
-    protected void emitReturn(Value input) {
+    public void emitReturn(Value input) {
         append(new ReturnOp(input));
     }
 
@@ -883,30 +865,8 @@
     }
 
     @Override
-    public void visitBreakpointNode(BreakpointNode node) {
-        throw GraalInternalError.unimplemented();
-    }
-
-    @Override
-    public void visitSafepointNode(SafepointNode i) {
-        Debug.log("visitSafePointNode unimplemented");
-    }
-
-    @Override
     public void emitUnwind(Value operand) {
         throw GraalInternalError.unimplemented();
     }
 
-    @Override
-    public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) {
-        assert v.stamp() instanceof ObjectStamp;
-        Variable obj = newVariable(Kind.Object);
-        emitMove(obj, operand(v));
-        append(new HSAILMove.NullCheckOp(obj, state(deopting)));
-    }
-
-    @Override
-    public void visitInfopointNode(InfopointNode i) {
-        throw GraalInternalError.unimplemented();
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILNodeLIRGenerator.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013, 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.compiler.hsail;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.hsail.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * This class implements the HSAIL specific portion of the LIR generator.
+ */
+public abstract class HSAILNodeLIRGenerator extends NodeLIRGenerator {
+
+    public HSAILNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult lirGenRes, LIRGenerator lirGen) {
+        super(graph, lirGenRes, lirGen);
+    }
+
+    @Override
+    protected boolean peephole(ValueNode valueNode) {
+        // No peephole optimizations for now.
+        return false;
+    }
+
+    @Override
+    protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    @Override
+    protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    @Override
+    public void visitBreakpointNode(BreakpointNode node) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    @Override
+    public void visitSafepointNode(SafepointNode i) {
+        Debug.log("visitSafePointNode unimplemented");
+    }
+
+    @Override
+    public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) {
+        assert v.stamp() instanceof ObjectStamp;
+        Variable obj = newVariable(Kind.Object);
+        gen.emitMove(obj, operand(v));
+        append(new HSAILMove.NullCheckOp(obj, gen.state(deopting)));
+    }
+
+    @Override
+    public void visitInfopointNode(InfopointNode i) {
+        throw GraalInternalError.unimplemented();
+    }
+}
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Thu Mar 27 17:31:20 2014 +0100
@@ -29,13 +29,10 @@
 import static com.oracle.graal.lir.ptx.PTXBitManipulationOp.IntrinsicOpcode.*;
 import static com.oracle.graal.lir.ptx.PTXCompare.*;
 
-import java.lang.reflect.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.JumpOp;
@@ -64,7 +61,6 @@
 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.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.util.*;
 
@@ -89,11 +85,11 @@
         }
     }
 
-    public PTXLIRGenerator(StructuredGraph graph, Providers providers, FrameMap frameMap, CallingConvention cc, LIR lir) {
-        super(graph, providers, frameMap, cc, lir);
-        lir.setSpillMoveFactory(new PTXSpillMoveFactory());
+    public PTXLIRGenerator(Providers providers, CallingConvention cc, LIRGenerationResult lirGenRes) {
+        super(providers, cc, lirGenRes);
+        lirGenRes.getLIR().setSpillMoveFactory(new PTXSpillMoveFactory());
         int callVariables = cc.getArgumentCount() + (cc.getReturn().equals(Value.ILLEGAL) ? 0 : 1);
-        lir.setFirstVariableNumber(callVariables);
+        lirGenRes.getLIR().setFirstVariableNumber(callVariables);
         nextPredRegNum = 0;
     }
 
@@ -134,43 +130,6 @@
         return value;
     }
 
-    @Override
-    public void emitPrologue(StructuredGraph graph) {
-        // Need to emit .param directives based on incoming arguments and return value
-        CallingConvention incomingArguments = cc;
-        Object returnObject = incomingArguments.getReturn();
-        AllocatableValue[] params = incomingArguments.getArguments();
-        int argCount = incomingArguments.getArgumentCount();
-
-        if (returnObject.equals(Value.ILLEGAL)) {
-            params = incomingArguments.getArguments();
-            append(new PTXParameterOp(params, false));
-        } else {
-            argCount = incomingArguments.getArgumentCount();
-            params = new Variable[argCount + 1];
-            for (int i = 0; i < argCount; i++) {
-                params[i] = incomingArguments.getArgument(i);
-            }
-            params[argCount] = (Variable) returnObject;
-            append(new PTXParameterOp(params, true));
-        }
-
-        for (ParameterNode param : graph.getNodes(ParameterNode.class)) {
-            int localIndex = param.index();
-            Value paramValue = params[param.index()];
-            int parameterIndex = localIndex;
-            if (!Modifier.isStatic(graph.method().getModifiers())) {
-                parameterIndex--;
-            }
-            Warp warpAnnotation = parameterIndex >= 0 ? MetaUtil.getParameterAnnotation(Warp.class, parameterIndex, graph.method()) : null;
-            if (warpAnnotation != null) {
-                setResult(param, emitWarpParam(paramValue.getKind().getStackKind(), warpAnnotation));
-            } else {
-                setResult(param, emitLoadParam(paramValue.getKind().getStackKind(), paramValue, null));
-            }
-        }
-    }
-
     public Variable emitWarpParam(Kind kind, Warp annotation) {
         Variable result = newVariable(kind);
         Variable tid = newVariable(Kind.Char);
@@ -538,12 +497,6 @@
     }
 
     @Override
-    protected boolean peephole(ValueNode valueNode) {
-        // No peephole optimizations for now
-        return false;
-    }
-
-    @Override
     public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) {
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
@@ -810,16 +763,6 @@
     }
 
     @Override
-    protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitDirectCall()");
-    }
-
-    @Override
-    protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitIndirectCall()");
-    }
-
-    @Override
     protected void emitForeignCall(ForeignCallLinkage callTarget, Value result, Value[] arguments, Value[] temps, LIRFrameState info) {
         throw GraalInternalError.unimplemented("PTXLIRGenerator.emitForeignCall()");
     }
@@ -885,11 +828,11 @@
     }
 
     @Override
-    protected void emitReturn(Value input) {
+    public void emitReturn(Value input) {
         append(new ReturnOp(input));
     }
 
-    private void emitReturnNoVal() {
+    void emitReturnNoVal() {
         append(new ReturnNoValOp());
     }
 
@@ -908,38 +851,10 @@
     }
 
     @Override
-    public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) {
-        throw GraalInternalError.unimplemented("PTXLIRGenerator.visitCompareAndSwap()");
-    }
-
-    @Override
-    public void visitBreakpointNode(BreakpointNode node) {
-        throw GraalInternalError.unimplemented("PTXLIRGenerator.visitBreakpointNode()");
-    }
-
-    @Override
-    public void visitSafepointNode(SafepointNode i) {
-        // LIRFrameState info = state(i);
-        // append(new PTXSafepointOp(info, runtime().config, this));
-        Debug.log("visitSafePointNode unimplemented");
-    }
-
-    @Override
     public void emitUnwind(Value operand) {
         throw GraalInternalError.unimplemented("PTXLIRGenerator.emitUnwind()");
     }
 
-    @Override
-    public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) {
-        assert v.getKind() == Kind.Object;
-        append(new PTXMove.NullCheckOp(load(operand(v)), state(deopting)));
-    }
-
-    @Override
-    public void visitInfopointNode(InfopointNode i) {
-        throw GraalInternalError.unimplemented("PTXLIRGenerator.visitInfopointNode()");
-    }
-
     public Variable emitLoadParam(Kind kind, Value address, DeoptimizingNode deopting) {
 
         PTXAddressValue loadAddress = asAddress(address);
@@ -984,16 +899,4 @@
         return (new Variable(kind, 0));
     }
 
-    @Override
-    public void visitReturn(ReturnNode x) {
-        AllocatableValue operand = Value.ILLEGAL;
-        if (x.result() != null) {
-            operand = resultOperandFor(x.result().getKind());
-            // Load the global memory address from return parameter
-            Variable loadVar = emitLoadReturnAddress(operand.getKind(), operand, null);
-            // Store result in global memory whose location is loadVar
-            emitStoreReturnValue(operand.getKind(), loadVar, operand(x.result()), null);
-        }
-        emitReturnNoVal();
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXNodeLIRGenerator.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2013, 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.compiler.ptx;
+
+import java.lang.reflect.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.ptx.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.nodes.java.*;
+
+/**
+ * This class implements the PTX specific portion of the LIR generator.
+ */
+public class PTXNodeLIRGenerator extends NodeLIRGenerator {
+
+    // Number of the predicate register that can be used when needed.
+    // This value will be recorded and incremented in the LIR instruction
+    // that sets a predicate register. (e.g., CompareOp)
+    private int nextPredRegNum;
+
+    public static final ForeignCallDescriptor ARITHMETIC_FREM = new ForeignCallDescriptor("arithmeticFrem", float.class, float.class, float.class);
+    public static final ForeignCallDescriptor ARITHMETIC_DREM = new ForeignCallDescriptor("arithmeticDrem", double.class, double.class, double.class);
+
+    public static class PTXSpillMoveFactory implements LIR.SpillMoveFactory {
+
+        @Override
+        public LIRInstruction createMove(AllocatableValue result, Value input) {
+            throw GraalInternalError.unimplemented("PTXSpillMoveFactory.createMove()");
+        }
+    }
+
+    public PTXNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult lirGenRes, LIRGenerator lirGen) {
+        super(graph, lirGenRes, lirGen);
+    }
+
+    public int getNextPredRegNumber() {
+        return nextPredRegNum;
+    }
+
+    @Override
+    public void emitPrologue(StructuredGraph graph) {
+        // Need to emit .param directives based on incoming arguments and return value
+        CallingConvention incomingArguments = gen.getCallingConvention();
+        Object returnObject = incomingArguments.getReturn();
+        AllocatableValue[] params = incomingArguments.getArguments();
+        int argCount = incomingArguments.getArgumentCount();
+
+        if (returnObject.equals(Value.ILLEGAL)) {
+            params = incomingArguments.getArguments();
+            append(new PTXParameterOp(params, false));
+        } else {
+            argCount = incomingArguments.getArgumentCount();
+            params = new Variable[argCount + 1];
+            for (int i = 0; i < argCount; i++) {
+                params[i] = incomingArguments.getArgument(i);
+            }
+            params[argCount] = (Variable) returnObject;
+            append(new PTXParameterOp(params, true));
+        }
+
+        for (ParameterNode param : graph.getNodes(ParameterNode.class)) {
+            int localIndex = param.index();
+            Value paramValue = params[param.index()];
+            int parameterIndex = localIndex;
+            if (!Modifier.isStatic(graph.method().getModifiers())) {
+                parameterIndex--;
+            }
+            Warp warpAnnotation = parameterIndex >= 0 ? MetaUtil.getParameterAnnotation(Warp.class, parameterIndex, graph.method()) : null;
+            if (warpAnnotation != null) {
+                setResult(param, getGen().emitWarpParam(paramValue.getKind().getStackKind(), warpAnnotation));
+            } else {
+                setResult(param, getGen().emitLoadParam(paramValue.getKind().getStackKind(), paramValue, null));
+            }
+        }
+    }
+
+    private PTXLIRGenerator getGen() {
+        return (PTXLIRGenerator) gen;
+    }
+
+    @Override
+    protected <T extends AbstractBlock<T>> void emitPrologue(ResolvedJavaMethod method, BytecodeParser<T> parser) {
+        // Need to emit .param directives based on incoming arguments and return value
+        CallingConvention incomingArguments = gen.getCallingConvention();
+        Object returnObject = incomingArguments.getReturn();
+        AllocatableValue[] params = incomingArguments.getArguments();
+        int argCount = incomingArguments.getArgumentCount();
+
+        if (returnObject.equals(Value.ILLEGAL)) {
+            params = incomingArguments.getArguments();
+            append(new PTXParameterOp(params, false));
+        } else {
+            argCount = incomingArguments.getArgumentCount();
+            params = new Variable[argCount + 1];
+            for (int i = 0; i < argCount; i++) {
+                params[i] = incomingArguments.getArgument(i);
+            }
+            params[argCount] = (Variable) returnObject;
+            append(new PTXParameterOp(params, true));
+        }
+
+        Signature sig = method.getSignature();
+        boolean isStatic = Modifier.isStatic(method.getModifiers());
+
+        for (int i = 0; i < sig.getParameterCount(!isStatic); i++) {
+            Value paramValue = params[i];
+            int parameterIndex = i;
+            if (!isStatic) {
+                parameterIndex--;
+            }
+            Warp warpAnnotation = parameterIndex >= 0 ? MetaUtil.getParameterAnnotation(Warp.class, parameterIndex, method) : null;
+            if (warpAnnotation != null) {
+                // setResult(param, emitWarpParam(paramValue.getKind().getStackKind(),
+                // warpAnnotation));
+                parser.setParameter(i, getGen().emitWarpParam(paramValue.getKind().getStackKind(), warpAnnotation));
+            } else {
+                // setResult(param, emitLoadParam(paramValue.getKind().getStackKind(), paramValue,
+                // null));
+                parser.setParameter(i, getGen().emitLoadParam(paramValue.getKind().getStackKind(), paramValue, null));
+            }
+        }
+    }
+
+    @Override
+    protected boolean peephole(ValueNode valueNode) {
+        // No peephole optimizations for now
+        return false;
+    }
+
+    @Override
+    protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitDirectCall()");
+    }
+
+    @Override
+    protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitIndirectCall()");
+    }
+
+    @Override
+    public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) {
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.visitCompareAndSwap()");
+    }
+
+    @Override
+    public void visitBreakpointNode(BreakpointNode node) {
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.visitBreakpointNode()");
+    }
+
+    @Override
+    public void visitSafepointNode(SafepointNode i) {
+        // LIRFrameState info = state(i);
+        // append(new PTXSafepointOp(info, runtime().config, this));
+        Debug.log("visitSafePointNode unimplemented");
+    }
+
+    @Override
+    public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) {
+        assert v.getKind() == Kind.Object;
+        append(new PTXMove.NullCheckOp(gen.load(operand(v)), gen.state(deopting)));
+    }
+
+    @Override
+    public void visitInfopointNode(InfopointNode i) {
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.visitInfopointNode()");
+    }
+
+    @Override
+    public void visitReturn(ReturnNode x) {
+        AllocatableValue operand = Value.ILLEGAL;
+        if (x.result() != null) {
+            operand = gen.resultOperandFor(x.result().getKind());
+            // Load the global memory address from return parameter
+            Variable loadVar = getGen().emitLoadReturnAddress(operand.getKind(), operand, null);
+            // Store result in global memory whose location is loadVar
+            getGen().emitStoreReturnValue(operand.getKind(), loadVar, operand(x.result()), null);
+        }
+        getGen().emitReturnNoVal();
+    }
+}
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Thu Mar 27 17:31:20 2014 +0100
@@ -56,12 +56,10 @@
 import com.oracle.graal.lir.sparc.SPARCMove.MembarOp;
 import com.oracle.graal.lir.sparc.SPARCMove.MoveFromRegOp;
 import com.oracle.graal.lir.sparc.SPARCMove.MoveToRegOp;
-import com.oracle.graal.lir.sparc.SPARCMove.NullCheckOp;
 import com.oracle.graal.lir.sparc.SPARCMove.StackLoadAddressOp;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert;
-import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.util.*;
 
@@ -78,9 +76,9 @@
         }
     }
 
-    public SPARCLIRGenerator(StructuredGraph graph, Providers providers, FrameMap frameMap, CallingConvention cc, LIR lir) {
-        super(graph, providers, frameMap, cc, lir);
-        lir.setSpillMoveFactory(new SPARCSpillMoveFactory());
+    public SPARCLIRGenerator(Providers providers, CallingConvention cc, LIRGenerationResult lirGenRes) {
+        super(providers, cc, lirGenRes);
+        lirGenRes.getLIR().setSpillMoveFactory(new SPARCSpillMoveFactory());
     }
 
     @Override
@@ -220,13 +218,7 @@
     }
 
     @Override
-    protected boolean peephole(ValueNode valueNode) {
-        // No peephole optimizations for now
-        return false;
-    }
-
-    @Override
-    protected void emitReturn(Value input) {
+    public void emitReturn(Value input) {
         append(new ReturnOp(input));
     }
 
@@ -923,35 +915,4 @@
         append(new ReturnOp(Value.ILLEGAL));
     }
 
-    @Override
-    public void visitCompareAndSwap(LoweredCompareAndSwapNode i, Value address) {
-        throw new InternalError("NYI");
-    }
-
-    @Override
-    public void visitBreakpointNode(BreakpointNode node) {
-        JavaType[] sig = new JavaType[node.arguments().size()];
-        for (int i = 0; i < sig.length; i++) {
-            sig[i] = node.arguments().get(i).stamp().javaType(getMetaAccess());
-        }
-
-        Value[] parameters = visitInvokeArguments(frameMap.registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, sig, target(), false), node.arguments());
-        append(new SPARCBreakpointOp(parameters));
-    }
-
-    @Override
-    public void emitUnwind(Value operand) {
-        throw new InternalError("NYI");
-    }
-
-    @Override
-    public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) {
-        assert v.getKind() == Kind.Object;
-        append(new NullCheckOp(load(operand(v)), state(deopting)));
-    }
-
-    @Override
-    public void visitInfopointNode(InfopointNode i) {
-        throw new InternalError("NYI");
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRGenerator.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2009, 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.compiler.sparc;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.lir.sparc.*;
+import com.oracle.graal.lir.sparc.SPARCMove.NullCheckOp;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+
+/**
+ * This class implements the SPARC specific portion of the LIR generator.
+ */
+public abstract class SPARCNodeLIRGenerator extends NodeLIRGenerator {
+
+    public SPARCNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult lirGenRes, LIRGenerator lirGen) {
+        super(graph, lirGenRes, lirGen);
+    }
+
+    @Override
+    protected boolean peephole(ValueNode valueNode) {
+        // No peephole optimizations for now
+        return false;
+    }
+
+    @Override
+    public void visitCompareAndSwap(LoweredCompareAndSwapNode i, Value address) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public void visitBreakpointNode(BreakpointNode node) {
+        JavaType[] sig = new JavaType[node.arguments().size()];
+        for (int i = 0; i < sig.length; i++) {
+            sig[i] = node.arguments().get(i).stamp().javaType(gen.getMetaAccess());
+        }
+
+        Value[] parameters = visitInvokeArguments(res.getFrameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, sig, gen.target(), false), node.arguments());
+        append(new SPARCBreakpointOp(parameters));
+    }
+
+    @Override
+    public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) {
+        assert v.getKind() == Kind.Object;
+        append(new NullCheckOp(gen.load(operand(v)), gen.state(deopting)));
+    }
+
+    @Override
+    public void visitInfopointNode(InfopointNode i) {
+        throw new InternalError("NYI");
+    }
+}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Thu Mar 27 17:31:20 2014 +0100
@@ -498,10 +498,9 @@
     }
 
     private CompilationResult compileBaseline(ResolvedJavaMethod javaMethod) {
-        try (Scope bds = Debug.scope("CompileBaseline")) {
+        try (Scope bds = Debug.scope("CompileBaseline", javaMethod, providers.getCodeCache())) {
             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 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Thu Mar 27 17:31:20 2014 +0100
@@ -73,8 +73,8 @@
         public RegisterStats(LIR lir) {
             this.lir = lir;
 
-            for (Block block : lir.codeEmittingOrder()) {
-                for (LIRInstruction instr : lir.lir(block)) {
+            for (AbstractBlock<?> block : lir.codeEmittingOrder()) {
+                for (LIRInstruction instr : lir.getLIRforBlock(block)) {
                     collectStats(instr);
                 }
             }
@@ -120,7 +120,7 @@
         }
 
         CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false);
-        LIRGenerator lirGen = GraalCompiler.emitLIR(getBackend(), getBackend().getTarget(), schedule, graph, null, cc);
-        return new RegisterStats(lirGen.lir);
+        LIRGenerationResult lirGen = GraalCompiler.emitLIR(getBackend(), getBackend().getTarget(), schedule, graph, null, cc);
+        return new RegisterStats(lirGen.getLIR());
     }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu Mar 27 17:31:20 2014 +0100
@@ -145,10 +145,10 @@
                 throw Debug.handle(e);
             }
             try (TimerCloseable a = BackEnd.start()) {
-                LIRGenerator lirGen = null;
-                lirGen = emitLIR(backend, target, schedule, graph, stub, cc);
-                try (Scope s = Debug.scope("CodeGen", lirGen)) {
-                    emitCode(backend, assumptions, lirGen, compilationResult, installedCodeOwner, factory);
+                LIRGenerationResult lirGenRes = null;
+                lirGenRes = emitLIR(backend, target, schedule, graph, stub, cc);
+                try (Scope s = Debug.scope("CodeGen", lirGenRes)) {
+                    emitCode(backend, assumptions, lirGenRes, compilationResult, installedCodeOwner, factory);
                 } catch (Throwable e) {
                     throw Debug.handle(e);
                 }
@@ -205,29 +205,32 @@
 
     }
 
-    private static void emitBlock(LIRGenerator lirGen, Block b, StructuredGraph graph, BlockMap<List<ScheduledNode>> blockMap) {
-        if (lirGen.lir.lir(b) == null) {
+    private static void emitBlock(NodeLIRGenerator nodeLirGen, LIRGenerationResult lirGenRes, Block b, StructuredGraph graph, BlockMap<List<ScheduledNode>> blockMap) {
+        if (lirGenRes.getLIR().getLIRforBlock(b) == null) {
             for (Block pred : b.getPredecessors()) {
                 if (!b.isLoopHeader() || !pred.isLoopEnd()) {
-                    emitBlock(lirGen, pred, graph, blockMap);
+                    emitBlock(nodeLirGen, lirGenRes, pred, graph, blockMap);
                 }
             }
-            lirGen.doBlock(b, graph, blockMap);
+            nodeLirGen.doBlock(b, graph, blockMap);
         }
     }
 
-    public static LIRGenerator emitLIR(Backend backend, TargetDescription target, SchedulePhase schedule, StructuredGraph graph, Object stub, CallingConvention cc) {
+    public static LIRGenerationResult emitLIR(Backend backend, TargetDescription target, SchedulePhase schedule, StructuredGraph graph, Object stub, CallingConvention cc) {
         Block[] blocks = schedule.getCFG().getBlocks();
         Block startBlock = schedule.getCFG().getStartBlock();
         assert startBlock != null;
         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);
+                BlocksToDoubles blockProbabilities = BlocksToDoubles.createFromNodeProbability(nodeProbabilities, schedule.getCFG());
+                codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock, blockProbabilities);
+                linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock, blockProbabilities);
 
                 lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder);
                 Debug.dump(lir, "After linear scan order");
@@ -239,11 +242,13 @@
         }
         try (Scope ds = Debug.scope("BackEnd", lir)) {
             FrameMap frameMap = backend.newFrameMap();
-            LIRGenerator lirGen = backend.newLIRGenerator(graph, stub, frameMap, cc, lir);
+            LIRGenerationResult lirGenRes = backend.newLIRGenerationResult(lir, frameMap, stub);
+            LIRGenerator lirGen = backend.newLIRGenerator(cc, lirGenRes);
+            NodeLIRGenerator nodeLirGen = backend.newNodeLIRGenerator(graph, lirGenRes, lirGen);
 
             try (Scope s = Debug.scope("LIRGen", lirGen)) {
-                for (Block b : lir.linearScanOrder()) {
-                    emitBlock(lirGen, b, graph, schedule.getBlockToNodesMap());
+                for (Block b : linearScanOrder) {
+                    emitBlock(nodeLirGen, lirGenRes, b, graph, schedule.getBlockToNodesMap());
                 }
                 lirGen.beforeRegisterAllocation();
 
@@ -252,7 +257,7 @@
                 throw Debug.handle(e);
             }
 
-            try (Scope s = Debug.scope("Allocator", lirGen)) {
+            try (Scope s = Debug.scope("Allocator", nodeLirGen)) {
                 if (backend.shouldAllocateRegisters()) {
                     new LinearScan(target, lir, frameMap).allocate();
                 }
@@ -262,7 +267,7 @@
 
             try (Scope s = Debug.scope("ControlFlowOptimizations")) {
                 EdgeMoveOptimizer.optimize(lir);
-                ControlFlowOptimizer.optimize(lir);
+                ControlFlowOptimizer.optimize(lir, codeEmittingOrder);
                 if (lirGen.canEliminateRedundantMoves()) {
                     RedundantMoveElimination.optimize(lir, frameMap);
                 }
@@ -272,16 +277,16 @@
             } catch (Throwable e) {
                 throw Debug.handle(e);
             }
-            return lirGen;
+            return lirGenRes;
         } catch (Throwable e) {
             throw Debug.handle(e);
         }
     }
 
-    public static void emitCode(Backend backend, Assumptions assumptions, LIRGenerator lirGen, CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner,
+    public static void emitCode(Backend backend, Assumptions assumptions, LIRGenerationResult lirGenRes, CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner,
                     CompilationResultBuilderFactory factory) {
-        CompilationResultBuilder crb = backend.newCompilationResultBuilder(lirGen, compilationResult, factory);
-        backend.emitCode(crb, lirGen.lir, installedCodeOwner);
+        CompilationResultBuilder crb = backend.newCompilationResultBuilder(lirGenRes, compilationResult, factory);
+        backend.emitCode(crb, lirGenRes.getLIR(), installedCodeOwner);
         crb.finish();
         if (!assumptions.isEmpty()) {
             compilationResult.setAssumptions(assumptions);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Thu Mar 27 17:31:20 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;
 
@@ -172,13 +172,13 @@
     }
 
     public int getFirstLirInstructionId(AbstractBlock<?> block) {
-        int result = ir.lir(block).get(0).id();
+        int result = ir.getLIRforBlock(block).get(0).id();
         assert result >= 0;
         return result;
     }
 
     public int getLastLirInstructionId(AbstractBlock<?> block) {
-        List<LIRInstruction> instructions = ir.lir(block);
+        List<LIRInstruction> instructions = ir.getLIRforBlock(block);
         int result = instructions.get(instructions.size() - 1).id();
         assert result >= 0;
         return result;
@@ -517,7 +517,7 @@
 
         LIRInsertionBuffer insertionBuffer = new LIRInsertionBuffer();
         for (AbstractBlock<?> block : sortedBlocks) {
-            List<LIRInstruction> instructions = ir.lir(block);
+            List<LIRInstruction> instructions = ir.getLIRforBlock(block);
             int numInst = instructions.size();
 
             // iterate all instructions of the block. skip the first because it is always a label
@@ -624,19 +624,19 @@
         // Assign IDs to LIR nodes and build a mapping, lirOps, from ID to LIRInstruction node.
         int numInstructions = 0;
         for (AbstractBlock<?> block : sortedBlocks) {
-            numInstructions += ir.lir(block).size();
+            numInstructions += ir.getLIRforBlock(block).size();
         }
 
         // initialize with correct length
         opIdToInstructionMap = new LIRInstruction[numInstructions];
-        opIdToBlockMap = new Block[numInstructions];
+        opIdToBlockMap = new AbstractBlock<?>[numInstructions];
 
         int opId = 0;
         int index = 0;
         for (AbstractBlock<?> block : sortedBlocks) {
             blockData.put(block, new BlockData());
 
-            List<LIRInstruction> instructions = ir.lir(block);
+            List<LIRInstruction> instructions = ir.getLIRforBlock(block);
 
             int numInst = instructions.size();
             for (int j = 0; j < numInst; j++) {
@@ -681,7 +681,7 @@
             final BitSet liveGen = new BitSet(liveSize);
             final BitSet liveKill = new BitSet(liveSize);
 
-            List<LIRInstruction> instructions = ir.lir(block);
+            List<LIRInstruction> instructions = ir.getLIRforBlock(block);
             int numInst = instructions.size();
 
             // iterate all instructions of the block
@@ -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);
@@ -880,9 +880,9 @@
         indent.outdent();
     }
 
-    private static LIRGenerator getLIRGeneratorFromDebugContext() {
+    private static NodeLIRGenerator getNodeLIRGeneratorFromDebugContext() {
         if (Debug.isEnabled()) {
-            LIRGenerator lirGen = Debug.contextLookup(LIRGenerator.class);
+            NodeLIRGenerator lirGen = Debug.contextLookup(NodeLIRGenerator.class);
             assert lirGen != null;
             return lirGen;
         }
@@ -890,7 +890,7 @@
     }
 
     private static ValueNode getValueForOperandFromDebugContext(Value value) {
-        LIRGenerator gen = getLIRGeneratorFromDebugContext();
+        NodeLIRGenerator gen = getNodeLIRGeneratorFromDebugContext();
         if (gen != null) {
             return gen.valueForOperand(value);
         }
@@ -920,7 +920,7 @@
                     if (blockData.get(block).liveGen.get(operandNum)) {
                         usedIn.add(block);
                         try (Indent indent3 = Debug.logAndIndent("used in block B%d", block.getId())) {
-                            for (LIRInstruction ins : ir.lir(block)) {
+                            for (LIRInstruction ins : ir.getLIRforBlock(block)) {
                                 try (Indent indent4 = Debug.logAndIndent("%d: %s", ins.id(), ins)) {
                                     ins.forEachState(new ValueProcedure() {
 
@@ -937,7 +937,7 @@
                     if (blockData.get(block).liveKill.get(operandNum)) {
                         definedIn.add(block);
                         try (Indent indent3 = Debug.logAndIndent("defined in block B%d", block.getId())) {
-                            for (LIRInstruction ins : ir.lir(block)) {
+                            for (LIRInstruction ins : ir.getLIRforBlock(block)) {
                                 Debug.log("%d: %s", ins.id(), ins);
                             }
                         }
@@ -1161,7 +1161,7 @@
             AbstractBlock<?> block = blockAt(i);
             Indent indent2 = Debug.logAndIndent("handle block %d", block.getId());
 
-            List<LIRInstruction> instructions = ir.lir(block);
+            List<LIRInstruction> instructions = ir.getLIRforBlock(block);
             final int blockFrom = getFirstLirInstructionId(block);
             int blockTo = getLastLirInstructionId(block);
 
@@ -1510,7 +1510,7 @@
         if (fromBlock.getSuccessorCount() <= 1) {
             Debug.log("inserting moves at end of fromBlock B%d", fromBlock.getId());
 
-            List<LIRInstruction> instructions = ir.lir(fromBlock);
+            List<LIRInstruction> instructions = ir.getLIRforBlock(fromBlock);
             LIRInstruction instr = instructions.get(instructions.size() - 1);
             if (instr instanceof StandardOp.JumpOp) {
                 // insert moves before branch
@@ -1523,7 +1523,7 @@
             Debug.log("inserting moves at beginning of toBlock B%d", toBlock.getId());
 
             if (DetailedAsserts.getValue()) {
-                assert ir.lir(fromBlock).get(0) instanceof StandardOp.LabelOp : "block does not start with a label";
+                assert ir.getLIRforBlock(fromBlock).get(0) instanceof StandardOp.LabelOp : "block does not start with a label";
 
                 // because the number of predecessor edges matches the number of
                 // successor edges, blocks which are reached by switch statements
@@ -1534,7 +1534,7 @@
                 }
             }
 
-            moveResolver.setInsertPosition(ir.lir(toBlock), 1);
+            moveResolver.setInsertPosition(ir.getLIRforBlock(toBlock), 1);
         }
     }
 
@@ -1554,7 +1554,7 @@
 
             // check if block has only one predecessor and only one successor
             if (block.getPredecessorCount() == 1 && block.getSuccessorCount() == 1) {
-                List<LIRInstruction> instructions = ir.lir(block);
+                List<LIRInstruction> instructions = ir.getLIRforBlock(block);
                 assert instructions.get(0) instanceof StandardOp.LabelOp : "block must start with label";
                 assert instructions.get(instructions.size() - 1) instanceof StandardOp.JumpOp : "block with successor must end with unconditional jump";
 
@@ -1636,7 +1636,7 @@
                     // before the branch instruction. So the split child information for this branch
                     // would
                     // be incorrect.
-                    LIRInstruction instr = ir.lir(block).get(ir.lir(block).size() - 1);
+                    LIRInstruction instr = ir.getLIRforBlock(block).get(ir.getLIRforBlock(block).size() - 1);
                     if (instr instanceof StandardOp.JumpOp) {
                         if (blockData.get(block).liveOut.get(operandNumber(operand))) {
                             assert false : "can't get split child for the last branch of a block because the information would be incorrect (moves are inserted before the branch in resolveDataFlow)";
@@ -1752,7 +1752,7 @@
                     // are not
                     // considered in the live ranges of intervals)
                     // Solution: use the first opId of the branch target block instead.
-                    final LIRInstruction instr = ir.lir(block).get(ir.lir(block).size() - 1);
+                    final LIRInstruction instr = ir.getLIRforBlock(block).get(ir.getLIRforBlock(block).size() - 1);
                     if (instr instanceof StandardOp.JumpOp) {
                         if (blockData.get(block).liveOut.get(operandNumber(operand))) {
                             tempOpId = getFirstLirInstructionId(block.getSuccessors().iterator().next());
@@ -1846,7 +1846,7 @@
         try (Indent indent = Debug.logAndIndent("assign locations")) {
             for (AbstractBlock<?> block : sortedBlocks) {
                 try (Indent indent2 = Debug.logAndIndent("assign locations in block B%d", block.getId())) {
-                    assignLocations(ir.lir(block), iw);
+                    assignLocations(ir.getLIRforBlock(block), iw);
                 }
             }
         }
@@ -2060,7 +2060,7 @@
             IntervalWalker iw = new IntervalWalker(this, fixedIntervals, otherIntervals);
 
             for (AbstractBlock<?> block : sortedBlocks) {
-                List<LIRInstruction> instructions = ir.lir(block);
+                List<LIRInstruction> instructions = ir.getLIRforBlock(block);
 
                 for (int j = 0; j < instructions.size(); j++) {
                     LIRInstruction op = instructions.get(j);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Thu Mar 27 17:31:20 2014 +0100
@@ -254,7 +254,7 @@
         // numbering of instructions is known.
         // When the block already contains spill moves, the index must be increased until the
         // correct index is reached.
-        List<LIRInstruction> instructions = allocator.ir.lir(opBlock);
+        List<LIRInstruction> instructions = allocator.ir.getLIRforBlock(opBlock);
         int index = (opId - instructions.get(0).id()) >> 1;
         assert instructions.get(index).id() <= opId : "error in calculation";
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java	Thu Mar 27 17:31:20 2014 +0100
@@ -106,7 +106,7 @@
             }
 
             // process all operations of the block
-            processOperations(allocator.ir.lir(block), inputState);
+            processOperations(allocator.ir.getLIRforBlock(block), inputState);
 
             // iterate all successors
             for (AbstractBlock<?> succ : block.getSuccessors()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/BytecodeParser.java	Thu Mar 27 17:31:20 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.compiler.gen;
+
+import com.oracle.graal.lir.*;
+import com.oracle.graal.nodes.cfg.*;
+
+public interface BytecodeParser<T extends AbstractBlock<T>> {
+    void processBlock(T block);
+
+    void setParameter(int i, Variable emitMove);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerationResult.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,35 @@
+/*
+ * 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.compiler.gen;
+
+import com.oracle.graal.lir.*;
+
+public interface LIRGenerationResult {
+    FrameMap getFrameMap();
+
+    LIR getLIR();
+
+    boolean hasForeignCall();
+
+    void setForeignCall(boolean b);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerationResultBase.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,59 @@
+/*
+ * 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.compiler.gen;
+
+import com.oracle.graal.lir.*;
+
+public class LIRGenerationResultBase implements LIRGenerationResult {
+    private final LIR lir;
+    private final FrameMap frameMap;
+    /**
+     * Records whether the code being generated makes at least one foreign call.
+     */
+    private boolean hasForeignCall;
+
+    public LIRGenerationResultBase(LIR lir, FrameMap frameMap) {
+        this.lir = lir;
+        this.frameMap = frameMap;
+    }
+
+    public LIR getLIR() {
+        return lir;
+    }
+
+    /**
+     * Determines whether the code being generated makes at least one foreign call.
+     */
+    public boolean hasForeignCall() {
+        return hasForeignCall;
+    }
+
+    public final void setForeignCall(boolean hasForeignCall) {
+        this.hasForeignCall = hasForeignCall;
+    }
+
+    public final FrameMap getFrameMap() {
+        return frameMap;
+    }
+
+}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Thu Mar 27 17:31:20 2014 +0100
@@ -26,39 +26,31 @@
 import static com.oracle.graal.api.meta.Value.*;
 import static com.oracle.graal.lir.LIR.*;
 import static com.oracle.graal.lir.LIRValueUtil.*;
-import static com.oracle.graal.nodes.ConstantNode.*;
 import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
-import java.util.Map.Entry;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
-import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.BlockEndOp;
-import com.oracle.graal.lir.StandardOp.JumpOp;
 import com.oracle.graal.lir.StandardOp.LabelOp;
 import com.oracle.graal.lir.StandardOp.NoOp;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.cfg.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.util.*;
 
 /**
  * This class traverses the HIR instructions and generates LIR instructions from them.
  */
-public abstract class LIRGenerator implements LIRGeneratorTool, LIRTypeTool {
+public abstract class LIRGenerator implements ArithmeticLIRGenerator, LIRGeneratorTool, LIRTypeTool {
 
     public static class Options {
         // @formatter:off
@@ -69,16 +61,12 @@
         // @formatter:on
     }
 
-    public final FrameMap frameMap;
-    public final NodeMap<Value> nodeOperands;
-    public final LIR lir;
+    private final Providers providers;
+    private final CallingConvention cc;
 
-    private final Providers providers;
-    protected final CallingConvention cc;
+    private DebugInfoBuilder debugInfoBuilder;
 
-    protected final DebugInfoBuilder debugInfoBuilder;
-
-    protected Block currentBlock;
+    protected AbstractBlock<?> currentBlock;
     private final int traceLevel;
     private final boolean printIRWithLIR;
 
@@ -104,12 +92,12 @@
          * The block that does or will contain {@link #op}. This is initially the block where the
          * first usage of the constant is seen during LIR generation.
          */
-        private Block block;
+        Block block;
 
         /**
          * The variable into which the constant is loaded.
          */
-        private final Variable variable;
+        final Variable variable;
 
         public LoadConstant(Variable variable, Block block, int index, LIRInstruction op) {
             this.variable = variable;
@@ -144,40 +132,40 @@
             if (index >= 0) {
                 // Replace the move with a filler op so that the operation
                 // list does not need to be adjusted.
-                List<LIRInstruction> instructions = lir.lir(block);
+                List<LIRInstruction> instructions = lir.getLIRforBlock(block);
                 instructions.set(index, new NoOp(null, -1));
                 index = -1;
             }
         }
     }
 
-    private Map<Constant, LoadConstant> constantLoads;
+    Map<Constant, LoadConstant> constantLoads;
 
-    private ValueNode currentInstruction;
-    private ValueNode lastInstructionPrinted; // Debugging only
+    protected LIRGenerationResult res;
 
     /**
-     * Records whether the code being generated makes at least one foreign call.
+     * Set this before using the LIRGenerator.
+     *
+     * TODO this should be removed
      */
-    private boolean hasForeignCall;
+    void setDebugInfoBuilder(DebugInfoBuilder builder) {
+        debugInfoBuilder = builder;
+    }
 
     /**
      * Checks whether the supplied constant can be used without loading it into a register for store
      * operations, i.e., on the right hand side of a memory access.
-     * 
+     *
      * @param c The constant to check.
      * @return True if the constant can be used directly, false if the constant needs to be in a
      *         register.
      */
     public abstract boolean canStoreConstant(Constant c, boolean isCompressed);
 
-    public LIRGenerator(StructuredGraph graph, Providers providers, FrameMap frameMap, CallingConvention cc, LIR lir) {
+    public LIRGenerator(Providers providers, CallingConvention cc, LIRGenerationResult res) {
+        this.res = res;
         this.providers = providers;
-        this.frameMap = frameMap;
         this.cc = cc;
-        this.nodeOperands = graph.createNodeMap();
-        this.lir = lir;
-        this.debugInfoBuilder = createDebugInfoBuilder(nodeOperands);
         this.traceLevel = Options.TraceLIRGeneratorLevel.getValue();
         this.printIRWithLIR = Options.PrintIRWithLIR.getValue();
     }
@@ -190,17 +178,12 @@
         return true;
     }
 
-    @SuppressWarnings("hiding")
-    protected DebugInfoBuilder createDebugInfoBuilder(NodeMap<Value> nodeOperands) {
-        return new DebugInfoBuilder(nodeOperands);
-    }
-
     @Override
     public TargetDescription target() {
         return getCodeCache().getTarget();
     }
 
-    protected Providers getProviders() {
+    public Providers getProviders() {
         return providers;
     }
 
@@ -220,112 +203,19 @@
     }
 
     /**
-     * Determines whether the code being generated makes at least one foreign call.
-     */
-    public boolean hasForeignCall() {
-        return hasForeignCall;
-    }
-
-    /**
-     * Returns the operand that has been previously initialized by
-     * {@link #setResult(ValueNode, Value)} with the result of an instruction. It's a code
-     * generation error to ask for the operand of ValueNode that doesn't have one yet.
-     * 
-     * @param node A node that produces a result value.
-     */
-    @Override
-    public Value operand(ValueNode node) {
-        Value operand = getOperand(node);
-        assert operand != null : String.format("missing operand for %1s", node);
-        return operand;
-    }
-
-    @Override
-    public boolean hasOperand(ValueNode node) {
-        return getOperand(node) != null;
-    }
-
-    private Value getOperand(ValueNode node) {
-        if (nodeOperands == null) {
-            return null;
-        }
-        Value operand = nodeOperands.get(node);
-        if (operand == null) {
-            operand = getConstantOperand(node);
-        }
-        return operand;
-    }
-
-    private Value getConstantOperand(ValueNode node) {
-        if (!ConstantNodeRecordsUsages) {
-            Constant value = node.asConstant();
-            if (value != null) {
-                if (canInlineConstant(value)) {
-                    return setResult(node, value);
-                } else {
-                    Variable loadedValue;
-                    if (constantLoads == null) {
-                        constantLoads = new HashMap<>();
-                    }
-                    LoadConstant load = constantLoads.get(value);
-                    if (load == null) {
-                        int index = lir.lir(currentBlock).size();
-                        loadedValue = emitMove(value);
-                        LIRInstruction op = lir.lir(currentBlock).get(index);
-                        constantLoads.put(value, new LoadConstant(loadedValue, currentBlock, index, op));
-                    } else {
-                        Block dominator = ControlFlowGraph.commonDominator(load.block, currentBlock);
-                        loadedValue = load.variable;
-                        if (dominator != load.block) {
-                            load.unpin(lir);
-                        } else {
-                            assert load.block != currentBlock || load.index < lir.lir(currentBlock).size();
-                        }
-                        load.block = dominator;
-                    }
-                    return loadedValue;
-                }
-            }
-        } else {
-            // Constant is loaded by ConstantNode.generate()
-        }
-        return null;
-    }
-
-    public ValueNode valueForOperand(Value value) {
-        for (Entry<Node, Value> entry : nodeOperands.entries()) {
-            if (entry.getValue().equals(value)) {
-                return (ValueNode) entry.getKey();
-            }
-        }
-        return null;
-    }
-
-    /**
      * Creates a new {@linkplain Variable variable}.
-     * 
+     *
      * @param platformKind The kind of the new variable.
      * @return a new variable
      */
     @Override
     public Variable newVariable(PlatformKind platformKind) {
-        return new Variable(platformKind, lir.nextVariable());
+        return new Variable(platformKind, res.getLIR().nextVariable());
     }
 
     @Override
     public RegisterAttributes attributes(Register register) {
-        return frameMap.registerConfig.getAttributesMap()[register.number];
-    }
-
-    @Override
-    public Value setResult(ValueNode x, Value operand) {
-        assert (!isRegister(operand) || !attributes(asRegister(operand)).isAllocatable());
-        assert nodeOperands == null || nodeOperands.get(x) == null : "operand cannot be set twice";
-        assert operand != null && isLegal(operand) : "operand must be legal";
-        assert operand.getKind().getStackKind() == x.getKind() || x.getKind() == Kind.Illegal : operand.getKind().getStackKind() + " must match " + x.getKind();
-        assert !(x instanceof VirtualObjectNode);
-        nodeOperands.set(x, operand);
-        return operand;
+        return res.getFrameMap().registerConfig.getAttributesMap()[register.number];
     }
 
     @Override
@@ -354,11 +244,13 @@
     }
 
     public LabelRef getLIRBlock(FixedNode b) {
-        Block result = lir.getControlFlowGraph().blockFor(b);
+        assert res.getLIR().getControlFlowGraph() instanceof ControlFlowGraph;
+        Block result = ((ControlFlowGraph) res.getLIR().getControlFlowGraph()).blockFor(b);
         int suxIndex = currentBlock.getSuccessors().indexOf(result);
         assert suxIndex != -1 : "Block not in successor list of current block";
 
-        return LabelRef.forSuccessor(lir, currentBlock, suxIndex);
+        assert currentBlock instanceof Block;
+        return LabelRef.forSuccessor(res.getLIR(), (Block) currentBlock, suxIndex);
     }
 
     /**
@@ -404,12 +296,12 @@
             return new LIRFrameState(null, null, null);
         }
         assert state != null;
-        return debugInfoBuilder.build(state, exceptionEdge);
+        return getDebugInfoBuilder().build(state, exceptionEdge);
     }
 
     /**
      * Gets the ABI specific operand used to return a value of a given kind from a method.
-     * 
+     *
      * @param kind the kind of value being returned
      * @return the operand representing the ABI defined location used return a value of kind
      *         {@code kind}
@@ -418,24 +310,24 @@
         if (kind == Kind.Void) {
             return ILLEGAL;
         }
-        return frameMap.registerConfig.getReturnRegister(kind).asValue(kind);
+        return res.getFrameMap().registerConfig.getReturnRegister(kind).asValue(kind);
     }
 
     public void append(LIRInstruction op) {
         if (printIRWithLIR && !TTY.isSuppressed()) {
-            if (currentInstruction != null && lastInstructionPrinted != currentInstruction) {
-                lastInstructionPrinted = currentInstruction;
-                InstructionPrinter ip = new InstructionPrinter(TTY.out());
-                ip.printInstructionListing(currentInstruction);
-            }
+            // if (currentInstruction != null && lastInstructionPrinted != currentInstruction) {
+            // lastInstructionPrinted = currentInstruction;
+            // InstructionPrinter ip = new InstructionPrinter(TTY.out());
+            // ip.printInstructionListing(currentInstruction);
+            // }
             TTY.println(op.toStringWithIdPrefix());
             TTY.println();
         }
         assert LIRVerifier.verify(op);
-        lir.lir(currentBlock).add(op);
+        res.getLIR().getLIRforBlock(currentBlock).add(op);
     }
 
-    public void doBlock(Block block, StructuredGraph graph, BlockMap<List<ScheduledNode>> blockMap) {
+    public final void doBlockStart(AbstractBlock<?> block) {
         if (printIRWithLIR) {
             TTY.print(block.toString());
         }
@@ -443,71 +335,17 @@
         currentBlock = block;
 
         // set up the list of LIR instructions
-        assert lir.lir(block) == null : "LIR list already computed for this block";
-        lir.setLir(block, new ArrayList<LIRInstruction>());
+        assert res.getLIR().getLIRforBlock(block) == null : "LIR list already computed for this block";
+        res.getLIR().setLIRforBlock(block, new ArrayList<LIRInstruction>());
 
         append(new LabelOp(new Label(block.getId()), block.isAligned()));
 
         if (traceLevel >= 1) {
             TTY.println("BEGIN Generating LIR for block B" + block.getId());
         }
-
-        if (block == lir.getControlFlowGraph().getStartBlock()) {
-            assert block.getPredecessorCount() == 0;
-            emitPrologue(graph);
-        } else {
-            assert block.getPredecessorCount() > 0;
-        }
+    }
 
-        List<ScheduledNode> nodes = blockMap.get(block);
-        int instructionsFolded = 0;
-        for (int i = 0; i < nodes.size(); i++) {
-            Node instr = nodes.get(i);
-            if (traceLevel >= 3) {
-                TTY.println("LIRGen for " + instr);
-            }
-            if (instructionsFolded > 0) {
-                instructionsFolded--;
-                continue;
-            }
-            if (!ConstantNodeRecordsUsages && instr instanceof ConstantNode) {
-                // Loading of constants is done lazily by operand()
-            } else if (instr instanceof ValueNode) {
-                ValueNode valueNode = (ValueNode) instr;
-                if (!hasOperand(valueNode)) {
-                    if (!peephole(valueNode)) {
-                        instructionsFolded = maybeFoldMemory(nodes, i, valueNode);
-                        if (instructionsFolded == 0) {
-                            try {
-                                doRoot((ValueNode) instr);
-                            } catch (GraalInternalError e) {
-                                throw e.addContext(instr);
-                            } catch (Throwable e) {
-                                throw new GraalInternalError(e).addContext(instr);
-                            }
-                        }
-                    }
-                } else {
-                    // There can be cases in which the result of an instruction is already set
-                    // before by other instructions.
-                }
-            }
-        }
-
-        if (!hasBlockEnd(block)) {
-            NodeClassIterable successors = block.getEndNode().successors();
-            assert successors.count() == block.getSuccessorCount();
-            if (block.getSuccessorCount() != 1) {
-                /*
-                 * If we have more than one successor, we cannot just use the first one. Since
-                 * successors are unordered, this would be a random choice.
-                 */
-                throw new GraalInternalError("Block without BlockEndOp: " + block.getEndNode());
-            }
-            emitJump(getLIRBlock((FixedNode) successors.first()));
-        }
-
-        assert verifyBlock(lir, block);
+    public final void doBlockEnd(AbstractBlock<?> block) {
 
         if (traceLevel >= 1) {
             TTY.println("END Generating LIR for block B" + block.getId());
@@ -520,324 +358,14 @@
         }
     }
 
-    private static final DebugMetric MemoryFoldSuccess = Debug.metric("MemoryFoldSuccess");
-    private static final DebugMetric MemoryFoldFailed = Debug.metric("MemoryFoldFailed");
-    private static final DebugMetric MemoryFoldFailedNonAdjacent = Debug.metric("MemoryFoldedFailedNonAdjacent");
-    private static final DebugMetric MemoryFoldFailedDifferentBlock = Debug.metric("MemoryFoldedFailedDifferentBlock");
-
-    /**
-     * Subclass can provide helper to fold memory operations into other operations.
-     */
-    protected MemoryArithmeticLIRLowerer getMemoryLowerer() {
-        return null;
-    }
-
-    private static final Object LOG_OUTPUT_LOCK = new Object();
-
-    /**
-     * Try to find a sequence of Nodes which can be passed to the backend to look for optimized
-     * instruction sequences using memory. Currently this basically is a read with a single
-     * arithmetic user followed by an possible if use. This should generalized to more generic
-     * pattern matching so that it can be more flexibly used.
-     */
-    private int maybeFoldMemory(List<ScheduledNode> nodes, int i, ValueNode access) {
-        MemoryArithmeticLIRLowerer lowerer = getMemoryLowerer();
-        if (lowerer != null && OptFoldMemory.getValue() && (access instanceof ReadNode || access instanceof FloatingReadNode) && access.usages().count() == 1 && i + 1 < nodes.size()) {
-            try (Scope s = Debug.scope("MaybeFoldMemory", access)) {
-                // This is all bit hacky since it's happening on the linearized schedule. This needs
-                // to be revisited at some point.
-
-                // Find a memory lowerable usage of this operation
-                if (access.usages().first() instanceof MemoryArithmeticLIRLowerable) {
-                    ValueNode operation = (ValueNode) access.usages().first();
-                    if (!nodes.contains(operation)) {
-                        Debug.log("node %1s in different block from %1s", access, operation);
-                        MemoryFoldFailedDifferentBlock.increment();
-                        return 0;
-                    }
-                    ValueNode firstOperation = operation;
-                    if (operation instanceof LogicNode) {
-                        if (operation.usages().count() == 1 && operation.usages().first() instanceof IfNode) {
-                            ValueNode ifNode = (ValueNode) operation.usages().first();
-                            if (!nodes.contains(ifNode)) {
-                                MemoryFoldFailedDifferentBlock.increment();
-                                Debug.log("if node %1s in different block from %1s", ifNode, operation);
-                                try (Indent indent = Debug.logAndIndent("checking operations")) {
-                                    int start = nodes.indexOf(access);
-                                    int end = nodes.indexOf(operation);
-                                    for (int i1 = Math.min(start, end); i1 <= Math.max(start, end); i1++) {
-                                        indent.log("%d: (%d) %1s", i1, nodes.get(i1).usages().count(), nodes.get(i1));
-                                    }
-                                }
-                                return 0;
-                            } else {
-                                operation = ifNode;
-                            }
-                        }
-                    }
-                    if (Debug.isLogEnabled()) {
-                        synchronized (LOG_OUTPUT_LOCK) {  // Hack to ensure the output is grouped.
-                            try (Indent indent = Debug.logAndIndent("checking operations")) {
-                                int start = nodes.indexOf(access);
-                                int end = nodes.indexOf(operation);
-                                for (int i1 = Math.min(start, end); i1 <= Math.max(start, end); i1++) {
-                                    indent.log("%d: (%d) %1s", i1, nodes.get(i1).usages().count(), nodes.get(i1));
-                                }
-                            }
-                        }
-                    }
-                    // Possible lowerable operation in the same block. Check out the dependencies.
-                    int opIndex = nodes.indexOf(operation);
-                    int current = i + 1;
-                    ArrayList<ValueNode> deferred = null;
-                    while (current < opIndex) {
-                        ScheduledNode node = nodes.get(current);
-                        if (node != firstOperation) {
-                            if (node instanceof LocationNode || node instanceof VirtualObjectNode) {
-                                // nothing to do
-                            } else if (node instanceof ConstantNode) {
-                                if (deferred == null) {
-                                    deferred = new ArrayList<>(2);
-                                }
-                                // These nodes are collected and the backend is expended to
-                                // evaluate them before generating the lowered form. This
-                                // basically works around unfriendly scheduling of values which
-                                // are defined in a block but not used there.
-                                deferred.add((ValueNode) node);
-                            } else {
-                                Debug.log("unexpected node %1s", node);
-                                // Unexpected inline node
-                                break;
-                            }
-                        }
-                        current++;
-                    }
-
-                    if (current == opIndex) {
-                        if (lowerer.memoryPeephole((Access) access, (MemoryArithmeticLIRLowerable) operation, deferred)) {
-                            MemoryFoldSuccess.increment();
-                            // if this operation had multiple access inputs, then previous attempts
-                            // would be marked as failures which is wrong. Try to adjust the
-                            // counters to account for this.
-                            for (Node input : operation.inputs()) {
-                                if (input == access) {
-                                    continue;
-                                }
-                                if (input instanceof Access && nodes.contains(input)) {
-                                    MemoryFoldFailedNonAdjacent.add(-1);
-                                }
-                            }
-                            if (deferred != null) {
-                                // Ensure deferred nodes were evaluated
-                                for (ValueNode node : deferred) {
-                                    assert hasOperand(node);
-                                }
-                            }
-                            return opIndex - i;
-                        } else {
-                            // This isn't true failure, it just means there wasn't match for the
-                            // pattern. Usually that means it's just not supported by the backend.
-                            MemoryFoldFailed.increment();
-                            return 0;
-                        }
-                    } else {
-                        MemoryFoldFailedNonAdjacent.increment();
-                    }
-                } else {
-                    // memory usage which isn't considered lowerable. Mostly these are
-                    // uninteresting but it might be worth looking at to ensure that interesting
-                    // nodes are being properly handled.
-                    // Debug.log("usage isn't lowerable %1s", access.usages().first());
-                }
-            }
-        }
-        return 0;
-    }
-
-    protected abstract boolean peephole(ValueNode valueNode);
-
-    private boolean hasBlockEnd(Block block) {
-        List<LIRInstruction> ops = lir.lir(block);
-        if (ops.size() == 0) {
-            return false;
-        }
-        return ops.get(ops.size() - 1) instanceof BlockEndOp;
-    }
-
-    private void doRoot(ValueNode instr) {
-        if (traceLevel >= 2) {
-            TTY.println("Emitting LIR for instruction " + instr);
-        }
-        currentInstruction = instr;
-
-        Debug.log("Visiting %s", instr);
-        emitNode(instr);
-        Debug.log("Operand for %s = %s", instr, getOperand(instr));
-    }
-
-    protected void emitNode(ValueNode node) {
-        if (Debug.isLogEnabled() && node.stamp() instanceof IllegalStamp) {
-            Debug.log("This node has invalid type, we are emitting dead code(?): %s", node);
-        }
-        if (node instanceof LIRGenLowerable) {
-            ((LIRGenLowerable) node).generate(this);
-        } else if (node instanceof LIRLowerable) {
-            ((LIRLowerable) node).generate(this);
-        } else if (node instanceof ArithmeticLIRLowerable) {
-            ((ArithmeticLIRLowerable) node).generate(this);
-        } else {
-            throw GraalInternalError.shouldNotReachHere("node is not LIRLowerable: " + node);
-        }
-    }
-
-    protected void emitPrologue(StructuredGraph graph) {
-        CallingConvention incomingArguments = cc;
-
-        Value[] params = new Value[incomingArguments.getArgumentCount()];
-        for (int i = 0; i < params.length; i++) {
-            params[i] = toStackKind(incomingArguments.getArgument(i));
-            if (ValueUtil.isStackSlot(params[i])) {
-                StackSlot slot = ValueUtil.asStackSlot(params[i]);
-                if (slot.isInCallerFrame() && !lir.hasArgInCallerFrame()) {
-                    lir.setHasArgInCallerFrame();
-                }
-            }
-        }
-
-        emitIncomingValues(params);
-
-        for (ParameterNode param : graph.getNodes(ParameterNode.class)) {
-            Value paramValue = params[param.index()];
-            assert paramValue.getKind() == param.getKind().getStackKind();
-            setResult(param, emitMove(paramValue));
-        }
-    }
-
     public void emitIncomingValues(Value[] params) {
-        ((LabelOp) lir.lir(currentBlock).get(0)).setIncomingValues(params);
-    }
-
-    @Override
-    public void visitReturn(ReturnNode x) {
-        AllocatableValue operand = ILLEGAL;
-        if (x.result() != null) {
-            operand = resultOperandFor(x.result().getKind());
-            emitMove(operand, operand(x.result()));
-        }
-        emitReturn(operand);
-    }
-
-    protected abstract void emitReturn(Value input);
-
-    @Override
-    public void visitMerge(MergeNode x) {
-    }
-
-    @Override
-    public void visitEndNode(AbstractEndNode end) {
-        moveToPhi(end.merge(), end);
-    }
-
-    /**
-     * Runtime specific classes can override this to insert a safepoint at the end of a loop.
-     */
-    @Override
-    public void visitLoopEnd(LoopEndNode x) {
-    }
-
-    private void moveToPhi(MergeNode merge, AbstractEndNode pred) {
-        if (traceLevel >= 1) {
-            TTY.println("MOVE TO PHI from " + pred + " to " + merge);
-        }
-        PhiResolver resolver = new PhiResolver(this);
-        for (PhiNode phi : merge.phis()) {
-            if (phi.type() == PhiType.Value) {
-                ValueNode curVal = phi.valueAt(pred);
-                resolver.move(operandForPhi(phi), operand(curVal));
-            }
-        }
-        resolver.dispose();
-
-        append(new JumpOp(getLIRBlock(merge)));
+        ((LabelOp) res.getLIR().getLIRforBlock(currentBlock).get(0)).setIncomingValues(params);
     }
 
     protected PlatformKind getPhiKind(PhiNode phi) {
         return phi.getKind();
     }
 
-    private Value operandForPhi(PhiNode phi) {
-        assert phi.type() == PhiType.Value : "wrong phi type: " + phi;
-        Value result = getOperand(phi);
-        if (result == null) {
-            // allocate a variable for this phi
-            Variable newOperand = newVariable(getPhiKind(phi));
-            setResult(phi, newOperand);
-            return newOperand;
-        } else {
-            return result;
-        }
-    }
-
-    @Override
-    public void emitIf(IfNode x) {
-        emitBranch(x.condition(), getLIRBlock(x.trueSuccessor()), getLIRBlock(x.falseSuccessor()), x.probability(x.trueSuccessor()));
-    }
-
-    public void emitBranch(LogicNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) {
-        if (node instanceof IsNullNode) {
-            emitNullCheckBranch((IsNullNode) node, trueSuccessor, falseSuccessor, trueSuccessorProbability);
-        } else if (node instanceof CompareNode) {
-            emitCompareBranch((CompareNode) node, trueSuccessor, falseSuccessor, trueSuccessorProbability);
-        } else if (node instanceof LogicConstantNode) {
-            emitConstantBranch(((LogicConstantNode) node).getValue(), trueSuccessor, falseSuccessor);
-        } else if (node instanceof IntegerTestNode) {
-            emitIntegerTestBranch((IntegerTestNode) node, trueSuccessor, falseSuccessor, trueSuccessorProbability);
-        } else {
-            throw GraalInternalError.unimplemented(node.toString());
-        }
-    }
-
-    private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) {
-        emitCompareBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueSuccessor, falseSuccessor, trueSuccessorProbability);
-    }
-
-    public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) {
-        emitCompareBranch(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueSuccessor, falseSuccessor, trueSuccessorProbability);
-    }
-
-    public void emitIntegerTestBranch(IntegerTestNode test, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) {
-        emitIntegerTestBranch(operand(test.x()), operand(test.y()), trueSuccessor, falseSuccessor, trueSuccessorProbability);
-    }
-
-    public void emitConstantBranch(boolean value, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock) {
-        LabelRef block = value ? trueSuccessorBlock : falseSuccessorBlock;
-        emitJump(block);
-    }
-
-    @Override
-    public void emitConditional(ConditionalNode conditional) {
-        Value tVal = operand(conditional.trueValue());
-        Value fVal = operand(conditional.falseValue());
-        setResult(conditional, emitConditional(conditional.condition(), tVal, fVal));
-    }
-
-    public Variable emitConditional(LogicNode node, Value trueValue, Value falseValue) {
-        if (node instanceof IsNullNode) {
-            IsNullNode isNullNode = (IsNullNode) node;
-            return emitConditionalMove(operand(isNullNode.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueValue, falseValue);
-        } else if (node instanceof CompareNode) {
-            CompareNode compare = (CompareNode) node;
-            return emitConditionalMove(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueValue, falseValue);
-        } else if (node instanceof LogicConstantNode) {
-            return emitMove(((LogicConstantNode) node).getValue() ? trueValue : falseValue);
-        } else if (node instanceof IntegerTestNode) {
-            IntegerTestNode test = (IntegerTestNode) node;
-            return emitIntegerTestMove(operand(test.x()), operand(test.y()), trueValue, falseValue);
-        } else {
-            throw GraalInternalError.unimplemented(node.toString());
-        }
-    }
-
     public abstract void emitJump(LabelRef label);
 
     public abstract void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability);
@@ -850,42 +378,6 @@
 
     public abstract Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value falseValue);
 
-    @Override
-    public void emitInvoke(Invoke x) {
-        LoweredCallTargetNode callTarget = (LoweredCallTargetNode) x.callTarget();
-        CallingConvention invokeCc = frameMap.registerConfig.getCallingConvention(callTarget.callType(), x.asNode().stamp().javaType(getMetaAccess()), callTarget.signature(), target(), false);
-        frameMap.callsMethod(invokeCc);
-
-        Value[] parameters = visitInvokeArguments(invokeCc, callTarget.arguments());
-
-        LabelRef exceptionEdge = null;
-        if (x instanceof InvokeWithExceptionNode) {
-            exceptionEdge = getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge());
-        }
-        LIRFrameState callState = stateWithExceptionEdge(x, exceptionEdge);
-
-        Value result = invokeCc.getReturn();
-        if (callTarget instanceof DirectCallTargetNode) {
-            emitDirectCall((DirectCallTargetNode) callTarget, result, parameters, AllocatableValue.NONE, callState);
-        } else if (callTarget instanceof IndirectCallTargetNode) {
-            emitIndirectCall((IndirectCallTargetNode) callTarget, result, parameters, AllocatableValue.NONE, callState);
-        } else {
-            throw GraalInternalError.shouldNotReachHere();
-        }
-
-        if (isLegal(result)) {
-            setResult(x.asNode(), emitMove(result));
-        }
-
-        if (x instanceof InvokeWithExceptionNode) {
-            emitJump(getLIRBlock(((InvokeWithExceptionNode) x).next()));
-        }
-    }
-
-    protected abstract void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState);
-
-    protected abstract void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState);
-
     protected abstract void emitForeignCall(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info);
 
     protected static AllocatableValue toStackKind(AllocatableValue value) {
@@ -903,23 +395,6 @@
         return value;
     }
 
-    public Value[] visitInvokeArguments(CallingConvention invokeCc, Collection<ValueNode> arguments) {
-        // for each argument, load it into the correct location
-        Value[] result = new Value[arguments.size()];
-        int j = 0;
-        for (ValueNode arg : arguments) {
-            if (arg != null) {
-                AllocatableValue operand = toStackKind(invokeCc.getArgument(j));
-                emitMove(operand, operand(arg));
-                result[j] = operand;
-                j++;
-            } else {
-                throw GraalInternalError.shouldNotReachHere("I thought we no longer have null entries for two-slot types...");
-            }
-        }
-        return result;
-    }
-
     @Override
     public Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args) {
         LIRFrameState state = null;
@@ -934,7 +409,7 @@
 
         // move the arguments into the correct location
         CallingConvention linkageCc = linkage.getOutgoingCallingConvention();
-        frameMap.callsMethod(linkageCc);
+        res.getFrameMap().callsMethod(linkageCc);
         assert linkageCc.getArgumentCount() == args.length : "argument count mismatch";
         Value[] argLocations = new Value[args.length];
         for (int i = 0; i < args.length; i++) {
@@ -943,7 +418,7 @@
             emitMove(loc, arg);
             argLocations[i] = loc;
         }
-        this.hasForeignCall = true;
+        res.setForeignCall(true);
         emitForeignCall(linkage, linkageCc.getReturn(), argLocations, linkage.getTemporaries(), state);
 
         if (isLegal(linkageCc.getReturn())) {
@@ -953,46 +428,6 @@
         }
     }
 
-    /**
-     * This method tries to create a switch implementation that is optimal for the given switch. It
-     * will either generate a sequential if/then/else cascade, a set of range tests or a table
-     * switch.
-     * 
-     * If the given switch does not contain int keys, it will always create a sequential
-     * implementation.
-     */
-    @Override
-    public void emitSwitch(SwitchNode x) {
-        assert x.defaultSuccessor() != null;
-        LabelRef defaultTarget = getLIRBlock(x.defaultSuccessor());
-        int keyCount = x.keyCount();
-        if (keyCount == 0) {
-            emitJump(defaultTarget);
-        } else {
-            Variable value = load(operand(x.value()));
-            if (keyCount == 1) {
-                assert defaultTarget != null;
-                double probability = x.probability(x.keySuccessor(0));
-                emitCompareBranch(load(operand(x.value())), x.keyAt(0), Condition.EQ, false, getLIRBlock(x.keySuccessor(0)), defaultTarget, probability);
-            } else {
-                LabelRef[] keyTargets = new LabelRef[keyCount];
-                Constant[] keyConstants = new Constant[keyCount];
-                double[] keyProbabilities = new double[keyCount];
-                for (int i = 0; i < keyCount; i++) {
-                    keyTargets[i] = getLIRBlock(x.keySuccessor(i));
-                    keyConstants[i] = x.keyAt(i);
-                    keyProbabilities[i] = x.keyProbability(i);
-                }
-                if (value.getKind() != Kind.Int || !x.isSorted()) {
-                    // hopefully only a few entries
-                    emitStrategySwitch(new SwitchStrategy.SequentialStrategy(keyProbabilities, keyConstants), value, keyTargets, defaultTarget);
-                } else {
-                    emitStrategySwitch(keyConstants, keyProbabilities, keyTargets, defaultTarget, value);
-                }
-            }
-        }
-    }
-
     protected void emitStrategySwitch(Constant[] keyConstants, double[] keyProbabilities, LabelRef[] keyTargets, LabelRef defaultTarget, Variable value) {
         int keyCount = keyConstants.length;
         SwitchStrategy strategy = SwitchStrategy.getBestStrategy(keyProbabilities, keyConstants, keyTargets);
@@ -1024,8 +459,13 @@
 
     protected abstract void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key);
 
-    public FrameMap frameMap() {
-        return frameMap;
+    public CallingConvention getCallingConvention() {
+        return cc;
+    }
+
+    public DebugInfoBuilder getDebugInfoBuilder() {
+        assert debugInfoBuilder != null;
+        return debugInfoBuilder;
     }
 
     @Override
@@ -1051,13 +491,13 @@
                         outOfLoopDominator = outOfLoopDominator.getDominator();
                     }
                     if (outOfLoopDominator != lc.block) {
-                        lc.unpin(lir);
+                        lc.unpin(res.getLIR());
                         lc.block = outOfLoopDominator;
                     }
                 }
 
                 if (lc.index != -1) {
-                    assert lir.lir(lc.block).get(lc.index) == lc.op;
+                    assert res.getLIR().getLIRforBlock(lc.block).get(lc.index) == lc.op;
                     iter.remove();
                 }
             }
@@ -1078,7 +518,7 @@
                 }
                 int groupSize = groupEnd - groupBegin;
 
-                List<LIRInstruction> ops = lir.lir(block);
+                List<LIRInstruction> ops = res.getLIR().getLIRforBlock(block);
                 int lastIndex = ops.size() - 1;
                 assert ops.get(lastIndex) instanceof BlockEndOp;
                 int insertionIndex = lastIndex;
@@ -1177,4 +617,12 @@
     public abstract void emitByteSwap(Variable result, Value operand);
 
     public abstract void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length);
+
+    public AbstractBlock<?> getCurrentBlock() {
+        return currentBlock;
+    }
+
+    void setCurrentBlock(AbstractBlock<?> block) {
+        currentBlock = block;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRGenerator.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,814 @@
+/*
+ * Copyright (c) 2009, 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.compiler.gen;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.api.meta.Value.*;
+import static com.oracle.graal.lir.LIR.*;
+import static com.oracle.graal.nodes.ConstantNode.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.Map.Entry;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.compiler.gen.LIRGenerator.LoadConstant;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.Debug.Scope;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.BlockEndOp;
+import com.oracle.graal.lir.StandardOp.JumpOp;
+import com.oracle.graal.lir.StandardOp.LabelOp;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.PhiNode.PhiType;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.virtual.*;
+import com.oracle.graal.phases.*;
+
+/**
+ * This class traverses the HIR instructions and generates LIR instructions from them.
+ */
+public abstract class NodeLIRGenerator implements NodeLIRGeneratorTool {
+
+    public static class Options {
+        // @formatter:off
+//        @Option(help = "Print HIR along side LIR as the latter is generated")
+//        public static final OptionValue<Boolean> PrintIRWithLIR = new OptionValue<>(false);
+//        @Option(help = "The trace level for the LIR generator")
+//        public static final OptionValue<Integer> TraceLIRGeneratorLevel = new OptionValue<>(0);
+        // @formatter:on
+    }
+
+    private final NodeMap<Value> nodeOperands;
+    private final DebugInfoBuilder debugInfoBuilder;
+
+    private final int traceLevel;
+    private final boolean printIRWithLIR;
+
+    protected final LIRGenerator gen;
+
+    private ValueNode currentInstruction;
+    private ValueNode lastInstructionPrinted; // Debugging only
+
+    protected LIRGenerationResult res;
+
+    public NodeLIRGenerator(StructuredGraph graph, LIRGenerationResult res, LIRGenerator gen) {
+        this.res = res;
+        this.nodeOperands = graph.createNodeMap();
+        this.debugInfoBuilder = createDebugInfoBuilder(nodeOperands);
+        this.gen = gen;
+        this.traceLevel = LIRGenerator.Options.TraceLIRGeneratorLevel.getValue();
+        this.printIRWithLIR = LIRGenerator.Options.PrintIRWithLIR.getValue();
+        gen.setDebugInfoBuilder(debugInfoBuilder);
+    }
+
+    @SuppressWarnings("hiding")
+    protected DebugInfoBuilder createDebugInfoBuilder(NodeMap<Value> nodeOperands) {
+        return new DebugInfoBuilder(nodeOperands);
+    }
+
+    /**
+     * Returns the operand that has been previously initialized by
+     * {@link #setResult(ValueNode, Value)} with the result of an instruction. It's a code
+     * generation error to ask for the operand of ValueNode that doesn't have one yet.
+     *
+     * @param node A node that produces a result value.
+     */
+    @Override
+    public Value operand(ValueNode node) {
+        Value operand = getOperand(node);
+        assert operand != null : String.format("missing operand for %1s", node);
+        return operand;
+    }
+
+    @Override
+    public boolean hasOperand(ValueNode node) {
+        return getOperand(node) != null;
+    }
+
+    private Value getOperand(ValueNode node) {
+        if (nodeOperands == null) {
+            return null;
+        }
+        Value operand = nodeOperands.get(node);
+        if (operand == null) {
+            operand = getConstantOperand(node);
+        }
+        return operand;
+    }
+
+    private Value getConstantOperand(ValueNode node) {
+        if (!ConstantNodeRecordsUsages) {
+            Constant value = node.asConstant();
+            if (value != null) {
+                if (gen.canInlineConstant(value)) {
+                    return setResult(node, value);
+                } else {
+                    Variable loadedValue;
+                    if (gen.constantLoads == null) {
+                        gen.constantLoads = new HashMap<>();
+                    }
+                    LoadConstant load = gen.constantLoads.get(value);
+                    assert gen.getCurrentBlock() instanceof Block;
+                    if (load == null) {
+                        int index = res.getLIR().getLIRforBlock(gen.getCurrentBlock()).size();
+                        loadedValue = gen.emitMove(value);
+                        LIRInstruction op = res.getLIR().getLIRforBlock(gen.getCurrentBlock()).get(index);
+                        gen.constantLoads.put(value, new LoadConstant(loadedValue, (Block) gen.getCurrentBlock(), index, op));
+                    } else {
+                        Block dominator = ControlFlowGraph.commonDominator(load.block, (Block) gen.getCurrentBlock());
+                        loadedValue = load.variable;
+                        if (dominator != load.block) {
+                            load.unpin(res.getLIR());
+                        } else {
+                            assert load.block != gen.getCurrentBlock() || load.index < res.getLIR().getLIRforBlock(gen.getCurrentBlock()).size();
+                        }
+                        load.block = dominator;
+                    }
+                    return loadedValue;
+                }
+            }
+        } else {
+            // Constant is loaded by ConstantNode.generate()
+        }
+        return null;
+    }
+
+    public ValueNode valueForOperand(Value value) {
+        for (Entry<Node, Value> entry : getNodeOperands().entries()) {
+            if (entry.getValue().equals(value)) {
+                return (ValueNode) entry.getKey();
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Value setResult(ValueNode x, Value operand) {
+        assert (!isRegister(operand) || !gen.attributes(asRegister(operand)).isAllocatable());
+        assert nodeOperands == null || nodeOperands.get(x) == null : "operand cannot be set twice";
+        assert operand != null && isLegal(operand) : "operand must be legal";
+        assert operand.getKind().getStackKind() == x.getKind() || x.getKind() == Kind.Illegal : operand.getKind().getStackKind() + " must match " + x.getKind();
+        assert !(x instanceof VirtualObjectNode);
+        nodeOperands.set(x, operand);
+        return operand;
+    }
+
+    public LabelRef getLIRBlock(FixedNode b) {
+        assert res.getLIR().getControlFlowGraph() instanceof ControlFlowGraph;
+        Block result = ((ControlFlowGraph) res.getLIR().getControlFlowGraph()).blockFor(b);
+        int suxIndex = gen.getCurrentBlock().getSuccessors().indexOf(result);
+        assert suxIndex != -1 : "Block not in successor list of current block";
+
+        assert gen.getCurrentBlock() instanceof Block;
+        return LabelRef.forSuccessor(res.getLIR(), (Block) gen.getCurrentBlock(), suxIndex);
+    }
+
+    public final void append(LIRInstruction op) {
+        if (printIRWithLIR && !TTY.isSuppressed()) {
+            if (currentInstruction != null && lastInstructionPrinted != currentInstruction) {
+                lastInstructionPrinted = currentInstruction;
+                InstructionPrinter ip = new InstructionPrinter(TTY.out());
+                ip.printInstructionListing(currentInstruction);
+            }
+        }
+        gen.append(op);
+    }
+
+    public final void doBlockStart(AbstractBlock<?> block) {
+        if (printIRWithLIR) {
+            TTY.print(block.toString());
+        }
+
+        gen.setCurrentBlock(block);
+
+        // set up the list of LIR instructions
+        assert res.getLIR().getLIRforBlock(block) == null : "LIR list already computed for this block";
+        res.getLIR().setLIRforBlock(block, new ArrayList<LIRInstruction>());
+
+        append(new LabelOp(new Label(block.getId()), block.isAligned()));
+
+        if (traceLevel >= 1) {
+            TTY.println("BEGIN Generating LIR for block B" + block.getId());
+        }
+    }
+
+    public final void doBlockEnd(AbstractBlock<?> block) {
+
+        if (traceLevel >= 1) {
+            TTY.println("END Generating LIR for block B" + block.getId());
+        }
+
+        gen.setCurrentBlock(null);
+
+        if (printIRWithLIR) {
+            TTY.println();
+        }
+    }
+
+    public void doBlock(Block block, StructuredGraph graph, BlockMap<List<ScheduledNode>> blockMap) {
+        doBlockStart(block);
+
+        if (block == res.getLIR().getControlFlowGraph().getStartBlock()) {
+            assert block.getPredecessorCount() == 0;
+            emitPrologue(graph);
+        } else {
+            assert block.getPredecessorCount() > 0;
+        }
+
+        List<ScheduledNode> nodes = blockMap.get(block);
+        int instructionsFolded = 0;
+        for (int i = 0; i < nodes.size(); i++) {
+            Node instr = nodes.get(i);
+            if (traceLevel >= 3) {
+                TTY.println("LIRGen for " + instr);
+            }
+            if (instructionsFolded > 0) {
+                instructionsFolded--;
+                continue;
+            }
+            if (!ConstantNodeRecordsUsages && instr instanceof ConstantNode) {
+                // Loading of constants is done lazily by operand()
+
+            } else if (instr instanceof ValueNode) {
+                ValueNode valueNode = (ValueNode) instr;
+                if (!hasOperand(valueNode)) {
+                    if (!peephole(valueNode)) {
+                        instructionsFolded = maybeFoldMemory(nodes, i, valueNode);
+                        if (instructionsFolded == 0) {
+                            try {
+                                doRoot((ValueNode) instr);
+                            } catch (GraalInternalError e) {
+                                throw e.addContext(instr);
+                            } catch (Throwable e) {
+                                throw new GraalInternalError(e).addContext(instr);
+                            }
+                        }
+                    }
+                } else {
+                    // There can be cases in which the result of an instruction is already set
+                    // before by other instructions.
+                }
+            }
+        }
+
+        if (!hasBlockEnd(block)) {
+            NodeClassIterable successors = block.getEndNode().successors();
+            assert successors.count() == block.getSuccessorCount();
+            if (block.getSuccessorCount() != 1) {
+                /*
+                 * If we have more than one successor, we cannot just use the first one. Since
+                 * successors are unordered, this would be a random choice.
+                 */
+                throw new GraalInternalError("Block without BlockEndOp: " + block.getEndNode());
+            }
+            gen.emitJump(getLIRBlock((FixedNode) successors.first()));
+        }
+
+        assert verifyBlock(res.getLIR(), block);
+        doBlockEnd(block);
+    }
+
+    private static final DebugMetric MemoryFoldSuccess = Debug.metric("MemoryFoldSuccess");
+    private static final DebugMetric MemoryFoldFailed = Debug.metric("MemoryFoldFailed");
+    private static final DebugMetric MemoryFoldFailedNonAdjacent = Debug.metric("MemoryFoldedFailedNonAdjacent");
+    private static final DebugMetric MemoryFoldFailedDifferentBlock = Debug.metric("MemoryFoldedFailedDifferentBlock");
+
+    /**
+     * Subclass can provide helper to fold memory operations into other operations.
+     */
+    public MemoryArithmeticLIRLowerer getMemoryLowerer() {
+        return null;
+    }
+
+    /**
+     * Try to find a sequence of Nodes which can be passed to the backend to look for optimized
+     * instruction sequences using memory. Currently this basically is a read with a single
+     * arithmetic user followed by an possible if use. This should generalized to more generic
+     * pattern matching so that it can be more flexibly used.
+     */
+    private int maybeFoldMemory(List<ScheduledNode> nodes, int i, ValueNode access) {
+        MemoryArithmeticLIRLowerer lowerer = getMemoryLowerer();
+        if (lowerer != null && GraalOptions.OptFoldMemory.getValue() && (access instanceof ReadNode || access instanceof FloatingReadNode) && access.usages().count() == 1 && i + 1 < nodes.size()) {
+            try (Scope s = Debug.scope("MaybeFoldMemory", access)) {
+                // This is all bit hacky since it's happening on the linearized schedule. This needs
+                // to be revisited at some point.
+
+                // Find a memory lowerable usage of this operation
+                if (access.usages().first() instanceof MemoryArithmeticLIRLowerable) {
+                    ValueNode operation = (ValueNode) access.usages().first();
+                    if (!nodes.contains(operation)) {
+                        Debug.log("node %1s in different block from %1s", access, operation);
+                        MemoryFoldFailedDifferentBlock.increment();
+                        return 0;
+                    }
+                    ValueNode firstOperation = operation;
+                    if (operation instanceof LogicNode) {
+                        if (operation.usages().count() == 1 && operation.usages().first() instanceof IfNode) {
+                            ValueNode ifNode = (ValueNode) operation.usages().first();
+                            if (!nodes.contains(ifNode)) {
+                                MemoryFoldFailedDifferentBlock.increment();
+                                Debug.log("if node %1s in different block from %1s", ifNode, operation);
+                                try (Indent indent = Debug.logAndIndent("checking operations")) {
+                                    int start = nodes.indexOf(access);
+                                    int end = nodes.indexOf(operation);
+                                    for (int i1 = Math.min(start, end); i1 <= Math.max(start, end); i1++) {
+                                        indent.log("%d: (%d) %1s", i1, nodes.get(i1).usages().count(), nodes.get(i1));
+                                    }
+                                }
+                                return 0;
+                            } else {
+                                operation = ifNode;
+                            }
+                        }
+                    }
+                    if (Debug.isLogEnabled()) {
+                        synchronized ("lock") {  // Hack to ensure the output is grouped.
+                            try (Indent indent = Debug.logAndIndent("checking operations")) {
+                                int start = nodes.indexOf(access);
+                                int end = nodes.indexOf(operation);
+                                for (int i1 = Math.min(start, end); i1 <= Math.max(start, end); i1++) {
+                                    indent.log("%d: (%d) %1s", i1, nodes.get(i1).usages().count(), nodes.get(i1));
+                                }
+                            }
+                        }
+                    }
+                    // Possible lowerable operation in the same block. Check out the dependencies.
+                    int opIndex = nodes.indexOf(operation);
+                    int current = i + 1;
+                    ArrayList<ValueNode> deferred = null;
+                    while (current < opIndex) {
+                        ScheduledNode node = nodes.get(current);
+                        if (node != firstOperation) {
+                            if (node instanceof LocationNode || node instanceof VirtualObjectNode) {
+                                // nothing to do
+                            } else if (node instanceof ConstantNode) {
+                                if (deferred == null) {
+                                    deferred = new ArrayList<>(2);
+                                }
+                                // These nodes are collected and the backend is expended to
+                                // evaluate them before generating the lowered form. This
+                                // basically works around unfriendly scheduling of values which
+                                // are defined in a block but not used there.
+                                deferred.add((ValueNode) node);
+                            } else {
+                                Debug.log("unexpected node %1s", node);
+                                // Unexpected inline node
+                                break;
+                            }
+                        }
+                        current++;
+                    }
+
+                    if (current == opIndex) {
+                        if (lowerer.memoryPeephole((Access) access, (MemoryArithmeticLIRLowerable) operation, deferred)) {
+                            MemoryFoldSuccess.increment();
+                            // if this operation had multiple access inputs, then previous attempts
+                            // would be marked as failures which is wrong. Try to adjust the
+                            // counters to account for this.
+                            for (Node input : operation.inputs()) {
+                                if (input == access) {
+                                    continue;
+                                }
+                                if (input instanceof Access && nodes.contains(input)) {
+                                    MemoryFoldFailedNonAdjacent.add(-1);
+                                }
+                            }
+                            if (deferred != null) {
+                                // Ensure deferred nodes were evaluated
+                                for (ValueNode node : deferred) {
+                                    assert hasOperand(node);
+                                }
+                            }
+                            return opIndex - i;
+                        } else {
+                            // This isn't true failure, it just means there wasn't match for the
+                            // pattern. Usually that means it's just not supported by the backend.
+                            MemoryFoldFailed.increment();
+                            return 0;
+                        }
+                    } else {
+                        MemoryFoldFailedNonAdjacent.increment();
+                    }
+                } else {
+                    // memory usage which isn't considered lowerable. Mostly these are
+                    // uninteresting but it might be worth looking at to ensure that interesting
+                    // nodes are being properly handled.
+                    // Debug.log("usage isn't lowerable %1s", access.usages().first());
+                }
+            }
+        }
+        return 0;
+    }
+
+    protected abstract boolean peephole(ValueNode valueNode);
+
+    private boolean hasBlockEnd(Block block) {
+        List<LIRInstruction> ops = res.getLIR().getLIRforBlock(block);
+        if (ops.size() == 0) {
+            return false;
+        }
+        return ops.get(ops.size() - 1) instanceof BlockEndOp;
+    }
+
+    private void doRoot(ValueNode instr) {
+        if (traceLevel >= 2) {
+            TTY.println("Emitting LIR for instruction " + instr);
+        }
+        currentInstruction = instr;
+
+        Debug.log("Visiting %s", instr);
+        emitNode(instr);
+        Debug.log("Operand for %s = %s", instr, getOperand(instr));
+    }
+
+    protected void emitNode(ValueNode node) {
+        if (Debug.isLogEnabled() && node.stamp() instanceof IllegalStamp) {
+            Debug.log("This node has invalid type, we are emitting dead code(?): %s", node);
+        }
+        if (node instanceof LIRGenLowerable) {
+            ((LIRGenLowerable) node).generate(this);
+        } else if (node instanceof LIRGenResLowerable) {
+            ((LIRGenResLowerable) node).generate(this, res);
+        } else if (node instanceof LIRLowerable) {
+            ((LIRLowerable) node).generate(this);
+        } else if (node instanceof ArithmeticLIRLowerable) {
+            ((ArithmeticLIRLowerable) node).generate(this);
+        } else {
+            throw GraalInternalError.shouldNotReachHere("node is not LIRLowerable: " + node);
+        }
+    }
+
+    protected void emitPrologue(StructuredGraph graph) {
+        CallingConvention incomingArguments = gen.getCallingConvention();
+
+        Value[] params = new Value[incomingArguments.getArgumentCount()];
+        for (int i = 0; i < params.length; i++) {
+            params[i] = toStackKind(incomingArguments.getArgument(i));
+            if (ValueUtil.isStackSlot(params[i])) {
+                StackSlot slot = ValueUtil.asStackSlot(params[i]);
+                if (slot.isInCallerFrame() && !res.getLIR().hasArgInCallerFrame()) {
+                    res.getLIR().setHasArgInCallerFrame();
+                }
+            }
+        }
+
+        emitIncomingValues(params);
+
+        for (ParameterNode param : graph.getNodes(ParameterNode.class)) {
+            Value paramValue = params[param.index()];
+            assert paramValue.getKind() == param.getKind().getStackKind();
+            setResult(param, gen.emitMove(paramValue));
+        }
+    }
+
+    protected <T extends AbstractBlock<T>> void emitPrologue(ResolvedJavaMethod method, BytecodeParser<T> parser) {
+        CallingConvention incomingArguments = gen.getCallingConvention();
+
+        Value[] params = new Value[incomingArguments.getArgumentCount()];
+        for (int i = 0; i < params.length; i++) {
+            params[i] = toStackKind(incomingArguments.getArgument(i));
+            if (ValueUtil.isStackSlot(params[i])) {
+                StackSlot slot = ValueUtil.asStackSlot(params[i]);
+                if (slot.isInCallerFrame() && !res.getLIR().hasArgInCallerFrame()) {
+                    res.getLIR().setHasArgInCallerFrame();
+                }
+            }
+        }
+
+        emitIncomingValues(params);
+
+        Signature sig = method.getSignature();
+        boolean isStatic = Modifier.isStatic(method.getModifiers());
+        for (int i = 0; i < sig.getParameterCount(!isStatic); i++) {
+            Value paramValue = params[i];
+            assert paramValue.getKind() == sig.getParameterKind(i).getStackKind();
+            // TODO setResult(param, emitMove(paramValue));
+            parser.setParameter(i, gen.emitMove(paramValue));
+        }
+
+        // return arguments;
+    }
+
+    public void emitIncomingValues(Value[] params) {
+        ((LabelOp) res.getLIR().getLIRforBlock(gen.getCurrentBlock()).get(0)).setIncomingValues(params);
+    }
+
+    @Override
+    public void visitReturn(ReturnNode x) {
+        AllocatableValue operand = ILLEGAL;
+        if (x.result() != null) {
+            operand = gen.resultOperandFor(x.result().getKind());
+            gen.emitMove(operand, operand(x.result()));
+        }
+        gen.emitReturn(operand);
+    }
+
+    @Override
+    public void visitMerge(MergeNode x) {
+    }
+
+    @Override
+    public void visitEndNode(AbstractEndNode end) {
+        moveToPhi(end.merge(), end);
+    }
+
+    /**
+     * Runtime specific classes can override this to insert a safepoint at the end of a loop.
+     */
+    @Override
+    public void visitLoopEnd(LoopEndNode x) {
+    }
+
+    private void moveToPhi(MergeNode merge, AbstractEndNode pred) {
+        if (traceLevel >= 1) {
+            TTY.println("MOVE TO PHI from " + pred + " to " + merge);
+        }
+        PhiResolver resolver = new PhiResolver(gen);
+        for (PhiNode phi : merge.phis()) {
+            if (phi.type() == PhiType.Value) {
+                ValueNode curVal = phi.valueAt(pred);
+                resolver.move(operandForPhi(phi), operand(curVal));
+            }
+        }
+        resolver.dispose();
+
+        append(new JumpOp(getLIRBlock(merge)));
+    }
+
+    protected PlatformKind getPhiKind(PhiNode phi) {
+        return phi.getKind();
+    }
+
+    private Value operandForPhi(PhiNode phi) {
+        assert phi.type() == PhiType.Value : "wrong phi type: " + phi;
+        Value result = getOperand(phi);
+        if (result == null) {
+            // allocate a variable for this phi
+            Variable newOperand = gen.newVariable(getPhiKind(phi));
+            setResult(phi, newOperand);
+            return newOperand;
+        } else {
+            return result;
+        }
+    }
+
+    @Override
+    public void emitIf(IfNode x) {
+        emitBranch(x.condition(), getLIRBlock(x.trueSuccessor()), getLIRBlock(x.falseSuccessor()), x.probability(x.trueSuccessor()));
+    }
+
+    public void emitBranch(LogicNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) {
+        if (node instanceof IsNullNode) {
+            emitNullCheckBranch((IsNullNode) node, trueSuccessor, falseSuccessor, trueSuccessorProbability);
+        } else if (node instanceof CompareNode) {
+            emitCompareBranch((CompareNode) node, trueSuccessor, falseSuccessor, trueSuccessorProbability);
+        } else if (node instanceof LogicConstantNode) {
+            emitConstantBranch(((LogicConstantNode) node).getValue(), trueSuccessor, falseSuccessor);
+        } else if (node instanceof IntegerTestNode) {
+            emitIntegerTestBranch((IntegerTestNode) node, trueSuccessor, falseSuccessor, trueSuccessorProbability);
+        } else {
+            throw GraalInternalError.unimplemented(node.toString());
+        }
+    }
+
+    private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) {
+        gen.emitCompareBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueSuccessor, falseSuccessor, trueSuccessorProbability);
+    }
+
+    public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) {
+        gen.emitCompareBranch(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueSuccessor, falseSuccessor, trueSuccessorProbability);
+    }
+
+    public void emitIntegerTestBranch(IntegerTestNode test, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) {
+        gen.emitIntegerTestBranch(operand(test.x()), operand(test.y()), trueSuccessor, falseSuccessor, trueSuccessorProbability);
+    }
+
+    public void emitConstantBranch(boolean value, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock) {
+        LabelRef block = value ? trueSuccessorBlock : falseSuccessorBlock;
+        gen.emitJump(block);
+    }
+
+    @Override
+    public void emitConditional(ConditionalNode conditional) {
+        Value tVal = operand(conditional.trueValue());
+        Value fVal = operand(conditional.falseValue());
+        setResult(conditional, emitConditional(conditional.condition(), tVal, fVal));
+    }
+
+    public Variable emitConditional(LogicNode node, Value trueValue, Value falseValue) {
+        if (node instanceof IsNullNode) {
+            IsNullNode isNullNode = (IsNullNode) node;
+            return gen.emitConditionalMove(operand(isNullNode.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueValue, falseValue);
+        } else if (node instanceof CompareNode) {
+            CompareNode compare = (CompareNode) node;
+            return gen.emitConditionalMove(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueValue, falseValue);
+        } else if (node instanceof LogicConstantNode) {
+            return gen.emitMove(((LogicConstantNode) node).getValue() ? trueValue : falseValue);
+        } else if (node instanceof IntegerTestNode) {
+            IntegerTestNode test = (IntegerTestNode) node;
+            return gen.emitIntegerTestMove(operand(test.x()), operand(test.y()), trueValue, falseValue);
+        } else {
+            throw GraalInternalError.unimplemented(node.toString());
+        }
+    }
+
+// public abstract void emitJump(LabelRef label);
+//
+// public abstract void emitCompareBranch(Value left, Value right, Condition cond, boolean
+// unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, double
+// trueDestinationProbability);
+//
+// public abstract void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double
+// overflowProbability);
+//
+// public abstract void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination,
+// LabelRef falseDestination, double trueSuccessorProbability);
+//
+// public abstract Variable emitConditionalMove(Value leftVal, Value right, Condition cond, boolean
+// unorderedIsTrue, Value trueValue, Value falseValue);
+//
+// public abstract Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value
+// falseValue);
+
+    @Override
+    public void emitInvoke(Invoke x) {
+        LoweredCallTargetNode callTarget = (LoweredCallTargetNode) x.callTarget();
+        CallingConvention invokeCc = res.getFrameMap().registerConfig.getCallingConvention(callTarget.callType(), x.asNode().stamp().javaType(gen.getMetaAccess()), callTarget.signature(),
+                        gen.target(), false);
+        res.getFrameMap().callsMethod(invokeCc);
+
+        Value[] parameters = visitInvokeArguments(invokeCc, callTarget.arguments());
+
+        LabelRef exceptionEdge = null;
+        if (x instanceof InvokeWithExceptionNode) {
+            exceptionEdge = getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge());
+        }
+        LIRFrameState callState = gen.stateWithExceptionEdge(x, exceptionEdge);
+
+        Value result = invokeCc.getReturn();
+        if (callTarget instanceof DirectCallTargetNode) {
+            emitDirectCall((DirectCallTargetNode) callTarget, result, parameters, AllocatableValue.NONE, callState);
+        } else if (callTarget instanceof IndirectCallTargetNode) {
+            emitIndirectCall((IndirectCallTargetNode) callTarget, result, parameters, AllocatableValue.NONE, callState);
+        } else {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+
+        if (isLegal(result)) {
+            setResult(x.asNode(), gen.emitMove(result));
+        }
+
+        if (x instanceof InvokeWithExceptionNode) {
+            gen.emitJump(getLIRBlock(((InvokeWithExceptionNode) x).next()));
+        }
+    }
+
+    protected abstract void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState);
+
+    protected abstract void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState);
+
+    protected static AllocatableValue toStackKind(AllocatableValue value) {
+        if (value.getKind().getStackKind() != value.getKind()) {
+            // We only have stack-kinds in the LIR, so convert the operand kind for values from the
+            // calling convention.
+            if (isRegister(value)) {
+                return asRegister(value).asValue(value.getKind().getStackKind());
+            } else if (isStackSlot(value)) {
+                return StackSlot.get(value.getKind().getStackKind(), asStackSlot(value).getRawOffset(), asStackSlot(value).getRawAddFrameSize());
+            } else {
+                throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+        return value;
+    }
+
+    @Override
+    public Value[] visitInvokeArguments(CallingConvention invokeCc, Collection<ValueNode> arguments) {
+        // for each argument, load it into the correct location
+        Value[] result = new Value[arguments.size()];
+        int j = 0;
+        for (ValueNode arg : arguments) {
+            if (arg != null) {
+                AllocatableValue operand = toStackKind(invokeCc.getArgument(j));
+                gen.emitMove(operand, operand(arg));
+                result[j] = operand;
+                j++;
+            } else {
+                throw GraalInternalError.shouldNotReachHere("I thought we no longer have null entries for two-slot types...");
+            }
+        }
+        return result;
+    }
+
+    /**
+     * This method tries to create a switch implementation that is optimal for the given switch. It
+     * will either generate a sequential if/then/else cascade, a set of range tests or a table
+     * switch.
+     *
+     * If the given switch does not contain int keys, it will always create a sequential
+     * implementation.
+     */
+    @Override
+    public void emitSwitch(SwitchNode x) {
+        assert x.defaultSuccessor() != null;
+        LabelRef defaultTarget = getLIRBlock(x.defaultSuccessor());
+        int keyCount = x.keyCount();
+        if (keyCount == 0) {
+            gen.emitJump(defaultTarget);
+        } else {
+            Variable value = gen.load(operand(x.value()));
+            if (keyCount == 1) {
+                assert defaultTarget != null;
+                double probability = x.probability(x.keySuccessor(0));
+                gen.emitCompareBranch(gen.load(operand(x.value())), x.keyAt(0), Condition.EQ, false, getLIRBlock(x.keySuccessor(0)), defaultTarget, probability);
+            } else {
+                LabelRef[] keyTargets = new LabelRef[keyCount];
+                Constant[] keyConstants = new Constant[keyCount];
+                double[] keyProbabilities = new double[keyCount];
+                for (int i = 0; i < keyCount; i++) {
+                    keyTargets[i] = getLIRBlock(x.keySuccessor(i));
+                    keyConstants[i] = x.keyAt(i);
+                    keyProbabilities[i] = x.keyProbability(i);
+                }
+                if (value.getKind() != Kind.Int || !x.isSorted()) {
+                    // hopefully only a few entries
+                    gen.emitStrategySwitch(new SwitchStrategy.SequentialStrategy(keyProbabilities, keyConstants), value, keyTargets, defaultTarget);
+                } else {
+                    gen.emitStrategySwitch(keyConstants, keyProbabilities, keyTargets, defaultTarget, value);
+                }
+            }
+        }
+    }
+
+    public final NodeMap<Value> getNodeOperands() {
+        assert nodeOperands != null;
+        return nodeOperands;
+    }
+
+    public DebugInfoBuilder getDebugInfoBuilder() {
+        assert debugInfoBuilder != null;
+        return debugInfoBuilder;
+    }
+
+    public void emitOverflowCheckBranch(AbstractBeginNode overflowSuccessor, AbstractBeginNode next, double probability) {
+        gen.emitOverflowCheckBranch(getLIRBlock(overflowSuccessor), getLIRBlock(next), probability);
+    }
+
+    public final void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length) {
+        gen.emitArrayEquals(kind, result, array1, array2, length);
+    }
+
+    public final Variable newVariable(Kind i) {
+        return gen.newVariable(i);
+    }
+
+    public final void emitBitCount(Variable result, Value operand) {
+        gen.emitBitCount(result, operand);
+    }
+
+    public final void emitBitScanForward(Variable result, Value operand) {
+        gen.emitBitScanForward(result, operand);
+    }
+
+    final void emitBitScanReverse(Variable result, Value operand) {
+        gen.emitBitScanReverse(result, operand);
+    }
+
+    @Override
+    public LIRGenerator getLIRGeneratorTool() {
+        return gen;
+    }
+
+    public LIRGenerator getLIRGenerator() {
+        return gen;
+    }
+}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Thu Mar 27 17:31:20 2014 +0100
@@ -65,7 +65,11 @@
 
     public abstract FrameMap newFrameMap();
 
-    public abstract LIRGenerator newLIRGenerator(StructuredGraph graph, Object stub, FrameMap frameMap, CallingConvention cc, LIR lir);
+    public abstract LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes);
+
+    public abstract LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub);
+
+    public abstract NodeLIRGenerator newNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult lirGenRes, LIRGenerator lirGen);
 
     /**
      * Creates the assembler used to emit the machine code.
@@ -75,7 +79,7 @@
     /**
      * Creates the object used to fill in the details of a given compilation result.
      */
-    public abstract CompilationResultBuilder newCompilationResultBuilder(LIRGenerator lirGen, CompilationResult compilationResult, CompilationResultBuilderFactory factory);
+    public abstract CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenResult, CompilationResult compilationResult, CompilationResultBuilderFactory factory);
 
     public abstract boolean shouldAllocateRegisters();
 
@@ -87,4 +91,5 @@
      *            argument can be null.
      */
     public abstract void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner);
+
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenLowerable.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenLowerable.java	Thu Mar 27 17:31:20 2014 +0100
@@ -32,5 +32,5 @@
  */
 public interface LIRGenLowerable {
 
-    void generate(LIRGenerator generator);
+    void generate(NodeLIRGenerator generator);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenResLowerable.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,36 @@
+/*
+ * 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.graal.compiler.target;
+
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.nodes.spi.*;
+
+/**
+ * An alternative to {@link LIRLowerable} for lowering that is tightly coupled to
+ * {@link LIRGenerationResult} and {@link LIRInstruction}.
+ */
+public interface LIRGenResLowerable {
+
+    void generate(NodeLIRGeneratorTool generator, LIRGenerationResult genRes);
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Thu Mar 27 17:31:20 2014 +0100
@@ -72,8 +72,18 @@
     }
 
     @Override
-    public LIRGenerator newLIRGenerator(StructuredGraph graph, Object stub, FrameMap frameMap, CallingConvention cc, LIR lir) {
-        return new AMD64HotSpotLIRGenerator(graph, stub, getProviders(), getRuntime().getConfig(), frameMap, cc, lir);
+    public LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) {
+        return new AMD64HotSpotLIRGenerator(getProviders(), getRuntime().getConfig(), cc, lirGenRes);
+    }
+
+    @Override
+    public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) {
+        return new AMD64HotSpotLIRGenerationResult(lir, frameMap, stub);
+    }
+
+    @Override
+    public NodeLIRGenerator newNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult lirGenRes, LIRGenerator lirGen) {
+        return new AMD64HotSpotNodeLIRGenerator(graph, lirGenRes, lirGen);
     }
 
     /**
@@ -192,17 +202,17 @@
     }
 
     @Override
-    public CompilationResultBuilder newCompilationResultBuilder(LIRGenerator lirGen, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
+    public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRen, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
         // Omit the frame if the method:
         // - has no spill slots or other slots allocated during register allocation
         // - has no callee-saved registers
         // - has no incoming arguments passed on the stack
         // - has no deoptimization points
         // - makes no foreign calls (which require an aligned stack)
-        AMD64HotSpotLIRGenerator gen = (AMD64HotSpotLIRGenerator) lirGen;
-        FrameMap frameMap = gen.frameMap;
-        LIR lir = gen.lir;
-        assert gen.deoptimizationRescueSlot == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame";
+        AMD64HotSpotLIRGenerationResult gen = (AMD64HotSpotLIRGenerationResult) lirGenRen;
+        FrameMap frameMap = gen.getFrameMap();
+        LIR lir = gen.getLIR();
+        assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame";
         boolean omitFrame = CanOmitFrame.getValue() && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame() && !gen.hasForeignCall();
 
         Stub stub = gen.getStub();
@@ -210,14 +220,14 @@
         HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null, omitFrame);
         CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult);
         crb.setFrameSize(frameMap.frameSize());
-        StackSlot deoptimizationRescueSlot = gen.deoptimizationRescueSlot;
+        StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot();
         if (deoptimizationRescueSlot != null && stub == null) {
             crb.compilationResult.setCustomStackAreaOffset(frameMap.offsetForStackSlot(deoptimizationRescueSlot));
         }
 
         if (stub != null) {
             Set<Register> definedRegisters = gatherDefinedRegisters(lir);
-            updateStub(stub, definedRegisters, gen.calleeSaveInfo, frameMap);
+            updateStub(stub, definedRegisters, gen.getCalleeSaveInfo(), frameMap);
         }
 
         return crb;
@@ -318,4 +328,5 @@
         };
         return new HotSpotNativeFunctionInterface(getProviders(), factory, this, config.dllLoad, config.dllLookup, config.rtldDefault);
     }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerationResult.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,70 @@
+/*
+ * 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.hotspot.amd64;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
+
+public class AMD64HotSpotLIRGenerationResult extends LIRGenerationResultBase {
+
+    /**
+     * The slot reserved for storing the original return address when a frame is marked for
+     * deoptimization. The return address slot in the callee is overwritten with the address of a
+     * deoptimization stub.
+     */
+    private StackSlot deoptimizationRescueSlot;
+    private final Object stub;
+
+    /**
+     * Map from debug infos that need to be updated with callee save information to the operations
+     * that provide the information.
+     */
+    private Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = new HashMap<>();
+
+    public AMD64HotSpotLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) {
+        super(lir, frameMap);
+        this.stub = stub;
+    }
+
+    StackSlot getDeoptimizationRescueSlot() {
+        return deoptimizationRescueSlot;
+    }
+
+    public final void setDeoptimizationRescueSlot(StackSlot deoptimizationRescueSlot) {
+        this.deoptimizationRescueSlot = deoptimizationRescueSlot;
+    }
+
+    Stub getStub() {
+        return (Stub) stub;
+    }
+
+    Map<LIRFrameState, SaveRegistersOp> getCalleeSaveInfo() {
+        return calleeSaveInfo;
+    }
+
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Thu Mar 27 17:31:20 2014 +0100
@@ -24,61 +24,45 @@
 
 import static com.oracle.graal.amd64.AMD64.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
-import static com.oracle.graal.hotspot.HotSpotBackend.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
-import java.lang.reflect.*;
 import java.util.*;
 
 import com.oracle.graal.amd64.*;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.asm.*;
-import com.oracle.graal.asm.amd64.AMD64Address.Scale;
 import com.oracle.graal.compiler.amd64.*;
 import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
-import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.CompareAndSwapCompressedOp;
 import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.LoadCompressedPointer;
 import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.StoreCompressedConstantOp;
 import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.StoreCompressedPointer;
 import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.NoOp;
-import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
 import com.oracle.graal.lir.amd64.*;
-import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp;
-import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp;
+import com.oracle.graal.lir.amd64.AMD64Move.LeaDataOp;
 import com.oracle.graal.lir.amd64.AMD64Move.LoadOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp;
 import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp;
 import com.oracle.graal.lir.amd64.AMD64Move.StoreOp;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 
 /**
  * LIR generator specialized for AMD64 HotSpot.
  */
 public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSpotLIRGenerator {
 
-    private final HotSpotVMConfig config;
+    final HotSpotVMConfig config;
 
-    private final Object stub;
-
-    protected AMD64HotSpotLIRGenerator(StructuredGraph graph, Object stub, HotSpotProviders providers, HotSpotVMConfig config, FrameMap frameMap, CallingConvention cc, LIR lir) {
-        super(graph, providers, frameMap, cc, lir);
+    protected AMD64HotSpotLIRGenerator(HotSpotProviders providers, HotSpotVMConfig config, CallingConvention cc, LIRGenerationResult lirGenRes) {
+        super(providers, cc, lirGenRes);
         assert config.basicLockSize == 8;
         this.config = config;
-        this.stub = stub;
-        memoryPeephole = new AMD64HotSpotMemoryPeephole(this);
     }
 
     @Override
@@ -87,13 +71,6 @@
     }
 
     /**
-     * The slot reserved for storing the original return address when a frame is marked for
-     * deoptimization. The return address slot in the callee is overwritten with the address of a
-     * deoptimization stub.
-     */
-    StackSlot deoptimizationRescueSlot;
-
-    /**
      * Utility for emitting the instruction to save RBP.
      */
     class SaveRbp {
@@ -107,7 +84,7 @@
 
         public SaveRbp(NoOp placeholder) {
             this.placeholder = placeholder;
-            this.reservedSlot = frameMap.allocateSpillSlot(Kind.Long);
+            this.reservedSlot = res.getFrameMap().allocateSpillSlot(Kind.Long);
             assert reservedSlot.getRawOffset() == -16 : reservedSlot.getRawOffset();
         }
 
@@ -121,16 +98,16 @@
             if (useStack) {
                 dst = reservedSlot;
             } else {
-                frameMap.freeSpillSlot(reservedSlot);
+                res.getFrameMap().freeSpillSlot(reservedSlot);
                 dst = newVariable(Kind.Long);
             }
 
-            placeholder.replace(lir, new MoveFromRegOp(dst, rbp.asValue(Kind.Long)));
+            placeholder.replace(res.getLIR(), new MoveFromRegOp(dst, rbp.asValue(Kind.Long)));
             return dst;
         }
     }
 
-    private SaveRbp saveRbp;
+    SaveRbp saveRbp;
 
     /**
      * List of epilogue operations that need to restore RBP.
@@ -145,45 +122,9 @@
         }
     }
 
-    @SuppressWarnings("hiding")
-    @Override
-    protected DebugInfoBuilder createDebugInfoBuilder(NodeMap<Value> nodeOperands) {
-        HotSpotLockStack lockStack = new HotSpotLockStack(frameMap, Kind.Long);
-        return new HotSpotDebugInfoBuilder(nodeOperands, lockStack);
-    }
-
     @Override
     public StackSlot getLockSlot(int lockDepth) {
-        return ((HotSpotDebugInfoBuilder) debugInfoBuilder).lockStack().makeLockSlot(lockDepth);
-    }
-
-    @Override
-    protected void emitPrologue(StructuredGraph graph) {
-
-        CallingConvention incomingArguments = cc;
-
-        Value[] params = new Value[incomingArguments.getArgumentCount() + 1];
-        for (int i = 0; i < params.length - 1; i++) {
-            params[i] = toStackKind(incomingArguments.getArgument(i));
-            if (isStackSlot(params[i])) {
-                StackSlot slot = ValueUtil.asStackSlot(params[i]);
-                if (slot.isInCallerFrame() && !lir.hasArgInCallerFrame()) {
-                    lir.setHasArgInCallerFrame();
-                }
-            }
-        }
-        params[params.length - 1] = rbp.asValue(Kind.Long);
-
-        emitIncomingValues(params);
-
-        saveRbp = new SaveRbp(new NoOp(currentBlock, lir.lir(currentBlock).size()));
-        append(saveRbp.placeholder);
-
-        for (ParameterNode param : graph.getNodes(ParameterNode.class)) {
-            Value paramValue = params[param.index()];
-            assert paramValue.getKind() == param.getKind().getStackKind();
-            setResult(param, emitMove(paramValue));
-        }
+        return ((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack().makeLockSlot(lockDepth);
     }
 
     private Register findPollOnReturnScratchRegister() {
@@ -199,7 +140,7 @@
     private Register pollOnReturnScratchRegister;
 
     @Override
-    protected void emitReturn(Value input) {
+    public void emitReturn(Value input) {
         if (pollOnReturnScratchRegister == null) {
             pollOnReturnScratchRegister = findPollOnReturnScratchRegister();
         }
@@ -209,14 +150,12 @@
     @Override
     protected boolean needOnlyOopMaps() {
         // Stubs only need oop maps
-        return stub != null;
+        return ((AMD64HotSpotLIRGenerationResult) res).getStub() != null;
     }
 
-    /**
-     * Map from debug infos that need to be updated with callee save information to the operations
-     * that provide the information.
-     */
-    Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = new HashMap<>();
+    public void emitData(AllocatableValue dst, byte[] data) {
+        append(new LeaDataOp(dst, data));
+    }
 
     private LIRFrameState currentRuntimeCallInfo;
 
@@ -236,8 +175,8 @@
         append(new AMD64RestoreRegistersOp(save.getSlots().clone(), save));
     }
 
-    Stub getStub() {
-        return (Stub) stub;
+    public Stub getStub() {
+        return ((AMD64HotSpotLIRGenerationResult) res).getStub();
     }
 
     @Override
@@ -249,12 +188,12 @@
         if (destroysRegisters) {
             if (getStub() != null) {
                 if (getStub().preservesRegisters()) {
-                    Register[] savedRegisters = frameMap.registerConfig.getAllocatableRegisters();
+                    Register[] savedRegisters = res.getFrameMap().registerConfig.getAllocatableRegisters();
                     savedRegisterLocations = new StackSlot[savedRegisters.length];
                     for (int i = 0; i < savedRegisters.length; i++) {
                         PlatformKind kind = target().arch.getLargestStorableKind(savedRegisters[i].getRegisterCategory());
                         assert kind != Kind.Illegal;
-                        StackSlot spillSlot = frameMap.allocateSpillSlot(kind);
+                        StackSlot spillSlot = res.getFrameMap().allocateSpillSlot(kind);
                         savedRegisterLocations[i] = spillSlot;
                     }
                     save = emitSaveRegisters(savedRegisters, savedRegisterLocations);
@@ -265,7 +204,7 @@
         Variable result;
 
         if (linkage.canDeoptimize()) {
-            assert info != null || stub != null;
+            assert info != null || ((AMD64HotSpotLIRGenerationResult) res).getStub() != null;
             Register thread = getProviders().getRegisters().getThreadRegister();
             append(new AMD64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread));
             result = super.emitForeignCall(linkage, info, args);
@@ -277,8 +216,8 @@
         if (destroysRegisters) {
             if (getStub() != null) {
                 if (getStub().preservesRegisters()) {
-                    assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo);
-                    calleeSaveInfo.put(currentRuntimeCallInfo, save);
+                    assert !((AMD64HotSpotLIRGenerationResult) res).getCalleeSaveInfo().containsKey(currentRuntimeCallInfo);
+                    ((AMD64HotSpotLIRGenerationResult) res).getCalleeSaveInfo().put(currentRuntimeCallInfo, save);
 
                     emitRestoreRegisters(save);
                 } else {
@@ -297,53 +236,18 @@
     }
 
     protected boolean zapRegisters() {
-        Register[] zappedRegisters = frameMap.registerConfig.getAllocatableRegisters();
+        Register[] zappedRegisters = res.getFrameMap().registerConfig.getAllocatableRegisters();
         Constant[] zapValues = new Constant[zappedRegisters.length];
         for (int i = 0; i < zappedRegisters.length; i++) {
             PlatformKind kind = target().arch.getLargestStorableKind(zappedRegisters[i].getRegisterCategory());
             assert kind != Kind.Illegal;
             zapValues[i] = zapValueForKind(kind);
         }
-        calleeSaveInfo.put(currentRuntimeCallInfo, emitZapRegisters(zappedRegisters, zapValues));
+        ((AMD64HotSpotLIRGenerationResult) res).getCalleeSaveInfo().put(currentRuntimeCallInfo, emitZapRegisters(zappedRegisters, zapValues));
         return true;
     }
 
     @Override
-    public void visitSafepointNode(SafepointNode i) {
-        LIRFrameState info = state(i);
-        append(new AMD64HotSpotSafepointOp(info, config, this));
-    }
-
-    @SuppressWarnings("hiding")
-    @Override
-    public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) {
-        Kind kind = x.newValue().getKind();
-        assert kind == x.expectedValue().getKind();
-
-        Value expected = loadNonConst(operand(x.expectedValue()));
-        Variable newVal = load(operand(x.newValue()));
-
-        int disp = 0;
-        AMD64AddressValue address;
-        Value index = operand(x.offset());
-        if (ValueUtil.isConstant(index) && NumUtil.isInt(ValueUtil.asConstant(index).asLong() + disp)) {
-            assert !getCodeCache().needsDataPatch(asConstant(index));
-            disp += (int) ValueUtil.asConstant(index).asLong();
-            address = new AMD64AddressValue(kind, load(operand(x.object())), disp);
-        } else {
-            address = new AMD64AddressValue(kind, load(operand(x.object())), load(index), Scale.Times1, disp);
-        }
-
-        RegisterValue rax = AMD64.rax.asValue(kind);
-        emitMove(rax, expected);
-        append(new CompareAndSwapOp(rax, address, rax, newVal));
-
-        Variable result = newVariable(x.getKind());
-        emitMove(result, rax);
-        setResult(x, result);
-    }
-
-    @Override
     public void emitTailcall(Value[] args, Value address) {
         append(new AMD64TailcallOp(args, address));
     }
@@ -351,7 +255,7 @@
     @Override
     public void emitCCall(long address, CallingConvention nativeCallingConvention, Value[] args, int numberOfFloatingPointArguments) {
         Value[] argLocations = new Value[args.length];
-        frameMap.callsMethod(nativeCallingConvention);
+        res.getFrameMap().callsMethod(nativeCallingConvention);
         // TODO(mg): in case a native function uses floating point varargs, the ABI requires that
         // RAX contains the length of the varargs
         AllocatableValue numberOfFloatingPointArgumentsRegister = AMD64.rax.asValue();
@@ -367,33 +271,6 @@
     }
 
     @Override
-    protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind();
-        if (invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual) {
-            append(new AMD64HotspotDirectVirtualCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind));
-        } else {
-            assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special;
-            HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target();
-            assert !Modifier.isAbstract(resolvedMethod.getModifiers()) : "Cannot make direct call to abstract method.";
-            Constant metaspaceMethod = resolvedMethod.getMetaspaceMethodConstant();
-            append(new AMD64HotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind, metaspaceMethod));
-        }
-    }
-
-    @Override
-    protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        if (callTarget instanceof HotSpotIndirectCallTargetNode) {
-            AllocatableValue metaspaceMethod = AMD64.rbx.asValue();
-            emitMove(metaspaceMethod, operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod()));
-            AllocatableValue targetAddress = AMD64.rax.asValue();
-            emitMove(targetAddress, operand(callTarget.computedAddress()));
-            append(new AMD64IndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod, targetAddress, callState));
-        } else {
-            super.emitIndirectCall(callTarget, result, parameters, temps, callState);
-        }
-    }
-
-    @Override
     public void emitUnwind(Value exception) {
         ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(HotSpotBackend.UNWIND_EXCEPTION_TO_CALLER);
         CallingConvention outgoingCc = linkage.getOutgoingCallingConvention();
@@ -428,32 +305,12 @@
     }
 
     @Override
-    public void emitPatchReturnAddress(ValueNode address) {
-        append(new AMD64HotSpotPatchReturnAddressOp(load(operand(address))));
-    }
-
-    @Override
-    public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) {
-        Variable handler = load(operand(handlerInCallerPc));
-        ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(EXCEPTION_HANDLER_IN_CALLER);
-        CallingConvention outgoingCc = linkage.getOutgoingCallingConvention();
-        assert outgoingCc.getArgumentCount() == 2;
-        RegisterValue exceptionFixed = (RegisterValue) outgoingCc.getArgument(0);
-        RegisterValue exceptionPcFixed = (RegisterValue) outgoingCc.getArgument(1);
-        emitMove(exceptionFixed, operand(exception));
-        emitMove(exceptionPcFixed, operand(exceptionPc));
-        Register thread = getProviders().getRegisters().getThreadRegister();
-        AMD64HotSpotJumpToExceptionHandlerInCallerOp op = new AMD64HotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed, config.threadIsMethodHandleReturnOffset, thread);
-        append(op);
-    }
-
-    @Override
     public void beforeRegisterAllocation() {
         super.beforeRegisterAllocation();
-        boolean hasDebugInfo = lir.hasDebugInfo();
+        boolean hasDebugInfo = res.getLIR().hasDebugInfo();
         AllocatableValue savedRbp = saveRbp.finalize(hasDebugInfo);
         if (hasDebugInfo) {
-            deoptimizationRescueSlot = frameMap.allocateSpillSlot(Kind.Long);
+            ((AMD64HotSpotLIRGenerationResult) res).setDeoptimizationRescueSlot(res.getFrameMap().allocateSpillSlot(Kind.Long));
         }
 
         for (AMD64HotSpotEpilogueOp op : epilogueOps) {
@@ -561,38 +418,4 @@
         }
     }
 
-    @Override
-    public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) {
-        Kind kind = node.getNewValue().getKind();
-        assert kind == node.getExpectedValue().getKind();
-        Value expected = loadNonConst(operand(node.getExpectedValue()));
-        Variable newValue = load(operand(node.getNewValue()));
-        AMD64AddressValue addressValue = asAddressValue(address);
-        RegisterValue raxRes = AMD64.rax.asValue(kind);
-        emitMove(raxRes, expected);
-        if (config.useCompressedOops && node.isCompressible()) {
-            Variable scratch = newVariable(Kind.Long);
-            Register heapBaseReg = getProviders().getRegisters().getHeapBaseRegister();
-            append(new CompareAndSwapCompressedOp(raxRes, addressValue, raxRes, newValue, scratch, config.getOopEncoding(), heapBaseReg));
-        } else {
-            append(new CompareAndSwapOp(raxRes, addressValue, raxRes, newValue));
-        }
-        Variable result = newVariable(node.getKind());
-        append(new CondMoveOp(result, Condition.EQ, load(Constant.TRUE), Constant.FALSE));
-        setResult(node, result);
-    }
-
-    @Override
-    public void visitInfopointNode(InfopointNode i) {
-        if (i.getState() != null && i.getState().bci == FrameState.AFTER_BCI) {
-            Debug.log("Ignoring InfopointNode for AFTER_BCI");
-        } else {
-            super.visitInfopointNode(i);
-        }
-    }
-
-    public void emitPrefetchAllocate(ValueNode address, ValueNode distance) {
-        AMD64AddressValue addr = emitAddress(operand(address), 0, loadNonConst(operand(distance)), 1);
-        append(new AMD64PrefetchOp(addr, config.allocatePrefetchInstr));
-    }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMemoryPeephole.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMemoryPeephole.java	Thu Mar 27 17:31:20 2014 +0100
@@ -75,7 +75,7 @@
         }
     }
 
-    AMD64HotSpotMemoryPeephole(AMD64LIRGenerator gen) {
+    AMD64HotSpotMemoryPeephole(AMD64NodeLIRGenerator gen) {
         super(gen);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRGenerator.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,229 @@
+/*
+ * 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.hotspot.amd64;
+
+import static com.oracle.graal.amd64.AMD64.*;
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.hotspot.HotSpotBackend.*;
+
+import java.lang.reflect.*;
+
+import com.oracle.graal.amd64.*;
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.asm.amd64.AMD64Address.Scale;
+import com.oracle.graal.compiler.amd64.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.amd64.AMD64HotSpotLIRGenerator.SaveRbp;
+import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.CompareAndSwapCompressedOp;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.NoOp;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp;
+import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
+
+/**
+ * LIR generator specialized for AMD64 HotSpot.
+ */
+public class AMD64HotSpotNodeLIRGenerator extends AMD64NodeLIRGenerator implements HotSpotNodeLIRGenerator {
+
+    public AMD64HotSpotNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult res, LIRGenerator gen) {
+        super(graph, res, gen);
+        memoryPeephole = new AMD64HotSpotMemoryPeephole(this);
+    }
+
+    private AMD64HotSpotLIRGenerator getGen() {
+        return (AMD64HotSpotLIRGenerator) gen;
+    }
+
+    private SaveRbp getSaveRbp() {
+        return getGen().saveRbp;
+    }
+
+    private void setSaveRbp(SaveRbp saveRbp) {
+        getGen().saveRbp = saveRbp;
+    }
+
+    @Override
+    protected DebugInfoBuilder createDebugInfoBuilder(NodeMap<Value> nodeOperands) {
+        HotSpotLockStack lockStack = new HotSpotLockStack(res.getFrameMap(), Kind.Long);
+        return new HotSpotDebugInfoBuilder(nodeOperands, lockStack);
+    }
+
+    @Override
+    protected void emitPrologue(StructuredGraph graph) {
+
+        CallingConvention incomingArguments = gen.getCallingConvention();
+
+        Value[] params = new Value[incomingArguments.getArgumentCount() + 1];
+        for (int i = 0; i < params.length - 1; i++) {
+            params[i] = toStackKind(incomingArguments.getArgument(i));
+            if (isStackSlot(params[i])) {
+                StackSlot slot = ValueUtil.asStackSlot(params[i]);
+                if (slot.isInCallerFrame() && !res.getLIR().hasArgInCallerFrame()) {
+                    res.getLIR().setHasArgInCallerFrame();
+                }
+            }
+        }
+        params[params.length - 1] = rbp.asValue(Kind.Long);
+
+        emitIncomingValues(params);
+
+        setSaveRbp(((AMD64HotSpotLIRGenerator) gen).new SaveRbp(new NoOp(gen.getCurrentBlock(), res.getLIR().getLIRforBlock(gen.getCurrentBlock()).size())));
+        append(getSaveRbp().placeholder);
+
+        for (ParameterNode param : graph.getNodes(ParameterNode.class)) {
+            Value paramValue = params[param.index()];
+            assert paramValue.getKind() == param.getKind().getStackKind();
+            setResult(param, gen.emitMove(paramValue));
+        }
+    }
+
+    @Override
+    public void visitSafepointNode(SafepointNode i) {
+        LIRFrameState info = gen.state(i);
+        append(new AMD64HotSpotSafepointOp(info, getGen().config, this));
+    }
+
+    @Override
+    protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
+        InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind();
+        if (invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual) {
+            append(new AMD64HotspotDirectVirtualCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind));
+        } else {
+            assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special;
+            HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target();
+            assert !Modifier.isAbstract(resolvedMethod.getModifiers()) : "Cannot make direct call to abstract method.";
+            Constant metaspaceMethod = resolvedMethod.getMetaspaceMethodConstant();
+            append(new AMD64HotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind, metaspaceMethod));
+        }
+    }
+
+    @Override
+    protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
+        if (callTarget instanceof HotSpotIndirectCallTargetNode) {
+            AllocatableValue metaspaceMethod = AMD64.rbx.asValue();
+            gen.emitMove(metaspaceMethod, operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod()));
+            AllocatableValue targetAddress = AMD64.rax.asValue();
+            gen.emitMove(targetAddress, operand(callTarget.computedAddress()));
+            append(new AMD64IndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod, targetAddress, callState));
+        } else {
+            super.emitIndirectCall(callTarget, result, parameters, temps, callState);
+        }
+    }
+
+    @Override
+    public void emitPatchReturnAddress(ValueNode address) {
+        append(new AMD64HotSpotPatchReturnAddressOp(gen.load(operand(address))));
+    }
+
+    @Override
+    public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) {
+        Variable handler = gen.load(operand(handlerInCallerPc));
+        ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(EXCEPTION_HANDLER_IN_CALLER);
+        CallingConvention outgoingCc = linkage.getOutgoingCallingConvention();
+        assert outgoingCc.getArgumentCount() == 2;
+        RegisterValue exceptionFixed = (RegisterValue) outgoingCc.getArgument(0);
+        RegisterValue exceptionPcFixed = (RegisterValue) outgoingCc.getArgument(1);
+        gen.emitMove(exceptionFixed, operand(exception));
+        gen.emitMove(exceptionPcFixed, operand(exceptionPc));
+        Register thread = getGen().getProviders().getRegisters().getThreadRegister();
+        AMD64HotSpotJumpToExceptionHandlerInCallerOp op = new AMD64HotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed, getGen().config.threadIsMethodHandleReturnOffset,
+                        thread);
+        append(op);
+    }
+
+    @Override
+    public void visitInfopointNode(InfopointNode i) {
+        if (i.getState() != null && i.getState().bci == FrameState.AFTER_BCI) {
+            Debug.log("Ignoring InfopointNode for AFTER_BCI");
+        } else {
+            super.visitInfopointNode(i);
+        }
+    }
+
+    public void emitPrefetchAllocate(ValueNode address, ValueNode distance) {
+        AMD64AddressValue addr = getGen().emitAddress(operand(address), 0, gen.loadNonConst(operand(distance)), 1);
+        append(new AMD64PrefetchOp(addr, getGen().config.allocatePrefetchInstr));
+    }
+
+    @Override
+    public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) {
+        Kind kind = x.newValue().getKind();
+        assert kind == x.expectedValue().getKind();
+
+        Value expected = gen.loadNonConst(operand(x.expectedValue()));
+        Variable newVal = gen.load(operand(x.newValue()));
+
+        int disp = 0;
+        AMD64AddressValue address;
+        Value index = operand(x.offset());
+        if (ValueUtil.isConstant(index) && NumUtil.isInt(ValueUtil.asConstant(index).asLong() + disp)) {
+            assert !gen.getCodeCache().needsDataPatch(asConstant(index));
+            disp += (int) ValueUtil.asConstant(index).asLong();
+            address = new AMD64AddressValue(kind, gen.load(operand(x.object())), disp);
+        } else {
+            address = new AMD64AddressValue(kind, gen.load(operand(x.object())), gen.load(index), Scale.Times1, disp);
+        }
+
+        RegisterValue raxLocal = AMD64.rax.asValue(kind);
+        gen.emitMove(raxLocal, expected);
+        append(new CompareAndSwapOp(raxLocal, address, raxLocal, newVal));
+
+        Variable result = newVariable(x.getKind());
+        gen.emitMove(result, raxLocal);
+        setResult(x, result);
+    }
+
+    @Override
+    public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) {
+        Kind kind = node.getNewValue().getKind();
+        assert kind == node.getExpectedValue().getKind();
+        Value expected = gen.loadNonConst(operand(node.getExpectedValue()));
+        Variable newValue = gen.load(operand(node.getNewValue()));
+        AMD64AddressValue addressValue = getGen().asAddressValue(address);
+        RegisterValue raxRes = AMD64.rax.asValue(kind);
+        gen.emitMove(raxRes, expected);
+        if (getGen().config.useCompressedOops && node.isCompressible()) {
+            Variable scratch = newVariable(Kind.Long);
+            Register heapBaseReg = getGen().getProviders().getRegisters().getHeapBaseRegister();
+            append(new CompareAndSwapCompressedOp(raxRes, addressValue, raxRes, newValue, scratch, getGen().config.getOopEncoding(), heapBaseReg));
+        } else {
+            append(new CompareAndSwapOp(raxRes, addressValue, raxRes, newValue));
+        }
+        Variable result = newVariable(node.getKind());
+        append(new CondMoveOp(result, Condition.EQ, gen.load(Constant.TRUE), Constant.FALSE));
+        setResult(node, result);
+    }
+
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java	Thu Mar 27 17:31:20 2014 +0100
@@ -47,11 +47,11 @@
 
     private final HotSpotVMConfig config;
 
-    public AMD64HotSpotSafepointOp(LIRFrameState state, HotSpotVMConfig config, LIRGeneratorTool tool) {
+    public AMD64HotSpotSafepointOp(LIRFrameState state, HotSpotVMConfig config, NodeLIRGeneratorTool tool) {
         this.state = state;
         this.config = config;
         if (isPollingPageFar(config) || ImmutableCode.getValue()) {
-            temp = tool.newVariable(tool.target().wordKind);
+            temp = tool.getLIRGeneratorTool().newVariable(tool.getLIRGeneratorTool().target().wordKind);
         } else {
             // Don't waste a register if it's unneeded
             temp = Value.ILLEGAL;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -44,19 +44,20 @@
     }
 
     @Override
-    public void generate(LIRGenerator generator) {
-        AMD64LIRGenerator gen = (AMD64LIRGenerator) generator;
+    public void generate(NodeLIRGenerator generator) {
+        AMD64NodeLIRGenerator gen = (AMD64NodeLIRGenerator) generator;
         Value[] parameter = new Value[args.count()];
         JavaType[] parameterTypes = new JavaType[args.count()];
         for (int i = 0; i < args.count(); i++) {
             parameter[i] = generator.operand(args.get(i));
-            parameterTypes[i] = args.get(i).stamp().javaType(gen.getMetaAccess());
+            parameterTypes[i] = args.get(i).stamp().javaType(gen.getLIRGeneratorTool().getMetaAccess());
         }
-        ResolvedJavaType returnType = stamp().javaType(gen.getMetaAccess());
-        CallingConvention cc = generator.getCodeCache().getRegisterConfig().getCallingConvention(Type.NativeCall, returnType, parameterTypes, generator.target(), false);
-        gen.emitCCall(functionPointer.asLong(), cc, parameter, countFloatingTypeArguments(args));
+        ResolvedJavaType returnType = stamp().javaType(gen.getLIRGeneratorTool().getMetaAccess());
+        CallingConvention cc = generator.getLIRGeneratorTool().getCodeCache().getRegisterConfig().getCallingConvention(Type.NativeCall, returnType, parameterTypes,
+                        generator.getLIRGeneratorTool().target(), false);
+        ((AMD64LIRGenerator) gen.getLIRGeneratorTool()).emitCCall(functionPointer.asLong(), cc, parameter, countFloatingTypeArguments(args));
         if (this.getKind() != Kind.Void) {
-            generator.setResult(this, gen.emitMove(cc.getReturn()));
+            generator.setResult(this, gen.getLIRGeneratorTool().emitMove(cc.getReturn()));
         }
     }
 
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Thu Mar 27 17:31:20 2014 +0100
@@ -26,6 +26,7 @@
 import static com.oracle.graal.api.code.CodeUtil.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.compiler.GraalCompiler.*;
+import static com.oracle.graal.api.meta.LocationIdentity.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -51,12 +52,17 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.CompilerToVM.CodeInstallResult;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hsail.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.hsail.*;
+import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizeOp;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.tiers.*;
@@ -359,8 +365,18 @@
     }
 
     @Override
-    public LIRGenerator newLIRGenerator(StructuredGraph graph, Object stub, FrameMap frameMap, CallingConvention cc, LIR lir) {
-        return new HSAILHotSpotLIRGenerator(graph, getProviders(), getRuntime().getConfig(), frameMap, cc, lir);
+    public LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) {
+        return new HSAILHotSpotLIRGenerator(getProviders(), getRuntime().getConfig(), cc, lirGenRes);
+    }
+
+    @Override
+    public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) {
+        return new HSAILHotSpotLIRGenerationResult(lir, frameMap);
+    }
+
+    @Override
+    public NodeLIRGenerator newNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult lirGenRes, LIRGenerator lirGen) {
+        return new HSAILHotSpotNodeLIRGenerator(graph, lirGenRes, lirGen);
     }
 
     class HotSpotFrameContext implements FrameContext {
@@ -384,12 +400,12 @@
      * a class to allow us to save lirGen.
      */
     static class HSAILCompilationResultBuilder extends CompilationResultBuilder {
-        public HSAILHotSpotLIRGenerator lirGen;
+        public HSAILHotSpotLIRGenerationResult lirGenRes;
 
         public HSAILCompilationResultBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, FrameContext frameContext,
-                        CompilationResult compilationResult, LIRGenerator lirGen) {
+                        CompilationResult compilationResult, HSAILHotSpotLIRGenerationResult lirGenRes) {
             super(codeCache, foreignCalls, frameMap, asm, frameContext, compilationResult);
-            this.lirGen = (HSAILHotSpotLIRGenerator) lirGen;
+            this.lirGenRes = lirGenRes;
         }
     }
 
@@ -399,12 +415,13 @@
     }
 
     @Override
-    public CompilationResultBuilder newCompilationResultBuilder(LIRGenerator lirGen, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
-        FrameMap frameMap = lirGen.frameMap;
+    public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRes, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
+        FrameMap frameMap = lirGenRes.getFrameMap();
         Assembler masm = createAssembler(frameMap);
         HotSpotFrameContext frameContext = new HotSpotFrameContext();
         // save lirGen for later use by setHostGraph
-        CompilationResultBuilder crb = new HSAILCompilationResultBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult, lirGen);
+        CompilationResultBuilder crb = new HSAILCompilationResultBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult,
+                        (HSAILHotSpotLIRGenerationResult) lirGenRes);
         crb.setFrameSize(frameMap.frameSize());
         return crb;
     }
@@ -760,6 +777,140 @@
         asm.emitString0("}; \n");
 
         ExternalCompilationResult compilationResult = (ExternalCompilationResult) crb.compilationResult;
-        compilationResult.setHostGraph(((HSAILCompilationResultBuilder) crb).lirGen.prepareHostGraph());
+        HSAILHotSpotLIRGenerationResult lirGenRes = ((HSAILCompilationResultBuilder) crb).lirGenRes;
+        compilationResult.setHostGraph(prepareHostGraph(method, lirGenRes.getDeopts(), getProviders(), getRuntime().getConfig()));
+    }
+
+    private static StructuredGraph prepareHostGraph(ResolvedJavaMethod method, List<DeoptimizeOp> deopts, HotSpotProviders providers, HotSpotVMConfig config) {
+        if (deopts.isEmpty()) {
+            return null;
+        }
+        StructuredGraph hostGraph = new StructuredGraph(method, -2);
+        ParameterNode deoptId = hostGraph.unique(new ParameterNode(0, StampFactory.intValue()));
+        ParameterNode hsailFrame = hostGraph.unique(new ParameterNode(1, StampFactory.forKind(providers.getCodeCache().getTarget().wordKind)));
+        ParameterNode reasonAndAction = hostGraph.unique(new ParameterNode(2, StampFactory.intValue()));
+        ParameterNode speculation = hostGraph.unique(new ParameterNode(3, StampFactory.object()));
+        AbstractBeginNode[] branches = new AbstractBeginNode[deopts.size() + 1];
+        int[] keys = new int[deopts.size()];
+        int[] keySuccessors = new int[deopts.size() + 1];
+        double[] keyProbabilities = new double[deopts.size() + 1];
+        int i = 0;
+        Collections.sort(deopts, new Comparator<DeoptimizeOp>() {
+            public int compare(DeoptimizeOp o1, DeoptimizeOp o2) {
+                return o1.getCodeBufferPos() - o2.getCodeBufferPos();
+            }
+        });
+        for (DeoptimizeOp deopt : deopts) {
+            keySuccessors[i] = i;
+            keyProbabilities[i] = 1.0 / deopts.size();
+            keys[i] = deopt.getCodeBufferPos();
+            assert keys[i] >= 0;
+            branches[i] = createHostDeoptBranch(deopt, hsailFrame, reasonAndAction, speculation, providers, config);
+
+            i++;
+        }
+        keyProbabilities[deopts.size()] = 0; // default
+        keySuccessors[deopts.size()] = deopts.size();
+        branches[deopts.size()] = createHostCrashBranch(hostGraph, deoptId);
+        IntegerSwitchNode switchNode = hostGraph.add(new IntegerSwitchNode(deoptId, branches, keys, keyProbabilities, keySuccessors));
+        StartNode start = hostGraph.start();
+        start.setNext(switchNode);
+        /*
+         * printf.setNext(printf2); printf2.setNext(switchNode);
+         */
+        hostGraph.setGuardsStage(GuardsStage.AFTER_FSA);
+        return hostGraph;
+    }
+
+    private static AbstractBeginNode createHostCrashBranch(StructuredGraph hostGraph, ValueNode deoptId) {
+        VMErrorNode vmError = hostGraph.add(new VMErrorNode("Error in HSAIL deopt. DeoptId=%d", deoptId));
+        // ConvertNode.convert(hostGraph, Kind.Long, deoptId)));
+        vmError.setNext(hostGraph.add(new ReturnNode(ConstantNode.defaultForKind(hostGraph.method().getSignature().getReturnKind(), hostGraph))));
+        return BeginNode.begin(vmError);
+    }
+
+    private static AbstractBeginNode createHostDeoptBranch(DeoptimizeOp deopt, ParameterNode hsailFrame, ValueNode reasonAndAction, ValueNode speculation, HotSpotProviders providers,
+                    HotSpotVMConfig config) {
+        BeginNode branch = hsailFrame.graph().add(new BeginNode());
+        DynamicDeoptimizeNode deoptimization = hsailFrame.graph().add(new DynamicDeoptimizeNode(reasonAndAction, speculation));
+        deoptimization.setStateBefore(createFrameState(deopt.getFrameState().topFrame, hsailFrame, providers, config));
+        branch.setNext(deoptimization);
+        return branch;
     }
+
+    private static FrameState createFrameState(BytecodeFrame lowLevelFrame, ParameterNode hsailFrame, HotSpotProviders providers, HotSpotVMConfig config) {
+        StructuredGraph hostGraph = hsailFrame.graph();
+        ValueNode[] locals = new ValueNode[lowLevelFrame.numLocals];
+        for (int i = 0; i < lowLevelFrame.numLocals; i++) {
+            locals[i] = getNodeForValueFromFrame(lowLevelFrame.getLocalValue(i), hsailFrame, hostGraph, providers, config);
+        }
+        List<ValueNode> stack = new ArrayList<>(lowLevelFrame.numStack);
+        for (int i = 0; i < lowLevelFrame.numStack; i++) {
+            stack.add(getNodeForValueFromFrame(lowLevelFrame.getStackValue(i), hsailFrame, hostGraph, providers, config));
+        }
+        ValueNode[] locks = new ValueNode[lowLevelFrame.numLocks];
+        MonitorIdNode[] monitorIds = new MonitorIdNode[lowLevelFrame.numLocks];
+        for (int i = 0; i < lowLevelFrame.numLocks; i++) {
+            HotSpotMonitorValue lockValue = (HotSpotMonitorValue) lowLevelFrame.getLockValue(i);
+            locks[i] = getNodeForValueFromFrame(lockValue, hsailFrame, hostGraph, providers, config);
+            monitorIds[i] = getMonitorIdForHotSpotMonitorValueFromFrame(lockValue, hsailFrame, hostGraph);
+        }
+        FrameState frameState = hostGraph.add(new FrameState(lowLevelFrame.getMethod(), lowLevelFrame.getBCI(), locals, stack, locks, monitorIds, lowLevelFrame.rethrowException, false));
+        if (lowLevelFrame.caller() != null) {
+            frameState.setOuterFrameState(createFrameState(lowLevelFrame.caller(), hsailFrame, providers, config));
+        }
+        return frameState;
+    }
+
+    @SuppressWarnings({"unused"})
+    private static MonitorIdNode getMonitorIdForHotSpotMonitorValueFromFrame(HotSpotMonitorValue lockValue, ParameterNode hsailFrame, StructuredGraph hsailGraph) {
+        if (lockValue.isEliminated()) {
+            return null;
+        }
+        throw GraalInternalError.unimplemented();
+    }
+
+    private static ValueNode getNodeForValueFromFrame(Value localValue, ParameterNode hsailFrame, StructuredGraph hostGraph, HotSpotProviders providers, HotSpotVMConfig config) {
+        ValueNode valueNode;
+        if (localValue instanceof Constant) {
+            valueNode = ConstantNode.forConstant((Constant) localValue, providers.getMetaAccess(), hostGraph);
+        } else if (localValue instanceof VirtualObject) {
+            throw GraalInternalError.unimplemented();
+        } else if (localValue instanceof StackSlot) {
+            throw GraalInternalError.unimplemented();
+        } else if (localValue instanceof HotSpotMonitorValue) {
+            HotSpotMonitorValue hotSpotMonitorValue = (HotSpotMonitorValue) localValue;
+            return getNodeForValueFromFrame(hotSpotMonitorValue.getOwner(), hsailFrame, hostGraph, providers, config);
+        } else if (localValue instanceof RegisterValue) {
+            RegisterValue registerValue = (RegisterValue) localValue;
+            int regNumber = registerValue.getRegister().number;
+            valueNode = getNodeForRegisterFromFrame(regNumber, localValue.getKind(), hsailFrame, hostGraph, providers, config);
+        } else if (Value.ILLEGAL.equals(localValue)) {
+            valueNode = null;
+        } else {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+        return valueNode;
+    }
+
+    private static ValueNode getNodeForRegisterFromFrame(int regNumber, Kind valueKind, ParameterNode hsailFrame, StructuredGraph hostGraph, HotSpotProviders providers, HotSpotVMConfig config) {
+        ValueNode valueNode;
+        LocationNode location;
+        if (regNumber >= HSAIL.s0.number && regNumber <= HSAIL.s31.number) {
+            int intSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Int);
+            long offset = config.hsailFrameSaveAreaOffset + intSize * (regNumber - HSAIL.s0.number);
+            location = ConstantLocationNode.create(FINAL_LOCATION, valueKind, offset, hostGraph);
+        } else if (regNumber >= HSAIL.d0.number && regNumber <= HSAIL.d15.number) {
+            int longSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Long);
+            long offset = config.hsailFrameSaveAreaOffset + longSize * (regNumber - HSAIL.d0.number);
+            LocationNode numSRegsLocation = ConstantLocationNode.create(FINAL_LOCATION, Kind.Byte, config.hsailFrameNumSRegOffset, hostGraph);
+            ValueNode numSRegs = hostGraph.unique(new FloatingReadNode(hsailFrame, numSRegsLocation, null, StampFactory.forKind(Kind.Byte)));
+            location = IndexedLocationNode.create(FINAL_LOCATION, valueKind, offset, numSRegs, hostGraph, 4);
+        } else {
+            throw GraalInternalError.shouldNotReachHere("unknown hsail register: " + regNumber);
+        }
+        valueNode = hostGraph.unique(new FloatingReadNode(hsailFrame, location, null, StampFactory.forKind(valueKind)));
+        return valueNode;
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerationResult.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,47 @@
+/*
+ * 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.hotspot.hsail;
+
+import java.util.*;
+
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizeOp;
+
+public class HSAILHotSpotLIRGenerationResult extends LIRGenerationResultBase {
+
+    private List<DeoptimizeOp> deopts = new ArrayList<>();
+
+    public HSAILHotSpotLIRGenerationResult(LIR lir, FrameMap frameMap) {
+        super(lir, frameMap);
+    }
+
+    public List<DeoptimizeOp> getDeopts() {
+        return deopts;
+    }
+
+    public void addDeopt(DeoptimizeOp deopt) {
+        deopts.add(deopt);
+    }
+
+}
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java	Thu Mar 27 17:31:20 2014 +0100
@@ -24,187 +24,40 @@
 package com.oracle.graal.hotspot.hsail;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
-import static com.oracle.graal.api.meta.LocationIdentity.*;
-
-import java.util.*;
-
-import sun.misc.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.hsail.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
 import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.hotspot.nodes.*;
-import com.oracle.graal.hsail.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.hsail.*;
-import com.oracle.graal.lir.hsail.HSAILControlFlow.CondMoveOp;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizeOp;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCall1ArgOp;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCall2ArgOp;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCallNoArgOp;
-import com.oracle.graal.lir.hsail.HSAILMove.CompareAndSwapCompressedOp;
-import com.oracle.graal.lir.hsail.HSAILMove.CompareAndSwapOp;
 import com.oracle.graal.lir.hsail.HSAILMove.LoadCompressedPointer;
 import com.oracle.graal.lir.hsail.HSAILMove.LoadOp;
 import com.oracle.graal.lir.hsail.HSAILMove.StoreCompressedPointer;
 import com.oracle.graal.lir.hsail.HSAILMove.StoreConstantOp;
 import com.oracle.graal.lir.hsail.HSAILMove.StoreOp;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
-import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.util.*;
 
 /**
  * The HotSpot specific portion of the HSAIL LIR generator.
  */
-public class HSAILHotSpotLIRGenerator extends HSAILLIRGenerator implements HotSpotLIRGenerator {
-
-    private final HotSpotVMConfig config;
-    private final List<DeoptimizeOp> deopts = new ArrayList<>();
-    private final ResolvedJavaMethod method;
-
-    public HSAILHotSpotLIRGenerator(StructuredGraph graph, Providers providers, HotSpotVMConfig config, FrameMap frameMap, CallingConvention cc, LIR lir) {
-        super(graph, providers, frameMap, cc, lir);
-        this.config = config;
-        this.method = graph.method();
-    }
+public class HSAILHotSpotLIRGenerator extends HSAILLIRGenerator {
 
-    protected StructuredGraph prepareHostGraph() {
-        if (deopts.isEmpty()) {
-            return null;
-        }
-        StructuredGraph hostGraph = new StructuredGraph(method, -2);
-        ParameterNode deoptId = hostGraph.unique(new ParameterNode(0, StampFactory.intValue()));
-        ParameterNode hsailFrame = hostGraph.unique(new ParameterNode(1, StampFactory.forKind(getProviders().getCodeCache().getTarget().wordKind)));
-        ParameterNode reasonAndAction = hostGraph.unique(new ParameterNode(2, StampFactory.intValue()));
-        ParameterNode speculation = hostGraph.unique(new ParameterNode(3, StampFactory.object()));
-        AbstractBeginNode[] branches = new AbstractBeginNode[deopts.size() + 1];
-        int[] keys = new int[deopts.size()];
-        int[] keySuccessors = new int[deopts.size() + 1];
-        double[] keyProbabilities = new double[deopts.size() + 1];
-        int i = 0;
-        Collections.sort(deopts, new Comparator<DeoptimizeOp>() {
-            public int compare(DeoptimizeOp o1, DeoptimizeOp o2) {
-                return o1.getCodeBufferPos() - o2.getCodeBufferPos();
-            }
-        });
-        for (DeoptimizeOp deopt : deopts) {
-            keySuccessors[i] = i;
-            keyProbabilities[i] = 1.0 / deopts.size();
-            keys[i] = deopt.getCodeBufferPos();
-            assert keys[i] >= 0;
-            branches[i] = createHostDeoptBranch(deopt, hsailFrame, reasonAndAction, speculation);
-
-            i++;
-        }
-        keyProbabilities[deopts.size()] = 0; // default
-        keySuccessors[deopts.size()] = deopts.size();
-        branches[deopts.size()] = createHostCrashBranch(hostGraph, deoptId);
-        IntegerSwitchNode switchNode = hostGraph.add(new IntegerSwitchNode(deoptId, branches, keys, keyProbabilities, keySuccessors));
-        StartNode start = hostGraph.start();
-        start.setNext(switchNode);
-        /*
-         * printf.setNext(printf2); printf2.setNext(switchNode);
-         */
-        hostGraph.setGuardsStage(GuardsStage.AFTER_FSA);
-        return hostGraph;
-    }
-
-    private static AbstractBeginNode createHostCrashBranch(StructuredGraph hostGraph, ValueNode deoptId) {
-        VMErrorNode vmError = hostGraph.add(new VMErrorNode("Error in HSAIL deopt. DeoptId=%d", deoptId));
-        // ConvertNode.convert(hostGraph, Kind.Long, deoptId)));
-        vmError.setNext(hostGraph.add(new ReturnNode(ConstantNode.defaultForKind(hostGraph.method().getSignature().getReturnKind(), hostGraph))));
-        return BeginNode.begin(vmError);
-    }
-
-    private AbstractBeginNode createHostDeoptBranch(DeoptimizeOp deopt, ParameterNode hsailFrame, ValueNode reasonAndAction, ValueNode speculation) {
-        BeginNode branch = hsailFrame.graph().add(new BeginNode());
-        DynamicDeoptimizeNode deoptimization = hsailFrame.graph().add(new DynamicDeoptimizeNode(reasonAndAction, speculation));
-        deoptimization.setStateBefore(createFrameState(deopt.getFrameState().topFrame, hsailFrame));
-        branch.setNext(deoptimization);
-        return branch;
-    }
+    final HotSpotVMConfig config;
 
-    private FrameState createFrameState(BytecodeFrame lowLevelFrame, ParameterNode hsailFrame) {
-        StructuredGraph hostGraph = hsailFrame.graph();
-        ValueNode[] locals = new ValueNode[lowLevelFrame.numLocals];
-        for (int i = 0; i < lowLevelFrame.numLocals; i++) {
-            locals[i] = getNodeForValueFromFrame(lowLevelFrame.getLocalValue(i), hsailFrame, hostGraph);
-        }
-        List<ValueNode> stack = new ArrayList<>(lowLevelFrame.numStack);
-        for (int i = 0; i < lowLevelFrame.numStack; i++) {
-            stack.add(getNodeForValueFromFrame(lowLevelFrame.getStackValue(i), hsailFrame, hostGraph));
-        }
-        ValueNode[] locks = new ValueNode[lowLevelFrame.numLocks];
-        MonitorIdNode[] monitorIds = new MonitorIdNode[lowLevelFrame.numLocks];
-        for (int i = 0; i < lowLevelFrame.numLocks; i++) {
-            HotSpotMonitorValue lockValue = (HotSpotMonitorValue) lowLevelFrame.getLockValue(i);
-            locks[i] = getNodeForValueFromFrame(lockValue, hsailFrame, hostGraph);
-            monitorIds[i] = getMonitorIdForHotSpotMonitorValueFromFrame(lockValue, hsailFrame, hostGraph);
-        }
-        FrameState frameState = hostGraph.add(new FrameState(lowLevelFrame.getMethod(), lowLevelFrame.getBCI(), locals, stack, locks, monitorIds, lowLevelFrame.rethrowException, false));
-        if (lowLevelFrame.caller() != null) {
-            frameState.setOuterFrameState(createFrameState(lowLevelFrame.caller(), hsailFrame));
-        }
-        return frameState;
-    }
-
-    @SuppressWarnings({"unused", "static-method"})
-    private MonitorIdNode getMonitorIdForHotSpotMonitorValueFromFrame(HotSpotMonitorValue lockValue, ParameterNode hsailFrame, StructuredGraph hsailGraph) {
-        if (lockValue.isEliminated()) {
-            return null;
-        }
-        throw GraalInternalError.unimplemented();
-    }
-
-    private ValueNode getNodeForValueFromFrame(Value localValue, ParameterNode hsailFrame, StructuredGraph hostGraph) {
-        ValueNode valueNode;
-        if (localValue instanceof Constant) {
-            valueNode = ConstantNode.forConstant((Constant) localValue, getProviders().getMetaAccess(), hostGraph);
-        } else if (localValue instanceof VirtualObject) {
-            throw GraalInternalError.unimplemented();
-        } else if (localValue instanceof StackSlot) {
-            throw GraalInternalError.unimplemented();
-        } else if (localValue instanceof HotSpotMonitorValue) {
-            HotSpotMonitorValue hotSpotMonitorValue = (HotSpotMonitorValue) localValue;
-            return getNodeForValueFromFrame(hotSpotMonitorValue.getOwner(), hsailFrame, hostGraph);
-        } else if (localValue instanceof RegisterValue) {
-            RegisterValue registerValue = (RegisterValue) localValue;
-            int regNumber = registerValue.getRegister().number;
-            valueNode = getNodeForRegisterFromFrame(regNumber, localValue.getKind(), hsailFrame, hostGraph);
-        } else if (Value.ILLEGAL.equals(localValue)) {
-            valueNode = null;
-        } else {
-            throw GraalInternalError.shouldNotReachHere();
-        }
-        return valueNode;
-    }
-
-    private ValueNode getNodeForRegisterFromFrame(int regNumber, Kind valueKind, ParameterNode hsailFrame, StructuredGraph hostGraph) {
-        ValueNode valueNode;
-        LocationNode location;
-        if (regNumber >= HSAIL.s0.number && regNumber <= HSAIL.s31.number) {
-            int intSize = getProviders().getCodeCache().getTarget().arch.getSizeInBytes(Kind.Int);
-            long offset = config.hsailFrameSaveAreaOffset + intSize * (regNumber - HSAIL.s0.number);
-            location = ConstantLocationNode.create(FINAL_LOCATION, valueKind, offset, hostGraph);
-        } else if (regNumber >= HSAIL.d0.number && regNumber <= HSAIL.d15.number) {
-            int longSize = getProviders().getCodeCache().getTarget().arch.getSizeInBytes(Kind.Long);
-            long offset = config.hsailFrameSaveAreaOffset + longSize * (regNumber - HSAIL.d0.number);
-            LocationNode numSRegsLocation = ConstantLocationNode.create(FINAL_LOCATION, Kind.Byte, config.hsailFrameNumSRegOffset, hostGraph);
-            ValueNode numSRegs = hostGraph.unique(new FloatingReadNode(hsailFrame, numSRegsLocation, null, StampFactory.forKind(Kind.Byte)));
-            location = IndexedLocationNode.create(FINAL_LOCATION, valueKind, offset, numSRegs, hostGraph, 4);
-        } else {
-            throw GraalInternalError.shouldNotReachHere("unknown hsail register: " + regNumber);
-        }
-        valueNode = hostGraph.unique(new FloatingReadNode(hsailFrame, location, null, StampFactory.forKind(valueKind)));
-        return valueNode;
+    public HSAILHotSpotLIRGenerator(Providers providers, HotSpotVMConfig config, CallingConvention cc, LIRGenerationResult lirGenRes) {
+        super(providers, cc, lirGenRes);
+        this.config = config;
     }
 
     @Override
@@ -212,27 +65,27 @@
         return (HotSpotProviders) super.getProviders();
     }
 
-    private int getLogMinObjectAlignment() {
+    int getLogMinObjectAlignment() {
         return config.logMinObjAlignment();
     }
 
-    private int getNarrowOopShift() {
+    int getNarrowOopShift() {
         return config.narrowOopShift;
     }
 
-    private long getNarrowOopBase() {
+    long getNarrowOopBase() {
         return config.narrowOopBase;
     }
 
-    private int getLogKlassAlignment() {
+    int getLogKlassAlignment() {
         return config.logKlassAlignment;
     }
 
-    private int getNarrowKlassShift() {
+    int getNarrowKlassShift() {
         return config.narrowKlassShift;
     }
 
-    private long getNarrowKlassBase() {
+    long getNarrowKlassBase() {
         return config.narrowKlassBase;
     }
 
@@ -245,76 +98,6 @@
         return true;
     }
 
-    @Override
-    public StackSlot getLockSlot(int lockDepth) {
-        throw GraalInternalError.shouldNotReachHere("NYI");
-    }
-
-    @Override
-    public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) {
-        throw GraalInternalError.shouldNotReachHere("NYI");
-    }
-
-    @Override
-    public void emitPrefetchAllocate(ValueNode address, ValueNode distance) {
-        throw GraalInternalError.shouldNotReachHere("NYI");
-    }
-
-    @Override
-    public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) {
-        throw GraalInternalError.shouldNotReachHere("NYI");
-    }
-
-    @Override
-    public void emitPatchReturnAddress(ValueNode address) {
-        throw GraalInternalError.shouldNotReachHere("NYI");
-    }
-
-    @Override
-    public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) {
-        throw GraalInternalError.shouldNotReachHere("NYI");
-    }
-
-    @Override
-    public void emitTailcall(Value[] args, Value address) {
-        throw GraalInternalError.shouldNotReachHere("NYI");
-    }
-
-    /**
-     * Appends either a {@link CompareAndSwapOp} or a {@link CompareAndSwapCompressedOp} depending
-     * on whether the memory location of a given {@link LoweredCompareAndSwapNode} contains a
-     * compressed oop. For the {@link CompareAndSwapCompressedOp} case, allocates a number of
-     * scratch registers. The result {@link #operand(ValueNode) operand} for {@code node} complies
-     * with the API for {@link Unsafe#compareAndSwapInt(Object, long, int, int)}.
-     * 
-     * @param address the memory location targeted by the operation
-     */
-    @Override
-    public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) {
-        Kind kind = node.getNewValue().getKind();
-        assert kind == node.getExpectedValue().getKind();
-        Variable expected = load(operand(node.getExpectedValue()));
-        Variable newValue = load(operand(node.getNewValue()));
-        HSAILAddressValue addressValue = asAddressValue(address);
-        Variable casResult = newVariable(kind);
-        if (config.useCompressedOops && node.isCompressible()) {
-            // make 64-bit scratch variables for expected and new
-            Variable scratchExpected64 = newVariable(Kind.Long);
-            Variable scratchNewValue64 = newVariable(Kind.Long);
-            // make 32-bit scratch variables for expected and new and result
-            Variable scratchExpected32 = newVariable(Kind.Int);
-            Variable scratchNewValue32 = newVariable(Kind.Int);
-            Variable scratchCasResult32 = newVariable(Kind.Int);
-            append(new CompareAndSwapCompressedOp(casResult, addressValue, expected, newValue, scratchExpected64, scratchNewValue64, scratchExpected32, scratchNewValue32, scratchCasResult32,
-                            getNarrowOopBase(), getNarrowOopShift(), getLogMinObjectAlignment()));
-        } else {
-            append(new CompareAndSwapOp(casResult, addressValue, expected, newValue));
-        }
-        Variable nodeResult = newVariable(node.getKind());
-        append(new CondMoveOp(mapKindToCompareOp(kind), casResult, expected, nodeResult, Condition.EQ, Constant.INT_1, Constant.INT_0));
-        setResult(node, nodeResult);
-    }
-
     /**
      * Returns whether or not the input access should be (de)compressed.
      */
@@ -391,19 +174,10 @@
      */
     private void emitDeoptimizeInner(Value actionAndReason, LIRFrameState lirFrameState, String emitName) {
         DeoptimizeOp deopt = new DeoptimizeOp(actionAndReason, lirFrameState, emitName, getMetaAccess());
-        deopts.add(deopt);
+        ((HSAILHotSpotLIRGenerationResult) res).addDeopt(deopt);
         append(deopt);
     }
 
-    @Override
-    protected void emitNode(ValueNode node) {
-        if (node instanceof CurrentJavaThreadNode) {
-            throw new GraalInternalError("HSAILHotSpotLIRGenerator cannot handle node: " + node);
-        } else {
-            super.emitNode(node);
-        }
-    }
-
     /***
      * This is a very temporary solution to emitForeignCall. We don't really support foreign calls
      * yet, but we do want to generate dummy code for them. The ForeignCallXXXOps just end up
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRGenerator.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2013, 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.hotspot.hsail;
+
+import sun.misc.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.hsail.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
+import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.hsail.*;
+import com.oracle.graal.lir.hsail.HSAILControlFlow.CondMoveOp;
+import com.oracle.graal.lir.hsail.HSAILMove.CompareAndSwapCompressedOp;
+import com.oracle.graal.lir.hsail.HSAILMove.CompareAndSwapOp;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.java.*;
+
+/**
+ * The HotSpot specific portion of the HSAIL LIR generator.
+ */
+public class HSAILHotSpotNodeLIRGenerator extends HSAILNodeLIRGenerator {
+
+    public HSAILHotSpotNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult lirGenRes, LIRGenerator lirGen) {
+        super(graph, lirGenRes, lirGen);
+    }
+
+    private HSAILHotSpotLIRGenerator getGen() {
+        return (HSAILHotSpotLIRGenerator) gen;
+    }
+
+    /**
+     * Appends either a {@link CompareAndSwapOp} or a {@link CompareAndSwapCompressedOp} depending
+     * on whether the memory location of a given {@link LoweredCompareAndSwapNode} contains a
+     * compressed oop. For the {@link CompareAndSwapCompressedOp} case, allocates a number of
+     * scratch registers. The result {@link #operand(ValueNode) operand} for {@code node} complies
+     * with the API for {@link Unsafe#compareAndSwapInt(Object, long, int, int)}.
+     *
+     * @param address the memory location targeted by the operation
+     */
+    @Override
+    public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) {
+        Kind kind = node.getNewValue().getKind();
+        assert kind == node.getExpectedValue().getKind();
+        Variable expected = gen.load(operand(node.getExpectedValue()));
+        Variable newValue = gen.load(operand(node.getNewValue()));
+        HSAILAddressValue addressValue = getGen().asAddressValue(address);
+        Variable casResult = newVariable(kind);
+        if (getGen().config.useCompressedOops && node.isCompressible()) {
+            // make 64-bit scratch variables for expected and new
+            Variable scratchExpected64 = newVariable(Kind.Long);
+            Variable scratchNewValue64 = newVariable(Kind.Long);
+            // make 32-bit scratch variables for expected and new and result
+            Variable scratchExpected32 = newVariable(Kind.Int);
+            Variable scratchNewValue32 = newVariable(Kind.Int);
+            Variable scratchCasResult32 = newVariable(Kind.Int);
+            append(new CompareAndSwapCompressedOp(casResult, addressValue, expected, newValue, scratchExpected64, scratchNewValue64, scratchExpected32, scratchNewValue32, scratchCasResult32,
+                            getGen().getNarrowOopBase(), getGen().getNarrowOopShift(), getGen().getLogMinObjectAlignment()));
+        } else {
+            append(new CompareAndSwapOp(casResult, addressValue, expected, newValue));
+        }
+        Variable nodeResult = newVariable(node.getKind());
+        append(new CondMoveOp(HSAILLIRGenerator.mapKindToCompareOp(kind), casResult, expected, nodeResult, Condition.EQ, Constant.INT_1, Constant.INT_0));
+        setResult(node, nodeResult);
+    }
+
+    @Override
+    protected void emitNode(ValueNode node) {
+        if (node instanceof CurrentJavaThreadNode) {
+            throw new GraalInternalError("HSAILHotSpotLIRGenerator cannot handle node: " + node);
+        } else {
+            super.emitNode(node);
+        }
+    }
+
+    /**
+     * @return a compressed version of the incoming constant lifted from AMD64HotSpotLIRGenerator
+     */
+    protected static Constant compress(Constant c, CompressEncoding encoding) {
+        if (c.getKind() == Kind.Long) {
+            return Constant.forIntegerKind(Kind.Int, (int) (((c.asLong() - encoding.base) >> encoding.shift) & 0xffffffffL), c.getPrimitiveAnnotation());
+        } else {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+}
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Thu Mar 27 17:31:20 2014 +0100
@@ -328,13 +328,13 @@
     }
 
     @Override
-    public CompilationResultBuilder newCompilationResultBuilder(LIRGenerator lirGen, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
+    public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRes, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
         // Omit the frame of the method:
         // - has no spill slots or other slots allocated during register allocation
         // - has no callee-saved registers
         // - has no incoming arguments passed on the stack
         // - has no instructions with debug info
-        FrameMap frameMap = lirGen.frameMap;
+        FrameMap frameMap = lirGenRes.getFrameMap();
         Assembler masm = createAssembler(frameMap);
         PTXFrameContext frameContext = new PTXFrameContext();
         CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult);
@@ -343,13 +343,23 @@
     }
 
     @Override
+    public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) {
+        return new LIRGenerationResultBase(lir, frameMap);
+    }
+
+    @Override
     protected Assembler createAssembler(FrameMap frameMap) {
         return new PTXMacroAssembler(getTarget(), frameMap.registerConfig);
     }
 
     @Override
-    public LIRGenerator newLIRGenerator(StructuredGraph graph, Object stub, FrameMap frameMap, CallingConvention cc, LIR lir) {
-        return new PTXHotSpotLIRGenerator(graph, getProviders(), getRuntime().getConfig(), frameMap, cc, lir);
+    public LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) {
+        return new PTXHotSpotLIRGenerator(getProviders(), getRuntime().getConfig(), cc, lirGenRes);
+    }
+
+    @Override
+    public NodeLIRGenerator newNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult lirGenRes, LIRGenerator lirGen) {
+        return new PTXHotSpotNodeLIRGenerator(graph, lirGenRes, lirGen);
     }
 
     private static void emitKernelEntry(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod codeCacheOwner) {
@@ -368,14 +378,14 @@
         asm.emitString("");
 
         // Get the start block
-        Block startBlock = lir.getControlFlowGraph().getStartBlock();
+        AbstractBlock<?> startBlock = lir.getControlFlowGraph().getStartBlock();
         // Keep a list of ParameterOp instructions to delete from the
         // list of instructions in the block.
         ArrayList<LIRInstruction> deleteOps = new ArrayList<>();
 
         // Emit .param arguments to kernel entry based on ParameterOp
         // instruction.
-        for (LIRInstruction op : lir.lir(startBlock)) {
+        for (LIRInstruction op : lir.getLIRforBlock(startBlock)) {
             if (op instanceof PTXParameterOp) {
                 op.emitCode(crb);
                 deleteOps.add(op);
@@ -384,7 +394,7 @@
 
         // Delete ParameterOp instructions.
         for (LIRInstruction op : deleteOps) {
-            lir.lir(startBlock).remove(op);
+            lir.getLIRforBlock(startBlock).remove(op);
         }
 
         // Start emiting body of the PTX kernel.
@@ -399,8 +409,8 @@
 
         RegisterAnalysis registerAnalysis = new RegisterAnalysis();
 
-        for (Block b : lir.codeEmittingOrder()) {
-            for (LIRInstruction op : lir.lir(b)) {
+        for (AbstractBlock<?> b : lir.codeEmittingOrder()) {
+            for (LIRInstruction op : lir.getLIRforBlock(b)) {
                 if (op instanceof LabelOp) {
                     // Don't consider this as a definition
                 } else {
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLIRGenerator.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLIRGenerator.java	Thu Mar 27 17:31:20 2014 +0100
@@ -23,36 +23,24 @@
 
 package com.oracle.graal.hotspot.ptx;
 
-import com.oracle.graal.api.code.CallingConvention;
-import com.oracle.graal.api.code.StackSlot;
-import com.oracle.graal.api.meta.DeoptimizationAction;
-import com.oracle.graal.api.meta.DeoptimizationReason;
-import com.oracle.graal.api.meta.Value;
-import com.oracle.graal.compiler.ptx.PTXLIRGenerator;
-import com.oracle.graal.graph.GraalInternalError;
-import com.oracle.graal.hotspot.HotSpotLIRGenerator;
-import com.oracle.graal.hotspot.HotSpotVMConfig;
-import com.oracle.graal.hotspot.meta.HotSpotProviders;
-import com.oracle.graal.hotspot.nodes.DirectCompareAndSwapNode;
-import com.oracle.graal.lir.FrameMap;
-import com.oracle.graal.lir.LIR;
-import com.oracle.graal.nodes.StructuredGraph;
-import com.oracle.graal.nodes.ValueNode;
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.ptx.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
 
 /**
  * LIR generator specialized for PTX HotSpot.
  */
 public class PTXHotSpotLIRGenerator extends PTXLIRGenerator implements HotSpotLIRGenerator {
 
-    protected PTXHotSpotLIRGenerator(StructuredGraph graph, HotSpotProviders providers, HotSpotVMConfig config, FrameMap frameMap, CallingConvention cc, LIR lir) {
-        super(graph, providers, frameMap, cc, lir);
+    protected PTXHotSpotLIRGenerator(HotSpotProviders providers, HotSpotVMConfig config, CallingConvention cc, LIRGenerationResult lirGenRes) {
+        super(providers, cc, lirGenRes);
         assert config.basicLockSize == 8;
     }
 
-    public void emitPrefetchAllocate(ValueNode address, ValueNode distance) {
-        // nop
-    }
-
     public void emitTailcall(Value[] args, Value address) {
         throw GraalInternalError.unimplemented();
     }
@@ -61,18 +49,6 @@
         throw GraalInternalError.unimplemented();
     }
 
-    public void emitPatchReturnAddress(ValueNode address) {
-        throw GraalInternalError.unimplemented();
-    }
-
-    public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) {
-        throw GraalInternalError.unimplemented();
-    }
-
-    public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) {
-        throw GraalInternalError.unimplemented();
-    }
-
     public StackSlot getLockSlot(int lockDepth) {
         throw GraalInternalError.unimplemented();
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotNodeLIRGenerator.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,58 @@
+/*
+ * 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.hotspot.ptx;
+
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.ptx.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * LIR generator specialized for PTX HotSpot.
+ */
+public class PTXHotSpotNodeLIRGenerator extends PTXNodeLIRGenerator implements HotSpotNodeLIRGenerator {
+
+    protected PTXHotSpotNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult lirGenRes, LIRGenerator lirGen) {
+        super(graph, lirGenRes, lirGen);
+    }
+
+    public void emitPrefetchAllocate(ValueNode address, ValueNode distance) {
+        // nop
+    }
+
+    public void emitPatchReturnAddress(ValueNode address) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) {
+        throw GraalInternalError.unimplemented();
+    }
+
+}
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Thu Mar 27 17:31:20 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.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Thu Mar 27 17:31:20 2014 +0100
@@ -22,6 +22,12 @@
  */
 package com.oracle.graal.hotspot.sparc;
 
+import static com.oracle.graal.api.code.CallingConvention.Type.*;
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.sparc.SPARC.*;
+import static java.lang.reflect.Modifier.*;
+
 import java.util.*;
 
 import sun.misc.*;
@@ -30,26 +36,27 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.asm.sparc.SPARCAssembler.*;
-import com.oracle.graal.compiler.gen.LIRGenerator;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Bpne;
+import com.oracle.graal.asm.sparc.SPARCAssembler.CC;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Ldx;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Save;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Stx;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Cmp;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Nop;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.RestoreWindow;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
+import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId;
-import com.oracle.graal.hotspot.stubs.Stub;
+import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.nodes.*;
 
-import static com.oracle.graal.sparc.SPARC.*;
-import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
-import static com.oracle.graal.api.code.CallingConvention.Type.*;
-import static com.oracle.graal.api.code.ValueUtil.*;
-import static com.oracle.graal.phases.GraalOptions.*;
-import static java.lang.reflect.Modifier.*;
-
 /**
  * HotSpot SPARC specific backend.
  */
@@ -72,8 +79,13 @@
     }
 
     @Override
-    public LIRGenerator newLIRGenerator(StructuredGraph graph, Object stub, FrameMap frameMap, CallingConvention cc, LIR lir) {
-        return new SPARCHotSpotLIRGenerator(graph, stub, getProviders(), getRuntime().getConfig(), frameMap, cc, lir);
+    public LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) {
+        return new SPARCHotSpotLIRGenerator(getProviders(), getRuntime().getConfig(), cc, lirGenRes);
+    }
+
+    @Override
+    public NodeLIRGenerator newNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult lirGenRes, LIRGenerator lirGen) {
+        return new SPARCHotSpotNodeLIRGenerator(graph, lirGenRes, lirGen);
     }
 
     /**
@@ -152,10 +164,10 @@
     }
 
     @Override
-    public CompilationResultBuilder newCompilationResultBuilder(LIRGenerator lirGen, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
-        SPARCHotSpotLIRGenerator gen = (SPARCHotSpotLIRGenerator) lirGen;
-        FrameMap frameMap = gen.frameMap;
-        assert gen.deoptimizationRescueSlot == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame";
+    public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRes, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
+        SPARCHotSpotLIRGenerationResult gen = (SPARCHotSpotLIRGenerationResult) lirGenRes;
+        FrameMap frameMap = gen.getFrameMap();
+        assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame";
 
         Stub stub = gen.getStub();
         Assembler masm = createAssembler(frameMap);
@@ -163,7 +175,7 @@
         HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null);
         CompilationResultBuilder crb = factory.createBuilder(getProviders().getCodeCache(), getProviders().getForeignCalls(), frameMap, masm, frameContext, compilationResult);
         crb.setFrameSize(frameMap.frameSize());
-        StackSlot deoptimizationRescueSlot = gen.deoptimizationRescueSlot;
+        StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot();
         if (deoptimizationRescueSlot != null && stub == null) {
             crb.compilationResult.setCustomStackAreaOffset(frameMap.offsetForStackSlot(deoptimizationRescueSlot));
         }
@@ -179,6 +191,11 @@
     }
 
     @Override
+    public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) {
+        return new LIRGenerationResultBase(lir, frameMap);
+    }
+
+    @Override
     public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner) {
         SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm;
         FrameMap frameMap = crb.frameMap;
@@ -233,4 +250,5 @@
     public NativeFunctionInterface getNativeFunctionInterface() {
         throw GraalInternalError.unimplemented("No NativeFunctionInterface of SPARC");
     }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerationResult.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,35 @@
+/*
+ * 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.hotspot.sparc;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.hotspot.stubs.*;
+
+public interface SPARCHotSpotLIRGenerationResult extends LIRGenerationResult {
+
+    StackSlot getDeoptimizationRescueSlot();
+
+    Stub getStub();
+
+}
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Thu Mar 27 17:31:20 2014 +0100
@@ -23,11 +23,7 @@
 package com.oracle.graal.hotspot.sparc;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
-import static com.oracle.graal.hotspot.HotSpotBackend.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-import static com.oracle.graal.sparc.SPARC.*;
-
-import java.lang.reflect.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
@@ -36,27 +32,22 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.sparc.*;
-import com.oracle.graal.lir.sparc.SPARCMove.CompareAndSwapOp;
 import com.oracle.graal.lir.sparc.SPARCMove.LoadOp;
 import com.oracle.graal.lir.sparc.SPARCMove.StoreConstantOp;
 import com.oracle.graal.lir.sparc.SPARCMove.StoreOp;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 
 public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSpotLIRGenerator {
 
-    private final HotSpotVMConfig config;
-    private final Object stub;
+    final HotSpotVMConfig config;
 
-    public SPARCHotSpotLIRGenerator(StructuredGraph graph, Object stub, HotSpotProviders providers, HotSpotVMConfig config, FrameMap frameMap, CallingConvention cc, LIR lir) {
-        super(graph, providers, frameMap, cc, lir);
+    public SPARCHotSpotLIRGenerator(HotSpotProviders providers, HotSpotVMConfig config, CallingConvention cc, LIRGenerationResult lirGenRes) {
+        super(providers, cc, lirGenRes);
         this.config = config;
-        this.stub = stub;
     }
 
     @Override
@@ -69,28 +60,21 @@
      * deoptimization. The return address slot in the callee is overwritten with the address of a
      * deoptimization stub.
      */
-    StackSlot deoptimizationRescueSlot;
-
-    @SuppressWarnings("hiding")
-    @Override
-    protected DebugInfoBuilder createDebugInfoBuilder(NodeMap<Value> nodeOperands) {
-        HotSpotLockStack lockStack = new HotSpotLockStack(frameMap, Kind.Long);
-        return new HotSpotDebugInfoBuilder(nodeOperands, lockStack);
-    }
+    private StackSlot deoptimizationRescueSlot;
 
     @Override
     public StackSlot getLockSlot(int lockDepth) {
-        return ((HotSpotDebugInfoBuilder) debugInfoBuilder).lockStack().makeLockSlot(lockDepth);
+        return ((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack().makeLockSlot(lockDepth);
     }
 
     @Override
     protected boolean needOnlyOopMaps() {
         // Stubs only need oop maps
-        return stub != null;
+        return getStub() != null;
     }
 
-    Stub getStub() {
-        return (Stub) stub;
+    public Stub getStub() {
+        return ((SPARCHotSpotLIRGenerationResult) res).getStub();
     }
 
     @Override
@@ -113,74 +97,17 @@
     }
 
     @Override
-    protected void emitReturn(Value input) {
+    public void emitReturn(Value input) {
         append(new SPARCHotSpotReturnOp(input, getStub() != null));
     }
 
     @Override
-    public void visitSafepointNode(SafepointNode i) {
-        LIRFrameState info = state(i);
-        append(new SPARCHotSpotSafepointOp(info, config, this));
-    }
-
-    @Override
-    public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) {
-        Kind kind = x.newValue().getKind();
-        assert kind == x.expectedValue().getKind();
-
-        Variable address = load(operand(x.object()));
-        Value offset = operand(x.offset());
-        Variable cmpValue = (Variable) loadNonConst(operand(x.expectedValue()));
-        Variable newValue = load(operand(x.newValue()));
-
-        if (ValueUtil.isConstant(offset)) {
-            assert !getCodeCache().needsDataPatch(asConstant(offset));
-            Variable longAddress = newVariable(Kind.Long);
-            emitMove(longAddress, address);
-            address = emitAdd(longAddress, asConstant(offset));
-        } else {
-            if (isLegal(offset)) {
-                address = emitAdd(address, offset);
-            }
-        }
-
-        append(new CompareAndSwapOp(address, cmpValue, newValue));
-
-        Variable result = newVariable(x.getKind());
-        emitMove(result, newValue);
-        setResult(x, result);
-    }
-
-    @Override
     public void emitTailcall(Value[] args, Value address) {
         // append(new AMD64TailcallOp(args, address));
         throw GraalInternalError.unimplemented();
     }
 
     @Override
-    protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind();
-        if (invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual) {
-            append(new SPARCHotspotDirectVirtualCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind));
-        } else {
-            assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special;
-            HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target();
-            assert !Modifier.isAbstract(resolvedMethod.getModifiers()) : "Cannot make direct call to abstract method.";
-            Constant metaspaceMethod = resolvedMethod.getMetaspaceMethodConstant();
-            append(new SPARCHotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind, metaspaceMethod));
-        }
-    }
-
-    @Override
-    protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        AllocatableValue metaspaceMethod = g5.asValue();
-        emitMove(metaspaceMethod, operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod()));
-        AllocatableValue targetAddress = g3.asValue();
-        emitMove(targetAddress, operand(callTarget.computedAddress()));
-        append(new SPARCIndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod, targetAddress, callState));
-    }
-
-    @Override
     public void emitUnwind(Value exception) {
         ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(HotSpotBackend.UNWIND_EXCEPTION_TO_CALLER);
         CallingConvention linkageCc = linkage.getOutgoingCallingConvention();
@@ -214,26 +141,6 @@
         append(new SPARCHotSpotDeoptimizeCallerOp());
     }
 
-    @Override
-    public void emitPatchReturnAddress(ValueNode address) {
-        append(new SPARCHotSpotPatchReturnAddressOp(load(operand(address))));
-    }
-
-    @Override
-    public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) {
-        Variable handler = load(operand(handlerInCallerPc));
-        ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(EXCEPTION_HANDLER_IN_CALLER);
-        CallingConvention linkageCc = linkage.getOutgoingCallingConvention();
-        assert linkageCc.getArgumentCount() == 2;
-        RegisterValue exceptionFixed = (RegisterValue) linkageCc.getArgument(0);
-        RegisterValue exceptionPcFixed = (RegisterValue) linkageCc.getArgument(1);
-        emitMove(exceptionFixed, operand(exception));
-        emitMove(exceptionPcFixed, operand(exceptionPc));
-        Register thread = getProviders().getRegisters().getThreadRegister();
-        SPARCHotSpotJumpToExceptionHandlerInCallerOp op = new SPARCHotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed, config.threadIsMethodHandleReturnOffset, thread);
-        append(op);
-    }
-
     private static boolean isCompressCandidate(Access access) {
         return access != null && access.isCompressible();
     }
@@ -321,8 +228,7 @@
         return null;
     }
 
-    public void emitPrefetchAllocate(ValueNode address, ValueNode distance) {
-        SPARCAddressValue addr = emitAddress(operand(address), 0, loadNonConst(operand(distance)), 1);
-        append(new SPARCPrefetchOp(addr, config.allocatePrefetchInstr));
+    public StackSlot getDeoptimizationRescueSlot() {
+        return deoptimizationRescueSlot;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRGenerator.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2013, 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.hotspot.sparc;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.hotspot.HotSpotBackend.*;
+import static com.oracle.graal.sparc.SPARC.*;
+
+import java.lang.reflect.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.sparc.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.sparc.*;
+import com.oracle.graal.lir.sparc.SPARCMove.CompareAndSwapOp;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
+
+public class SPARCHotSpotNodeLIRGenerator extends SPARCNodeLIRGenerator implements HotSpotNodeLIRGenerator {
+
+    public SPARCHotSpotNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult lirGenRes, LIRGenerator lirGen) {
+        super(graph, lirGenRes, lirGen);
+    }
+
+    @Override
+    protected DebugInfoBuilder createDebugInfoBuilder(NodeMap<Value> nodeOperands) {
+        HotSpotLockStack lockStack = new HotSpotLockStack(res.getFrameMap(), Kind.Long);
+        return new HotSpotDebugInfoBuilder(nodeOperands, lockStack);
+    }
+
+    private SPARCHotSpotLIRGenerator getGen() {
+        return (SPARCHotSpotLIRGenerator) gen;
+    }
+
+    @Override
+    public void visitSafepointNode(SafepointNode i) {
+        LIRFrameState info = gen.state(i);
+        append(new SPARCHotSpotSafepointOp(info, getGen().config, gen));
+    }
+
+    @Override
+    public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) {
+        Kind kind = x.newValue().getKind();
+        assert kind == x.expectedValue().getKind();
+
+        Variable address = gen.load(operand(x.object()));
+        Value offset = operand(x.offset());
+        Variable cmpValue = (Variable) gen.loadNonConst(operand(x.expectedValue()));
+        Variable newValue = gen.load(operand(x.newValue()));
+
+        if (ValueUtil.isConstant(offset)) {
+            assert !gen.getCodeCache().needsDataPatch(asConstant(offset));
+            Variable longAddress = newVariable(Kind.Long);
+            gen.emitMove(longAddress, address);
+            address = getGen().emitAdd(longAddress, asConstant(offset));
+        } else {
+            if (isLegal(offset)) {
+                address = getGen().emitAdd(address, offset);
+            }
+        }
+
+        append(new CompareAndSwapOp(address, cmpValue, newValue));
+
+        Variable result = newVariable(x.getKind());
+        gen.emitMove(result, newValue);
+        setResult(x, result);
+    }
+
+    @Override
+    protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
+        InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind();
+        if (invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual) {
+            append(new SPARCHotspotDirectVirtualCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind));
+        } else {
+            assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special;
+            HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target();
+            assert !Modifier.isAbstract(resolvedMethod.getModifiers()) : "Cannot make direct call to abstract method.";
+            Constant metaspaceMethod = resolvedMethod.getMetaspaceMethodConstant();
+            append(new SPARCHotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind, metaspaceMethod));
+        }
+    }
+
+    @Override
+    protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
+        AllocatableValue metaspaceMethod = g5.asValue();
+        gen.emitMove(metaspaceMethod, operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod()));
+        AllocatableValue targetAddress = g3.asValue();
+        gen.emitMove(targetAddress, operand(callTarget.computedAddress()));
+        append(new SPARCIndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod, targetAddress, callState));
+    }
+
+    @Override
+    public void emitPatchReturnAddress(ValueNode address) {
+        append(new SPARCHotSpotPatchReturnAddressOp(gen.load(operand(address))));
+    }
+
+    @Override
+    public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) {
+        Variable handler = gen.load(operand(handlerInCallerPc));
+        ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(EXCEPTION_HANDLER_IN_CALLER);
+        CallingConvention linkageCc = linkage.getOutgoingCallingConvention();
+        assert linkageCc.getArgumentCount() == 2;
+        RegisterValue exceptionFixed = (RegisterValue) linkageCc.getArgument(0);
+        RegisterValue exceptionPcFixed = (RegisterValue) linkageCc.getArgument(1);
+        gen.emitMove(exceptionFixed, operand(exception));
+        gen.emitMove(exceptionPcFixed, operand(exceptionPc));
+        Register thread = getGen().getProviders().getRegisters().getThreadRegister();
+        SPARCHotSpotJumpToExceptionHandlerInCallerOp op = new SPARCHotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed, getGen().config.threadIsMethodHandleReturnOffset,
+                        thread);
+        append(op);
+    }
+
+    public void emitPrefetchAllocate(ValueNode address, ValueNode distance) {
+        SPARCAddressValue addr = getGen().emitAddress(operand(address), 0, getGen().loadNonConst(operand(distance)), 1);
+        append(new SPARCPrefetchOp(addr, getGen().config.allocatePrefetchInstr));
+    }
+
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Thu Mar 27 17:31:20 2014 +0100
@@ -40,6 +40,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.baseline.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
@@ -47,6 +48,7 @@
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.phases.*;
+import com.oracle.graal.java.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -251,34 +253,41 @@
             final long allocatedBytesBefore = threadMXBean.getThreadAllocatedBytes(threadId);
 
             try (Scope s = Debug.scope("Compiling", new DebugDumpScope(String.valueOf(id), true))) {
-                Map<ResolvedJavaMethod, StructuredGraph> graphCache = null;
-                if (GraalOptions.CacheGraphs.getValue()) {
-                    graphCache = new HashMap<>();
-                }
+
+                if (UseBaselineCompiler.getValue() == true) {
+                    HotSpotProviders providers = backend.getProviders();
+                    BaselineCompiler baselineCompiler = new BaselineCompiler(GraphBuilderConfiguration.getDefault(), providers.getMetaAccess());
+                    result = baselineCompiler.generate(method, -1, backend, new CompilationResult(), method, CompilationResultBuilderFactory.Default);
+                } else {
+                    Map<ResolvedJavaMethod, StructuredGraph> graphCache = null;
+                    if (GraalOptions.CacheGraphs.getValue()) {
+                        graphCache = new HashMap<>();
+                    }
 
-                HotSpotProviders providers = backend.getProviders();
-                Replacements replacements = providers.getReplacements();
-                graph = replacements.getMethodSubstitution(method);
-                if (graph == null || entryBCI != INVOCATION_ENTRY_BCI) {
-                    graph = new StructuredGraph(method, entryBCI);
-                } else {
-                    // Compiling method substitution - must clone the graph
-                    graph = graph.copy();
+                    HotSpotProviders providers = backend.getProviders();
+                    Replacements replacements = providers.getReplacements();
+                    graph = replacements.getMethodSubstitution(method);
+                    if (graph == null || entryBCI != INVOCATION_ENTRY_BCI) {
+                        graph = new StructuredGraph(method, entryBCI);
+                    } else {
+                        // Compiling method substitution - must clone the graph
+                        graph = graph.copy();
+                    }
+                    InlinedBytecodes.add(method.getCodeSize());
+                    CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false);
+                    if (graph.getEntryBCI() != StructuredGraph.INVOCATION_ENTRY_BCI) {
+                        // for OSR, only a pointer is passed to the method.
+                        JavaType[] parameterTypes = new JavaType[]{providers.getMetaAccess().lookupJavaType(long.class)};
+                        CallingConvention tmp = providers.getCodeCache().getRegisterConfig().getCallingConvention(JavaCallee, providers.getMetaAccess().lookupJavaType(void.class), parameterTypes,
+                                        backend.getTarget(), false);
+                        cc = new CallingConvention(cc.getStackSize(), cc.getReturn(), tmp.getArgument(0));
+                    }
+                    Suites suites = getSuites(providers);
+                    ProfilingInfo profilingInfo = getProfilingInfo();
+                    OptimisticOptimizations optimisticOpts = getOptimisticOpts(profilingInfo);
+                    result = compileGraph(graph, null, cc, method, providers, backend, backend.getTarget(), graphCache, getGraphBuilderSuite(providers), optimisticOpts, profilingInfo,
+                                    method.getSpeculationLog(), suites, new CompilationResult(), CompilationResultBuilderFactory.Default);
                 }
-                InlinedBytecodes.add(method.getCodeSize());
-                CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false);
-                if (graph.getEntryBCI() != StructuredGraph.INVOCATION_ENTRY_BCI) {
-                    // for OSR, only a pointer is passed to the method.
-                    JavaType[] parameterTypes = new JavaType[]{providers.getMetaAccess().lookupJavaType(long.class)};
-                    CallingConvention tmp = providers.getCodeCache().getRegisterConfig().getCallingConvention(JavaCallee, providers.getMetaAccess().lookupJavaType(void.class), parameterTypes,
-                                    backend.getTarget(), false);
-                    cc = new CallingConvention(cc.getStackSize(), cc.getReturn(), tmp.getArgument(0));
-                }
-                Suites suites = getSuites(providers);
-                ProfilingInfo profilingInfo = getProfilingInfo();
-                OptimisticOptimizations optimisticOpts = getOptimisticOpts(profilingInfo);
-                result = compileGraph(graph, null, cc, method, providers, backend, backend.getTarget(), graphCache, getGraphBuilderSuite(providers), optimisticOpts, profilingInfo,
-                                method.getSpeculationLog(), suites, new CompilationResult(), CompilationResultBuilderFactory.Default);
                 result.setId(getId());
                 result.setEntryBCI(entryBCI);
             } catch (Throwable e) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Thu Mar 27 17:31:20 2014 +0100
@@ -113,8 +113,8 @@
                 return value;
             }
         };
-        for (Block block : lir.codeEmittingOrder()) {
-            for (LIRInstruction op : lir.lir(block)) {
+        for (AbstractBlock<?> block : lir.codeEmittingOrder()) {
+            for (LIRInstruction op : lir.getLIRforBlock(block)) {
                 if (op instanceof LabelOp) {
                     // Don't consider this as a definition
                 } else {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java	Thu Mar 27 17:31:20 2014 +0100
@@ -26,13 +26,11 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.hotspot.nodes.*;
-import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
  * This interface defines the contract a HotSpot backend LIR generator needs to fulfill in addition
- * to abstract methods from {@link LIRGenerator} and {@link LIRGeneratorTool}.
+ * to abstract methods from {@link LIRGenerator} and {@link NodeLIRGeneratorTool}.
  */
 public interface HotSpotLIRGenerator {
 
@@ -46,14 +44,6 @@
 
     void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason);
 
-    void emitPatchReturnAddress(ValueNode address);
-
-    void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc);
-
-    void emitPrefetchAllocate(ValueNode address, ValueNode distance);
-
-    void visitDirectCompareAndSwap(DirectCompareAndSwapNode x);
-
     /**
      * Gets a stack slot for a lock at a given lock nesting depth.
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotNodeLIRGenerator.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,44 @@
+/*
+ * 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.hotspot;
+
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+
+/**
+ * This interface defines the contract a HotSpot backend LIR generator needs to fulfill in addition
+ * to abstract methods from {@link LIRGenerator} and {@link NodeLIRGeneratorTool}.
+ */
+public interface HotSpotNodeLIRGenerator {
+
+    void emitPatchReturnAddress(ValueNode address);
+
+    void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc);
+
+    void emitPrefetchAllocate(ValueNode address, ValueNode distance);
+
+    void visitDirectCompareAndSwap(DirectCompareAndSwapNode x);
+
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java	Thu Mar 27 17:31:20 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.getKind());
+                int size = HIRFrameStateBuilder.stackSlots(osrLocal.getKind());
                 int offset = localsOffset - (osrLocal.index() + size - 1) * 8;
                 IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, osrLocal.getKind(), 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 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java	Thu Mar 27 17:31:20 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/AllocaNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -30,13 +30,14 @@
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
 /**
  * Reserves a block of memory in the stack frame of a method. The block is reserved in the frame for
  * the entire execution of the associated method.
  */
-public final class AllocaNode extends FixedWithNextNode implements LIRGenLowerable {
+public final class AllocaNode extends FixedWithNextNode implements LIRGenResLowerable {
 
     /**
      * The number of slots in block.
@@ -57,9 +58,9 @@
     }
 
     @Override
-    public void generate(LIRGenerator gen) {
-        StackSlot array = gen.frameMap().allocateStackSlots(slots, objects, null);
-        Value result = gen.emitAddress(array);
+    public void generate(NodeLIRGeneratorTool gen, LIRGenerationResult res) {
+        StackSlot array = res.getFrameMap().allocateStackSlots(slots, objects, null);
+        Value result = gen.getLIRGeneratorTool().emitAddress(array);
         gen.setResult(this, result);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -57,11 +57,11 @@
     }
 
     @Override
-    public void generate(LIRGenerator gen) {
+    public void generate(NodeLIRGenerator gen) {
         assert lockDepth != -1;
-        HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen;
+        HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen.getLIRGeneratorTool();
         StackSlot slot = hsGen.getLockSlot(lockDepth);
-        Value result = gen.emitAddress(slot);
+        Value result = gen.getLIRGeneratorTool().emitAddress(slot);
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -41,13 +41,13 @@
         this.string = string;
     }
 
-    public void generate(LIRGenerator gen) {
+    public void generate(NodeLIRGenerator gen) {
         gen.setResult(this, emitCString(gen, string));
     }
 
-    public static AllocatableValue emitCString(LIRGeneratorTool gen, String value) {
-        AllocatableValue dst = gen.newVariable(gen.target().wordKind);
-        gen.emitData(dst, toCString(value));
+    public static AllocatableValue emitCString(NodeLIRGeneratorTool gen, String value) {
+        AllocatableValue dst = gen.getLIRGeneratorTool().newVariable(gen.getLIRGeneratorTool().target().wordKind);
+        gen.getLIRGeneratorTool().emitData(dst, toCString(value));
         return dst;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -41,8 +41,8 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
-        Register rawThread = ((HotSpotLIRGenerator) gen).getProviders().getRegisters().getThreadRegister();
+    public void generate(NodeLIRGeneratorTool gen) {
+        Register rawThread = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).getProviders().getRegisters().getThreadRegister();
         gen.setResult(this, rawThread.asValue(this.getKind()));
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -24,16 +24,15 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
 
 /**
  * Intrinsic for getting the lock in the current {@linkplain BeginLockScopeNode lock scope}.
  */
-public final class CurrentLockNode extends FixedWithNextNode implements LIRGenLowerable {
+public final class CurrentLockNode extends FixedWithNextNode implements LIRLowerable {
 
     private int lockDepth;
 
@@ -43,12 +42,12 @@
     }
 
     @Override
-    public void generate(LIRGenerator gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         assert lockDepth != -1;
-        HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen;
+        HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen.getLIRGeneratorTool();
         StackSlot slot = hsGen.getLockSlot(lockDepth);
         // The register allocator cannot handle stack -> register moves so we use an LEA here
-        Value result = gen.emitMove(gen.emitAddress(slot));
+        Value result = gen.getLIRGeneratorTool().emitMove(gen.getLIRGeneratorTool().emitAddress(slot));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -45,8 +45,8 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
-        ((HotSpotLIRGenerator) gen).emitDeoptimizeCaller(action, reason);
+    public void generate(NodeLIRGeneratorTool gen) {
+        ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitDeoptimizeCaller(action, reason);
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -31,13 +31,14 @@
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
 
 /**
  * Intrinsic for allocating an on-stack array of integers to hold the dimensions of a multianewarray
  * instruction.
  */
-public final class DimensionsNode extends FixedWithNextNode implements LIRGenLowerable {
+public final class DimensionsNode extends FixedWithNextNode implements LIRGenResLowerable {
 
     private final int rank;
 
@@ -47,12 +48,12 @@
     }
 
     @Override
-    public void generate(LIRGenerator gen) {
+    public void generate(NodeLIRGeneratorTool gen, LIRGenerationResult res) {
         int size = rank * 4;
-        int wordSize = gen.target().wordSize;
+        int wordSize = gen.getLIRGeneratorTool().target().wordSize;
         int slots = roundUp(size, wordSize) / wordSize;
-        StackSlot array = gen.frameMap().allocateStackSlots(slots, new BitSet(0), null);
-        Value result = gen.emitAddress(array);
+        StackSlot array = res.getFrameMap().allocateStackSlots(slots, new BitSet(0), null);
+        Value result = gen.getLIRGeneratorTool().emitAddress(array);
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -77,8 +77,8 @@
     }
 
     @Override
-    public void generate(LIRGenerator gen) {
-        ((HotSpotLIRGenerator) gen).visitDirectCompareAndSwap(this);
+    public void generate(NodeLIRGenerator gen) {
+        ((HotSpotNodeLIRGenerator) gen).visitDirectCompareAndSwap(this);
     }
 
     /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -23,17 +23,16 @@
 package com.oracle.graal.hotspot.nodes;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
 /**
  * Intrinsic for closing a {@linkplain BeginLockScopeNode scope} binding a stack-based lock with an
  * object.
  */
-public final class EndLockScopeNode extends AbstractMemoryCheckpoint implements LIRGenLowerable, MonitorExit, MemoryCheckpoint.Single {
+public final class EndLockScopeNode extends AbstractMemoryCheckpoint implements LIRLowerable, MonitorExit, MemoryCheckpoint.Single {
 
     public EndLockScopeNode() {
         super(StampFactory.forVoid());
@@ -50,7 +49,7 @@
     }
 
     @Override
-    public void generate(LIRGenerator gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -45,9 +45,9 @@
     public static native long get(Object array);
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
-        AllocatableValue obj = gen.newVariable(gen.target().wordKind);
-        gen.emitMove(obj, gen.operand(object));
+    public void generate(NodeLIRGeneratorTool gen) {
+        AllocatableValue obj = gen.getLIRGeneratorTool().newVariable(gen.getLIRGeneratorTool().target().wordKind);
+        gen.getLIRGeneratorTool().emitMove(obj, gen.operand(object));
         gen.setResult(this, obj);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -46,8 +46,8 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
-        ((HotSpotLIRGenerator) gen).emitJumpToExceptionHandlerInCaller(handlerInCallerPc, exception, exceptionPc);
+    public void generate(NodeLIRGeneratorTool gen) {
+        ((HotSpotNodeLIRGenerator) gen).emitJumpToExceptionHandlerInCaller(handlerInCallerPc, exception, exceptionPc);
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -29,22 +29,23 @@
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
 
 /**
  * Node that is used to maintain a stack based counter of how many locks are currently held.
  */
-public final class MonitorCounterNode extends FloatingNode implements LIRGenLowerable {
+public final class MonitorCounterNode extends FloatingNode implements LIRGenResLowerable {
 
     private MonitorCounterNode() {
         super(null);
     }
 
     @Override
-    public void generate(LIRGenerator gen) {
+    public void generate(NodeLIRGeneratorTool gen, LIRGenerationResult res) {
         assert graph().getNodes().filter(MonitorCounterNode.class).count() == 1 : "monitor counters not canonicalized to single instance";
-        StackSlot counter = gen.frameMap().allocateStackSlots(1, new BitSet(0), null);
-        Value result = gen.emitAddress(counter);
+        StackSlot counter = res.getFrameMap().allocateStackSlots(1, new BitSet(0), null);
+        Value result = gen.getLIRGeneratorTool().emitAddress(counter);
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java	Thu Mar 27 17:31:20 2014 +0100
@@ -47,12 +47,12 @@
     }
 
     @Override
-    public void generate(LIRGenerator gen) {
+    public void generate(NodeLIRGenerator gen) {
         assert lockDepth != -1;
-        HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen;
+        HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen.getLIRGeneratorTool();
         StackSlot slot = hsGen.getLockSlot(lockDepth);
-        ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(MonitorExitStubCall.MONITOREXIT);
-        gen.emitForeignCall(linkage, this, gen.operand(object), gen.emitAddress(slot));
+        ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(MonitorExitStubCall.MONITOREXIT);
+        gen.getLIRGeneratorTool().emitForeignCall(linkage, this, gen.operand(object), gen.getLIRGeneratorTool().emitAddress(slot));
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java	Thu Mar 27 17:31:20 2014 +0100
@@ -61,9 +61,9 @@
     }
 
     @Override
-    public void generate(LIRGenerator gen) {
-        ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(NEW_ARRAY);
-        Variable result = gen.emitForeignCall(linkage, this, gen.operand(hub), gen.operand(length));
+    public void generate(NodeLIRGenerator gen) {
+        ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(NEW_ARRAY);
+        Variable result = gen.getLIRGenerator().emitForeignCall(linkage, this, gen.operand(hub), gen.operand(length));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Thu Mar 27 17:31:20 2014 +0100
@@ -24,19 +24,17 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.stubs.*;
-import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.word.*;
 
 /**
  * A call to the {@link NewInstanceStub}.
  */
-public class NewInstanceStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
+public class NewInstanceStubCall extends DeoptimizingStubCall implements LIRLowerable {
 
     private static final Stamp defaultStamp = StampFactory.objectNonNull();
 
@@ -59,9 +57,9 @@
     }
 
     @Override
-    public void generate(LIRGenerator gen) {
-        ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(NEW_INSTANCE);
-        Variable result = gen.emitForeignCall(linkage, this, gen.operand(hub));
+    public void generate(NodeLIRGeneratorTool gen) {
+        ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(NEW_INSTANCE);
+        Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, this, gen.operand(hub));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java	Thu Mar 27 17:31:20 2014 +0100
@@ -61,7 +61,7 @@
     }
 
     @Override
-    protected Value[] operands(LIRGeneratorTool gen) {
+    protected Value[] operands(NodeLIRGeneratorTool gen) {
         return new Value[]{gen.operand(hub), Constant.forInt(rank), gen.operand(dims)};
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PatchReturnAddressNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PatchReturnAddressNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -41,8 +41,8 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
-        ((HotSpotLIRGenerator) gen).emitPatchReturnAddress(address);
+    public void generate(NodeLIRGeneratorTool gen) {
+        ((HotSpotNodeLIRGenerator) gen).emitPatchReturnAddress(address);
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -42,8 +42,8 @@
     }
 
     @Override
-    public void generate(LIRGenerator gen) {
-        ((HotSpotLIRGenerator) gen).emitPrefetchAllocate(address, distance);
+    public void generate(NodeLIRGenerator gen) {
+        ((HotSpotNodeLIRGenerator) gen).emitPrefetchAllocate(address, distance);
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -57,7 +57,7 @@
         return foreignCalls.getKilledLocations(descriptor);
     }
 
-    protected Value[] operands(LIRGeneratorTool gen) {
+    protected Value[] operands(NodeLIRGeneratorTool gen) {
         Value[] operands = new Value[arguments.size()];
         for (int i = 0; i < operands.length; i++) {
             operands[i] = gen.operand(arguments.get(i));
@@ -66,11 +66,11 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         assert graph().start() instanceof StubStartNode;
-        ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(descriptor);
+        ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(descriptor);
         Value[] operands = operands(gen);
-        Value result = gen.emitForeignCall(linkage, null, operands);
+        Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, null, operands);
         if (result != null) {
             gen.setResult(this, result);
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -30,6 +30,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
@@ -40,7 +41,7 @@
  * Performs a tail call to the specified target compiled method, with the parameter taken from the
  * supplied FrameState.
  */
-public class TailcallNode extends FixedWithNextNode implements LIRLowerable {
+public class TailcallNode extends FixedWithNextNode implements LIRGenResLowerable {
 
     @Input private FrameState frameState;
     @Input private ValueNode target;
@@ -57,22 +58,20 @@
         this.frameState = frameState;
     }
 
-    @Override
-    public void generate(LIRGeneratorTool generator) {
-        LIRGenerator gen = (LIRGenerator) generator;
+    public void generate(NodeLIRGeneratorTool gen, LIRGenerationResult res) {
         HotSpotVMConfig config = runtime().getConfig();
         ResolvedJavaMethod method = frameState.method();
         boolean isStatic = Modifier.isStatic(method.getModifiers());
 
         JavaType[] signature = MetaUtil.signatureToTypes(method.getSignature(), isStatic ? null : method.getDeclaringClass());
-        CallingConvention cc = gen.frameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, signature, gen.target(), false);
+        CallingConvention cc = res.getFrameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, signature, gen.getLIRGeneratorTool().target(), false);
         List<ValueNode> parameters = new ArrayList<>();
-        for (int i = 0, slot = 0; i < cc.getArgumentCount(); i++, slot += FrameStateBuilder.stackSlots(frameState.localAt(slot).getKind())) {
+        for (int i = 0, slot = 0; i < cc.getArgumentCount(); i++, slot += HIRFrameStateBuilder.stackSlots(frameState.localAt(slot).getKind())) {
             parameters.add(frameState.localAt(slot));
         }
         Value[] args = gen.visitInvokeArguments(cc, parameters);
-        Value address = gen.emitAddress(gen.operand(target), config.nmethodEntryOffset, Value.ILLEGAL, 0);
-        Value entry = gen.emitLoad(Kind.Long, address, null);
+        Value address = gen.getLIRGeneratorTool().emitAddress(gen.operand(target), config.nmethodEntryOffset, Value.ILLEGAL, 0);
+        Value entry = gen.getLIRGeneratorTool().emitLoad(Kind.Long, address, null);
         HotSpotLIRGenerator hsgen = (HotSpotLIRGenerator) gen;
         hsgen.emitTailcall(args, entry);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -27,9 +27,8 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.replacements.*;
 
@@ -37,11 +36,11 @@
  * Causes the VM to exit with a description of the current Java location and an optional
  * {@linkplain Log#printf(String, long) formatted} error message specified.
  */
-public final class VMErrorNode extends DeoptimizingStubCall implements LIRGenLowerable {
+public final class VMErrorNode extends DeoptimizingStubCall implements LIRLowerable {
 
     private final String format;
     @Input private ValueNode value;
-    public static final ForeignCallDescriptor VM_ERROR = new ForeignCallDescriptor("vm_error", void.class, long.class, long.class, long.class);
+    public static final ForeignCallDescriptor VM_ERROR = new ForeignCallDescriptor("vm_error", void.class, Object.class, Object.class, long.class);
 
     public VMErrorNode(String format, ValueNode value) {
         super(StampFactory.forVoid());
@@ -50,7 +49,7 @@
     }
 
     @Override
-    public void generate(LIRGenerator gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         String whereString;
         if (stateBefore() != null) {
             String nl = CodeUtil.NEW_LINE;
@@ -68,8 +67,8 @@
         Value whereArg = emitCString(gen, whereString);
         Value formatArg = emitCString(gen, format);
 
-        ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(VMErrorNode.VM_ERROR);
-        gen.emitForeignCall(linkage, null, whereArg, formatArg, gen.operand(value));
+        ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(VMErrorNode.VM_ERROR);
+        gen.getLIRGeneratorTool().emitForeignCall(linkage, null, whereArg, formatArg, gen.operand(value));
     }
 
     @NodeIntrinsic
--- /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 27 17:31:20 2014 +0100
@@ -0,0 +1,227 @@
+/*
+ * 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.java;
+
+import com.oracle.graal.api.meta.*;
+
+public abstract class AbstractFrameStateBuilder<T extends KindInterface> {
+
+    protected final ResolvedJavaMethod method;
+    protected int stackSize;
+
+    public AbstractFrameStateBuilder(ResolvedJavaMethod method) {
+        this.method = method;
+    }
+
+    protected AbstractFrameStateBuilder(AbstractFrameStateBuilder other) {
+        this.method = other.method;
+    }
+
+    /**
+     * 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 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);
+
+    public static int stackSlots(Kind kind) {
+        return isTwoSlot(kind) ? 2 : 1;
+    }
+
+    /**
+     * Clears all values on this stack.
+     */
+    public void clearStack() {
+        stackSize = 0;
+    }
+
+    protected static boolean isTwoSlot(Kind kind) {
+        assert kind != Kind.Void && kind != Kind.Illegal;
+        return kind == Kind.Long || kind == Kind.Double;
+    }
+
+}
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Thu Mar 27 17:31:20 2014 +0100
@@ -33,6 +33,7 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.*;
 
 /**
  * Builds a mapping between bytecodes and basic blocks and builds a conservative control flow graph
@@ -73,33 +74,40 @@
  */
 public final class BciBlockMapping {
 
-    public static class Block implements Cloneable {
+    public static class BciBlock extends AbstractBlockBase<BciBlock> implements Cloneable {
 
         public int startBci;
         public int endBci;
         public boolean isExceptionEntry;
         public boolean isLoopHeader;
         public int loopId;
-        public int blockID;
 
         public FixedWithNextNode firstInstruction;
-        public FrameStateBuilder entryState;
+        public HIRFrameStateBuilder entryState;
 
-        public ArrayList<Block> successors = new ArrayList<>(2);
+        // public ArrayList<BciBlock> successors = new ArrayList<>(2);
+        // public ArrayList<BciBlock> predecessors = new ArrayList<>(2); // only used in the
+// baseline
+
         public long exits;
 
         private boolean visited;
         private boolean active;
         public long loops;
 
-        public HashMap<JsrScope, Block> jsrAlternatives;
+        public HashMap<JsrScope, BciBlock> jsrAlternatives;
         public JsrScope jsrScope = JsrScope.EMPTY_SCOPE;
-        public Block jsrSuccessor;
+        public BciBlock jsrSuccessor;
         public int jsrReturnBci;
-        public Block retSuccessor;
+        public BciBlock retSuccessor;
         public boolean endsWithRet = false;
 
-        public Block exceptionDispatchBlock() {
+        public BciBlock() {
+            this.successors = new ArrayList<>();
+            this.predecessors = new ArrayList<>();
+        }
+
+        public BciBlock exceptionDispatchBlock() {
             if (successors.size() > 0 && successors.get(successors.size() - 1) instanceof ExceptionDispatchBlock) {
                 return successors.get(successors.size() - 1);
             }
@@ -113,9 +121,9 @@
             return successors.size();
         }
 
-        public Block copy() {
+        public BciBlock copy() {
             try {
-                Block block = (Block) super.clone();
+                BciBlock block = (BciBlock) super.clone();
                 block.successors = new ArrayList<>(successors);
                 return block;
             } catch (CloneNotSupportedException e) {
@@ -125,7 +133,7 @@
 
         @Override
         public String toString() {
-            StringBuilder sb = new StringBuilder("B").append(blockID);
+            StringBuilder sb = new StringBuilder("B").append(getId());
             sb.append('[').append(startBci).append("->").append(endBci);
             if (isLoopHeader || isExceptionEntry) {
                 sb.append(' ');
@@ -139,9 +147,41 @@
             sb.append(']');
             return sb.toString();
         }
+
+        public Loop getLoop() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        public int getLoopDepth() {
+            // TODO Auto-generated method stub
+            return 0;
+        }
+
+        public boolean isLoopHeader() {
+            return isLoopHeader;
+        }
+
+        public boolean isLoopEnd() {
+            // TODO Auto-generated method stub
+            return false;
+        }
+
+        public boolean isExceptionEntry() {
+            // TODO Auto-generated method stub
+            return false;
+        }
+
+        public BciBlock getSuccessor(int index) {
+            return successors.get(index);
+        }
+
+        public BciBlock getPredecessor(int index) {
+            return predecessors.get(index);
+        }
     }
 
-    public static class ExceptionDispatchBlock extends Block {
+    public static class ExceptionDispatchBlock extends BciBlock {
 
         private HashMap<ExceptionHandler, ExceptionDispatchBlock> exceptionDispatch = new HashMap<>();
 
@@ -152,15 +192,15 @@
     /**
      * The blocks found in this method, in reverse postorder.
      */
-    public final List<Block> blocks;
+    public final List<BciBlock> blocks;
     public final ResolvedJavaMethod method;
     public boolean hasJsrBytecodes;
-    public Block startBlock;
+    public BciBlock startBlock;
 
     private final BytecodeStream stream;
     private final ExceptionHandler[] exceptionHandlers;
-    private Block[] blockMap;
-    public Block[] loopHeaders;
+    private BciBlock[] blockMap;
+    public BciBlock[] loopHeaders;
 
     public LocalLiveness liveness;
 
@@ -173,9 +213,9 @@
         this.method = method;
         exceptionHandlers = method.getExceptionHandlers();
         stream = new BytecodeStream(method.getCode());
-        this.blockMap = new Block[method.getCodeSize()];
+        this.blockMap = new BciBlock[method.getCodeSize()];
         this.blocks = new ArrayList<>();
-        this.loopHeaders = new Block[64];
+        this.loopHeaders = new BciBlock[64];
     }
 
     /**
@@ -218,13 +258,13 @@
     }
 
     private boolean verify() {
-        for (Block block : blocks) {
-            assert blocks.get(block.blockID) == block;
+        for (BciBlock block : blocks) {
+            assert blocks.get(block.getId()) == block;
 
-            for (int i = 0; i < block.successors.size(); i++) {
-                Block sux = block.successors.get(i);
+            for (int i = 0; i < block.getSuccessorCount(); i++) {
+                BciBlock sux = block.getSuccessor(i);
                 if (sux instanceof ExceptionDispatchBlock) {
-                    assert i == block.successors.size() - 1 : "Only one exception handler allowed, and it must be last in successors list";
+                    assert i == block.getSuccessorCount() - 1 : "Only one exception handler allowed, and it must be last in successors list";
                 }
             }
         }
@@ -234,14 +274,14 @@
 
     private void initializeBlockIds() {
         for (int i = 0; i < blocks.size(); i++) {
-            blocks.get(i).blockID = i;
+            blocks.get(i).setId(i);
         }
     }
 
     private void makeExceptionEntries() {
         // start basic blocks at all exception handler blocks and mark them as exception entries
         for (ExceptionHandler h : this.exceptionHandlers) {
-            Block xhandler = makeBlock(h.getHandlerBCI());
+            BciBlock xhandler = makeBlock(h.getHandlerBCI());
             xhandler.isExceptionEntry = true;
         }
     }
@@ -250,13 +290,13 @@
         // iterate over the bytecodes top to bottom.
         // mark the entrypoints of basic blocks and build lists of successors for
         // all bytecodes that end basic blocks (i.e. goto, ifs, switches, throw, jsr, returns, ret)
-        Block current = null;
+        BciBlock current = null;
         stream.setBCI(0);
         while (stream.currentBC() != Bytecodes.END) {
             int bci = stream.currentBCI();
 
             if (current == null || blockMap[bci] != null) {
-                Block b = makeBlock(bci);
+                BciBlock b = makeBlock(bci);
                 if (current != null) {
                     addSuccessor(current.endBci, b);
                 }
@@ -327,7 +367,7 @@
                     if (target == 0) {
                         throw new JsrNotSupportedBailout("jsr target bci 0 not allowed");
                     }
-                    Block b1 = makeBlock(target);
+                    BciBlock b1 = makeBlock(target);
                     current.jsrSuccessor = b1;
                     current.jsrReturnBci = stream.nextBCI();
                     current = null;
@@ -382,10 +422,10 @@
         }
     }
 
-    private Block makeBlock(int startBci) {
-        Block oldBlock = blockMap[startBci];
+    private BciBlock makeBlock(int startBci) {
+        BciBlock oldBlock = blockMap[startBci];
         if (oldBlock == null) {
-            Block newBlock = new Block();
+            BciBlock newBlock = new BciBlock();
             newBlock.startBci = startBci;
             blockMap[startBci] = newBlock;
             return newBlock;
@@ -393,14 +433,14 @@
         } else if (oldBlock.startBci != startBci) {
             // Backward branch into the middle of an already processed block.
             // Add the correct fall-through successor.
-            Block newBlock = new Block();
+            BciBlock newBlock = new BciBlock();
             newBlock.startBci = startBci;
             newBlock.endBci = oldBlock.endBci;
-            newBlock.successors.addAll(oldBlock.successors);
+            newBlock.getSuccessors().addAll(oldBlock.getSuccessors());
 
             oldBlock.endBci = startBci - 1;
-            oldBlock.successors.clear();
-            oldBlock.successors.add(newBlock);
+            oldBlock.getSuccessors().clear();
+            oldBlock.getSuccessors().add(newBlock);
 
             for (int i = startBci; i <= newBlock.endBci; i++) {
                 blockMap[i] = newBlock;
@@ -424,30 +464,30 @@
         }
     }
 
-    private void addSuccessor(int predBci, Block sux) {
-        Block predecessor = blockMap[predBci];
+    private void addSuccessor(int predBci, BciBlock sux) {
+        BciBlock predecessor = blockMap[predBci];
         if (sux.isExceptionEntry) {
             throw new BailoutException("Exception handler can be reached by both normal and exceptional control flow");
         }
-        predecessor.successors.add(sux);
+        predecessor.getSuccessors().add(sux);
     }
 
-    private final ArrayList<Block> jsrVisited = new ArrayList<>();
+    private final ArrayList<BciBlock> jsrVisited = new ArrayList<>();
 
-    private void createJsrAlternatives(Block block) {
+    private void createJsrAlternatives(BciBlock block) {
         jsrVisited.add(block);
         JsrScope scope = block.jsrScope;
 
         if (block.endsWithRet) {
             block.retSuccessor = blockMap[scope.nextReturnAddress()];
-            block.successors.add(block.retSuccessor);
+            block.getSuccessors().add(block.retSuccessor);
             assert block.retSuccessor != block.jsrSuccessor;
         }
-        Debug.log("JSR alternatives block %s  sux %s  jsrSux %s  retSux %s  jsrScope %s", block, block.successors, block.jsrSuccessor, block.retSuccessor, block.jsrScope);
+        Debug.log("JSR alternatives block %s  sux %s  jsrSux %s  retSux %s  jsrScope %s", block, block.getSuccessors(), block.jsrSuccessor, block.retSuccessor, block.jsrScope);
 
         if (block.jsrSuccessor != null || !scope.isEmpty()) {
-            for (int i = 0; i < block.successors.size(); i++) {
-                Block successor = block.successors.get(i);
+            for (int i = 0; i < block.getSuccessorCount(); i++) {
+                BciBlock successor = block.getSuccessor(i);
                 JsrScope nextScope = scope;
                 if (successor == block.jsrSuccessor) {
                     nextScope = scope.push(block.jsrReturnBci);
@@ -459,7 +499,7 @@
                     throw new JsrNotSupportedBailout("unstructured control flow  (" + successor.jsrScope + " " + nextScope + ")");
                 }
                 if (!nextScope.isEmpty()) {
-                    Block clone;
+                    BciBlock clone;
                     if (successor.jsrAlternatives != null && successor.jsrAlternatives.containsKey(nextScope)) {
                         clone = successor.jsrAlternatives.get(nextScope);
                     } else {
@@ -470,7 +510,7 @@
                         clone.jsrScope = nextScope;
                         successor.jsrAlternatives.put(nextScope, clone);
                     }
-                    block.successors.set(i, clone);
+                    block.getSuccessors().set(i, clone);
                     if (successor == block.jsrSuccessor) {
                         block.jsrSuccessor = clone;
                     }
@@ -480,7 +520,7 @@
                 }
             }
         }
-        for (Block successor : block.successors) {
+        for (BciBlock successor : block.getSuccessors()) {
             if (!jsrVisited.contains(successor)) {
                 createJsrAlternatives(successor);
             }
@@ -509,9 +549,9 @@
                     curHandler.endBci = -1;
                     curHandler.deoptBci = bci;
                     curHandler.handler = h;
-                    curHandler.successors.add(blockMap[h.getHandlerBCI()]);
+                    curHandler.getSuccessors().add(blockMap[h.getHandlerBCI()]);
                     if (lastHandler != null) {
-                        curHandler.successors.add(lastHandler);
+                        curHandler.getSuccessors().add(lastHandler);
                     }
                     exceptionDispatch.put(h, curHandler);
                 }
@@ -526,7 +566,7 @@
     private void fixLoopBits() {
         do {
             loopChanges = false;
-            for (Block b : blocks) {
+            for (BciBlock b : blocks) {
                 b.visited = false;
             }
 
@@ -563,17 +603,17 @@
             String n = System.lineSeparator();
             StringBuilder sb = new StringBuilder(Debug.currentScope()).append("BlockMap ").append(name).append(" :");
             sb.append(n);
-            Iterable<Block> it;
+            Iterable<BciBlock> it;
             if (blocks.isEmpty()) {
                 it = new HashSet<>(Arrays.asList(blockMap));
             } else {
                 it = blocks;
             }
-            for (Block b : it) {
+            for (BciBlock b : it) {
                 if (b == null) {
                     continue;
                 }
-                sb.append("B").append(b.blockID).append(" (").append(b.startBci).append(" -> ").append(b.endBci).append(")");
+                sb.append("B").append(b.getId()).append(" (").append(b.startBci).append(" -> ").append(b.endBci).append(")");
                 if (b.isLoopHeader) {
                     sb.append(" LoopHeader");
                 }
@@ -581,8 +621,8 @@
                     sb.append(" ExceptionEntry");
                 }
                 sb.append(n).append("  Sux : ");
-                for (Block s : b.successors) {
-                    sb.append("B").append(s.blockID).append(" (").append(s.startBci).append(" -> ").append(s.endBci).append(")");
+                for (BciBlock s : b.getSuccessors()) {
+                    sb.append("B").append(s.getId()).append(" (").append(s.startBci).append(" -> ").append(s.endBci).append(")");
                     if (s.isExceptionEntry) {
                         sb.append("!");
                     }
@@ -594,7 +634,7 @@
                 while (l != 0) {
                     int lMask = 1 << pos;
                     if ((l & lMask) != 0) {
-                        sb.append("B").append(loopHeaders[pos].blockID).append(" ");
+                        sb.append("B").append(loopHeaders[pos].getId()).append(" ");
                         l &= ~lMask;
                     }
                     pos++;
@@ -605,7 +645,7 @@
                 while (l != 0) {
                     int lMask = 1 << pos;
                     if ((l & lMask) != 0) {
-                        sb.append("B").append(loopHeaders[pos].blockID).append(" ");
+                        sb.append("B").append(loopHeaders[pos].getId()).append(" ");
                         l &= ~lMask;
                     }
                     pos++;
@@ -625,7 +665,7 @@
      * Mark the block as a loop header, using the next available loop number. Also checks for corner
      * cases that we don't want to compile.
      */
-    private void makeLoopHeader(Block block) {
+    private void makeLoopHeader(BciBlock block) {
         if (!block.isLoopHeader) {
             block.isLoopHeader = true;
 
@@ -655,11 +695,11 @@
     }
 
     /**
-     * Depth-first traversal of the control flow graph. The flag {@linkplain Block#visited} is used
-     * to visit every block only once. The flag {@linkplain Block#active} is used to detect cycles
-     * (backward edges).
+     * Depth-first traversal of the control flow graph. The flag {@linkplain BciBlock#visited} is
+     * used to visit every block only once. The flag {@linkplain BciBlock#active} is used to detect
+     * cycles (backward edges).
      */
-    private long computeBlockOrder(Block block) {
+    private long computeBlockOrder(BciBlock block) {
         if (block.visited) {
             if (block.active) {
                 // Reached block via backward branch.
@@ -677,7 +717,7 @@
         block.active = true;
 
         long loops = 0;
-        for (Block successor : block.successors) {
+        for (BciBlock successor : block.getSuccessors()) {
             // Recursively process successors.
             loops |= computeBlockOrder(successor);
         }
@@ -695,7 +735,7 @@
         return loops;
     }
 
-    private long fixLoopBits(Block block) {
+    private long fixLoopBits(BciBlock block) {
         if (block.visited) {
             // Return cached loop information for this block.
             if (block.isLoopHeader) {
@@ -707,11 +747,11 @@
 
         block.visited = true;
         long loops = block.loops;
-        for (Block successor : block.successors) {
+        for (BciBlock successor : block.getSuccessors()) {
             // Recursively process successors.
             loops |= fixLoopBits(successor);
         }
-        for (Block successor : block.successors) {
+        for (BciBlock successor : block.getSuccessors()) {
             successor.exits = loops & ~successor.loops;
         }
         if (block.loops != loops) {
@@ -734,7 +774,7 @@
     public abstract class LocalLiveness {
 
         private void computeLiveness() {
-            for (Block block : blocks) {
+            for (BciBlock block : blocks) {
                 computeLocalLiveness(block);
             }
 
@@ -744,22 +784,22 @@
                 Debug.log("Iteration %d", iteration);
                 changed = false;
                 for (int i = blocks.size() - 1; i >= 0; i--) {
-                    Block block = blocks.get(i);
-                    int blockID = block.blockID;
+                    BciBlock block = blocks.get(i);
+                    int blockID = block.getId();
                     // log statements in IFs because debugLiveX creates a new String
                     if (Debug.isLogEnabled()) {
-                        Debug.logv("  start B%d  [%d, %d]  in: %s  out: %s  gen: %s  kill: %s", block.blockID, block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID),
+                        Debug.logv("  start B%d  [%d, %d]  in: %s  out: %s  gen: %s  kill: %s", block.getId(), block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID),
                                         debugLiveGen(blockID), debugLiveKill(blockID));
                     }
 
                     boolean blockChanged = (iteration == 0);
-                    if (block.successors.size() > 0) {
+                    if (block.getSuccessorCount() > 0) {
                         int oldCardinality = liveOutCardinality(blockID);
-                        for (Block sux : block.successors) {
+                        for (BciBlock sux : block.getSuccessors()) {
                             if (Debug.isLogEnabled()) {
-                                Debug.log("    Successor B%d: %s", sux.blockID, debugLiveIn(sux.blockID));
+                                Debug.log("    Successor B%d: %s", sux.getId(), debugLiveIn(sux.getId()));
                             }
-                            propagateLiveness(blockID, sux.blockID);
+                            propagateLiveness(blockID, sux.getId());
                         }
                         blockChanged |= (oldCardinality != liveOutCardinality(blockID));
                     }
@@ -767,7 +807,7 @@
                     if (blockChanged) {
                         updateLiveness(blockID);
                         if (Debug.isLogEnabled()) {
-                            Debug.logv("  end   B%d  [%d, %d]  in: %s  out: %s  gen: %s  kill: %s", block.blockID, block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID),
+                            Debug.logv("  end   B%d  [%d, %d]  in: %s  out: %s  gen: %s  kill: %s", block.getId(), block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID),
                                             debugLiveGen(blockID), debugLiveKill(blockID));
                         }
                     }
@@ -780,12 +820,12 @@
         /**
          * Returns whether the local is live at the beginning of the given block.
          */
-        public abstract boolean localIsLiveIn(Block block, int local);
+        public abstract boolean localIsLiveIn(BciBlock block, int local);
 
         /**
          * Returns whether the local is live at the end of the given block.
          */
-        public abstract boolean localIsLiveOut(Block block, int local);
+        public abstract boolean localIsLiveOut(BciBlock block, int local);
 
         /**
          * Returns a string representation of the liveIn values of the given block.
@@ -832,11 +872,11 @@
          */
         protected abstract void storeOne(int blockID, int local);
 
-        private void computeLocalLiveness(Block block) {
+        private void computeLocalLiveness(BciBlock block) {
             if (block.startBci < 0 || block.endBci < 0) {
                 return;
             }
-            int blockID = block.blockID;
+            int blockID = block.getId();
             stream.setBCI(block.startBci);
             while (stream.currentBCI() <= block.endBci) {
                 switch (stream.currentBC()) {
@@ -1043,14 +1083,14 @@
         }
 
         @Override
-        public boolean localIsLiveIn(Block block, int local) {
-            int blockID = block.blockID;
+        public boolean localIsLiveIn(BciBlock block, int local) {
+            int blockID = block.getId();
             return blockID >= Integer.MAX_VALUE ? false : (localsLiveIn[blockID] & (1L << local)) != 0L;
         }
 
         @Override
-        public boolean localIsLiveOut(Block block, int local) {
-            int blockID = block.blockID;
+        public boolean localIsLiveOut(BciBlock block, int local) {
+            int blockID = block.getId();
             return blockID >= Integer.MAX_VALUE ? false : (localsLiveOut[blockID] & (1L << local)) != 0L;
         }
     }
@@ -1128,13 +1168,13 @@
         }
 
         @Override
-        public boolean localIsLiveIn(Block block, int local) {
-            return block.blockID >= Integer.MAX_VALUE ? true : localsLiveIn[block.blockID].get(local);
+        public boolean localIsLiveIn(BciBlock block, int local) {
+            return block.getId() >= Integer.MAX_VALUE ? true : localsLiveIn[block.getId()].get(local);
         }
 
         @Override
-        public boolean localIsLiveOut(Block block, int local) {
-            return block.blockID >= Integer.MAX_VALUE ? true : localsLiveOut[block.blockID].get(local);
+        public boolean localIsLiveOut(BciBlock block, int local) {
+            return block.getId() >= Integer.MAX_VALUE ? true : localsLiveOut[block.getId()].get(local);
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParseHelper.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,138 @@
+/*
+ * 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.java;
+
+import static com.oracle.graal.bytecode.Bytecodes.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+
+public class BytecodeParseHelper<T extends KindInterface> {
+
+    private AbstractFrameStateBuilder<T> frameState;
+
+    public BytecodeParseHelper(AbstractFrameStateBuilder<T> frameState) {
+        this.frameState = frameState;
+    }
+
+    public void setCurrentFrameState(AbstractFrameStateBuilder<T> frameState) {
+        this.frameState = frameState;
+    }
+
+    public void loadLocal(int index, Kind kind) {
+        frameState.push(kind, frameState.loadLocal(index));
+    }
+
+    public void storeLocal(Kind kind, int index) {
+        T value;
+        if (kind == Kind.Object) {
+            value = frameState.xpop();
+            // astore and astore_<n> may be used to store a returnAddress (jsr)
+            assert value.getKind() == Kind.Object || value.getKind() == Kind.Int;
+        } else {
+            value = frameState.pop(kind);
+        }
+        frameState.storeLocal(index, value);
+    }
+
+    public void stackOp(int opcode) {
+        switch (opcode) {
+            case POP: {
+                frameState.xpop();
+                break;
+            }
+            case POP2: {
+                frameState.xpop();
+                frameState.xpop();
+                break;
+            }
+            case DUP: {
+                T w = frameState.xpop();
+                frameState.xpush(w);
+                frameState.xpush(w);
+                break;
+            }
+            case DUP_X1: {
+                T w1 = frameState.xpop();
+                T w2 = frameState.xpop();
+                frameState.xpush(w1);
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                break;
+            }
+            case DUP_X2: {
+                T w1 = frameState.xpop();
+                T w2 = frameState.xpop();
+                T w3 = frameState.xpop();
+                frameState.xpush(w1);
+                frameState.xpush(w3);
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                break;
+            }
+            case DUP2: {
+                T w1 = frameState.xpop();
+                T w2 = frameState.xpop();
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                break;
+            }
+            case DUP2_X1: {
+                T w1 = frameState.xpop();
+                T w2 = frameState.xpop();
+                T w3 = frameState.xpop();
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                frameState.xpush(w3);
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                break;
+            }
+            case DUP2_X2: {
+                T w1 = frameState.xpop();
+                T w2 = frameState.xpop();
+                T w3 = frameState.xpop();
+                T w4 = frameState.xpop();
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                frameState.xpush(w4);
+                frameState.xpush(w3);
+                frameState.xpush(w2);
+                frameState.xpush(w1);
+                break;
+            }
+            case SWAP: {
+                T w1 = frameState.xpop();
+                T w2 = frameState.xpop();
+                frameState.xpush(w1);
+                frameState.xpush(w2);
+                break;
+            }
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+}
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Thu Mar 27 16:54:47 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,707 +0,0 @@
-/*
- * 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.java.BciBlockMapping.Block;
-import com.oracle.graal.java.BciBlockMapping.LocalLiveness;
-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 FrameStateBuilder {
-
-    private static final ValueNode[] EMPTY_ARRAY = new ValueNode[0];
-    private static final MonitorIdNode[] EMPTY_MONITOR_ARRAY = new MonitorIdNode[0];
-
-    private final ResolvedJavaMethod method;
-    private final StructuredGraph graph;
-
-    private final ValueNode[] locals;
-    private final ValueNode[] stack;
-    private ValueNode[] lockedObjects;
-    private MonitorIdNode[] monitorIds;
-
-    private int stackSize;
-
-    /**
-     * @see BytecodeFrame#rethrowException
-     */
-    private boolean rethrowException;
-
-    public FrameStateBuilder(ResolvedJavaMethod method, StructuredGraph graph, boolean eagerResolve) {
-        assert graph != null;
-        this.method = method;
-        this.graph = 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 FrameStateBuilder(FrameStateBuilder other) {
-        method = other.method;
-        graph = other.graph;
-        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 FrameStateBuilder copy() {
-        return new FrameStateBuilder(this);
-    }
-
-    public boolean isCompatibleWith(FrameStateBuilder other) {
-        assert method.equals(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.getKind() != y.getKind())) {
-                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, FrameStateBuilder 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.getKind() != otherValue.getKind()) {
-                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.getKind() != otherValue.getKind()) {
-                return null;
-            }
-
-            PhiNode phi = graph.addWithoutUnique(new PhiNode(currentValue.stamp().unrestricted(), 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, FrameStateBuilder 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.stamp().unrestricted(), 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(Block block, LocalLiveness liveness, boolean liveIn) {
-        if (liveness == null) {
-            return;
-        }
-        if (liveIn) {
-            for (int i = 0; i < locals.length; i++) {
-                if (!liveness.localIsLiveIn(block, i)) {
-                    locals[i] = null;
-                }
-            }
-        } else {
-            for (int i = 0; i < locals.length; i++) {
-                if (!liveness.localIsLiveOut(block, i)) {
-                    locals[i] = null;
-                }
-            }
-        }
-    }
-
-    /**
-     * @see BytecodeFrame#rethrowException
-     */
-    public boolean rethrowException() {
-        return rethrowException;
-    }
-
-    /**
-     * @see BytecodeFrame#rethrowException
-     */
-    public void setRethrowException(boolean b) {
-        rethrowException = b;
-    }
-
-    /**
-     * Returns the size of the local variables.
-     * 
-     * @return the size of the local variables
-     */
-    public int localsSize() {
-        return locals.length;
-    }
-
-    /**
-     * 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 final ValueNode localAt(int i) {
-        return locals[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 final ValueNode stackAt(int i) {
-        return stack[i];
-    }
-
-    public final ValueNode lockAt(int i) {
-        return lockedObjects[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.getKind() == 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;
-    }
-
-    /**
-     * 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 ValueNode loadLocal(int i) {
-        ValueNode x = locals[i];
-        assert !x.isDeleted();
-        assert !isTwoSlot(x.getKind()) || locals[i + 1] == null;
-        assert i == 0 || locals[i - 1] == null || !isTwoSlot(locals[i - 1].getKind());
-        return x;
-    }
-
-    /**
-     * Stores a given local variable at the specified index. If the value occupies
-     * {@linkplain FrameStateBuilder#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 void storeLocal(int i, ValueNode x) {
-        assert x == null || x.isAlive() && x.getKind() != Kind.Void && x.getKind() != Kind.Illegal : "unexpected value: " + x;
-        locals[i] = x;
-        if (x != null && isTwoSlot(x.getKind())) {
-            // 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.getKind())) {
-                // if there was a double word at i - 1, then kill it
-                locals[i - 1] = null;
-            }
-        }
-    }
-
-    public void storeStack(int i, ValueNode x) {
-        assert x == null || x.isAlive() && (stack[i] == null || x.getKind() == stack[i].getKind()) : "Method does not handle changes from one-slot to two-slot values or non-alive values";
-        stack[i] = x;
-    }
-
-    public void storeLock(int i, ValueNode x) {
-        assert x == null || x.isAlive() && (lockedObjects[i] == null || x.getKind() == lockedObjects[i].getKind()) : "unexpected lock value: " + x;
-        lockedObjects[i] = 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 void push(Kind kind, ValueNode x) {
-        assert x.isAlive() && x.getKind() != Kind.Void && x.getKind() != Kind.Illegal;
-        xpush(assertKind(kind, x));
-        if (isTwoSlot(kind)) {
-            xpush(null);
-        }
-    }
-
-    /**
-     * Pushes a value onto the stack without checking the type.
-     * 
-     * @param x the instruction to push onto the stack
-     */
-    public void xpush(ValueNode x) {
-        assert x == null || (x.isAlive() && x.getKind() != Kind.Void && x.getKind() != Kind.Illegal);
-        stack[stackSize++] = x;
-    }
-
-    /**
-     * Pushes a value onto the stack and checks that it is an int.
-     * 
-     * @param x the instruction to push onto the stack
-     */
-    public void ipush(ValueNode x) {
-        xpush(assertInt(x));
-    }
-
-    /**
-     * Pushes a value onto the stack and checks that it is a float.
-     * 
-     * @param x the instruction to push onto the stack
-     */
-    public void fpush(ValueNode x) {
-        xpush(assertFloat(x));
-    }
-
-    /**
-     * Pushes a value onto the stack and checks that it is an object.
-     * 
-     * @param x the instruction to push onto the stack
-     */
-    public void apush(ValueNode x) {
-        xpush(assertObject(x));
-    }
-
-    /**
-     * Pushes a value onto the stack and checks that it is a long.
-     * 
-     * @param x the instruction to push onto the stack
-     */
-    public void lpush(ValueNode x) {
-        xpush(assertLong(x));
-        xpush(null);
-    }
-
-    /**
-     * Pushes a value onto the stack and checks that it is a double.
-     * 
-     * @param x the instruction to push onto the stack
-     */
-    public void dpush(ValueNode x) {
-        xpush(assertDouble(x));
-        xpush(null);
-    }
-
-    public void pushReturn(Kind kind, ValueNode x) {
-        if (kind != Kind.Void) {
-            push(kind.getStackKind(), 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 ValueNode pop(Kind kind) {
-        assert kind != Kind.Void;
-        if (isTwoSlot(kind)) {
-            xpop();
-        }
-        return assertKind(kind, xpop());
-    }
-
-    /**
-     * Pops a value off of the stack without checking the type.
-     * 
-     * @return x the instruction popped off the stack
-     */
-    public ValueNode xpop() {
-        ValueNode result = stack[--stackSize];
-        assert result == null || !result.isDeleted();
-        return result;
-    }
-
-    /**
-     * Pops a value off of the stack and checks that it is an int.
-     * 
-     * @return x the instruction popped off the stack
-     */
-    public ValueNode ipop() {
-        return assertInt(xpop());
-    }
-
-    /**
-     * Pops a value off of the stack and checks that it is a float.
-     * 
-     * @return x the instruction popped off the stack
-     */
-    public ValueNode fpop() {
-        return assertFloat(xpop());
-    }
-
-    /**
-     * Pops a value off of the stack and checks that it is an object.
-     * 
-     * @return x the instruction popped off the stack
-     */
-    public ValueNode apop() {
-        return assertObject(xpop());
-    }
-
-    /**
-     * Pops a value off of the stack and checks that it is a long.
-     * 
-     * @return x the instruction popped off the stack
-     */
-    public ValueNode lpop() {
-        assertHigh(xpop());
-        return assertLong(xpop());
-    }
-
-    /**
-     * Pops a value off of the stack and checks that it is a double.
-     * 
-     * @return x the instruction popped off the stack
-     */
-    public ValueNode dpop() {
-        assertHigh(xpop());
-        return assertDouble(xpop());
-    }
-
-    /**
-     * 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 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.getKind());
-        }
-        stackSize = base;
-        return r;
-    }
-
-    /**
-     * 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 ValueNode peek(int argumentNumber) {
-        int idx = stackSize() - 1;
-        for (int i = 0; i < argumentNumber; i++) {
-            if (stackAt(idx) == null) {
-                idx--;
-                assert isTwoSlot(stackAt(idx).getKind());
-            }
-            idx--;
-        }
-        return stackAt(idx);
-    }
-
-    /**
-     * Clears all values on this stack.
-     */
-    public void clearStack() {
-        stackSize = 0;
-    }
-
-    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.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Mar 27 17:31:20 2014 +0100
@@ -40,7 +40,7 @@
 import com.oracle.graal.bytecode.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.java.BciBlockMapping.Block;
+import com.oracle.graal.java.BciBlockMapping.BciBlock;
 import com.oracle.graal.java.BciBlockMapping.ExceptionDispatchBlock;
 import com.oracle.graal.java.BciBlockMapping.LocalLiveness;
 import com.oracle.graal.nodes.*;
@@ -117,8 +117,9 @@
 
         private BytecodeStream stream;           // the bytecode stream
 
-        protected FrameStateBuilder frameState;          // the current execution state
-        private Block currentBlock;
+        protected HIRFrameStateBuilder frameState;          // the current execution state
+        private BytecodeParseHelper<ValueNode> parseHelper;
+        private BciBlock currentBlock;
 
         private ValueNode methodSynchronizedObject;
         private ExceptionDispatchBlock unwindBlock;
@@ -159,13 +160,13 @@
             }
         }
 
-        private Block[] loopHeaders;
+        private BciBlock[] loopHeaders;
         private LocalLiveness liveness;
 
         /**
          * Gets the current frame state being processed by this builder.
          */
-        protected FrameStateBuilder getCurrentFrameState() {
+        protected HIRFrameStateBuilder getCurrentFrameState() {
             return frameState;
         }
 
@@ -202,7 +203,8 @@
             unwindBlock = null;
             methodSynchronizedObject = null;
             this.currentGraph = graph;
-            this.frameState = new FrameStateBuilder(method, graph, graphBuilderConfig.eagerResolving());
+            this.frameState = new HIRFrameStateBuilder(method, graph, graphBuilderConfig.eagerResolving());
+            this.parseHelper = new BytecodeParseHelper<>(frameState);
             TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method);
             try {
                 build();
@@ -260,7 +262,7 @@
                 blockMap.startBlock.firstInstruction = lastInstr;
             }
 
-            for (Block block : blockMap.blocks) {
+            for (BciBlock block : blockMap.blocks) {
                 processBlock(block);
             }
             processBlock(unwindBlock);
@@ -289,19 +291,19 @@
         /**
          * A hook for derived classes to modify the graph start instruction or append new
          * instructions to it.
-         * 
+         *
          * @param startInstr The start instruction of the graph.
          */
         protected void finishPrepare(FixedWithNextNode startInstr) {
         }
 
-        private Block unwindBlock(int bci) {
+        private BciBlock unwindBlock(int bci) {
             if (unwindBlock == null) {
                 unwindBlock = new ExceptionDispatchBlock();
                 unwindBlock.startBci = -1;
                 unwindBlock.endBci = -1;
                 unwindBlock.deoptBci = bci;
-                unwindBlock.blockID = Integer.MAX_VALUE;
+                unwindBlock.setId(Integer.MAX_VALUE);
             }
             return unwindBlock;
         }
@@ -314,6 +316,7 @@
             return stream.currentBCI();
         }
 
+        @SuppressWarnings("unused")
         private void loadLocal(int index, Kind kind) {
             frameState.push(kind, frameState.loadLocal(index));
         }
@@ -438,7 +441,7 @@
             assert bci == FrameState.BEFORE_BCI || bci == bci() : "invalid bci";
             Debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, profilingInfo.getExceptionSeen(bci));
 
-            Block dispatchBlock = currentBlock.exceptionDispatchBlock();
+            BciBlock dispatchBlock = currentBlock.exceptionDispatchBlock();
             /*
              * The exception dispatch block is always for the last bytecode of a block, so if we are
              * not at the endBci yet, there is no exception handler for this bci and we can unwind
@@ -448,7 +451,7 @@
                 dispatchBlock = unwindBlock(bci);
             }
 
-            FrameStateBuilder dispatchState = frameState.copy();
+            HIRFrameStateBuilder dispatchState = frameState.copy();
             dispatchState.clearStack();
 
             DispatchBeginNode dispatchBegin;
@@ -582,7 +585,6 @@
                 default:
                     throw GraalInternalError.shouldNotReachHere();
             }
-
         }
 
         private void genArithmeticOp(Kind result, int opcode) {
@@ -740,15 +742,15 @@
         }
 
         private void genGoto() {
-            appendGoto(createTarget(currentBlock.successors.get(0), frameState));
+            appendGoto(createTarget(currentBlock.getSuccessor(0), frameState));
             assert currentBlock.numNormalSuccessors() == 1;
         }
 
         private void ifNode(ValueNode x, Condition cond, ValueNode y) {
             assert !x.isDeleted() && !y.isDeleted();
             assert currentBlock.numNormalSuccessors() == 2;
-            Block trueBlock = currentBlock.successors.get(0);
-            Block falseBlock = currentBlock.successors.get(1);
+            BciBlock trueBlock = currentBlock.getSuccessor(0);
+            BciBlock falseBlock = currentBlock.getSuccessor(1);
             if (trueBlock == falseBlock) {
                 appendGoto(createTarget(trueBlock, frameState));
                 return;
@@ -912,7 +914,7 @@
         /**
          * Gets the kind of array elements for the array type code that appears in a
          * {@link Bytecodes#NEWARRAY} bytecode.
-         * 
+         *
          * @param code the array type code
          * @return the kind from the array type code
          */
@@ -1210,7 +1212,7 @@
 
                 InvokeWithExceptionNode invoke = createInvokeWithException(callTarget, resultType);
 
-                Block nextBlock = currentBlock.successors.get(0);
+                BciBlock nextBlock = currentBlock.getSuccessor(0);
                 invoke.setNext(createTarget(nextBlock, frameState));
             }
         }
@@ -1229,7 +1231,7 @@
             DispatchBeginNode exceptionEdge = handleException(null, bci());
             InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, bci()));
             frameState.pushReturn(resultType, invoke);
-            Block nextBlock = currentBlock.successors.get(0);
+            BciBlock nextBlock = currentBlock.getSuccessor(0);
             invoke.setStateAfter(frameState.create(nextBlock.startBci));
             return invoke;
         }
@@ -1267,7 +1269,7 @@
         }
 
         private void genJsr(int dest) {
-            Block successor = currentBlock.jsrSuccessor;
+            BciBlock successor = currentBlock.jsrSuccessor;
             assert successor.startBci == dest : successor.startBci + " != " + dest + " @" + bci();
             JsrScope scope = currentBlock.jsrScope;
             if (!successor.jsrScope.pop().equals(scope)) {
@@ -1281,7 +1283,7 @@
         }
 
         private void genRet(int localIndex) {
-            Block successor = currentBlock.retSuccessor;
+            BciBlock successor = currentBlock.retSuccessor;
             ValueNode local = frameState.loadLocal(localIndex);
             JsrScope scope = currentBlock.jsrScope;
             int retAddress = scope.nextReturnAddress();
@@ -1319,7 +1321,7 @@
         /**
          * Helper function that sums up the probabilities of all keys that lead to a specific
          * successor.
-         * 
+         *
          * @return an array of size successorCount with the accumulated probability for each
          *         successor.
          */
@@ -1339,14 +1341,14 @@
             double[] keyProbabilities = switchProbability(nofCases + 1, bci);
 
             Map<Integer, SuccessorInfo> bciToBlockSuccessorIndex = new HashMap<>();
-            for (int i = 0; i < currentBlock.successors.size(); i++) {
-                assert !bciToBlockSuccessorIndex.containsKey(currentBlock.successors.get(i).startBci);
-                if (!bciToBlockSuccessorIndex.containsKey(currentBlock.successors.get(i).startBci)) {
-                    bciToBlockSuccessorIndex.put(currentBlock.successors.get(i).startBci, new SuccessorInfo(i));
+            for (int i = 0; i < currentBlock.getSuccessorCount(); i++) {
+                assert !bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci);
+                if (!bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci)) {
+                    bciToBlockSuccessorIndex.put(currentBlock.getSuccessor(i).startBci, new SuccessorInfo(i));
                 }
             }
 
-            ArrayList<Block> actualSuccessors = new ArrayList<>();
+            ArrayList<BciBlock> actualSuccessors = new ArrayList<>();
             int[] keys = new int[nofCases];
             int[] keySuccessors = new int[nofCases + 1];
             int deoptSuccessorIndex = -1;
@@ -1367,7 +1369,7 @@
                     SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci);
                     if (info.actualIndex < 0) {
                         info.actualIndex = nextSuccessorIndex++;
-                        actualSuccessors.add(currentBlock.successors.get(info.blockIndex));
+                        actualSuccessors.add(currentBlock.getSuccessor(info.blockIndex));
                     }
                     keySuccessors[i] = info.actualIndex;
                 }
@@ -1433,15 +1435,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, BciBlock targetBlock, HIRFrameStateBuilder state) {
             if (currentBlock != null) {
                 long exits = currentBlock.loops & ~targetBlock.loops;
                 if (exits != 0) {
@@ -1449,7 +1451,7 @@
                     LoopExitNode lastLoopExit = null;
 
                     int pos = 0;
-                    ArrayList<Block> exitLoops = new ArrayList<>(Long.bitCount(exits));
+                    ArrayList<BciBlock> exitLoops = new ArrayList<>(Long.bitCount(exits));
                     do {
                         long lMask = 1L << pos;
                         if ((exits & lMask) != 0) {
@@ -1459,10 +1461,10 @@
                         pos++;
                     } while (exits != 0);
 
-                    Collections.sort(exitLoops, new Comparator<Block>() {
+                    Collections.sort(exitLoops, new Comparator<BciBlock>() {
 
                         @Override
-                        public int compare(Block o1, Block o2) {
+                        public int compare(BciBlock o1, BciBlock o2) {
                             return Long.bitCount(o2.loops) - Long.bitCount(o1.loops);
                         }
                     });
@@ -1471,8 +1473,8 @@
                     if (targetBlock instanceof ExceptionDispatchBlock) {
                         bci = ((ExceptionDispatchBlock) targetBlock).deoptBci;
                     }
-                    FrameStateBuilder newState = state.copy();
-                    for (Block loop : exitLoops) {
+                    HIRFrameStateBuilder newState = state.copy();
+                    for (BciBlock loop : exitLoops) {
                         LoopBeginNode loopBegin = (LoopBeginNode) loop.firstInstruction;
                         LoopExitNode loopExit = currentGraph.add(new LoopExitNode(loopBegin));
                         if (lastLoopExit != null) {
@@ -1494,7 +1496,7 @@
             return new Target(target, state);
         }
 
-        private FixedNode createTarget(double probability, Block block, FrameStateBuilder stateAfter) {
+        private FixedNode createTarget(double probability, BciBlock block, HIRFrameStateBuilder stateAfter) {
             assert probability >= 0 && probability <= 1.01 : probability;
             if (isNeverExecutedCode(probability)) {
                 return currentGraph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode));
@@ -1508,7 +1510,7 @@
             return probability == 0 && optimisticOpts.removeNeverExecutedCode() && entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI;
         }
 
-        private FixedNode createTarget(Block block, FrameStateBuilder state) {
+        private FixedNode createTarget(BciBlock block, HIRFrameStateBuilder state) {
             assert block != null && state != null;
             assert !block.isExceptionEntry || state.stackSize() == 1;
 
@@ -1534,7 +1536,7 @@
             }
 
             if (block.firstInstruction instanceof LoopBeginNode) {
-                assert block.isLoopHeader && currentBlock.blockID >= block.blockID : "must be backward branch";
+                assert block.isLoopHeader && currentBlock.getId() >= block.getId() : "must be backward branch";
                 /*
                  * Backward loop edge. We need to create a special LoopEndNode and merge with the
                  * loop begin node created before.
@@ -1547,7 +1549,7 @@
                 Debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result);
                 return result;
             }
-            assert currentBlock == null || currentBlock.blockID < block.blockID : "must not be backward branch";
+            assert currentBlock == null || currentBlock.getId() < block.getId() : "must not be backward branch";
             assert block.firstInstruction.next() == null : "bytecodes already parsed for block";
 
             if (block.firstInstruction instanceof BlockPlaceholderNode) {
@@ -1588,7 +1590,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, BciBlock block, HIRFrameStateBuilder stateAfter) {
             FixedNode target = createTarget(probability, block, stateAfter);
             AbstractBeginNode begin = AbstractBeginNode.begin(target);
 
@@ -1597,7 +1599,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 {
@@ -1605,7 +1607,7 @@
             }
         }
 
-        private void processBlock(Block block) {
+        private void processBlock(BciBlock block) {
             // Ignore blocks that have no predecessors by the time their bytecodes are parsed
             if (block == null || block.firstInstruction == null) {
                 Debug.log("Ignoring block %s", block);
@@ -1615,6 +1617,7 @@
 
             lastInstr = block.firstInstruction;
             frameState = block.entryState;
+            parseHelper.setCurrentFrameState(frameState);
             currentBlock = block;
 
             frameState.cleanupDeletedPhis();
@@ -1681,8 +1684,8 @@
         private void createExceptionDispatch(ExceptionDispatchBlock block) {
             assert frameState.stackSize() == 1 : frameState;
             if (block.handler.isCatchAll()) {
-                assert block.successors.size() == 1;
-                appendGoto(createTarget(block.successors.get(0), frameState));
+                assert block.getSuccessorCount() == 1;
+                appendGoto(createTarget(block.getSuccessor(0), frameState));
                 return;
             }
 
@@ -1695,7 +1698,7 @@
                 ResolvedJavaType resolvedCatchType = (ResolvedJavaType) catchType;
                 for (ResolvedJavaType skippedType : graphBuilderConfig.getSkippedExceptionTypes()) {
                     if (skippedType.isAssignableFrom(resolvedCatchType)) {
-                        Block nextBlock = block.successors.size() == 1 ? unwindBlock(block.deoptBci) : block.successors.get(1);
+                        BciBlock nextBlock = block.getSuccessorCount() == 1 ? unwindBlock(block.deoptBci) : block.getSuccessor(1);
                         ValueNode exception = frameState.stackAt(0);
                         FixedNode trueSuccessor = currentGraph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode));
                         FixedNode nextDispatch = createTarget(nextBlock, frameState);
@@ -1706,12 +1709,12 @@
             }
 
             if (initialized) {
-                Block nextBlock = block.successors.size() == 1 ? unwindBlock(block.deoptBci) : block.successors.get(1);
+                BciBlock nextBlock = block.getSuccessorCount() == 1 ? unwindBlock(block.deoptBci) : block.getSuccessor(1);
                 ValueNode exception = frameState.stackAt(0);
                 CheckCastNode checkCast = currentGraph.add(new CheckCastNode((ResolvedJavaType) catchType, exception, null, false));
                 frameState.apop();
                 frameState.push(Kind.Object, checkCast);
-                FixedNode catchSuccessor = createTarget(block.successors.get(0), frameState);
+                FixedNode catchSuccessor = createTarget(block.getSuccessor(0), frameState);
                 frameState.apop();
                 frameState.push(Kind.Object, exception);
                 FixedNode nextDispatch = createTarget(nextBlock, frameState);
@@ -1732,7 +1735,7 @@
             return n instanceof ControlSplitNode || n instanceof ControlSinkNode;
         }
 
-        private void iterateBytecodesForBlock(Block block) {
+        private void iterateBytecodesForBlock(BciBlock block) {
             if (block.isLoopHeader) {
                 // Create the loop header block, which later will merge the backward branches of the
                 // loop.
@@ -1818,10 +1821,10 @@
                 lastInstr = finishInstruction(lastInstr, frameState);
                 if (bci < endBCI) {
                     if (bci > block.endBci) {
-                        assert !block.successors.get(0).isExceptionEntry;
+                        assert !block.getSuccessor(0).isExceptionEntry;
                         assert block.numNormalSuccessors() == 1;
                         // we fell through to the next block, add a goto and break
-                        appendGoto(createTarget(block.successors.get(0), frameState));
+                        appendGoto(createTarget(block.getSuccessor(0), frameState));
                         break;
                     }
                 }
@@ -1830,12 +1833,12 @@
 
         /**
          * A hook for derived classes to modify the last instruction or add other instructions.
-         * 
+         *
          * @param instr The last instruction (= fixed node) which was added.
          * @param state The current frame state.
          * @Returns Returns the (new) last instruction.
          */
-        protected FixedWithNextNode finishInstruction(FixedWithNextNode instr, FrameStateBuilder state) {
+        protected FixedWithNextNode finishInstruction(FixedWithNextNode instr, HIRFrameStateBuilder state) {
             return instr;
         }
 
@@ -1882,31 +1885,31 @@
             case LDC            : // fall through
             case LDC_W          : // fall through
             case LDC2_W         : genLoadConstant(stream.readCPI(), opcode); break;
-            case ILOAD          : loadLocal(stream.readLocalIndex(), Kind.Int); break;
-            case LLOAD          : loadLocal(stream.readLocalIndex(), Kind.Long); break;
-            case FLOAD          : loadLocal(stream.readLocalIndex(), Kind.Float); break;
-            case DLOAD          : loadLocal(stream.readLocalIndex(), Kind.Double); break;
-            case ALOAD          : loadLocal(stream.readLocalIndex(), Kind.Object); break;
+            case ILOAD          : parseHelper.loadLocal(stream.readLocalIndex(), Kind.Int); break;
+            case LLOAD          : parseHelper.loadLocal(stream.readLocalIndex(), Kind.Long); break;
+            case FLOAD          : parseHelper.loadLocal(stream.readLocalIndex(), Kind.Float); break;
+            case DLOAD          : parseHelper.loadLocal(stream.readLocalIndex(), Kind.Double); break;
+            case ALOAD          : parseHelper.loadLocal(stream.readLocalIndex(), Kind.Object); break;
             case ILOAD_0        : // fall through
             case ILOAD_1        : // fall through
             case ILOAD_2        : // fall through
-            case ILOAD_3        : loadLocal(opcode - ILOAD_0, Kind.Int); break;
+            case ILOAD_3        : parseHelper.loadLocal(opcode - ILOAD_0, Kind.Int); break;
             case LLOAD_0        : // fall through
             case LLOAD_1        : // fall through
             case LLOAD_2        : // fall through
-            case LLOAD_3        : loadLocal(opcode - LLOAD_0, Kind.Long); break;
+            case LLOAD_3        : parseHelper.loadLocal(opcode - LLOAD_0, Kind.Long); break;
             case FLOAD_0        : // fall through
             case FLOAD_1        : // fall through
             case FLOAD_2        : // fall through
-            case FLOAD_3        : loadLocal(opcode - FLOAD_0, Kind.Float); break;
+            case FLOAD_3        : parseHelper.loadLocal(opcode - FLOAD_0, Kind.Float); break;
             case DLOAD_0        : // fall through
             case DLOAD_1        : // fall through
             case DLOAD_2        : // fall through
-            case DLOAD_3        : loadLocal(opcode - DLOAD_0, Kind.Double); break;
+            case DLOAD_3        : parseHelper.loadLocal(opcode - DLOAD_0, Kind.Double); break;
             case ALOAD_0        : // fall through
             case ALOAD_1        : // fall through
             case ALOAD_2        : // fall through
-            case ALOAD_3        : loadLocal(opcode - ALOAD_0, Kind.Object); break;
+            case ALOAD_3        : parseHelper.loadLocal(opcode - ALOAD_0, Kind.Object); break;
             case IALOAD         : genLoadIndexed(Kind.Int   ); break;
             case LALOAD         : genLoadIndexed(Kind.Long  ); break;
             case FALOAD         : genLoadIndexed(Kind.Float ); break;
--- /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 27 17:31:20 2014 +0100
@@ -0,0 +1,579 @@
+/*
+ * 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.java.BciBlockMapping.BciBlock;
+import com.oracle.graal.java.BciBlockMapping.LocalLiveness;
+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;
+    private final StructuredGraph graph;
+
+    /**
+     * @see BytecodeFrame#rethrowException
+     */
+    private boolean rethrowException;
+
+    public HIRFrameStateBuilder(ResolvedJavaMethod method, StructuredGraph graph, boolean eagerResolve) {
+        super(method);
+
+        assert graph != null;
+
+        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;
+        this.graph = graph;
+
+        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);
+        assert other.graph != null;
+        graph = other.graph;
+        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.equals(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.getKind() != y.getKind())) {
+                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.getKind() != otherValue.getKind()) {
+                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.getKind() != otherValue.getKind()) {
+                return null;
+            }
+
+            PhiNode phi = graph.addWithoutUnique(new PhiNode(currentValue.stamp().unrestricted(), 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.stamp().unrestricted(), 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(BciBlock block, LocalLiveness liveness, boolean liveIn) {
+        if (liveness == null) {
+            return;
+        }
+        if (liveIn) {
+            for (int i = 0; i < locals.length; i++) {
+                if (!liveness.localIsLiveIn(block, i)) {
+                    locals[i] = null;
+                }
+            }
+        } else {
+            for (int i = 0; i < locals.length; i++) {
+                if (!liveness.localIsLiveOut(block, 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.getKind() == 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.getKind()) || locals[i + 1] == null;
+        assert i == 0 || locals[i - 1] == null || !isTwoSlot(locals[i - 1].getKind());
+        return x;
+    }
+
+    @Override
+    public void storeLocal(int i, ValueNode x) {
+        assert x == null || x.isAlive() && x.getKind() != Kind.Void && x.getKind() != Kind.Illegal : "unexpected value: " + x;
+        locals[i] = x;
+        if (x != null && isTwoSlot(x.getKind())) {
+            // 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.getKind())) {
+                // 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.getKind() == stack[i].getKind()) : "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.getKind() != Kind.Void && x.getKind() != Kind.Illegal;
+        xpush(assertKind(kind, x));
+        if (isTwoSlot(kind)) {
+            xpush(null);
+        }
+    }
+
+    @Override
+    public void xpush(ValueNode x) {
+        assert x == null || (x.isAlive() && x.getKind() != Kind.Void && x.getKind() != 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.getKind());
+        }
+        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).getKind());
+            }
+            idx--;
+        }
+        return stackAt(idx);
+    }
+
+    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 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java	Thu Mar 27 17:31:20 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,41 +53,41 @@
      * @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;
         }
 
-        List<LIRInstruction> instructions = lir.lir(block);
+        List<LIRInstruction> instructions = lir.getLIRforBlock(block);
 
         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.getLIRforBlock(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);
+            List<LIRInstruction> instructions = lir.getLIRforBlock(block);
             assert instructions.get(0) instanceof StandardOp.LabelOp : "first instruction must always be a label";
             StandardOp.LabelOp label = (StandardOp.LabelOp) instructions.get(0);
             instructions.set(0, new StandardOp.LabelOp(label.getLabel(), true));
         }
     }
 
-    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 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java	Thu Mar 27 17:31:20 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,10 +118,10 @@
         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);
+            assert ir.getLIRforBlock(pred) != null;
+            List<LIRInstruction> predInstructions = ir.getLIRforBlock(pred);
 
             if (pred.getSuccessorCount() != 1) {
                 // this can happen with switch-statements where multiple edges are between
@@ -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()) {
@@ -158,7 +158,7 @@
             }
 
             // insert the instruction at the beginning of the current block
-            ir.lir(block).add(1, op);
+            ir.getLIRforBlock(block).add(1, op);
 
             // delete the instruction at the end of all predecessors
             for (int i = 0; i < numPreds; i++) {
@@ -173,12 +173,12 @@
      * {@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();
 
-        List<LIRInstruction> instructions = ir.lir(block);
+        List<LIRInstruction> instructions = ir.getLIRforBlock(block);
 
         assert numSux == 2 : "method should not be called otherwise";
 
@@ -203,8 +203,8 @@
         int insertIdx = instructions.size() - 1;
 
         // setup a list with the lir-instructions of all successors
-        for (Block sux : block.getSuccessors()) {
-            List<LIRInstruction> suxInstructions = ir.lir(sux);
+        for (AbstractBlock<?> sux : block.getSuccessors()) {
+            List<LIRInstruction> suxInstructions = ir.getLIRforBlock(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());
@@ -238,7 +238,7 @@
             }
 
             // insert instruction at end of current block
-            ir.lir(block).add(insertIdx, op);
+            ir.getLIRforBlock(block).add(insertIdx, op);
             insertIdx++;
 
             // delete the instructions at the beginning of all successors
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Thu Mar 27 17:31:20 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,8 +80,8 @@
      * Determines if any instruction in the LIR has debug info associated with it.
      */
     public boolean hasDebugInfo() {
-        for (Block b : linearScanOrder()) {
-            for (LIRInstruction op : lir(b)) {
+        for (AbstractBlock<?> b : linearScanOrder()) {
+            for (LIRInstruction op : getLIRforBlock(b)) {
                 if (op.hasState()) {
                     return true;
                 }
@@ -94,12 +94,12 @@
         return spillMoveFactory;
     }
 
-    public List<LIRInstruction> lir(AbstractBlock<?> block) {
+    public List<LIRInstruction> getLIRforBlock(AbstractBlock<?> block) {
         return lirInstructions.get(block);
     }
 
-    public void setLir(Block block, List<LIRInstruction> list) {
-        assert lir(block) == null : "lir instruction list should only be initialized once";
+    public void setLIRforBlock(AbstractBlock<?> block, List<LIRInstruction> list) {
+        assert getLIRforBlock(block) == null : "lir instruction list should only be initialized once";
         lirInstructions.put(block, list);
     }
 
@@ -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,8 +169,8 @@
      */
     public static final int MAX_EXCEPTION_EDGE_OP_DISTANCE_FROM_END = 3;
 
-    public static boolean verifyBlock(LIR lir, Block block) {
-        List<LIRInstruction> ops = lir.lir(block);
+    public static boolean verifyBlock(LIR lir, AbstractBlock<?> block) {
+        List<LIRInstruction> ops = lir.getLIRforBlock(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 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Thu Mar 27 17:31:20 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];
@@ -129,14 +129,14 @@
                 curVariablesLive.or(liveOutFor(block.getDominator()));
             }
 
-            assert lir.lir(block).get(0) instanceof StandardOp.LabelOp : "block must start with label";
+            assert lir.getLIRforBlock(block).get(0) instanceof StandardOp.LabelOp : "block must start with label";
 
             if (block.getSuccessorCount() > 0) {
-                LIRInstruction last = lir.lir(block).get(lir.lir(block).size() - 1);
+                LIRInstruction last = lir.getLIRforBlock(block).get(lir.getLIRforBlock(block).size() - 1);
                 assert last instanceof StandardOp.JumpOp : "block with successor must end with unconditional jump";
             }
 
-            for (LIRInstruction op : lir.lir(block)) {
+            for (LIRInstruction op : lir.getLIRforBlock(block)) {
                 curInstruction = op;
 
                 op.forEachInput(useProc);
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java	Thu Mar 27 17:31:20 2014 +0100
@@ -73,7 +73,7 @@
     }
 
     public Label label() {
-        return ((StandardOp.LabelOp) lir.lir(getTargetBlock()).get(0)).getLabel();
+        return ((StandardOp.LabelOp) lir.getLIRforBlock(getTargetBlock()).get(0)).getLabel();
     }
 
     @Override
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java	Thu Mar 27 17:31:20 2014 +0100
@@ -31,16 +31,16 @@
 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) {
-            List<LIRInstruction> list = ir.lir(block);
+    private static void foldNullChecks(LIR ir, List<? extends AbstractBlock<?>> blocks, int implicitNullCheckLimit) {
+        for (AbstractBlock<?> block : blocks) {
+            List<LIRInstruction> list = ir.getLIRforBlock(block);
 
             if (!list.isEmpty()) {
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java	Thu Mar 27 17:31:20 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,8 +143,8 @@
          * 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) {
-            List<LIRInstruction> instructions = lir.lir(block);
+        for (AbstractBlock<?> block : blocks) {
+            List<LIRInstruction> instructions = lir.getLIRforBlock(block);
             for (LIRInstruction op : instructions) {
                 if (isEligibleMove(op)) {
                     Value dest = ((MoveOp) op).getResult();
@@ -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);
                     }
@@ -244,7 +244,7 @@
                      */
                     int[] iterState = data.exitState;
                     copyState(iterState, data.entryState);
-                    List<LIRInstruction> instructions = lir.lir(block);
+                    List<LIRInstruction> instructions = lir.getLIRforBlock(block);
 
                     for (LIRInstruction op : instructions) {
                         valueNum = updateState(iterState, op, valueNum);
@@ -281,13 +281,13 @@
 
         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());
 
-            List<LIRInstruction> instructions = lir.lir(block);
+            List<LIRInstruction> instructions = lir.getLIRforBlock(block);
             BlockData data = blockData.get(block);
             boolean hasDead = false;
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Thu Mar 27 17:31:20 2014 +0100
@@ -182,20 +182,20 @@
         /**
          * The block in which this instruction is located.
          */
-        final Block block;
+        final AbstractBlock<?> block;
 
         /**
          * The block index of this instruction.
          */
         final int index;
 
-        public NoOp(Block block, int index) {
+        public NoOp(AbstractBlock<?> block, int index) {
             this.block = block;
             this.index = index;
         }
 
         public void replace(LIR lir, LIRInstruction replacement) {
-            lir.lir(block).set(index, replacement);
+            lir.getLIRforBlock(block).set(index, replacement);
         }
 
         @Override
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Thu Mar 27 17:31:20 2014 +0100
@@ -301,7 +301,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();
     }
@@ -315,7 +315,7 @@
         this.lir = lir;
         this.currentBlockIndex = 0;
         frameContext.enter(this);
-        for (Block b : lir.codeEmittingOrder()) {
+        for (AbstractBlock<?> b : lir.codeEmittingOrder()) {
             emitBlock(b);
             currentBlockIndex++;
         }
@@ -323,12 +323,12 @@
         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()));
         }
 
-        for (LIRInstruction op : lir.lir(block)) {
+        for (LIRInstruction op : lir.getLIRforBlock(block)) {
             if (Debug.isDumpEnabled()) {
                 blockComment(String.format("%d %s", op.id(), op));
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -128,7 +128,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         // nop
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -35,7 +35,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         gen.visitEndNode(this);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -54,7 +54,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         gen.visitBreakpointNode(this);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -54,7 +54,7 @@
     public abstract String targetName();
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         // nop
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -120,12 +120,12 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         assert ConstantNodeRecordsUsages : "LIR generator should generate constants per-usage";
-        if (gen.canInlineConstant(value) || onlyUsedInVirtualState()) {
+        if (gen.getLIRGeneratorTool().canInlineConstant(value) || onlyUsedInVirtualState()) {
             gen.setResult(this, value);
         } else {
-            gen.setResult(this, gen.emitMove(value));
+            gen.setResult(this, gen.getLIRGeneratorTool().emitMove(value));
         }
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -62,8 +62,8 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
-        gen.emitDeoptimize(gen.getMetaAccess().encodeDeoptActionAndReason(action, reason, debugId), speculation, this);
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.getLIRGeneratorTool().emitDeoptimize(gen.getLIRGeneratorTool().getMetaAccess().encodeDeoptActionAndReason(action, reason, debugId), speculation, this);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -54,8 +54,8 @@
         return getSpeculation();
     }
 
-    public void generate(LIRGeneratorTool generator) {
-        generator.emitDeoptimize(generator.operand(actionAndReason), generator.operand(speculation), this);
+    public void generate(NodeLIRGeneratorTool generator) {
+        generator.getLIRGeneratorTool().emitDeoptimize(generator.operand(actionAndReason), generator.operand(speculation), this);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -38,7 +38,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         throw new GraalInternalError("OnStackReplacementNode should not survive");
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -53,7 +53,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool generator) {
+    public void generate(NodeLIRGeneratorTool generator) {
         if (object.getKind() != Kind.Void && object.getKind() != Kind.Illegal) {
             generator.setResult(this, generator.operand(object));
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -127,7 +127,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         gen.emitIf(this);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -41,7 +41,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool generator) {
+    public void generate(NodeLIRGeneratorTool generator) {
         generator.visitInfopointNode(this);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -113,7 +113,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         gen.emitInvoke(this);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -133,7 +133,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         gen.emitInvoke(this);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicConstantNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicConstantNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -68,7 +68,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool generator) {
+    public void generate(NodeLIRGeneratorTool generator) {
         // nothing to do
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -98,7 +98,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         // Nothing to emit, since this is node is used for structural purposes only.
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -64,7 +64,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         gen.visitLoopEnd(this);
         super.generate(gen);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -42,7 +42,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool generator) {
+    public void generate(NodeLIRGeneratorTool generator) {
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -41,7 +41,7 @@
     @Input(notDataflow = true) private final NodeInputList<AbstractEndNode> ends = new NodeInputList<>(this);
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         gen.visitMerge(this);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -62,7 +62,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool generator) {
+    public void generate(NodeLIRGeneratorTool generator) {
         if (object.getKind() != Kind.Void && object.getKind() != Kind.Illegal) {
             generator.setResult(this, generator.operand(object));
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -57,7 +57,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         gen.visitReturn(this);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -35,7 +35,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         gen.visitSafepointNode(this);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -49,7 +49,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
-        gen.emitUnwind(gen.operand(exception()));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.getLIRGeneratorTool().emitUnwind(gen.operand(exception()));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -31,7 +31,7 @@
  * This class represents a value within the graph, including local variables, phis, and all other
  * instructions.
  */
-public abstract class ValueNode extends ScheduledNode implements StampProvider {
+public abstract class ValueNode extends ScheduledNode implements StampProvider, KindInterface {
 
     /**
      * The kind of this value. This is {@link Kind#Void} for instructions that produce no value.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -81,8 +81,8 @@
     }
 
     @Override
-    public void generate(ArithmeticLIRGenerator gen) {
-        gen.setResult(this, gen.emitAnd(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.setResult(this, gen.getLIRGeneratorTool().emitAnd(gen.operand(x()), gen.operand(y())));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -75,7 +75,7 @@
     public abstract boolean unorderedIsTrue();
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
     }
 
     private LogicNode optimizeConditional(Constant constant, ConditionalNode conditionalNode, ConstantReflectionProvider constantReflection, Condition cond) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -109,7 +109,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool generator) {
+    public void generate(NodeLIRGeneratorTool generator) {
         generator.emitConditional(this);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -65,7 +65,7 @@
     }
 
     @Override
-    public void generate(ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         Value op1 = gen.operand(x());
         Value op2 = gen.operand(y());
         if (!y().isConstant() && !livesLonger(this, y(), gen)) {
@@ -73,10 +73,10 @@
             op1 = op2;
             op2 = op;
         }
-        gen.setResult(this, gen.emitAdd(op1, op2));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitAdd(op1, op2));
     }
 
-    public static boolean livesLonger(ValueNode after, ValueNode value, ArithmeticLIRGenerator gen) {
+    public static boolean livesLonger(ValueNode after, ValueNode value, NodeLIRGeneratorTool gen) {
         for (Node usage : value.usages()) {
             if (usage != after && usage instanceof ValueNode && gen.hasOperand(((ValueNode) usage))) {
                 return true;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -192,8 +192,8 @@
         tool.getLowerer().lower(this, tool);
     }
 
-    public void generate(ArithmeticLIRGenerator gen) {
-        gen.setResult(this, gen.emitFloatConvert(op, gen.operand(getInput())));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.setResult(this, gen.getLIRGeneratorTool().emitFloatConvert(op, gen.operand(getInput())));
     }
 
     public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -57,8 +57,8 @@
     }
 
     @Override
-    public void generate(ArithmeticLIRGenerator gen) {
-        gen.setResult(this, gen.emitDiv(gen.operand(x()), gen.operand(y()), null));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.setResult(this, gen.getLIRGeneratorTool().emitDiv(gen.operand(x()), gen.operand(y()), null));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -60,7 +60,7 @@
     }
 
     @Override
-    public void generate(ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         Value op1 = gen.operand(x());
         Value op2 = gen.operand(y());
         if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), gen)) {
@@ -68,7 +68,7 @@
             op1 = op2;
             op2 = op;
         }
-        gen.setResult(this, gen.emitMul(op1, op2));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitMul(op1, op2));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -57,8 +57,8 @@
     }
 
     @Override
-    public void generate(ArithmeticLIRGenerator gen) {
-        gen.setResult(this, gen.emitRem(gen.operand(x()), gen.operand(y()), null));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.setResult(this, gen.getLIRGeneratorTool().emitRem(gen.operand(x()), gen.operand(y()), null));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -76,8 +76,8 @@
     }
 
     @Override
-    public void generate(ArithmeticLIRGenerator gen) {
-        gen.setResult(this, gen.emitSub(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.setResult(this, gen.getLIRGeneratorTool().emitSub(gen.operand(x()), gen.operand(y())));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -89,7 +89,7 @@
     }
 
     @Override
-    public void generate(ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         Value op1 = gen.operand(x());
         assert op1 != null : x() + ", this=" + this;
         Value op2 = gen.operand(y());
@@ -98,7 +98,7 @@
             op1 = op2;
             op2 = op;
         }
-        gen.setResult(this, gen.emitAdd(op1, op2));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitAdd(op1, op2));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -106,8 +106,8 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitDiv(gen.operand(x()), gen.operand(y()), this));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.setResult(this, gen.getLIRGeneratorTool().emitDiv(gen.operand(x()), gen.operand(y()), this));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -75,7 +75,7 @@
     }
 
     @Override
-    public void generate(ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         Value op1 = gen.operand(x());
         Value op2 = gen.operand(y());
         if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), gen)) {
@@ -83,7 +83,7 @@
             op1 = op2;
             op2 = op;
         }
-        gen.setResult(this, gen.emitMul(op1, op2));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitMul(op1, op2));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -61,8 +61,8 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitRem(gen.operand(x()), gen.operand(y()), this));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.setResult(this, gen.getLIRGeneratorTool().emitRem(gen.operand(x()), gen.operand(y()), this));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -117,8 +117,8 @@
     }
 
     @Override
-    public void generate(ArithmeticLIRGenerator gen) {
-        gen.setResult(this, gen.emitSub(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.setResult(this, gen.getLIRGeneratorTool().emitSub(gen.operand(x()), gen.operand(y())));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -60,7 +60,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -50,7 +50,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         // Nothing to do.
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -92,7 +92,7 @@
     }
 
     @Override
-    public void generate(ArithmeticLIRGenerator gen) {
-        gen.setResult(this, gen.emitShl(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.setResult(this, gen.getLIRGeneratorTool().emitShl(gen.operand(x()), gen.operand(y())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -110,8 +110,8 @@
     }
 
     @Override
-    public void generate(ArithmeticLIRGenerator gen) {
-        gen.setResult(this, gen.emitNarrow(gen.operand(getInput()), getResultBits()));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.setResult(this, gen.getLIRGeneratorTool().emitNarrow(gen.operand(getInput()), getResultBits()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -88,7 +88,7 @@
     }
 
     @Override
-    public void generate(ArithmeticLIRGenerator gen) {
-        gen.setResult(this, gen.emitNegate(gen.operand(x())));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.setResult(this, gen.getLIRGeneratorTool().emitNegate(gen.operand(x())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -73,7 +73,7 @@
     }
 
     @Override
-    public void generate(ArithmeticLIRGenerator gen) {
-        gen.setResult(this, gen.emitNot(gen.operand(x())));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.setResult(this, gen.getLIRGeneratorTool().emitNot(gen.operand(x())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -73,8 +73,8 @@
     }
 
     @Override
-    public void generate(ArithmeticLIRGenerator gen) {
-        gen.setResult(this, gen.emitOr(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.setResult(this, gen.getLIRGeneratorTool().emitOr(gen.operand(x()), gen.operand(y())));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -102,9 +102,9 @@
     }
 
     @Override
-    public void generate(ArithmeticLIRGenerator gen) {
-        PlatformKind kind = gen.getPlatformKind(stamp());
-        gen.setResult(this, gen.emitReinterpret(kind, gen.operand(value())));
+    public void generate(NodeLIRGeneratorTool gen) {
+        PlatformKind kind = gen.getLIRGeneratorTool().getPlatformKind(stamp());
+        gen.setResult(this, gen.getLIRGeneratorTool().emitReinterpret(kind, gen.operand(value())));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -98,7 +98,7 @@
     }
 
     @Override
-    public void generate(ArithmeticLIRGenerator gen) {
-        gen.setResult(this, gen.emitShr(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.setResult(this, gen.getLIRGeneratorTool().emitShr(gen.operand(x()), gen.operand(y())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -105,8 +105,8 @@
     }
 
     @Override
-    public void generate(ArithmeticLIRGenerator gen) {
-        gen.setResult(this, gen.emitSignExtend(gen.operand(getInput()), getInputBits(), getResultBits()));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.setResult(this, gen.getLIRGeneratorTool().emitSignExtend(gen.operand(getInput()), getInputBits(), getResultBits()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -71,8 +71,8 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitUDiv(gen.operand(x()), gen.operand(y()), this));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.setResult(this, gen.getLIRGeneratorTool().emitUDiv(gen.operand(x()), gen.operand(y()), this));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -70,8 +70,8 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitURem(gen.operand(x()), gen.operand(y()), this));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.setResult(this, gen.getLIRGeneratorTool().emitURem(gen.operand(x()), gen.operand(y()), this));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -92,7 +92,7 @@
     }
 
     @Override
-    public void generate(ArithmeticLIRGenerator gen) {
-        gen.setResult(this, gen.emitUShr(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.setResult(this, gen.getLIRGeneratorTool().emitUShr(gen.operand(x()), gen.operand(y())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -72,8 +72,8 @@
     }
 
     @Override
-    public void generate(ArithmeticLIRGenerator gen) {
-        gen.setResult(this, gen.emitXor(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.setResult(this, gen.getLIRGeneratorTool().emitXor(gen.operand(x()), gen.operand(y())));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -85,8 +85,8 @@
     }
 
     @Override
-    public void generate(ArithmeticLIRGenerator gen) {
-        gen.setResult(this, gen.emitZeroExtend(gen.operand(getInput()), getInputBits(), getResultBits()));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.setResult(this, gen.getLIRGeneratorTool().emitZeroExtend(gen.operand(getInput()), getInputBits(), getResultBits()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractBlock.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractBlock.java	Thu Mar 27 17:31:20 2014 +0100
@@ -22,14 +22,12 @@
  */
 package com.oracle.graal.nodes.cfg;
 
-import com.oracle.graal.nodes.*;
+import java.util.*;
 
 public interface AbstractBlock<T extends AbstractBlock<?>> {
 
     int getId();
 
-    AbstractBeginNode getBeginNode();
-
     Loop getLoop();
 
     int getLoopDepth();
@@ -40,11 +38,11 @@
 
     boolean isExceptionEntry();
 
-    Iterable<T> getPredecessors();
+    List<T> getPredecessors();
 
     int getPredecessorCount();
 
-    Iterable<T> getSuccessors();
+    List<T> getSuccessors();
 
     int getSuccessorCount();
 
@@ -55,4 +53,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/AbstractBlockBase.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2009, 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.nodes.cfg;
+
+import java.util.*;
+
+public abstract class AbstractBlockBase<T extends AbstractBlock<T>> implements AbstractBlock<T> {
+
+    protected int id;
+
+    protected List<T> predecessors;
+    protected List<T> successors;
+
+    protected T dominator;
+
+    private boolean align;
+    private int linearScanNumber;
+
+    protected AbstractBlockBase() {
+        this.id = ControlFlowGraph.BLOCK_ID_INITIAL;
+        this.linearScanNumber = -1;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public List<T> getPredecessors() {
+        return predecessors;
+    }
+
+    public List<T> getSuccessors() {
+        return successors;
+    }
+
+    public T getDominator() {
+        return dominator;
+    }
+
+    @Override
+    public String toString() {
+        return "B" + id;
+    }
+
+    public int getPredecessorCount() {
+        return getPredecessors().size();
+    }
+
+    public int getSuccessorCount() {
+        return getSuccessors().size();
+    }
+
+    public int getLinearScanNumber() {
+        return linearScanNumber;
+    }
+
+    public void setLinearScanNumber(int linearScanNumber) {
+        this.linearScanNumber = linearScanNumber;
+    }
+
+    public boolean isAligned() {
+        return align;
+    }
+
+    public void setAlign(boolean align) {
+        this.align = align;
+    }
+}
--- /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 27 17:31:20 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();
+
+    T getStartBlock();
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java	Thu Mar 27 17:31:20 2014 +0100
@@ -27,34 +27,18 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 
-public final class Block implements AbstractBlock<Block> {
+public final class Block extends AbstractBlockBase<Block> {
 
     protected final AbstractBeginNode beginNode;
 
-    protected int id;
-
     protected FixedNode endNode;
     protected Loop loop;
 
-    protected List<Block> predecessors;
-    protected List<Block> successors;
-
-    protected Block dominator;
     protected List<Block> dominated;
     protected Block postdominator;
 
-    private boolean align;
-    private int linearScanNumber;
-
     protected Block(AbstractBeginNode node) {
         this.beginNode = node;
-
-        this.id = ControlFlowGraph.BLOCK_ID_INITIAL;
-        this.linearScanNumber = -1;
-    }
-
-    public int getId() {
-        return id;
     }
 
     public AbstractBeginNode getBeginNode() {
@@ -89,22 +73,10 @@
         return predecessors.get(0);
     }
 
-    public List<Block> getPredecessors() {
-        return predecessors;
-    }
-
     public Block getFirstSuccessor() {
         return successors.get(0);
     }
 
-    public List<Block> getSuccessors() {
-        return successors;
-    }
-
-    public Block getDominator() {
-        return dominator;
-    }
-
     public Block getEarliestPostDominated() {
         Block b = this;
         while (true) {
@@ -187,14 +159,6 @@
         return "B" + id;
     }
 
-    public int getPredecessorCount() {
-        return getPredecessors().size();
-    }
-
-    public int getSuccessorCount() {
-        return getSuccessors().size();
-    }
-
     public boolean dominates(Block block) {
         return block.isDominatedBy(this);
     }
@@ -209,19 +173,4 @@
         return dominator.isDominatedBy(block);
     }
 
-    public int getLinearScanNumber() {
-        return linearScanNumber;
-    }
-
-    public void setLinearScanNumber(int linearScanNumber) {
-        this.linearScanNumber = linearScanNumber;
-    }
-
-    public boolean isAligned() {
-        return align;
-    }
-
-    public void setAlign(boolean align) {
-        this.align = align;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/BlockMap.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/BlockMap.java	Thu Mar 27 17:31:20 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];
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/BlocksToDoubles.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013, 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;
+
+import java.util.*;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.util.*;
+
+public class BlocksToDoubles {
+
+    private final IdentityHashMap<AbstractBlock<?>, Double> nodeProbabilities;
+
+    public BlocksToDoubles(int numberOfNodes) {
+        this.nodeProbabilities = new IdentityHashMap<>(numberOfNodes);
+    }
+
+    public void put(AbstractBlock<?> n, double value) {
+        assert value >= 0.0 : value;
+        nodeProbabilities.put(n, value);
+    }
+
+    public boolean contains(AbstractBlock<?> n) {
+        return nodeProbabilities.containsKey(n);
+    }
+
+    public double get(AbstractBlock<?> n) {
+        Double value = nodeProbabilities.get(n);
+        assert value != null;
+        return value;
+    }
+
+    public static BlocksToDoubles createFromNodeProbability(NodesToDoubles nodeProbabilities, ControlFlowGraph cfg) {
+        BlocksToDoubles blockProbabilities = new BlocksToDoubles(cfg.getBlocks().length);
+        for (Block block : cfg.getBlocks()) {
+            blockProbabilities.put(block, nodeProbabilities.get(block.getBeginNode()));
+        }
+        assert verify(nodeProbabilities, cfg, blockProbabilities) : "Probabilities differ for nodes in the same block.";
+        return blockProbabilities;
+    }
+
+    private static boolean verify(NodesToDoubles nodeProbabilities, ControlFlowGraph cfg, BlocksToDoubles blockProbabilities) {
+        for (Block b : cfg.getBlocks()) {
+            double p = blockProbabilities.get(b);
+            for (FixedNode n : b.getNodes()) {
+                if (nodeProbabilities.get(n) != p) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Thu Mar 27 17:31:20 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.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -107,7 +107,7 @@
     }
 
     @Override
-    public Value generateAddress(LIRGeneratorTool gen, Value base) {
+    public Value generateAddress(NodeLIRGeneratorTool gen, Value base) {
         Value xAddr = getX().generateAddress(gen, base);
         return getY().generateAddress(gen, xAddr);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -48,7 +48,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         Value addr = getLocation().generateAddress(gen, gen.operand(getObject()));
         gen.setResult(this, addr);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -65,7 +65,7 @@
     }
 
     @Override
-    public Value generateAddress(LIRGeneratorTool gen, Value base) {
-        return gen.emitAddress(base, getDisplacement(), Value.ILLEGAL, 0);
+    public Value generateAddress(NodeLIRGeneratorTool gen, Value base) {
+        return gen.getLIRGeneratorTool().emitAddress(base, getDisplacement(), Value.ILLEGAL, 0);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -49,7 +49,7 @@
     public static native <T> T getObject(Object object);
 
     @Override
-    public void generate(LIRGeneratorTool generator) {
+    public void generate(NodeLIRGeneratorTool generator) {
         generator.setResult(this, generator.operand(object));
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -60,9 +60,9 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         Value address = location().generateAddress(gen, gen.operand(object()));
-        gen.setResult(this, gen.emitLoad(location().getValueKind(), address, this));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(location().getValueKind(), address, this));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -82,7 +82,7 @@
         return foreignCalls.getKilledLocations(descriptor);
     }
 
-    protected Value[] operands(LIRGeneratorTool gen) {
+    protected Value[] operands(NodeLIRGeneratorTool gen) {
         Value[] operands = new Value[arguments.size()];
         for (int i = 0; i < operands.length; i++) {
             operands[i] = gen.operand(arguments.get(i));
@@ -91,10 +91,10 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
-        ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(descriptor);
+    public void generate(NodeLIRGeneratorTool gen) {
+        ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(descriptor);
         Value[] operands = operands(gen);
-        Value result = gen.emitForeignCall(linkage, this, operands);
+        Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, this, operands);
         if (result != null) {
             gen.setResult(this, result);
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -96,7 +96,7 @@
     }
 
     @Override
-    public Value generateAddress(LIRGeneratorTool gen, Value base) {
-        return gen.emitAddress(base, displacement, gen.operand(getIndex()), getIndexScaling());
+    public Value generateAddress(NodeLIRGeneratorTool gen, Value base) {
+        return gen.getLIRGeneratorTool().emitAddress(base, displacement, gen.operand(getIndex()), getIndexScaling());
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -101,7 +101,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         gen.emitSwitch(this);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -56,9 +56,9 @@
     public abstract LocationIdentity getLocationIdentity();
 
     @Override
-    public final void generate(LIRGeneratorTool generator) {
+    public final void generate(NodeLIRGeneratorTool generator) {
         // nothing to do...
     }
 
-    public abstract Value generateAddress(LIRGeneratorTool gen, Value base);
+    public abstract Value generateAddress(NodeLIRGeneratorTool gen, Value base);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -56,8 +56,8 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool generator) {
-        generator.emitMembar(barriers);
+    public void generate(NodeLIRGeneratorTool generator) {
+        generator.getLIRGeneratorTool().emitMembar(barriers);
     }
 
     public MemoryCheckpoint asMemoryCheckpoint() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -40,7 +40,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool generator) {
+    public void generate(NodeLIRGeneratorTool generator) {
         generator.emitNullCheck(object, this);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -53,9 +53,9 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         Value address = location().generateAddress(gen, gen.operand(object()));
-        gen.setResult(this, gen.emitLoad(location().getValueKind(), address, this));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(location().getValueKind(), address, this));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SnippetLocationNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SnippetLocationNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -100,7 +100,7 @@
     }
 
     @Override
-    public Value generateAddress(LIRGeneratorTool gen, Value base) {
+    public Value generateAddress(NodeLIRGeneratorTool gen, Value base) {
         throw new GraalInternalError("locationIdentity must be a constant so that this node can be canonicalized: " + locationIdentity);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -94,7 +94,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool generator) {
+    public void generate(NodeLIRGeneratorTool generator) {
         assert getKind() == Kind.Object && object.getKind() == Kind.Object;
         /*
          * The LIR only cares about the kind of an operand, not the actual type of an object. So we
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -42,7 +42,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         // Nothing to emit, since this node is used for structural purposes only.
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -80,17 +80,17 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         Value address = location().generateAddress(gen, gen.operand(object()));
         // It's possible a constant was forced for other usages so inspect the value directly and
         // use a constant if it can be directly stored.
         Value v;
-        if (value().isConstant() && gen.canStoreConstant(value().asConstant(), isCompressible())) {
+        if (value().isConstant() && gen.getLIRGeneratorTool().canStoreConstant(value().asConstant(), isCompressible())) {
             v = value().asConstant();
         } else {
             v = gen.operand(value());
         }
-        gen.emitStore(location().getValueKind(), address, v, this);
+        gen.getLIRGeneratorTool().emitStore(location().getValueKind(), address, v, this);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -72,7 +72,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         gen.visitCompareAndSwap(this, location().generateAddress(gen, gen.operand(object())));
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -49,7 +49,7 @@
         this.lockDepth = lockDepth;
     }
 
-    public void generate(LIRGeneratorTool generator) {
+    public void generate(NodeLIRGeneratorTool generator) {
         // nothing to do
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -51,9 +51,9 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
-        ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(REGISTER_FINALIZER);
-        gen.emitForeignCall(linkage, this, gen.operand(object()));
+    public void generate(NodeLIRGeneratorTool gen) {
+        ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(REGISTER_FINALIZER);
+        gen.getLIRGeneratorTool().emitForeignCall(linkage, this, gen.operand(object()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -29,7 +29,7 @@
 import com.oracle.graal.graph.GraalInternalError;
 import com.oracle.graal.graph.NodeInputList;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.LIRGeneratorTool;
+import com.oracle.graal.nodes.spi.NodeLIRGeneratorTool;
 import com.oracle.graal.nodes.spi.Lowerable;
 import com.oracle.graal.nodes.spi.LoweringTool;
 
@@ -78,7 +78,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         throw GraalInternalError.shouldNotReachHere("should have replaced itself");
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -92,7 +92,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         gen.emitSwitch(this);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRGenerator.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRGenerator.java	Thu Mar 27 17:31:20 2014 +0100
@@ -28,17 +28,12 @@
 import com.oracle.graal.nodes.type.*;
 
 /**
- * This interface can be used to generate LIR for arithmetic operations (@see
- * ArithmeticLIRLowerable).
+ * This interface can be used to generate LIR for arithmetic operations.
  */
 public interface ArithmeticLIRGenerator {
-
-    Value operand(ValueNode object);
-
-    boolean hasOperand(ValueNode object);
-
-    Value setResult(ValueNode x, Value operand);
-
+    /**
+     * TODO remove reference to {@link Stamp}.
+     */
     PlatformKind getPlatformKind(Stamp stamp);
 
     Value emitNegate(Value input);
@@ -49,12 +44,24 @@
 
     Value emitMul(Value a, Value b);
 
+    /**
+     * TODO remove {@link DeoptimizeNode}.
+     */
     Value emitDiv(Value a, Value b, DeoptimizingNode deopting);
 
+    /**
+     * TODO remove {@link DeoptimizeNode}.
+     */
     Value emitRem(Value a, Value b, DeoptimizingNode deopting);
 
+    /**
+     * TODO remove {@link DeoptimizeNode}.
+     */
     Value emitUDiv(Value a, Value b, DeoptimizingNode deopting);
 
+    /**
+     * TODO remove {@link DeoptimizeNode}.
+     */
     Value emitURem(Value a, Value b, DeoptimizingNode deopting);
 
     Value emitNot(Value input);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRLowerable.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRLowerable.java	Thu Mar 27 17:31:20 2014 +0100
@@ -26,5 +26,5 @@
 
 public interface ArithmeticLIRLowerable extends ArithmeticOperation {
 
-    void generate(ArithmeticLIRGenerator gen);
+    void generate(NodeLIRGeneratorTool gen);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Thu Mar 27 17:31:20 2014 +0100
@@ -25,9 +25,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.java.*;
 
 public interface LIRGeneratorTool extends ArithmeticLIRGenerator {
 
@@ -39,6 +37,14 @@
 
     ForeignCallsProvider getForeignCalls();
 
+    Value emitLoad(Kind kind, Value address, Access access);
+
+    void emitStore(Kind kind, Value address, Value input, Access access);
+
+    void emitDeoptimize(Value actionAndReason, Value failedSpeculation, DeoptimizingNode deopting);
+
+    Value emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args);
+
     /**
      * Checks whether the supplied constant can be used without loading it into a register for most
      * operations, i.e., for commonly used arithmetic, logical, and comparison operations.
@@ -71,43 +77,8 @@
 
     Value emitAddress(StackSlot slot);
 
-    Value emitLoad(Kind kind, Value address, Access access);
-
-    void emitStore(Kind kind, Value address, Value input, Access access);
-
     void emitMembar(int barriers);
 
-    void emitDeoptimize(Value actionAndReason, Value failedSpeculation, DeoptimizingNode deopting);
-
-    void emitNullCheck(ValueNode v, DeoptimizingNode deopting);
-
-    Value emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args);
-
-    void emitIf(IfNode i);
-
-    void emitConditional(ConditionalNode i);
-
-    void emitSwitch(SwitchNode i);
-
-    void emitInvoke(Invoke i);
-
-    // Handling of block-end nodes still needs to be unified in the LIRGenerator.
-    void visitMerge(MergeNode i);
-
-    void visitEndNode(AbstractEndNode i);
-
-    void visitLoopEnd(LoopEndNode i);
-
-    void visitCompareAndSwap(LoweredCompareAndSwapNode i, Value address);
-
-    // These methods define the contract a runtime specific backend must provide.
-
-    void visitReturn(ReturnNode i);
-
-    void visitSafepointNode(SafepointNode i);
-
-    void visitBreakpointNode(BreakpointNode i);
-
     void emitUnwind(Value operand);
 
     /**
@@ -116,5 +87,7 @@
      */
     void beforeRegisterAllocation();
 
-    void visitInfopointNode(InfopointNode i);
+    void emitIncomingValues(Value[] params);
+
+    void emitReturn(Value input);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRLowerable.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRLowerable.java	Thu Mar 27 17:31:20 2014 +0100
@@ -24,5 +24,5 @@
 
 public interface LIRLowerable {
 
-    void generate(LIRGeneratorTool generator);
+    void generate(NodeLIRGeneratorTool generator);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRGeneratorTool.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2011, 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.nodes.spi;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
+
+public interface NodeLIRGeneratorTool extends NodeMappableLIRGenerator {
+
+    void emitNullCheck(ValueNode v, DeoptimizingNode deopting);
+
+    void emitIf(IfNode i);
+
+    void emitConditional(ConditionalNode i);
+
+    void emitSwitch(SwitchNode i);
+
+    void emitInvoke(Invoke i);
+
+    // Handling of block-end nodes still needs to be unified in the LIRGenerator.
+    void visitMerge(MergeNode i);
+
+    void visitEndNode(AbstractEndNode i);
+
+    void visitLoopEnd(LoopEndNode i);
+
+    void visitCompareAndSwap(LoweredCompareAndSwapNode i, Value address);
+
+    // These methods define the contract a runtime specific backend must provide.
+
+    void visitReturn(ReturnNode i);
+
+    void visitSafepointNode(SafepointNode i);
+
+    void visitBreakpointNode(BreakpointNode i);
+
+    void visitInfopointNode(InfopointNode i);
+
+    LIRGeneratorTool getLIRGeneratorTool();
+
+    void emitOverflowCheckBranch(AbstractBeginNode overflowSuccessor, AbstractBeginNode next, double probability);
+
+    Value[] visitInvokeArguments(CallingConvention cc, Collection<ValueNode> arguments);
+
+    MemoryArithmeticLIRLowerer getMemoryLowerer();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeMappableLIRGenerator.java	Thu Mar 27 17:31:20 2014 +0100
@@ -0,0 +1,36 @@
+/*
+ * 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.spi;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+
+public interface NodeMappableLIRGenerator {
+
+    Value operand(ValueNode object);
+
+    boolean hasOperand(ValueNode object);
+
+    Value setResult(ValueNode x, Value operand);
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -56,7 +56,7 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         // nothing to do...
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -91,7 +91,7 @@
     public abstract ValueNode getMaterializedRepresentation(FixedNode fixed, ValueNode[] entries, LockState locks);
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         // nothing to do...
     }
 }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Thu Mar 27 17:31:20 2014 +0100
@@ -50,7 +50,7 @@
 
     protected TargetDescription target;
     protected LIR lir;
-    protected LIRGenerator lirGenerator;
+    protected NodeLIRGenerator nodeLirGenerator;
     protected ControlFlowGraph cfg;
     protected SchedulePhase schedule;
 
@@ -73,7 +73,7 @@
     public void printCFG(String label, BciBlockMapping blockMap) {
         begin("cfg");
         out.print("name \"").print(label).println('"');
-        for (BciBlockMapping.Block block : blockMap.blocks) {
+        for (BciBlockMapping.BciBlock block : blockMap.blocks) {
             begin("block");
             printBlock(block);
             end("block");
@@ -81,7 +81,7 @@
         end("cfg");
     }
 
-    private void printBlock(BciBlockMapping.Block block) {
+    private void printBlock(BciBlockMapping.BciBlock block) {
         out.print("name \"B").print(block.startBci).println('"');
         out.print("from_bci ").println(block.startBci);
         out.print("to_bci ").println(block.endBci);
@@ -89,7 +89,7 @@
         out.println("predecessors ");
 
         out.print("successors ");
-        for (BciBlockMapping.Block succ : block.successors) {
+        for (BciBlockMapping.BciBlock succ : block.getSuccessors()) {
             if (!succ.isExceptionEntry) {
                 out.print("\"B").print(succ.startBci).print("\" ");
             }
@@ -97,7 +97,7 @@
         out.println();
 
         out.print("xhandlers");
-        for (BciBlockMapping.Block succ : block.successors) {
+        for (BciBlockMapping.BciBlock succ : block.getSuccessors()) {
             if (succ.isExceptionEntry) {
                 out.print("\"B").print(succ.startBci).print("\" ");
             }
@@ -129,10 +129,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;
@@ -146,17 +147,15 @@
                 }
             }
         }
-        printedNodes = new NodeBitMap(cfg.graph);
 
         begin("cfg");
         out.print("name \"").print(label).println('"');
-        for (Block block : blocks) {
+        for (AbstractBlock<?> block : blocks) {
             printBlock(block, printNodes);
         }
         end("cfg");
 
         latestScheduling = null;
-        printedNodes = null;
     }
 
     private void scheduleInputs(Node node, Block nodeBlock) {
@@ -187,20 +186,21 @@
         }
     }
 
-    private void printBlock(Block block, boolean printNodes) {
+    private void printBlock(AbstractBlock<?> block, boolean printNodes) {
         printBlockProlog(block);
         if (printNodes) {
-            printNodes(block);
+            assert block instanceof Block;
+            printNodes((Block) block);
         }
         printBlockEpilog(block);
     }
 
-    private void printBlockEpilog(Block block) {
+    private void printBlockEpilog(AbstractBlock<?> block) {
         printLIR(block);
         end("block");
     }
 
-    private void printBlockProlog(Block block) {
+    private void printBlockProlog(AbstractBlock<?> block) {
         begin("block");
 
         out.print("name \"").print(blockToString(block)).println('"');
@@ -208,13 +208,13 @@
         out.println("to_bci -1");
 
         out.print("predecessors ");
-        for (Block pred : block.getPredecessors()) {
+        for (AbstractBlock<?> pred : block.getPredecessors()) {
             out.print("\"").print(blockToString(pred)).print("\" ");
         }
         out.println();
 
         out.print("successors ");
-        for (Block succ : block.getSuccessors()) {
+        for (AbstractBlock<?> succ : block.getSuccessors()) {
             if (!succ.isExceptionEntry()) {
                 out.print("\"").print(blockToString(succ)).print("\" ");
             }
@@ -222,7 +222,7 @@
         out.println();
 
         out.print("xhandlers");
-        for (Block succ : block.getSuccessors()) {
+        for (AbstractBlock<?> succ : block.getSuccessors()) {
             if (succ.isExceptionEntry()) {
                 out.print("\"").print(blockToString(succ)).print("\" ");
             }
@@ -248,6 +248,7 @@
     }
 
     private void printNodes(Block block) {
+        printedNodes = new NodeBitMap(cfg.graph);
         begin("IR");
         out.println("HIR");
         out.disableIndentation();
@@ -281,6 +282,7 @@
 
         out.enableIndentation();
         end("IR");
+        printedNodes = null;
     }
 
     private void printNode(Node node, boolean unscheduled) {
@@ -307,8 +309,8 @@
         }
         out.print("tid ").print(nodeToString(node)).println(COLUMN_END);
 
-        if (lirGenerator != null) {
-            Value operand = lirGenerator.nodeOperands.get(node);
+        if (nodeLirGenerator != null) {
+            Value operand = nodeLirGenerator.getNodeOperands().get(node);
             if (operand != null) {
                 out.print("result ").print(operand.toString()).println(COLUMN_END);
             }
@@ -412,8 +414,8 @@
 
     private String stateValueToString(ValueNode value) {
         String result = nodeToString(value);
-        if (lirGenerator != null && lirGenerator.nodeOperands != null && value != null) {
-            Value operand = lirGenerator.nodeOperands.get(value);
+        if (nodeLirGenerator != null && nodeLirGenerator.getNodeOperands() != null && value != null) {
+            Value operand = nodeLirGenerator.getNodeOperands().get(value);
             if (operand != null) {
                 result += ": " + operand;
             }
@@ -426,11 +428,11 @@
      * 
      * @param block the block to print
      */
-    private void printLIR(Block block) {
+    private void printLIR(AbstractBlock<?> block) {
         if (lir == null) {
             return;
         }
-        List<LIRInstruction> lirInstructions = lir.lir(block);
+        List<LIRInstruction> lirInstructions = lir.getLIRforBlock(block);
         if (lirInstructions == null) {
             return;
         }
@@ -488,13 +490,13 @@
         return prefix + node.toString(Verbosity.Id);
     }
 
-    private String blockToString(Block block) {
-        if (lir == null && schedule == null) {
+    private String blockToString(AbstractBlock<?> block) {
+        if (lir == null && schedule == null && block instanceof Block) {
             // During all the front-end phases, the block schedule is built only for the debug
             // output.
             // Therefore, the block numbers would be different for every CFG printed -> use the id
             // of the first instruction.
-            return "B" + block.getBeginNode().toString(Verbosity.Id);
+            return "B" + ((Block) block).getBeginNode().toString(Verbosity.Id);
         } else {
             // LIR instructions contain references to blocks and these blocks are printed as the
             // blockID -> use the blockID.
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Thu Mar 27 17:31:20 2014 +0100
@@ -137,12 +137,12 @@
         } else {
             cfgPrinter.lir = Debug.contextLookup(LIR.class);
         }
-        cfgPrinter.lirGenerator = Debug.contextLookup(LIRGenerator.class);
-        if (cfgPrinter.lirGenerator != null) {
-            cfgPrinter.target = cfgPrinter.lirGenerator.target();
+        cfgPrinter.nodeLirGenerator = Debug.contextLookup(NodeLIRGenerator.class);
+        if (cfgPrinter.nodeLirGenerator != null) {
+            cfgPrinter.target = cfgPrinter.nodeLirGenerator.getLIRGeneratorTool().target();
         }
-        if (cfgPrinter.lir != null) {
-            cfgPrinter.cfg = cfgPrinter.lir.getControlFlowGraph();
+        if (cfgPrinter.lir != null && cfgPrinter.lir.getControlFlowGraph() instanceof ControlFlowGraph) {
+            cfgPrinter.cfg = (ControlFlowGraph) cfgPrinter.lir.getControlFlowGraph();
         }
 
         CodeCacheProvider codeCache = Debug.contextLookup(CodeCacheProvider.class);
@@ -160,7 +160,7 @@
         } else if (object instanceof LIR) {
             // No need to print the HIR nodes again if this is not the first
             // time dumping the same LIR since the HIR will not have changed.
-            boolean printNodes = previousObject != object;
+            boolean printNodes = previousObject != object && cfgPrinter.cfg != null;
             cfgPrinter.printCFG(message, cfgPrinter.lir.codeEmittingOrder(), printNodes);
 
         } else if (object instanceof SchedulePhase) {
@@ -185,7 +185,7 @@
 
         cfgPrinter.target = null;
         cfgPrinter.lir = null;
-        cfgPrinter.lirGenerator = null;
+        cfgPrinter.nodeLirGenerator = null;
         cfgPrinter.cfg = null;
         cfgPrinter.flush();
 
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -51,7 +51,7 @@
         throw GraalInternalError.shouldNotReachHere();
     }
 
-    public void generate(ArithmeticLIRGenerator gen) {
-        gen.setResult(this, gen.emitFloatConvert(op, gen.operand(value)));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.setResult(this, gen.getLIRGeneratorTool().emitFloatConvert(op, gen.operand(value)));
     }
 }
--- a/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -33,8 +33,7 @@
 import com.oracle.graal.nodes.calc.FloatingNode;
 import com.oracle.graal.nodes.ConstantNode;
 import com.oracle.graal.nodes.ValueNode;
-import com.oracle.graal.nodes.spi.ArithmeticLIRGenerator;
-import com.oracle.graal.nodes.spi.ArithmeticLIRLowerable;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.StampFactory;
 
 /**
@@ -86,24 +85,24 @@
      * Generates the LIR instructions for the math operation represented by this node.
      */
     @Override
-    public void generate(ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         Value input = gen.operand(getParameter());
         Value result;
         switch (operation()) {
             case ABS:
-                result = gen.emitMathAbs(input);
+                result = gen.getLIRGeneratorTool().emitMathAbs(input);
                 break;
             case CEIL:
-                result = ((HSAILLIRGenerator) (gen)).emitMathCeil(input);
+                result = ((HSAILLIRGenerator) (gen.getLIRGeneratorTool())).emitMathCeil(input);
                 break;
             case FLOOR:
-                result = ((HSAILLIRGenerator) (gen)).emitMathFloor(input);
+                result = ((HSAILLIRGenerator) (gen.getLIRGeneratorTool())).emitMathFloor(input);
                 break;
             case RINT:
-                result = ((HSAILLIRGenerator) (gen)).emitMathRint(input);
+                result = ((HSAILLIRGenerator) (gen.getLIRGeneratorTool())).emitMathRint(input);
                 break;
             case SQRT:
-                result = gen.emitMathSqrt(input);
+                result = gen.getLIRGeneratorTool().emitMathSqrt(input);
                 break;
 
             default:
@@ -175,4 +174,5 @@
      */
     @NodeIntrinsic
     public static native double compute(double value, @ConstantNodeParameter HSAILArithmetic op);
+
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java	Thu Mar 27 17:31:20 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/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -131,7 +131,7 @@
     public static native boolean equals(double[] array1, double[] array2, int length);
 
     @Override
-    public void generate(LIRGenerator gen) {
+    public void generate(NodeLIRGenerator gen) {
         Variable result = gen.newVariable(Kind.Int);
         gen.emitArrayEquals(kind, result, gen.operand(array1), gen.operand(array2), gen.operand(length));
         gen.setResult(this, result);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -65,7 +65,7 @@
     }
 
     @Override
-    public void generate(LIRGenerator gen) {
+    public void generate(NodeLIRGenerator gen) {
         Variable result = gen.newVariable(Kind.Int);
         gen.emitBitCount(result, gen.operand(value));
         gen.setResult(this, result);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -72,7 +72,7 @@
     }
 
     @Override
-    public void generate(LIRGenerator gen) {
+    public void generate(NodeLIRGenerator gen) {
         Variable result = gen.newVariable(Kind.Int);
         gen.emitBitScanForward(result, gen.operand(value));
         gen.setResult(this, result);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -79,9 +79,9 @@
     }
 
     @Override
-    public void generate(LIRGenerator gen) {
+    public void generate(NodeLIRGenerator gen) {
         Variable result = gen.newVariable(Kind.Int);
-        gen.emitBitScanReverse(result, gen.operand(value));
+        gen.getLIRGeneratorTool().emitBitScanReverse(result, gen.operand(value));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -46,8 +46,8 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitLoad(readKind, gen.operand(address), null));
+    public void generate(NodeLIRGeneratorTool gen) {
+        gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, gen.operand(address), null));
     }
 
     @SuppressWarnings("unchecked")
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -48,9 +48,9 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         Value v = gen.operand(value);
-        gen.emitStore(kind, gen.operand(address), v, null);
+        gen.getLIRGeneratorTool().emitStore(kind, gen.operand(address), v, null);
     }
 
     /*
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -55,30 +55,30 @@
     }
 
     @Override
-    public void generate(ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRGeneratorTool gen) {
         Value input = gen.operand(x());
         Value result;
         switch (operation()) {
             case ABS:
-                result = gen.emitMathAbs(input);
+                result = gen.getLIRGeneratorTool().emitMathAbs(input);
                 break;
             case SQRT:
-                result = gen.emitMathSqrt(input);
+                result = gen.getLIRGeneratorTool().emitMathSqrt(input);
                 break;
             case LOG:
-                result = gen.emitMathLog(input, false);
+                result = gen.getLIRGeneratorTool().emitMathLog(input, false);
                 break;
             case LOG10:
-                result = gen.emitMathLog(input, true);
+                result = gen.getLIRGeneratorTool().emitMathLog(input, true);
                 break;
             case SIN:
-                result = gen.emitMathSin(input);
+                result = gen.getLIRGeneratorTool().emitMathSin(input);
                 break;
             case COS:
-                result = gen.emitMathCos(input);
+                result = gen.getLIRGeneratorTool().emitMathCos(input);
                 break;
             case TAN:
-                result = gen.emitMathTan(input);
+                result = gen.getLIRGeneratorTool().emitMathTan(input);
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReadRegisterNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReadRegisterNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -24,17 +24,16 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
 /**
  * Access the value of a specific register.
  */
 @NodeInfo(nameTemplate = "ReadRegister %{p#register}")
-public final class ReadRegisterNode extends FixedWithNextNode implements LIRGenLowerable {
+public final class ReadRegisterNode extends FixedWithNextNode implements LIRLowerable {
 
     /**
      * The fixed register to access.
@@ -75,13 +74,13 @@
     }
 
     @Override
-    public void generate(LIRGenerator generator) {
+    public void generate(NodeLIRGeneratorTool generator) {
         Value result = register.asValue(getKind());
         if (incoming) {
-            generator.emitIncomingValues(new Value[]{result});
+            generator.getLIRGeneratorTool().emitIncomingValues(new Value[]{result});
         }
         if (!directUse) {
-            result = generator.emitMove(result);
+            result = generator.getLIRGeneratorTool().emitMove(result);
         }
         generator.setResult(this, result);
     }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -66,9 +66,9 @@
     }
 
     @Override
-    public void generate(LIRGenerator gen) {
+    public void generate(NodeLIRGenerator gen) {
         Variable result = gen.newVariable(value.getKind());
-        gen.emitByteSwap(result, gen.operand(value));
+        gen.getLIRGenerator().emitByteSwap(result, gen.operand(value));
         gen.setResult(this, result);
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -52,9 +52,9 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool generator) {
+    public void generate(NodeLIRGeneratorTool generator) {
         Value val = generator.operand(value);
-        generator.emitMove(register.asValue(val.getKind()), val);
+        generator.getLIRGeneratorTool().emitMove(register.asValue(val.getKind()), val);
     }
 
     @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -34,7 +34,7 @@
     }
 
     @Override
-    protected Value generateArithmetic(LIRGeneratorTool gen) {
-        return gen.emitAdd(gen.operand(getX()), gen.operand(getY()));
+    protected Value generateArithmetic(NodeLIRGeneratorTool gen) {
+        return gen.getLIRGeneratorTool().emitAdd(gen.operand(getX()), gen.operand(getY()));
     }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -23,14 +23,12 @@
 package com.oracle.graal.truffle.nodes.arithmetic;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public abstract class IntegerExactArithmeticSplitNode extends ControlSplitNode implements LIRGenLowerable {
+public abstract class IntegerExactArithmeticSplitNode extends ControlSplitNode implements LIRLowerable {
 
     @Successor private AbstractBeginNode overflowSuccessor;
     @Successor private AbstractBeginNode next;
@@ -72,12 +70,12 @@
     }
 
     @Override
-    public void generate(LIRGenerator generator) {
+    public void generate(NodeLIRGeneratorTool generator) {
         generator.setResult(this, generateArithmetic(generator));
-        generator.emitOverflowCheckBranch(generator.getLIRBlock(getOverflowSuccessor()), generator.getLIRBlock(getNext()), probability(getOverflowSuccessor()));
+        generator.emitOverflowCheckBranch(getOverflowSuccessor(), getNext(), probability(getOverflowSuccessor()));
     }
 
-    protected abstract Value generateArithmetic(LIRGeneratorTool generator);
+    protected abstract Value generateArithmetic(NodeLIRGeneratorTool generator);
 
     static void lower(LoweringTool tool, IntegerExactArithmeticNode node) {
         if (node.asNode().graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -34,7 +34,7 @@
     }
 
     @Override
-    protected Value generateArithmetic(LIRGeneratorTool gen) {
-        return gen.emitMul(gen.operand(getX()), gen.operand(getY()));
+    protected Value generateArithmetic(NodeLIRGeneratorTool gen) {
+        return gen.getLIRGeneratorTool().emitMul(gen.operand(getX()), gen.operand(getY()));
     }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -34,7 +34,7 @@
     }
 
     @Override
-    protected Value generateArithmetic(LIRGeneratorTool gen) {
-        return gen.emitSub(gen.operand(getX()), gen.operand(getY()));
+    protected Value generateArithmetic(NodeLIRGeneratorTool gen) {
+        return gen.getLIRGeneratorTool().emitSub(gen.operand(getX()), gen.operand(getY()));
     }
 }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java	Thu Mar 27 16:54:47 2014 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java	Thu Mar 27 17:31:20 2014 +0100
@@ -67,12 +67,12 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool generator) {
+    public void generate(NodeLIRGeneratorTool generator) {
         assert getKind() != input.getKind();
-        assert generator.target().getSizeInBytes(getKind()) == generator.target().getSizeInBytes(input.getKind());
+        assert generator.getLIRGeneratorTool().target().getSizeInBytes(getKind()) == generator.getLIRGeneratorTool().target().getSizeInBytes(input.getKind());
 
-        AllocatableValue result = generator.newVariable(getKind());
-        generator.emitMove(result, generator.operand(input));
+        AllocatableValue result = generator.getLIRGeneratorTool().newVariable(getKind());
+        generator.getLIRGeneratorTool().emitMove(result, generator.operand(input));
         generator.setResult(this, result);
     }
 }
--- a/mx/projects	Thu Mar 27 16:54:47 2014 +0100
+++ b/mx/projects	Thu Mar 27 17:31:20 2014 +0100
@@ -145,7 +145,7 @@
 # graal.hotspot
 project@com.oracle.graal.hotspot@subDir=graal
 project@com.oracle.graal.hotspot@sourceDirs=src
-project@com.oracle.graal.hotspot@dependencies=com.oracle.graal.replacements,com.oracle.graal.runtime,com.oracle.graal.printer
+project@com.oracle.graal.hotspot@dependencies=com.oracle.graal.replacements,com.oracle.graal.runtime,com.oracle.graal.printer, com.oracle.graal.baseline
 project@com.oracle.graal.hotspot@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot@annotationProcessors=com.oracle.graal.replacements.verifier,com.oracle.graal.service.processor
 project@com.oracle.graal.hotspot@javaCompliance=1.8
@@ -487,7 +487,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.8
 project@com.oracle.graal.baseline@workingSets=Graal,Java