changeset 15169:0ba58961ba14

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Wed, 16 Apr 2014 19:00:14 +0200
parents 78530cbd8940 (current diff) 8fc3ca046532 (diff)
children ac66c9c60d02
files graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/AbstractNodeIterable.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/FastNodeClassRegistry.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp src/cpu/x86/vm/graalCodeInstaller_x86.hpp src/share/vm/classfile/systemDictionary.hpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/graal/graalCompilerToVM.cpp
diffstat 199 files changed, 2746 insertions(+), 1962 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java	Wed Apr 16 19:00:14 2014 +0200
@@ -34,12 +34,12 @@
  * with the most likely path that was left out during this process. The process iteratively
  * continues until all blocks are scheduled. Additionally, it is guaranteed that all blocks of a
  * loop are scheduled before any block following the loop is scheduled.
- * 
+ *
  * The machine code generator order includes reordering of loop headers such that the backward jump
  * is a conditional jump if there is only one loop end block. Additionally, the target of loop
  * backward jumps are always marked as aligned. Aligning the target of conditional jumps does not
  * bring a measurable benefit and is therefore avoided to keep the code size small.
- * 
+ *
  * The linear scan register allocator order has an additional mechanism that prevents merge nodes
  * from being scheduled if there is at least one highly likely predecessor still unscheduled. This
  * increases the probability that the merge node and the corresponding predecessor are more closely
@@ -63,7 +63,7 @@
 
     /**
      * Computes the block order used for the linear scan register allocator.
-     * 
+     *
      * @return sorted list of blocks
      */
     public static <T extends AbstractBlock<T>> List<T> computeLinearScanOrder(int blockCount, T startBlock, BlocksToDoubles blockProbabilities) {
@@ -77,7 +77,7 @@
 
     /**
      * Computes the block order used for code emission.
-     * 
+     *
      * @return sorted list of blocks
      */
     public static <T extends AbstractBlock<T>> List<T> computeCodeEmittingOrder(int blockCount, T startBlock, BlocksToDoubles blockProbabilities) {
@@ -151,7 +151,6 @@
     /**
      * 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, BlocksToDoubles blockProbabilities) {
         T block = initialBlock;
         while (block != null) {
@@ -166,17 +165,17 @@
                 addBlock(block, order);
             }
 
-            Loop loop = block.getLoop();
+            Loop<T> loop = block.getLoop();
             if (block.isLoopEnd() && skipLoopHeader(loop.header)) {
 
                 // This is the only loop end of a skipped loop header.
                 // Add the header immediately afterwards.
-                addBlock((T) loop.header, order);
+                addBlock(loop.header, order);
 
                 // Make sure the loop successors of the loop header are aligned
                 // as they are the target
                 // of the backward jump.
-                for (Block successor : loop.header.getSuccessors()) {
+                for (T successor : loop.header.getSuccessors()) {
                     if (successor.getLoopDepth() == block.getLoopDepth()) {
                         successor.setAlign(true);
                     }
@@ -230,8 +229,8 @@
      * Skip the loop header block if the loop consists of more than one block and it has only a
      * single loop end block.
      */
-    private static boolean skipLoopHeader(AbstractBlock<?> block) {
-        return (block.isLoopHeader() && !block.isLoopEnd() && block.getLoop().loopBegin().loopEnds().count() == 1);
+    private static <T extends AbstractBlock<T>> boolean skipLoopHeader(AbstractBlock<T> block) {
+        return (block.isLoopHeader() && !block.isLoopEnd() && block.getLoop().numBackedges() == 1);
     }
 
     /**
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Wed Apr 16 19:00:14 2014 +0200
@@ -57,7 +57,7 @@
     private LocalLiveness liveness;
     private BciBlockBitMap blockVisited;
 
-    private class BciBlockBitMap {
+    private static class BciBlockBitMap {
         BitSet bitSet;
 
         public BciBlockBitMap(BciBlockMapping blockMap) {
@@ -121,7 +121,7 @@
             // 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]);
+            LIRControlFlowGraph cfg = new LIRControlFlowGraph(blockMap);
 
             BlocksToDoubles blockProbabilities = new BlocksToDoubles(blockMap.blocks.size());
             for (BciBlock b : blockMap.blocks) {
@@ -261,8 +261,7 @@
 
     @Override
     protected Value genIntegerMul(Kind kind, Value x, Value y) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
+        return gen.emitMul(x, y);
     }
 
     @Override
@@ -584,9 +583,9 @@
         return v;
     }
 
-    private void createTarget(BciBlock block, LIRFrameStateBuilder state) {
-        assert block != null && state != null;
-        assert !block.isExceptionEntry || state.stackSize() == 1;
+    private void createTarget(BciBlock block) {
+        assert block != null && frameState != null;
+        assert !block.isExceptionEntry || frameState.stackSize() == 1;
 
         if (!blockVisited.get(block)) {
             /*
@@ -594,7 +593,14 @@
              * placeholder that later can be replaced with a MergeNode when we see this block again.
              */
             blockVisited.set(block);
-            block.entryState = state.copy();
+            if (block.getPredecessorCount() > 1) {
+                /*
+                 * If there are more than one predecessors we have to ensure that we are not passing
+                 * constants to the new framestate otherwise we will get interfacing problems.
+                 */
+                moveConstantsToVariables();
+            }
+            block.entryState = frameState.copy();
             block.entryState.clearNonLiveLocals(block, liveness, true);
 
             Debug.log("createTarget %s: first visit", block);
@@ -602,12 +608,17 @@
         }
 
         // We already saw this block before, so we have to merge states.
-        if (!((LIRFrameStateBuilder) block.entryState).isCompatibleWith(state)) {
+        if (!((LIRFrameStateBuilder) block.entryState).isCompatibleWith(frameState)) {
             throw new BailoutException("stacks do not match; bytecodes would not verify");
         }
 
         if (block.isLoopHeader) {
-            assert currentBlock.getId() >= block.getId() : "must be backward branch";
+            assert currentBlock == null || currentBlock.getId() >= block.getId() : "must be backward branch";
+            if (currentBlock != null && currentBlock.numNormalSuccessors() == 1) {
+                // this is the only successor of the current block so we can adjust
+                adaptFramestate((LIRFrameStateBuilder) block.entryState);
+                return;
+            }
             GraalInternalError.unimplemented("Loops not yet supported");
         }
         assert currentBlock == null || currentBlock.getId() < block.getId() : "must not be backward branch";
@@ -629,30 +640,54 @@
         Debug.log("createTarget %s: merging state", block);
     }
 
-    private void adaptValues(Value dst, Value src) {
+    private void moveConstantsToVariables() {
+        Debug.log("moveConstantsToVariables: framestate before: %s", frameState);
+        for (int i = 0; i < frameState.stackSize(); i++) {
+            Value src = frameState.stackAt(i);
+            if (src instanceof Constant) {
+                AllocatableValue dst = gen.newVariable(src.getPlatformKind());
+                gen.emitMove(dst, src);
+                frameState.storeStack(i, dst);
+                Debug.log("introduce new variabe %s for stackslot %d (end of block %s", dst, i, currentBlock);
+            }
+        }
+        for (int i = 0; i < frameState.localsSize(); i++) {
+            Value src = frameState.localAt(i);
+            if (src instanceof Constant) {
+                AllocatableValue dst = gen.newVariable(src.getPlatformKind());
+                gen.emitMove(dst, src);
+                frameState.storeLocal(i, dst);
+                Debug.log("introduce new variabe %s for local %d (end of block %s", dst, i, currentBlock);
+            }
+        }
+        Debug.log("moveConstantsToVariables: framestate after: %s", frameState);
+    }
+
+    private static void adaptValues(Value dst, Value src, PhiResolver resolver) {
         if (dst == null) {
             return;
         }
         assert src != null : "Source is null but Destination is not!";
 
         if (!dst.equals(src)) {
-            assert dst instanceof AllocatableValue;
-            gen.emitMove((AllocatableValue) dst, src);
+            resolver.move(dst, src);
         }
     }
 
     private void adaptFramestate(LIRFrameStateBuilder other) {
         assert frameState.isCompatibleWith(other) : "framestates not compatible!";
+        PhiResolver resolver = new PhiResolver(gen);
         for (int i = 0; i < frameState.stackSize(); i++) {
             Value src = frameState.stackAt(i);
             Value dst = other.stackAt(i);
-            adaptValues(dst, src);
+            adaptValues(dst, src, resolver);
         }
         for (int i = 0; i < frameState.localsSize(); i++) {
             Value src = frameState.localAt(i);
             Value dst = other.localAt(i);
-            adaptValues(dst, src);
+            adaptValues(dst, src, resolver);
         }
+        resolver.dispose();
     }
 
     @Override
@@ -682,6 +717,14 @@
             assert block.getPredecessorCount() > 0;
         }
 
+        if (block.isLoopHeader) {
+            /*
+             * We need to preserve the frame state builder of the loop header so that we can merge
+             * values for phi functions, so make a copy of it.
+             */
+            block.entryState = frameState.copy();
+
+        }
         int endBCI = stream.endBCI();
 
         stream.setBCI(block.startBci);
@@ -725,7 +768,7 @@
     }
 
     LabelRef getSuccessor(int index) {
-        createTarget(currentBlock.getSuccessor(index), frameState);
+        createTarget(currentBlock.getSuccessor(index));
         return LabelRef.forSuccessor(lirGenRes.getLIR(), currentBlock, index);
     }
 
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRBlock.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRBlock.java	Wed Apr 16 19:00:14 2014 +0200
@@ -34,7 +34,7 @@
         successors = Collections.emptyList();
     }
 
-    public Loop getLoop() {
+    public Loop<LIRBlock> getLoop() {
         // TODO Auto-generated method stub
         return null;
     }
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRControlFlowGraph.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRControlFlowGraph.java	Wed Apr 16 19:00:14 2014 +0200
@@ -22,24 +22,30 @@
  */
 package com.oracle.graal.baseline;
 
+import java.util.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.java.*;
 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;
+    private Collection<Loop<BciBlock>> loops;
+    private BitSet visited;
 
-    public LIRControlFlowGraph(BciBlock[] blocks, Loop[] loops) {
-        this.blocks = blocks;
-        this.loops = loops;
+    public LIRControlFlowGraph(BciBlockMapping blockMap) {
+        blocks = blockMap.blocks.toArray(new BciBlock[0]);
+        loops = new ArrayList<>();
+        computeLoopInformation();
     }
 
     public BciBlock[] getBlocks() {
         return blocks;
     }
 
-    public Loop[] getLoops() {
+    public Collection<Loop<BciBlock>> getLoops() {
         return loops;
     }
 
@@ -50,4 +56,44 @@
         return null;
     }
 
+    private void computeLoopInformation() {
+        visited = new BitSet(blocks.length);
+        Deque<LIRLoop> stack = new ArrayDeque<>();
+        for (int i = blocks.length - 1; i >= 0; i--) {
+            BciBlock block = blocks[i];
+            calcLoop(block, stack);
+        }
+    }
+
+    private void calcLoop(BciBlock block, Deque<LIRLoop> stack) {
+        if (visited.get(block.getId())) {
+            return;
+        }
+        visited.set(block.getId());
+        if (block.isLoopEnd()) {
+            BciBlock loopHeader = getLoopHeader(block);
+            LIRLoop l = new LIRLoop(stack.peek(), loops.size(), loopHeader);
+            loops.add(l);
+            stack.push(l);
+        }
+        block.loop = stack.peek();
+        if (block.isLoopHeader()) {
+            assert block.loop.header.equals(block);
+            stack.pop();
+        }
+        for (BciBlock pred : block.getPredecessors()) {
+            calcLoop(pred, stack);
+        }
+    }
+
+    private static BciBlock getLoopHeader(BciBlock block) {
+        assert block.isLoopEnd();
+        for (BciBlock sux : block.getSuccessors()) {
+            if (sux.isLoopHeader() && sux.getId() <= block.getId() && block.loops == sux.loops) {
+                return sux;
+            }
+        }
+        throw GraalInternalError.shouldNotReachHere("No loop header found for " + block);
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRLoop.java	Wed Apr 16 19:00:14 2014 +0200
@@ -0,0 +1,41 @@
+/*
+ * 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 LIRLoop extends Loop<BciBlock> {
+
+    protected LIRLoop(Loop<BciBlock> parent, int index, BciBlock header) {
+        super(parent, index, header);
+    }
+
+    @Override
+    public long numBackedges() {
+        // currently only loops with one backedge are supported
+        return 1;
+    }
+
+}
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64MemoryPeephole.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64MemoryPeephole.java	Wed Apr 16 19:00:14 2014 +0200
@@ -81,7 +81,7 @@
     }
 
     protected AMD64AddressValue makeAddress(Access access) {
-        return (AMD64AddressValue) access.accessLocation().generateAddress(gen, gen.operand(access.object()));
+        return (AMD64AddressValue) access.accessLocation().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(access.object()));
     }
 
     protected Value emitBinaryMemory(AMD64Arithmetic op, boolean commutative, ValueNode x, ValueNode y, Access access) {
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BasicHSAILTest.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BasicHSAILTest.java	Wed Apr 16 19:00:14 2014 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.compiler.hsail.test;
 
+import static com.oracle.graal.debug.DelegatingDebugConfig.Feature.*;
+
 import java.lang.reflect.*;
 
 import org.junit.*;
@@ -30,7 +32,6 @@
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
-import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.gpu.*;
 import com.oracle.graal.hotspot.hsail.*;
 import com.oracle.graal.hsail.*;
@@ -344,15 +345,7 @@
     }
 
     private void test(final String snippet) {
-        DebugConfig debugConfig = DebugScope.getConfig();
-        DebugConfig noInterceptConfig = new DelegatingDebugConfig(debugConfig) {
-            @Override
-            public RuntimeException interceptException(Throwable e) {
-                return null;
-            }
-        };
-
-        try (DebugConfigScope dcs = Debug.setConfig(noInterceptConfig)) {
+        try (DebugConfigScope dcs = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT))) {
             try (Scope s = Debug.scope("HSAILCodeGen")) {
                 Method method = getMethod(snippet);
                 ExternalCompilationResult hsailCode = getBackend().compileKernel(getMetaAccess().lookupJavaMethod(method), false);
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewStringConcatTest.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewStringConcatTest.java	Wed Apr 16 19:00:14 2014 +0200
@@ -22,8 +22,12 @@
  */
 package com.oracle.graal.compiler.hsail.test;
 
+import static com.oracle.graal.debug.Debug.*;
+
 import org.junit.Test;
 
+import com.oracle.graal.debug.*;
+
 /**
  * Tests allocation of a new String based on string concatenation.
  */
@@ -49,6 +53,8 @@
     // Node implementing Lowerable not handled in HSAIL Backend: 6274|MonitorEnter
     @Test(expected = com.oracle.graal.graph.GraalInternalError.class)
     public void test() {
-        testGeneratedHsail();
+        try (DebugConfigScope s = disableIntercept()) {
+            testGeneratedHsail();
+        }
     }
 }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewStringInternTest.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewStringInternTest.java	Wed Apr 16 19:00:14 2014 +0200
@@ -22,8 +22,12 @@
  */
 package com.oracle.graal.compiler.hsail.test;
 
+import static com.oracle.graal.debug.Debug.*;
+
 import org.junit.Test;
 
+import com.oracle.graal.debug.*;
+
 /**
  * Tests allocation of a new String based on string interning.
  */
@@ -37,6 +41,8 @@
     // at node: 12|Invoke#Direct#intern
     @Test(expected = com.oracle.graal.graph.GraalInternalError.class)
     public void test() {
-        testGeneratedHsail();
+        try (DebugConfigScope s = disableIntercept()) {
+            testGeneratedHsail();
+        }
     }
 }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMethod16InArraysTest.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMethod16InArraysTest.java	Wed Apr 16 19:00:14 2014 +0200
@@ -23,10 +23,11 @@
 
 package com.oracle.graal.compiler.hsail.test;
 
+import static com.oracle.graal.debug.DelegatingDebugConfig.Feature.*;
+
 import org.junit.*;
 
 import com.oracle.graal.debug.*;
-import com.oracle.graal.debug.internal.*;
 
 /**
  * Tests the addition of elements from sixteen input arrays.
@@ -64,15 +65,7 @@
     @Test(expected = java.lang.ClassCastException.class)
     @Ignore("until GPU backends can co-exist")
     public void test() {
-        DebugConfig debugConfig = DebugScope.getConfig();
-        DebugConfig noInterceptConfig = new DelegatingDebugConfig(debugConfig) {
-            @Override
-            public RuntimeException interceptException(Throwable e) {
-                return null;
-            }
-        };
-
-        try (DebugConfigScope s = Debug.setConfig(noInterceptConfig)) {
+        try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT))) {
             testGeneratedHsail();
         }
     }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ArrayListGetTest.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ArrayListGetTest.java	Wed Apr 16 19:00:14 2014 +0200
@@ -23,8 +23,13 @@
 
 package com.oracle.graal.compiler.hsail.test.lambda;
 
+import static com.oracle.graal.debug.Debug.*;
+
 import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import com.oracle.graal.debug.*;
+
 import org.junit.Test;
+
 import java.util.ArrayList;
 
 /**
@@ -56,7 +61,9 @@
     // NYI emitForeignCall charAlignedDisjointArraycopy
     @Test(expected = com.oracle.graal.graph.GraalInternalError.class)
     public void testUsingLambdaMethod() {
-        testGeneratedHsailUsingLambdaMethod();
+        try (DebugConfigScope s = disableIntercept()) {
+            testGeneratedHsailUsingLambdaMethod();
+        }
     }
 
 }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntAddAndGetGidTest.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntAddAndGetGidTest.java	Wed Apr 16 19:00:14 2014 +0200
@@ -57,11 +57,11 @@
         // note: the actual order of entries in outArray is not predictable
         // thus we sort before we compare results
         Arrays.sort(outArray);
-        System.out.print("outArray: ");
-        for (int val : outArray) {
-            System.out.print(val + ", ");
-        }
-        System.out.println();
+        // System.out.print("outArray: ");
+        // for (int val : outArray) {
+        // System.out.print(val + ", ");
+        // }
+        // System.out.println();
         // create array of gaps
         gaps[0] = outArray[0] - 0;
         for (int i = 1; i < NUM; i++) {
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/HashMapGetTest.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/HashMapGetTest.java	Wed Apr 16 19:00:14 2014 +0200
@@ -23,8 +23,13 @@
 
 package com.oracle.graal.compiler.hsail.test.lambda;
 
+import static com.oracle.graal.debug.Debug.*;
+
 import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import com.oracle.graal.debug.*;
+
 import java.util.HashMap;
+
 import org.junit.Test;
 
 /**
@@ -88,12 +93,16 @@
     // type profile exists
     @Test(expected = com.oracle.graal.graph.GraalInternalError.class)
     public void test() {
-        testGeneratedHsail();
+        try (DebugConfigScope s = disableIntercept()) {
+            testGeneratedHsail();
+        }
     }
 
     @Test(expected = com.oracle.graal.graph.GraalInternalError.class)
     public void testUsingLambdaMethod() {
-        testGeneratedHsailUsingLambdaMethod();
+        try (DebugConfigScope s = disableIntercept()) {
+            testGeneratedHsailUsingLambdaMethod();
+        }
     }
 
 }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/LongAdderTest.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/LongAdderTest.java	Wed Apr 16 19:00:14 2014 +0200
@@ -23,8 +23,13 @@
 
 package com.oracle.graal.compiler.hsail.test.lambda;
 
+import static com.oracle.graal.debug.Debug.*;
+import static com.oracle.graal.debug.DelegatingDebugConfig.Feature.*;
+
 import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import com.oracle.graal.debug.*;
 import java.util.concurrent.atomic.LongAdder;
+
 import org.junit.Test;
 
 /**
@@ -53,11 +58,15 @@
     // cannot handle node: CurrentJavaThread
     @Test(expected = com.oracle.graal.graph.GraalInternalError.class)
     public void test() {
-        testGeneratedHsail();
+        try (DebugConfigScope dcs = setConfig(new DelegatingDebugConfig().disable(INTERCEPT))) {
+            testGeneratedHsail();
+        }
     }
 
     @Test(expected = com.oracle.graal.graph.GraalInternalError.class)
     public void testUsingLambdaMethod() {
-        testGeneratedHsailUsingLambdaMethod();
+        try (DebugConfigScope dcs = setConfig(new DelegatingDebugConfig().disable(INTERCEPT))) {
+            testGeneratedHsailUsingLambdaMethod();
+        }
     }
 }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/NewStringEqualsTest.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/NewStringEqualsTest.java	Wed Apr 16 19:00:14 2014 +0200
@@ -23,7 +23,11 @@
 
 package com.oracle.graal.compiler.hsail.test.lambda;
 
+import static com.oracle.graal.debug.Debug.*;
+
 import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import com.oracle.graal.debug.*;
+
 import org.junit.Test;
 
 /**
@@ -62,12 +66,16 @@
     // NYI emitForeignCall charAlignedDisjointArraycopy
     @Test(expected = com.oracle.graal.graph.GraalInternalError.class)
     public void test() {
-        testGeneratedHsail();
+        try (DebugConfigScope s = disableIntercept()) {
+            testGeneratedHsail();
+        }
     }
 
     @Test(expected = com.oracle.graal.graph.GraalInternalError.class)
     public void testUsingLambdaMethod() {
-        testGeneratedHsailUsingLambdaMethod();
+        try (DebugConfigScope s = disableIntercept()) {
+            testGeneratedHsailUsingLambdaMethod();
+        }
     }
 
 }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/NonEscapingNewObjWithArrayTest.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/NonEscapingNewObjWithArrayTest.java	Wed Apr 16 19:00:14 2014 +0200
@@ -23,8 +23,14 @@
 
 package com.oracle.graal.compiler.hsail.test.lambda;
 
+import static com.oracle.graal.debug.Debug.*;
+import static com.oracle.graal.debug.DelegatingDebugConfig.Feature.*;
+
 import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import com.oracle.graal.debug.*;
+
 import org.junit.Test;
+
 import java.util.Arrays;
 
 /**
@@ -74,12 +80,16 @@
     // NYI emitForeignCall floatArraycopy
     @Test(expected = com.oracle.graal.graph.GraalInternalError.class)
     public void test() {
-        testGeneratedHsail();
+        try (DebugConfigScope s = disableIntercept()) {
+            testGeneratedHsail();
+        }
     }
 
     @Test(expected = com.oracle.graal.graph.GraalInternalError.class)
     public void testUsingLambdaMethod() {
-        testGeneratedHsailUsingLambdaMethod();
+        try (DebugConfigScope dcs = setConfig(new DelegatingDebugConfig().disable(INTERCEPT))) {
+            testGeneratedHsailUsingLambdaMethod();
+        }
     }
 
 }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/SynchronizedMethodTest.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/SynchronizedMethodTest.java	Wed Apr 16 19:00:14 2014 +0200
@@ -23,7 +23,11 @@
 
 package com.oracle.graal.compiler.hsail.test.lambda;
 
+import static com.oracle.graal.debug.Debug.*;
+
 import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import com.oracle.graal.debug.*;
+
 import org.junit.Test;
 
 /**
@@ -58,13 +62,17 @@
     // cannot handle the BeginLockScope node
     @Test(expected = com.oracle.graal.graph.GraalInternalError.class)
     public void test() {
-        testGeneratedHsail();
+        try (DebugConfigScope s = disableIntercept()) {
+            testGeneratedHsail();
+        }
     }
 
     // cannot handle the BeginLockScope node
     @Test(expected = com.oracle.graal.graph.GraalInternalError.class)
     public void testUsingLambdaMethod() {
-        testGeneratedHsailUsingLambdaMethod();
+        try (DebugConfigScope s = disableIntercept()) {
+            testGeneratedHsailUsingLambdaMethod();
+        }
     }
 
 }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/VirtualCallTest.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/VirtualCallTest.java	Wed Apr 16 19:00:14 2014 +0200
@@ -23,7 +23,11 @@
 
 package com.oracle.graal.compiler.hsail.test.lambda;
 
+import static com.oracle.graal.debug.Debug.*;
+
 import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import com.oracle.graal.debug.*;
+
 import org.junit.Test;
 
 /**
@@ -92,12 +96,16 @@
     // graal says not inlining getArea():float (0 bytes): no type profile exists
     @Test(expected = com.oracle.graal.graph.GraalInternalError.class)
     public void test() {
-        testGeneratedHsail();
+        try (DebugConfigScope s = disableIntercept()) {
+            testGeneratedHsail();
+        }
     }
 
     @Test(expected = com.oracle.graal.graph.GraalInternalError.class)
     public void testUsingLambdaMethod() {
-        testGeneratedHsailUsingLambdaMethod();
+        try (DebugConfigScope s = disableIntercept()) {
+            testGeneratedHsailUsingLambdaMethod();
+        }
     }
 
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java	Wed Apr 16 19:00:14 2014 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.compiler.test;
 
+import static com.oracle.graal.debug.DelegatingDebugConfig.Feature.*;
+
 import java.io.*;
 import java.lang.reflect.*;
 import java.util.*;
@@ -33,7 +35,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.*;
@@ -106,14 +107,7 @@
                         String methodName = className + "." + m.getName();
                         if (matches(filters, methodName)) {
                             StructuredGraph graph = new StructuredGraph(metaAccess.lookupJavaMethod(m));
-                            DebugConfig debugConfig = DebugScope.getConfig();
-                            DebugConfig noInterceptConfig = new DelegatingDebugConfig(debugConfig) {
-                                @Override
-                                public RuntimeException interceptException(Throwable e) {
-                                    return null;
-                                }
-                            };
-                            try (DebugConfigScope s = Debug.setConfig(noInterceptConfig)) {
+                            try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT))) {
                                 graphBuilderSuite.apply(graph, context);
                                 checkGraph(context, graph);
                             } catch (VerificationError e) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java	Wed Apr 16 19:00:14 2014 +0200
@@ -148,10 +148,10 @@
         Debug.dump(graph, "Graph");
         ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true);
 
-        Assert.assertTrue(cfg.getLoops().length == 3);
-        Loop rootLoop = cfg.getLoops()[0];
-        Loop nestedLoop = cfg.getLoops()[1];
-        Loop innerMostLoop = cfg.getLoops()[2];
+        Assert.assertTrue(cfg.getLoops().size() == 3);
+        Loop<Block> rootLoop = cfg.getLoops().get(0);
+        Loop<Block> nestedLoop = cfg.getLoops().get(1);
+        Loop<Block> innerMostLoop = cfg.getLoops().get(2);
         Invoke a = getInvoke("a", graph);
         Invoke b = getInvoke("b", graph);
         Invoke c = getInvoke("c", graph);
@@ -168,14 +168,14 @@
         Debug.dump(graph, "Graph");
     }
 
-    private static boolean contains(Loop loop, Invoke node, ControlFlowGraph cfg) {
+    private static boolean contains(Loop<Block> loop, Invoke node, ControlFlowGraph cfg) {
         Block block = cfg.blockFor((Node) node);
         Assert.assertNotNull(block);
         return loop.blocks.contains(block);
     }
 
-    private static boolean containsDirect(Loop loop, Invoke node, ControlFlowGraph cfg) {
-        for (Loop child : loop.children) {
+    private static boolean containsDirect(Loop<Block> loop, Invoke node, ControlFlowGraph cfg) {
+        for (Loop<Block> child : loop.children) {
             if (contains(child, node, cfg)) {
                 return false;
             }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java	Wed Apr 16 19:00:14 2014 +0200
@@ -41,9 +41,9 @@
         AbstractEndNode trueEnd = graph.add(new EndNode());
         AbstractEndNode falseEnd = graph.add(new EndNode());
 
-        AbstractBeginNode trueBegin = graph.add(new BeginNode());
+        BeginNode trueBegin = graph.add(new BeginNode());
         trueBegin.setNext(trueEnd);
-        AbstractBeginNode falseBegin = graph.add(new BeginNode());
+        BeginNode falseBegin = graph.add(new BeginNode());
         falseBegin.setNext(falseEnd);
 
         IfNode ifNode = graph.add(new IfNode(null, trueBegin, falseBegin, 0.5));
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Wed Apr 16 19:00:14 2014 +0200
@@ -279,7 +279,7 @@
 
     @SuppressWarnings("unused")
     public static void testNewNodeSnippet() {
-        new IntegerAddNode(new IntegerStamp(32, false, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0xFFFFFFFF), null, null);
+        new IntegerAddNode(new IntegerStamp(32, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0xFFFFFFFF), null, null);
     }
 
     /**
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Wed Apr 16 19:00:14 2014 +0200
@@ -335,7 +335,7 @@
     }
 
     int numLoops() {
-        return ir.getControlFlowGraph().getLoops().length;
+        return ir.getControlFlowGraph().getLoops().size();
     }
 
     boolean isIntervalInLoop(int interval, int loop) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Wed Apr 16 19:00:14 2014 +0200
@@ -585,7 +585,7 @@
         return stamp.getPlatformKind(this);
     }
 
-    public PlatformKind getIntegerKind(int bits, boolean unsigned) {
+    public PlatformKind getIntegerKind(int bits) {
         if (bits <= 8) {
             return Kind.Byte;
         } else if (bits <= 16) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Wed Apr 16 19:00:14 2014 +0200
@@ -412,7 +412,7 @@
         } else if (node instanceof LIRLowerable) {
             ((LIRLowerable) node).generate(this);
         } else if (node instanceof ArithmeticLIRLowerable) {
-            ((ArithmeticLIRLowerable) node).generate(this);
+            ((ArithmeticLIRLowerable) node).generate(this, gen);
         } else {
             throw GraalInternalError.shouldNotReachHere("node is not LIRLowerable: " + node);
         }
@@ -659,7 +659,7 @@
         return debugInfoBuilder;
     }
 
-    public void emitOverflowCheckBranch(AbstractBeginNode overflowSuccessor, AbstractBeginNode next, double probability) {
+    public void emitOverflowCheckBranch(BeginNode overflowSuccessor, BeginNode next, double probability) {
         gen.emitOverflowCheckBranch(getLIRBlock(overflowSuccessor), getLIRBlock(next), probability);
     }
 
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Wed Apr 16 19:00:14 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.debug;
 
 import static com.oracle.graal.debug.Debug.Initialization.*;
+import static com.oracle.graal.debug.DelegatingDebugConfig.Feature.*;
 import static java.util.FormattableFlags.*;
 
 import java.io.*;
@@ -187,6 +188,19 @@
 
     /**
      * @see #scope(Object)
+     * @param contextObjects an array of object to be appended to the {@linkplain #context()
+     *            current} debug context
+     */
+    public static Scope scope(Object name, Object[] contextObjects) {
+        if (ENABLED) {
+            return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null, contextObjects);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * @see #scope(Object)
      * @param context an object to be appended to the {@linkplain #context() current} debug context
      */
     public static Scope scope(Object name, Object context) {
@@ -259,17 +273,25 @@
     }
 
     public static Scope forceLog() {
-        return Debug.sandbox("forceLog", new DelegatingDebugConfig(DebugScope.getConfig()) {
-            @Override
-            public boolean isLogEnabled() {
-                return true;
-            }
+        return Debug.sandbox("forceLog", new DelegatingDebugConfig().enable(LOG).enable(LOG_METHOD));
+    }
 
-            @Override
-            public boolean isLogEnabledForMethod() {
-                return true;
-            }
-        });
+    /**
+     * Opens a scope in which exception {@linkplain DebugConfig#interceptException(Throwable)
+     * interception} is disabled. It is recommended to use the try-with-resource statement for
+     * managing entering and leaving such scopes:
+     *
+     * <pre>
+     * try (DebugConfigScope s = Debug.disableIntercept()) {
+     *     ...
+     * }
+     * </pre>
+     *
+     * This is particularly useful to suppress extraneous output in JUnit tests that are expected to
+     * throw an exception.
+     */
+    public static DebugConfigScope disableIntercept() {
+        return Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT));
     }
 
     /**
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java	Wed Apr 16 19:00:14 2014 +0200
@@ -25,45 +25,139 @@
 import java.io.*;
 import java.util.*;
 
+import com.oracle.graal.debug.internal.*;
+
 public class DelegatingDebugConfig implements DebugConfig {
 
     protected final DebugConfig delegate;
 
+    /**
+     * The features of a {@link DelegatingDebugConfig} that can be force
+     * {@linkplain DelegatingDebugConfig#enable(Feature) enabled}/
+     * {@linkplain DelegatingDebugConfig#disable(Feature) disabled} or
+     * {@linkplain DelegatingDebugConfig#delegate(Feature) delegated}.
+     */
+    public enum Feature {
+        /**
+         * @see Debug#isLogEnabled()
+         */
+        LOG,
+        /**
+         * @see Debug#isLogEnabledForMethod()
+         */
+        LOG_METHOD,
+        /**
+         * @see Debug#isDumpEnabled()
+         */
+        DUMP,
+        /**
+         * @see Debug#isDumpEnabledForMethod()
+         */
+        DUMP_METHOD,
+        /**
+         * @see Debug#isMeterEnabled()
+         */
+        METER,
+        /**
+         * @see Debug#isTimeEnabled()
+         */
+        TIME,
+        /**
+         * @see DebugConfig#interceptException(Throwable)
+         */
+        INTERCEPT
+    }
+
+    private final Map<Feature, Boolean> featureState = new EnumMap<>(Feature.class);
+
+    /**
+     * Creates a config that delegates to the {@link DebugScope#getConfig() current config}.
+     */
+    public DelegatingDebugConfig() {
+        this(DebugScope.getConfig());
+    }
+
+    /**
+     * Creates a config that delegates to a given config.
+     */
     public DelegatingDebugConfig(DebugConfig delegate) {
         this.delegate = delegate;
     }
 
+    public DelegatingDebugConfig enable(Feature feature) {
+        featureState.put(feature, Boolean.TRUE);
+        return this;
+    }
+
+    public DelegatingDebugConfig disable(Feature feature) {
+        featureState.put(feature, Boolean.FALSE);
+        return this;
+    }
+
+    public DelegatingDebugConfig delegate(Feature feature) {
+        featureState.put(feature, null);
+        return this;
+    }
+
     @Override
     public boolean isLogEnabled() {
-        return delegate.isLogEnabled();
+        Boolean fs = featureState.get(Feature.LOG);
+        if (fs == null) {
+            return delegate.isLogEnabled();
+        }
+        return fs.booleanValue();
     }
 
     public boolean isLogEnabledForMethod() {
-        return delegate.isLogEnabledForMethod();
+        Boolean fs = featureState.get(Feature.LOG_METHOD);
+        if (fs == null) {
+            return delegate.isLogEnabledForMethod();
+        }
+        return fs.booleanValue();
     }
 
     @Override
     public boolean isMeterEnabled() {
-        return delegate.isMeterEnabled();
+        Boolean fs = featureState.get(Feature.METER);
+        if (fs == null) {
+            return delegate.isMeterEnabled();
+        }
+        return fs.booleanValue();
     }
 
     @Override
     public boolean isDumpEnabled() {
-        return delegate.isDumpEnabled();
+        Boolean fs = featureState.get(Feature.DUMP);
+        if (fs == null) {
+            return delegate.isDumpEnabled();
+        }
+        return fs.booleanValue();
     }
 
     public boolean isDumpEnabledForMethod() {
-        return delegate.isDumpEnabledForMethod();
+        Boolean fs = featureState.get(Feature.DUMP_METHOD);
+        if (fs == null) {
+            return delegate.isDumpEnabledForMethod();
+        }
+        return fs.booleanValue();
     }
 
     @Override
     public boolean isTimeEnabled() {
-        return delegate.isTimeEnabled();
+        Boolean fs = featureState.get(Feature.TIME);
+        if (fs == null) {
+            return delegate.isTimeEnabled();
+        }
+        return fs.booleanValue();
     }
 
     @Override
     public RuntimeException interceptException(Throwable e) {
-        return delegate.interceptException(e);
+        Boolean fs = featureState.get(Feature.INTERCEPT);
+        if (fs == null || fs) {
+            return delegate.interceptException(e);
+        }
+        return null;
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeUsagesTests.java	Wed Apr 16 19:00:14 2014 +0200
@@ -0,0 +1,425 @@
+/*
+ * 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.graph.test;
+
+import static com.oracle.graal.graph.test.matchers.NodeIterableContains.*;
+import static com.oracle.graal.graph.test.matchers.NodeIterableIsEmpty.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.graal.graph.*;
+
+public class NodeUsagesTests {
+
+    private static class Def extends Node {
+
+    }
+
+    private static class Use extends Node {
+        private @Input Def in0;
+        private @Input Def in1;
+        private @Input Def in2;
+
+        public Use(Def in0, Def in1, Def in2) {
+            this.in0 = in0;
+            this.in1 = in1;
+            this.in2 = in2;
+        }
+    }
+
+    @Test
+    public void testReplaceAtUsages() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+
+        assertEquals(3, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtUsages(def1);
+
+        assertThat(def0.usages(), isEmpty());
+
+        assertEquals(3, def1.usages().count());
+        assertThat(def1.usages(), contains(use0));
+        assertThat(def1.usages(), contains(use1));
+        assertThat(def1.usages(), contains(use2));
+
+        assertThat(def1.usages(), isNotEmpty());
+    }
+
+    @Test
+    public void testReplaceAtUsagesWithPredicateAll() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+
+        assertEquals(3, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtMatchingUsages(def1, u -> true);
+
+        assertThat(def0.usages(), isEmpty());
+
+        assertEquals(3, def1.usages().count());
+        assertThat(def1.usages(), contains(use0));
+        assertThat(def1.usages(), contains(use1));
+        assertThat(def1.usages(), contains(use2));
+
+        assertThat(def1.usages(), isNotEmpty());
+    }
+
+    @Test
+    public void testReplaceAtUsagesWithPredicateNone() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+
+        assertEquals(3, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtMatchingUsages(def1, u -> false);
+
+        assertThat(def1.usages(), isEmpty());
+
+        assertEquals(3, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+    }
+
+    @Test
+    public void testReplaceAtUsagesWithPredicate1() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+
+        assertEquals(3, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtMatchingUsages(def1, u -> u == use1);
+
+        assertEquals(1, def1.usages().count());
+        assertThat(def1.usages(), contains(use1));
+
+        assertThat(def1.usages(), isNotEmpty());
+
+        assertEquals(2, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+    }
+
+    @Test
+    public void testReplaceAtUsagesWithPredicate2() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+
+        assertEquals(3, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtMatchingUsages(def1, u -> u == use2);
+
+        assertEquals(1, def1.usages().count());
+        assertThat(def1.usages(), contains(use2));
+
+        assertThat(def1.usages(), isNotEmpty());
+
+        assertEquals(2, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+
+        assertThat(def0.usages(), isNotEmpty());
+    }
+
+    @Test
+    public void testReplaceAtUsagesWithPredicate0() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+
+        assertEquals(3, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtMatchingUsages(def1, u -> u == use0);
+
+        assertEquals(1, def1.usages().count());
+        assertThat(def1.usages(), contains(use0));
+
+        assertThat(def1.usages(), isNotEmpty());
+
+        assertEquals(2, def0.usages().count());
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+    }
+
+    @Test
+    public void testReplaceAtUsagesWithPredicate02() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+
+        assertEquals(3, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtMatchingUsages(def1, u -> u != use1);
+
+        assertEquals(1, def0.usages().count());
+        assertThat(def0.usages(), contains(use1));
+
+        assertThat(def0.usages(), isNotEmpty());
+
+        assertEquals(2, def1.usages().count());
+        assertThat(def1.usages(), contains(use0));
+        assertThat(def1.usages(), contains(use2));
+
+        assertThat(def1.usages(), isNotEmpty());
+    }
+
+    @Test
+    public void testReplaceAtUsagesWithPredicate023() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+        Use use3 = graph.add(new Use(null, null, def0));
+
+        assertEquals(4, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+        assertThat(def0.usages(), contains(use3));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtMatchingUsages(def1, u -> u != use1);
+
+        assertEquals(1, def0.usages().count());
+        assertThat(def0.usages(), contains(use1));
+
+        assertThat(def0.usages(), isNotEmpty());
+
+        assertEquals(3, def1.usages().count());
+        assertThat(def1.usages(), contains(use0));
+        assertThat(def1.usages(), contains(use2));
+        assertThat(def1.usages(), contains(use3));
+
+        assertThat(def1.usages(), isNotEmpty());
+    }
+
+    @Test
+    public void testReplaceAtUsagesWithPredicate013() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+        Use use3 = graph.add(new Use(null, null, def0));
+
+        assertEquals(4, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+        assertThat(def0.usages(), contains(use3));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtMatchingUsages(def1, u -> u != use2);
+
+        assertEquals(1, def0.usages().count());
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+
+        assertEquals(3, def1.usages().count());
+        assertThat(def1.usages(), contains(use0));
+        assertThat(def1.usages(), contains(use1));
+        assertThat(def1.usages(), contains(use3));
+
+        assertThat(def1.usages(), isNotEmpty());
+    }
+
+    @Test
+    public void testReplaceAtUsagesWithPredicate2_3() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+        Use use3 = graph.add(new Use(null, null, def0));
+
+        assertEquals(4, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+        assertThat(def0.usages(), contains(use3));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtMatchingUsages(def1, u -> u == use2);
+
+        assertEquals(1, def1.usages().count());
+        assertThat(def1.usages(), contains(use2));
+
+        assertThat(def1.usages(), isNotEmpty());
+
+        assertEquals(3, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use3));
+
+        assertThat(def0.usages(), isNotEmpty());
+    }
+
+    @Test
+    public void testReplaceAtUsagesWithPredicate01() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+
+        assertEquals(3, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtMatchingUsages(def1, u -> u != use2);
+
+        assertEquals(1, def0.usages().count());
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+
+        assertEquals(2, def1.usages().count());
+        assertThat(def1.usages(), contains(use0));
+        assertThat(def1.usages(), contains(use1));
+
+        assertThat(def1.usages(), isNotEmpty());
+    }
+
+    @Test
+    public void testReplaceAtUsagesWithPredicate12() {
+        Graph graph = new Graph();
+        Def def0 = graph.add(new Def());
+        Def def1 = graph.add(new Def());
+        Use use0 = graph.add(new Use(def0, null, null));
+        Use use1 = graph.add(new Use(null, def0, null));
+        Use use2 = graph.add(new Use(null, null, def0));
+
+        assertEquals(3, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+        assertThat(def0.usages(), contains(use1));
+        assertThat(def0.usages(), contains(use2));
+
+        assertThat(def0.usages(), isNotEmpty());
+        assertThat(def1.usages(), isEmpty());
+
+        def0.replaceAtMatchingUsages(def1, u -> u != use0);
+
+        assertEquals(1, def0.usages().count());
+        assertThat(def0.usages(), contains(use0));
+
+        assertThat(def0.usages(), isNotEmpty());
+
+        assertEquals(2, def1.usages().count());
+        assertThat(def1.usages(), contains(use1));
+        assertThat(def1.usages(), contains(use2));
+
+        assertThat(def1.usages(), isNotEmpty());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableContains.java	Wed Apr 16 19:00:14 2014 +0200
@@ -0,0 +1,53 @@
+/*
+ * 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.graph.test.matchers;
+
+import org.hamcrest.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
+
+public class NodeIterableContains<T extends Node> extends TypeSafeDiagnosingMatcher<NodeIterable<T>> {
+    private T node;
+
+    public NodeIterableContains(T node) {
+        this.node = node;
+    }
+
+    public void describeTo(Description description) {
+        description.appendText("is a NodeIterable containing").appendValue(node);
+    }
+
+    public static <T extends Node> NodeIterableContains<T> contains(T node) {
+        return new NodeIterableContains<>(node);
+    }
+
+    public static <T extends Node> NodeIterableContains<T> d(T node) {
+        return new NodeIterableContains<>(node);
+    }
+
+    @Override
+    protected boolean matchesSafely(NodeIterable<T> iterable, Description description) {
+        return iterable.contains(node);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableIsEmpty.java	Wed Apr 16 19:00:14 2014 +0200
@@ -0,0 +1,49 @@
+/*
+ * 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.graph.test.matchers;
+
+import org.hamcrest.*;
+import org.hamcrest.core.*;
+
+import com.oracle.graal.graph.iterators.*;
+
+public class NodeIterableIsEmpty extends BaseMatcher<NodeIterable<?>> {
+
+    private static final NodeIterableIsEmpty INSTANCE = new NodeIterableIsEmpty();
+
+    public boolean matches(Object iterable) {
+        return iterable instanceof NodeIterable<?> && ((NodeIterable<?>) iterable).isEmpty();
+    }
+
+    public void describeTo(Description description) {
+        description.appendText("is an empty NodeIterable");
+    }
+
+    public static Matcher<NodeIterable<?>> isEmpty() {
+        return INSTANCE;
+    }
+
+    public static Matcher<NodeIterable<?>> isNotEmpty() {
+        return IsNot.not(INSTANCE);
+    }
+}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Wed Apr 16 19:00:14 2014 +0200
@@ -525,7 +525,7 @@
      */
     public NodeIterable<Node> getNewNodes(Mark mark) {
         final int index = mark.getValue();
-        return new AbstractNodeIterable<Node>() {
+        return new NodeIterable<Node>() {
 
             @Override
             public Iterator<Node> iterator() {
@@ -540,7 +540,7 @@
      * @return an {@link Iterable} providing all the live nodes.
      */
     public NodeIterable<Node> getNodes() {
-        return new AbstractNodeIterable<Node>() {
+        return new NodeIterable<Node>() {
 
             @Override
             public Iterator<Node> iterator() {
@@ -714,7 +714,7 @@
      */
     public <T extends Node & IterableNodeType> NodeIterable<T> getNodes(final Class<T> type) {
         final NodeClass nodeClass = NodeClass.get(type);
-        return new AbstractNodeIterable<T>() {
+        return new NodeIterable<T>() {
 
             @Override
             public Iterator<T> iterator() {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Wed Apr 16 19:00:14 2014 +0200
@@ -189,7 +189,6 @@
         Node current;
 
         private void advance() {
-            assert index == -1 || current != null;
             current = null;
             index++;
             if (index == 0) {
@@ -228,7 +227,7 @@
         }
     }
 
-    class NodeUsageIterable extends AbstractNodeIterable<Node> {
+    class NodeUsageIterable implements NodeIterable<Node> {
 
         public NodeUsageIterator iterator() {
             return new NodeUsageIterator();
@@ -246,13 +245,7 @@
 
         @Override
         public int count() {
-            if (usage0 == null) {
-                return 0;
-            }
-            if (usage1 == null) {
-                return 1;
-            }
-            return 2 + indexOfLastNonNull(extraUsages) + 1;
+            return usageCount();
         }
     }
 
@@ -349,6 +342,81 @@
         }
     }
 
+    private int usageCount() {
+        if (usage0 == null) {
+            return 0;
+        }
+        if (usage1 == null) {
+            return 1;
+        }
+        return 2 + indexOfLastNonNull(extraUsages) + 1;
+    }
+
+    /**
+     * Remove all usages between {@code fromIndex} and {@code toIndex} (exclusive), also, if
+     * {@code toIndex} is a valid usage, it is moved to {@code fromIndex}.
+     *
+     * <p>
+     * Visually,
+     *
+     * <pre>
+     * {@code
+     * [1, 2, 3, 4, 5, 6, 7].removeUsagesAndShiftFirst(1, 2) == [1, 4, 6, 7, 5, null, null]}
+     * </pre>
+     *
+     *
+     * @param fromIndex the index of the first element to be removed
+     * @param toIndex the index after the last element to be removed
+     */
+    private void removeUsagesAndShiftFirst(int fromIndex, int toIndex) {
+        assert fromIndex < toIndex;
+        int firstNullIndex = usageCount();
+        assert toIndex <= firstNullIndex;
+        int i = fromIndex;
+        int limit = toIndex;
+        if (toIndex < firstNullIndex) {
+            // move usage at toIndex to fromIndex(!)
+            movUsageTo(toIndex, fromIndex);
+            limit++;
+            i++;
+        }
+        while (i < limit && firstNullIndex > limit) {
+            movUsageTo(firstNullIndex - 1, i);
+            firstNullIndex--;
+            i++;
+        }
+        while (i < limit) {
+            if (i == 0) {
+                usage0 = null;
+            } else if (i == 1) {
+                usage1 = null;
+            } else {
+                extraUsages[i - INLINE_USAGE_COUNT] = null;
+            }
+            i++;
+        }
+
+    }
+
+    private void movUsageTo(int usageIndex, int toIndex) {
+        assert usageIndex > toIndex;
+        if (toIndex == 0) {
+            if (usageIndex == 1) {
+                usage0 = usage1;
+                usage1 = null;
+            } else {
+                usage0 = extraUsages[usageIndex - INLINE_USAGE_COUNT];
+                extraUsages[usageIndex - INLINE_USAGE_COUNT] = null;
+            }
+        } else if (toIndex == 1) {
+            usage1 = extraUsages[usageIndex - INLINE_USAGE_COUNT];
+            extraUsages[usageIndex - INLINE_USAGE_COUNT] = null;
+        } else {
+            extraUsages[toIndex - INLINE_USAGE_COUNT] = extraUsages[usageIndex - INLINE_USAGE_COUNT];
+            extraUsages[usageIndex - INLINE_USAGE_COUNT] = null;
+        }
+    }
+
     /**
      * Removes a given node from this node's {@linkplain #usages() usages}.
      *
@@ -357,6 +425,7 @@
      */
     private boolean removeUsage(Node node) {
         assert recordsUsages();
+        assert node != null;
         // It is critical that this method maintains the invariant that
         // the usage list has no null element preceding a non-null element
         incUsageModCount();
@@ -388,20 +457,19 @@
             }
             return true;
         }
-        int lastNonNull = indexOfLastNonNull(extraUsages);
-        if (lastNonNull >= 0) {
-            for (int i = 0; i <= lastNonNull; ++i) {
-                Node n = extraUsages[i];
-                if (n == node) {
-                    if (i < lastNonNull) {
-                        extraUsages[i] = extraUsages[lastNonNull];
-                        extraUsages[lastNonNull] = null;
-                    } else {
-                        extraUsages[i] = null;
-                    }
-                    return true;
-                }
+        int matchIndex = -1;
+        int i = 0;
+        Node n;
+        while (i < extraUsages.length && (n = extraUsages[i]) != null) {
+            if (n == node) {
+                matchIndex = i;
             }
+            i++;
+        }
+        if (matchIndex >= 0) {
+            extraUsages[matchIndex] = extraUsages[i - 1];
+            extraUsages[i - 1] = null;
+            return true;
         }
         return false;
     }
@@ -543,6 +611,40 @@
         clearUsages();
     }
 
+    public void replaceAtMatchingUsages(Node other, NodePredicate usagePredicate) {
+        assert checkReplaceWith(other);
+        NodeUsageIterator it = (NodeUsageIterator) usages().iterator();
+        int removeStart = -1;
+        while (it.hasNext()) {
+            Node usage = it.next();
+            if (usagePredicate.apply(usage)) {
+                if (removeStart < 0) {
+                    removeStart = it.index - 1;
+                }
+                boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other);
+                assert assertTrue(result, "not found in inputs, usage: %s", usage);
+                if (other != null) {
+                    maybeNotifyChanged(usage);
+                    if (other.recordsUsages()) {
+                        other.addUsage(usage);
+                    }
+                }
+            } else {
+                if (removeStart >= 0) {
+                    int removeEndIndex = it.index - 1;
+                    removeUsagesAndShiftFirst(removeStart, removeEndIndex);
+                    it.index = removeStart;
+                    it.advance();
+                    removeStart = -1;
+                }
+            }
+        }
+        if (removeStart >= 0) {
+            int removeEndIndex = it.index;
+            removeUsagesAndShiftFirst(removeStart, removeEndIndex);
+        }
+    }
+
     public void replaceAtUsages(InputType type, Node other) {
         assert checkReplaceWith(other);
         for (Node usage : usages().snapshot()) {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java	Wed Apr 16 19:00:14 2014 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.graph.iterators.*;
 
-public final class NodeBitMap extends AbstractNodeIterable<Node> {
+public final class NodeBitMap implements NodeIterable<Node> {
 
     private final boolean autoGrow;
     private final BitSet bitMap;
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Wed Apr 16 19:00:14 2014 +0200
@@ -26,7 +26,6 @@
 
 import java.lang.reflect.*;
 import java.util.*;
-import java.util.concurrent.*;
 
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.Graph.DuplicationReplacement;
@@ -36,7 +35,7 @@
 import com.oracle.graal.graph.spi.*;
 
 /**
- * Lazily associated metadata for every {@link Node} type. The metadata includes:
+ * Metadata for every {@link Node} type. The metadata includes:
  * <ul>
  * <li>The offsets of fields annotated with {@link Input} and {@link Successor} as well as methods
  * for iterating over such fields.</li>
@@ -45,72 +44,7 @@
  */
 public final class NodeClass extends FieldIntrospection {
 
-    /**
-     * Maps {@link Class} values (for {@link Node} types) to {@link NodeClass} values.
-     *
-     * Only a single Registry instance can be created. If a runtime creates a specialized registry,
-     * it must do so before the class initializer of {@link NodeClass} is executed.
-     */
-    public static class Registry {
-
-        private static Registry instance;
-
-        /**
-         * Gets the singleton {@link Registry} instance, creating it first if necessary.
-         */
-        static synchronized Registry instance() {
-            if (instance == null) {
-                return new Registry();
-            }
-            return instance;
-        }
-
-        protected Registry() {
-            assert instance == null : "exactly one registry can be created";
-            instance = this;
-        }
-
-        /**
-         * @return the {@link NodeClass} value for {@code key} or {@code null} if no such mapping
-         *         exists
-         */
-        protected NodeClass get(Class<? extends Node> key) {
-            return (NodeClass) allClasses.get(key);
-        }
-
-        /**
-         * Same as {@link #get(Class)} except that a {@link NodeClass} is created if no such mapping
-         * exists. The creation of a {@link NodeClass} must be serialized as
-         * {@link NodeClass#NodeClass(Class)} accesses both {@link FieldIntrospection#allClasses}
-         * and {@link NodeClass#nextIterableId}.
-         * <p>
-         * The fact that {@link ConcurrentHashMap#put} {@link ConcurrentHashMap#get} are used should
-         * make the double-checked locking idiom work in the way {@link NodeClass#get(Class)} uses
-         * this method and {@link #get(Class)}.
-         */
-        final synchronized NodeClass make(Class<? extends Node> key) {
-            NodeClass value = (NodeClass) allClasses.get(key);
-            if (value == null) {
-                value = new NodeClass(key);
-                Object old = allClasses.putIfAbsent(key, value);
-                assert old == null;
-                registered(key, value);
-            }
-            return value;
-        }
-
-        /**
-         * Hook for a subclass to be notified of a new mapping added to the registry.
-         *
-         * @param key
-         * @param value
-         */
-        protected void registered(Class<? extends Node> key, NodeClass value) {
-
-        }
-    }
-
-    private static final Registry registry = Registry.instance();
+    private static final Object GetNodeClassLock = new Object();
 
     /**
      * Gets the {@link NodeClass} associated with a given {@link Class}.
@@ -118,11 +52,22 @@
     @SuppressWarnings("unchecked")
     public static NodeClass get(Class<?> c) {
         Class<? extends Node> key = (Class<? extends Node>) c;
-        NodeClass value = registry.get(key);
-        if (value != null) {
-            return value;
+        NodeClass value = (NodeClass) allClasses.get(key);
+        // The fact that {@link ConcurrentHashMap#put} and {@link ConcurrentHashMap#get}
+        // are used makes the double-checked locking idiom work.
+        if (value == null) {
+            // The creation of a NodeClass must be serialized as the NodeClass constructor accesses
+            // both FieldIntrospection.allClasses and NodeClass.nextIterableId.
+            synchronized (GetNodeClassLock) {
+                value = (NodeClass) allClasses.get(key);
+                if (value == null) {
+                    value = new NodeClass(key);
+                    Object old = allClasses.putIfAbsent(key, value);
+                    assert old == null : old + "   " + key;
+                }
+            }
         }
-        return registry.make(key);
+        return value;
     }
 
     public static final int NOT_ITERABLE = -1;
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClassIterable.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClassIterable.java	Wed Apr 16 19:00:14 2014 +0200
@@ -30,7 +30,7 @@
  * The iterator returned by this iterable can be used to access {@link Position Positions} during
  * iteration using {@link NodeClassIterator#nextPosition()}.
  */
-public abstract class NodeClassIterable extends AbstractNodeIterable<Node> {
+public interface NodeClassIterable extends NodeIterable<Node> {
 
     @Override
     public abstract NodeClassIterator iterator();
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java	Wed Apr 16 19:00:14 2014 +0200
@@ -348,42 +348,6 @@
     }
 
     @Override
-    public NodeIterable<T> until(final T u) {
-        return new FilteredNodeIterable<>(this).until(u);
-    }
-
-    @Override
-    public NodeIterable<T> until(final Class<? extends T> clazz) {
-        return new FilteredNodeIterable<>(this).until(clazz);
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public <F extends T> NodeIterable<F> filter(Class<F> clazz) {
-        return (NodeIterable<F>) new FilteredNodeIterable<>(this).and(NodePredicates.isA(clazz));
-    }
-
-    @Override
-    public NodeIterable<T> filterInterface(Class<?> iface) {
-        return new FilteredNodeIterable<>(this).and(NodePredicates.isAInterface(iface));
-    }
-
-    @Override
-    public FilteredNodeIterable<T> filter(NodePredicate predicate) {
-        return new FilteredNodeIterable<>(this).and(predicate);
-    }
-
-    @Override
-    public FilteredNodeIterable<T> nonNull() {
-        return new FilteredNodeIterable<>(this).and(NodePredicates.isNotNull());
-    }
-
-    @Override
-    public NodeIterable<T> distinct() {
-        return new FilteredNodeIterable<>(this).distinct();
-    }
-
-    @Override
     public T first() {
         if (size() > 0) {
             return get(0);
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/AbstractNodeIterable.java	Wed Apr 16 18:57:14 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * 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.graph.iterators;
-
-import java.util.*;
-
-import com.oracle.graal.graph.*;
-
-public abstract class AbstractNodeIterable<T extends Node> implements NodeIterable<T> {
-
-    @Override
-    public NodeIterable<T> until(final T u) {
-        return new FilteredNodeIterable<>(this).until(u);
-    }
-
-    @Override
-    public NodeIterable<T> until(final Class<? extends T> clazz) {
-        return new FilteredNodeIterable<>(this).until(clazz);
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public <F extends T> NodeIterable<F> filter(Class<F> clazz) {
-        return (NodeIterable<F>) new FilteredNodeIterable<>(this).and(NodePredicates.isA(clazz));
-    }
-
-    @Override
-    public NodeIterable<T> filterInterface(Class<?> iface) {
-        return new FilteredNodeIterable<>(this).and(NodePredicates.isAInterface(iface));
-    }
-
-    @Override
-    public FilteredNodeIterable<T> filter(NodePredicate predicate) {
-        return new FilteredNodeIterable<>(this).and(predicate);
-    }
-
-    @Override
-    public FilteredNodeIterable<T> nonNull() {
-        return new FilteredNodeIterable<>(this).and(NodePredicates.isNotNull());
-    }
-
-    @Override
-    public NodeIterable<T> distinct() {
-        return new FilteredNodeIterable<>(this).distinct();
-    }
-
-    @Override
-    public List<T> snapshot() {
-        ArrayList<T> list = new ArrayList<>();
-        for (T n : this) {
-            list.add(n);
-        }
-        return list;
-    }
-
-    @Override
-    public void snapshotTo(Collection<T> to) {
-        for (T n : this) {
-            to.add(n);
-        }
-    }
-
-    @Override
-    public T first() {
-        Iterator<T> iterator = iterator();
-        if (iterator.hasNext()) {
-            return iterator.next();
-        }
-        return null;
-    }
-
-    @Override
-    public int count() {
-        int count = 0;
-        Iterator<T> iterator = iterator();
-        while (iterator.hasNext()) {
-            iterator.next();
-            count++;
-        }
-        return count;
-    }
-
-    @Override
-    public boolean isEmpty() {
-        return !iterator().hasNext();
-    }
-
-    @Override
-    public boolean isNotEmpty() {
-        return iterator().hasNext();
-    }
-
-    @Override
-    public boolean contains(T node) {
-        return this.filter(NodePredicates.equals(node)).isNotEmpty();
-    }
-}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/FilteredNodeIterable.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/FilteredNodeIterable.java	Wed Apr 16 19:00:14 2014 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.graph.*;
 
-public class FilteredNodeIterable<T extends Node> extends AbstractNodeIterable<T> {
+public class FilteredNodeIterable<T extends Node> implements NodeIterable<T> {
 
     protected final NodeIterable<T> nodeIterable;
     protected NodePredicate predicate = NodePredicates.alwaysTrue();
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java	Wed Apr 16 19:00:14 2014 +0200
@@ -28,32 +28,74 @@
 
 public interface NodeIterable<T extends Node> extends Iterable<T> {
 
-    NodeIterable<T> until(T u);
+    default NodeIterable<T> until(final T u) {
+        return new FilteredNodeIterable<>(this).until(u);
+    }
+
+    default NodeIterable<T> until(final Class<? extends T> clazz) {
+        return new FilteredNodeIterable<>(this).until(clazz);
+    }
 
-    NodeIterable<T> until(Class<? extends T> clazz);
+    @SuppressWarnings("unchecked")
+    default <F extends T> NodeIterable<F> filter(Class<F> clazz) {
+        return (NodeIterable<F>) new FilteredNodeIterable<>(this).and(NodePredicates.isA(clazz));
+    }
 
-    <F extends T> NodeIterable<F> filter(Class<F> clazz);
+    default NodeIterable<T> filterInterface(Class<?> iface) {
+        return new FilteredNodeIterable<>(this).and(NodePredicates.isAInterface(iface));
+    }
 
-    NodeIterable<T> filterInterface(Class<?> iface);
+    default FilteredNodeIterable<T> filter(NodePredicate predicate) {
+        return new FilteredNodeIterable<>(this).and(predicate);
+    }
 
-    FilteredNodeIterable<T> filter(NodePredicate predicate);
+    default FilteredNodeIterable<T> nonNull() {
+        return new FilteredNodeIterable<>(this).and(NodePredicates.isNotNull());
+    }
 
-    FilteredNodeIterable<T> nonNull();
+    default NodeIterable<T> distinct() {
+        return new FilteredNodeIterable<>(this).distinct();
+    }
 
-    NodeIterable<T> distinct();
+    default List<T> snapshot() {
+        ArrayList<T> list = new ArrayList<>();
+        snapshotTo(list);
+        return list;
+    }
 
-    List<T> snapshot();
-
-    void snapshotTo(Collection<T> to);
+    default void snapshotTo(Collection<T> to) {
+        for (T n : this) {
+            to.add(n);
+        }
+    }
 
-    T first();
-
-    int count();
+    default T first() {
+        Iterator<T> iterator = iterator();
+        if (iterator.hasNext()) {
+            return iterator.next();
+        }
+        return null;
+    }
 
-    boolean isEmpty();
-
-    boolean isNotEmpty();
+    default int count() {
+        int count = 0;
+        Iterator<T> iterator = iterator();
+        while (iterator.hasNext()) {
+            iterator.next();
+            count++;
+        }
+        return count;
+    }
 
-    boolean contains(T node);
+    default boolean isEmpty() {
+        return !iterator().hasNext();
+    }
 
+    default boolean isNotEmpty() {
+        return iterator().hasNext();
+    }
+
+    default boolean contains(T node) {
+        return this.filter(NodePredicates.equals(node)).isNotEmpty();
+    }
 }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodePredicate.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodePredicate.java	Wed Apr 16 19:00:14 2014 +0200
@@ -23,20 +23,21 @@
 package com.oracle.graal.graph.iterators;
 
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.NodePredicates.*;
 
-public abstract class NodePredicate {
+public interface NodePredicate {
 
-    public abstract boolean apply(Node n);
+    boolean apply(Node n);
 
-    public NodePredicate and(NodePredicate np) {
-        return NodePredicates.and(this, np);
+    default NodePredicate and(NodePredicate np) {
+        return new AndPredicate(this, np);
     }
 
-    public NodePredicate or(NodePredicate np) {
-        return NodePredicates.or(this, np);
+    default NodePredicate or(NodePredicate np) {
+        return new OrPredicate(this, np);
     }
 
-    public NodePredicate negate() {
-        return NodePredicates.not(this);
+    default NodePredicate negate() {
+        return new NotPredicate(this);
     }
 }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodePredicates.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodePredicates.java	Wed Apr 16 19:00:14 2014 +0200
@@ -27,7 +27,7 @@
 public abstract class NodePredicates {
 
     private static final TautologyPredicate TAUTOLOGY = new TautologyPredicate();
-    private static final FalsePredicate FALSE = new FalsePredicate();
+    private static final ContradictionPredicate CONTRADICTION = new ContradictionPredicate();
     private static final IsNullPredicate IS_NULL = new IsNullPredicate();
     private static final IsNotNullPredicate IS_NOT_NULL = new IsNotNullPredicate();
 
@@ -36,7 +36,7 @@
     }
 
     public static NodePredicate alwaysFalse() {
-        return FALSE;
+        return CONTRADICTION;
     }
 
     public static NodePredicate isNull() {
@@ -52,60 +52,7 @@
     }
 
     public static NodePredicate not(NodePredicate a) {
-        if (a == TAUTOLOGY) {
-            return FALSE;
-        }
-        if (a == FALSE) {
-            return TAUTOLOGY;
-        }
-        if (a == IS_NULL) {
-            return IS_NOT_NULL;
-        }
-        if (a == IS_NOT_NULL) {
-            return IS_NULL;
-        }
-        if (a instanceof NotPredicate) {
-            return ((NotPredicate) a).a;
-        }
-        if (a instanceof PositiveTypePredicate) {
-            return new NegativeTypePredicate((PositiveTypePredicate) a);
-        }
-        if (a instanceof NegativeTypePredicate) {
-            return new PositiveTypePredicate((NegativeTypePredicate) a);
-        }
-        if (a instanceof EqualsPredicate) {
-            return new NotEqualsPredicate(((EqualsPredicate) a).u);
-        }
-        if (a instanceof NotEqualsPredicate) {
-            return new EqualsPredicate(((NotEqualsPredicate) a).u);
-        }
-        return new NotPredicate(a);
-    }
-
-    public static NodePredicate and(NodePredicate a, NodePredicate b) {
-        if (a == TAUTOLOGY) {
-            return b;
-        }
-        if (b == TAUTOLOGY) {
-            return a;
-        }
-        if (a == FALSE || b == FALSE) {
-            return FALSE;
-        }
-        return new AndPredicate(a, b);
-    }
-
-    public static NodePredicate or(NodePredicate a, NodePredicate b) {
-        if (a == FALSE) {
-            return b;
-        }
-        if (b == FALSE) {
-            return a;
-        }
-        if (a == TAUTOLOGY || b == TAUTOLOGY) {
-            return TAUTOLOGY;
-        }
-        return new OrPredicate(a, b);
+        return a.negate();
     }
 
     public static NegativeTypePredicate isNotA(Class<? extends Node> clazz) {
@@ -126,28 +73,52 @@
         return new NegativeTypePredicate(iface);
     }
 
-    private static final class TautologyPredicate extends NodePredicate {
+    static final class TautologyPredicate implements NodePredicate {
 
         @Override
         public boolean apply(Node n) {
             return true;
         }
+
+        public NodePredicate and(NodePredicate np) {
+            return np;
+        }
+
+        public NodePredicate negate() {
+            return CONTRADICTION;
+        }
+
+        public NodePredicate or(NodePredicate np) {
+            return this;
+        }
     }
 
-    private static final class FalsePredicate extends NodePredicate {
+    static final class ContradictionPredicate implements NodePredicate {
 
         @Override
         public boolean apply(Node n) {
             return false;
         }
+
+        public NodePredicate and(NodePredicate np) {
+            return this;
+        }
+
+        public NodePredicate negate() {
+            return TAUTOLOGY;
+        }
+
+        public NodePredicate or(NodePredicate np) {
+            return np;
+        }
     }
 
-    private static final class AndPredicate extends NodePredicate {
+    static final class AndPredicate implements NodePredicate {
 
         private final NodePredicate a;
         private final NodePredicate b;
 
-        private AndPredicate(NodePredicate a, NodePredicate b) {
+        AndPredicate(NodePredicate a, NodePredicate b) {
             this.a = a;
             this.b = b;
         }
@@ -158,11 +129,11 @@
         }
     }
 
-    private static final class NotPredicate extends NodePredicate {
+    static final class NotPredicate implements NodePredicate {
 
         private final NodePredicate a;
 
-        private NotPredicate(NodePredicate n) {
+        NotPredicate(NodePredicate n) {
             this.a = n;
         }
 
@@ -170,14 +141,18 @@
         public boolean apply(Node n) {
             return !a.apply(n);
         }
+
+        public NodePredicate negate() {
+            return a;
+        }
     }
 
-    private static final class OrPredicate extends NodePredicate {
+    static final class OrPredicate implements NodePredicate {
 
         private final NodePredicate a;
         private final NodePredicate b;
 
-        private OrPredicate(NodePredicate a, NodePredicate b) {
+        OrPredicate(NodePredicate a, NodePredicate b) {
             this.a = a;
             this.b = b;
         }
@@ -188,27 +163,35 @@
         }
     }
 
-    private static final class IsNullPredicate extends NodePredicate {
+    static final class IsNullPredicate implements NodePredicate {
 
         @Override
         public boolean apply(Node n) {
             return n == null;
         }
+
+        public NodePredicate negate() {
+            return IS_NOT_NULL;
+        }
     }
 
-    private static final class IsNotNullPredicate extends NodePredicate {
+    static final class IsNotNullPredicate implements NodePredicate {
 
         @Override
         public boolean apply(Node n) {
             return n != null;
         }
+
+        public NodePredicate negate() {
+            return IS_NULL;
+        }
     }
 
-    private static final class EqualsPredicate extends NodePredicate {
+    static final class EqualsPredicate implements NodePredicate {
 
         private final Node u;
 
-        public EqualsPredicate(Node u) {
+        EqualsPredicate(Node u) {
             this.u = u;
         }
 
@@ -216,13 +199,17 @@
         public boolean apply(Node n) {
             return u == n;
         }
+
+        public NodePredicate negate() {
+            return new NotEqualsPredicate(u);
+        }
     }
 
-    private static final class NotEqualsPredicate extends NodePredicate {
+    static final class NotEqualsPredicate implements NodePredicate {
 
         private final Node u;
 
-        public NotEqualsPredicate(Node u) {
+        NotEqualsPredicate(Node u) {
             this.u = u;
         }
 
@@ -230,14 +217,18 @@
         public boolean apply(Node n) {
             return u != n;
         }
+
+        public NodePredicate negate() {
+            return new EqualsPredicate(u);
+        }
     }
 
-    public static final class PositiveTypePredicate extends NodePredicate {
+    public static final class PositiveTypePredicate implements NodePredicate {
 
         private final Class<?> type;
         private PositiveTypePredicate or;
 
-        public PositiveTypePredicate(Class<?> type) {
+        PositiveTypePredicate(Class<?> type) {
             this.type = type;
         }
 
@@ -261,14 +252,18 @@
             }
             return this;
         }
+
+        public NodePredicate negate() {
+            return new NegativeTypePredicate(this);
+        }
     }
 
-    public static final class NegativeTypePredicate extends NodePredicate {
+    public static final class NegativeTypePredicate implements NodePredicate {
 
         private final Class<?> type;
         private NegativeTypePredicate nor;
 
-        public NegativeTypePredicate(Class<?> type) {
+        NegativeTypePredicate(Class<?> type) {
             this.type = type;
         }
 
@@ -292,5 +287,9 @@
             }
             return this;
         }
+
+        public NodePredicate negate() {
+            return new PositiveTypePredicate(this);
+        }
     }
 }
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Wed Apr 16 19:00:14 2014 +0200
@@ -843,7 +843,7 @@
         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];
+        BeginNode[] branches = new BeginNode[deopts.size() + 1];
         int[] keys = new int[deopts.size()];
         int[] keySuccessors = new int[deopts.size() + 1];
         double[] keyProbabilities = new double[deopts.size() + 1];
@@ -875,15 +875,14 @@
         return hostGraph;
     }
 
-    private static AbstractBeginNode createHostCrashBranch(StructuredGraph hostGraph, ValueNode deoptId) {
+    private static BeginNode 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) {
+    private static BeginNode 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));
@@ -957,7 +956,7 @@
             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.forInteger(8, false)));
+            ValueNode numSRegs = hostGraph.unique(new FloatingReadNode(hsailFrame, numSRegsLocation, null, StampFactory.forInteger(8)));
             numSRegs = SignExtendNode.convert(numSRegs, StampFactory.forKind(Kind.Byte));
             location = IndexedLocationNode.create(FINAL_LOCATION, valueKind, offset, numSRegs, hostGraph, 4);
         } else {
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/nodes/LoweredAtomicGetAndAddNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/nodes/LoweredAtomicGetAndAddNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -74,7 +74,7 @@
     @Override
     public void generate(NodeLIRBuilderTool gen) {
         HSAILHotSpotNodeLIRBuilder hsailGen = (HSAILHotSpotNodeLIRBuilder) gen;
-        hsailGen.visitAtomicGetAndAdd(this, location().generateAddress(hsailGen, hsailGen.operand(object())));
+        hsailGen.visitAtomicGetAndAdd(this, location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object())));
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Wed Apr 16 19:00:14 2014 +0200
@@ -685,7 +685,7 @@
                 }
 
                 @Override
-                protected Boolean afterSplit(AbstractBeginNode node, Boolean oldState) {
+                protected Boolean afterSplit(BeginNode node, Boolean oldState) {
                     return false;
                 }
             };
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Wed Apr 16 19:00:14 2014 +0200
@@ -284,8 +284,6 @@
 
     Class<?> getJavaMirror(long metaspaceKlass);
 
-    void setNodeClass(Class<?> c, NodeClass nodeClass);
-
     long readUnsafeKlassPointer(Object o);
 
     void doNotInlineOrCompile(long metaspaceMethod);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Wed Apr 16 19:00:14 2014 +0200
@@ -24,7 +24,6 @@
 package com.oracle.graal.hotspot.bridge;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 
@@ -145,9 +144,6 @@
     public native Class<?> getJavaMirror(long metaspaceKlass);
 
     @Override
-    public native void setNodeClass(Class<?> c, NodeClass nodeClass);
-
-    @Override
     public native long readUnsafeKlassPointer(Object o);
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/FastNodeClassRegistry.java	Wed Apr 16 18:57:14 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * 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.bridge;
-
-import com.oracle.graal.graph.*;
-import com.oracle.graal.hotspot.replacements.*;
-
-/**
- * Updates the {@code InstanceKlass::_graal_node_class} field when a {@link NodeClass} is created so
- * that the {@link HotSpotNodeClassSubstitutions} and {@link HotSpotNodeSubstitutions}
- * intrinsifications can read it.
- */
-class FastNodeClassRegistry extends NodeClass.Registry {
-
-    private final CompilerToVM vm;
-
-    public FastNodeClassRegistry(CompilerToVM vm) {
-        this.vm = vm;
-    }
-
-    @SuppressWarnings("unused")
-    static void initialize(CompilerToVM vm) {
-        new FastNodeClassRegistry(vm);
-    }
-
-    @Override
-    protected void registered(Class<? extends Node> key, NodeClass value) {
-        vm.setNodeClass(key, value);
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Wed Apr 16 19:00:14 2014 +0200
@@ -38,11 +38,7 @@
 
     void shutdownCompiler() throws Exception;
 
-    /**
-     * @param hostedOnly specifies if the Graal compiler is only being used in hosted mode (i.e., it
-     *            will never compile itself)
-     */
-    void startCompiler(boolean bootstrapEnabled, boolean hostedOnly) throws Throwable;
+    void startCompiler(boolean bootstrapEnabled) throws Throwable;
 
     void bootstrap() throws Throwable;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Wed Apr 16 19:00:14 2014 +0200
@@ -142,11 +142,7 @@
         this.runtime = runtime;
     }
 
-    public void startCompiler(boolean bootstrapEnabled, boolean hostedOnly) throws Throwable {
-
-        if (!hostedOnly) {
-            FastNodeClassRegistry.initialize(runtime.getCompilerToVM());
-        }
+    public void startCompiler(boolean bootstrapEnabled) throws Throwable {
 
         bootstrapRunning = bootstrapEnabled;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java	Wed Apr 16 19:00:14 2014 +0200
@@ -474,7 +474,7 @@
                 ReadNode memoryRead = createUnsafeRead(graph, load, null);
                 // An unsafe read must not float outside its block otherwise
                 // it may float above an explicit null check on its object.
-                memoryRead.setGuard(AbstractBeginNode.prevBegin(load));
+                memoryRead.setGuard(BeginNode.prevBegin(load));
                 graph.replaceFixedWithFixed(load, memoryRead);
             }
         }
@@ -816,7 +816,7 @@
 
         Stamp hubStamp;
         if (config.useCompressedClassPointers) {
-            hubStamp = StampFactory.forInteger(32, false);
+            hubStamp = StampFactory.forInteger(32);
         } else {
             hubStamp = StampFactory.forKind(wordKind);
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Wed Apr 16 19:00:14 2014 +0200
@@ -174,8 +174,6 @@
 
                 fields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("UNASSIGNED_STACK")));
                 fields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("SUPPRESSED_SENTINEL")));
-
-                fields.add(metaAccess.lookupJavaField(NodeClass.class.getDeclaredField("registry")));
             } catch (SecurityException | NoSuchFieldException e) {
                 throw new GraalInternalError(e);
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -73,7 +73,7 @@
                 } else if (input instanceof IntegerStamp) {
                     // compressed metaspace pointer
                     assert PrimitiveStamp.getBits(input) == 64;
-                    return StampFactory.forInteger(32, false);
+                    return StampFactory.forInteger(32);
                 }
                 break;
             case Uncompress:
@@ -84,7 +84,7 @@
                 } else if (input instanceof IntegerStamp) {
                     // metaspace pointer
                     assert PrimitiveStamp.getBits(input) == 32;
-                    return StampFactory.forInteger(64, false);
+                    return StampFactory.forInteger(64);
                 }
                 break;
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetAnchorNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetAnchorNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -37,7 +37,7 @@
 
     @Override
     public void simplify(SimplifierTool tool) {
-        AbstractBeginNode prevBegin = BeginNode.prevBegin(this);
+        BeginNode prevBegin = BeginNode.prevBegin(this);
         replaceAtUsages(InputType.Anchor, prevBegin);
         replaceAtUsages(InputType.Guard, prevBegin);
         if (usages().isEmpty()) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java	Wed Apr 16 19:00:14 2014 +0200
@@ -27,6 +27,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.tiers.*;
 
@@ -45,7 +46,7 @@
     protected boolean verify(StructuredGraph graph, PhaseContext context) {
         for (ConstantNode node : getConstantNodes(graph)) {
             if (node.recordsUsages() || !node.gatherUsages(graph).isEmpty()) {
-                if (isObject(node) && !isNullReference(node) && !isInternedString(node)) {
+                if (isObject(node) && !isNullReference(node) && !isInternedString(node) && !isDirectMethodHandle(node)) {
                     throw new VerificationError("illegal object constant: " + node);
                 }
             }
@@ -61,6 +62,13 @@
         return isObject(node) && node.asConstant().isNull();
     }
 
+    private static boolean isDirectMethodHandle(ConstantNode node) {
+        if (!isObject(node)) {
+            return false;
+        }
+        return "Ljava/lang/invoke/DirectMethodHandle;".equals(ObjectStamp.typeOrNull(node).getName());
+    }
+
     @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "reference equality is what we want")
     private static boolean isInternedString(ConstantNode node) {
         if (!isObject(node)) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeClassSubstitutions.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeClassSubstitutions.java	Wed Apr 16 19:00:14 2014 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
-import static com.oracle.graal.nodes.PiNode.*;
 import static com.oracle.graal.phases.GraalOptions.*;
 
 import com.oracle.graal.api.meta.*;
@@ -33,7 +31,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.nodes.*;
-import com.oracle.graal.word.*;
 
 /**
  * Substitutions for improving the performance of {@link NodeClass#get}.
@@ -61,15 +58,12 @@
         }
     }
 
+    /**
+     * NOTE: A {@link MethodSubstitution} similar to
+     * {@link HotSpotNodeSubstitutions#getNodeClass(Node)} is not possible here because there is no
+     * guarantee that {@code c} is initialized (accessing a Class literal in Java is not a class
+     * initialization barrier).
+     */
     @MacroSubstitution(isStatic = true, forced = true, macro = NodeClassGetNode.class)
-    @MethodSubstitution(isStatic = true)
-    public static NodeClass get(Class<?> c) {
-        Word klass = loadWordFromObject(c, klassOffset());
-        NodeClass nc = piCastExact(klass.readObject(Word.signed(klassNodeClassOffset()), KLASS_NODE_CLASS), NodeClass.class);
-        if (nc != null) {
-            return nc;
-        }
-        return get(c);
-
-    }
+    public static native NodeClass get(Class<?> c);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeSubstitutions.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeSubstitutions.java	Wed Apr 16 19:00:14 2014 +0200
@@ -33,16 +33,15 @@
 public class HotSpotNodeSubstitutions {
 
     /**
-     * Partial substitution of {@link Node#getNodeClass()} that returns the value of the
-     * {@code InstanceKlass::_graal_node_class} field if it is non-null.
+     * Gets the value of the {@code InstanceKlass::_graal_node_class} field from the InstanceKlass
+     * pointed to by {@code node}'s header.
      */
     @MethodSubstitution(isStatic = false)
-    public static NodeClass getNodeClass(final Node thisObj) {
-        Word klass = loadHub(thisObj);
-        NodeClass nc = piCastExact(klass.readObject(Word.signed(klassNodeClassOffset()), KLASS_NODE_CLASS), NodeClass.class);
-        if (nc != null) {
-            return nc;
-        }
-        return getNodeClass(thisObj);
+    public static NodeClass getNodeClass(final Node node) {
+        // HotSpot creates the NodeClass for each Node subclass while initializing it
+        // so we are guaranteed to read a non-null value here. As long as NodeClass
+        // is final, the stamp of the PiNode below will automatically be exact.
+        Word klass = loadHub(node);
+        return piCastNonNull(klass.readObject(Word.signed(klassNodeClassOffset()), KLASS_NODE_CLASS), NodeClass.class);
     }
 }
--- a/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerLoopSimplify.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerLoopSimplify.java	Wed Apr 16 19:00:14 2014 +0200
@@ -46,7 +46,7 @@
             cfgBlocks.remove(0);
             if (firstBlock.isLoopHeader()) {
                 DecompilerLoopBlock loopBlock = new DecompilerLoopBlock(firstBlock, decompiler, decompiler.getSchedule(), infoStream);
-                Loop loop = firstBlock.getLoop();
+                Loop<Block> loop = firstBlock.getLoop();
 
                 for (int i = 0; i < cfgBlocks.size(); i++) {
                     if (loop.blocks.contains(cfgBlocks.get(i)) && cfgBlocks.get(i) != firstBlock) {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Wed Apr 16 19:00:14 2014 +0200
@@ -82,6 +82,12 @@
         public boolean isLoopHeader;
         public int loopId;
 
+        /**
+         * XXX to be removed - currently only used by baseline compiler
+         */
+        public Loop<BciBlock> loop;
+        public boolean isLoopEnd;
+
         public FixedWithNextNode firstInstruction;
         public AbstractFrameStateBuilder<?, ?> entryState;
 
@@ -144,14 +150,12 @@
             return sb.toString();
         }
 
-        public Loop getLoop() {
-            // TODO Auto-generated method stub
-            return null;
+        public Loop<BciBlock> getLoop() {
+            return loop;
         }
 
         public int getLoopDepth() {
-            // TODO Auto-generated method stub
-            return 0;
+            return Long.bitCount(loops);
         }
 
         public boolean isLoopHeader() {
@@ -159,13 +163,11 @@
         }
 
         public boolean isLoopEnd() {
-            // TODO Auto-generated method stub
-            return false;
+            return isLoopEnd;
         }
 
         public boolean isExceptionEntry() {
-            // TODO Auto-generated method stub
-            return false;
+            return isExceptionEntry;
         }
 
         public BciBlock getSuccessor(int index) {
@@ -716,6 +718,10 @@
         for (BciBlock successor : block.getSuccessors()) {
             // Recursively process successors.
             loops |= computeBlockOrder(successor);
+            if (block.visited && successor.active) {
+                // Reached block via backward branch.
+                block.isLoopEnd = true;
+            }
         }
 
         block.loops = loops;
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Apr 16 19:00:14 2014 +0200
@@ -1077,11 +1077,11 @@
              * Returns a block begin node with the specified state. If the specified probability is
              * 0, the block deoptimizes immediately.
              */
-            private AbstractBeginNode createBlockTarget(double probability, BciBlock block, HIRFrameStateBuilder stateAfter) {
+            private BeginNode createBlockTarget(double probability, BciBlock block, HIRFrameStateBuilder stateAfter) {
                 FixedNode target = createTarget(probability, block, stateAfter);
-                AbstractBeginNode begin = AbstractBeginNode.begin(target);
+                BeginNode begin = BeginNode.begin(target);
 
-                assert !(target instanceof DeoptimizeNode && begin.stateAfter() != null) : "We are not allowed to set the stateAfter of the begin node, because we have to deoptimize "
+                assert !(target instanceof DeoptimizeNode && begin instanceof BeginStateSplitNode && ((BeginStateSplitNode) begin).stateAfter() != null) : "We are not allowed to set the stateAfter of the begin node, because we have to deoptimize "
                                 + "to a bci _before_ the actual if, so that the interpreter can update the profiling information.";
                 return begin;
             }
@@ -1299,7 +1299,7 @@
                         frameState.clearNonLiveLocals(currentBlock, liveness, false);
                     }
                     if (lastInstr instanceof StateSplit) {
-                        if (lastInstr.getClass() == AbstractBeginNode.class) {
+                        if (lastInstr.getClass() == BeginNode.class) {
                             // BeginNodes do not need a frame state
                         } else {
                             StateSplit stateSplit = (StateSplit) lastInstr;
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java	Wed Apr 16 19:00:14 2014 +0200
@@ -259,7 +259,7 @@
         }
     }
 
-    public void insertProxies(AbstractBeginNode begin) {
+    public void insertProxies(BeginNode begin) {
         for (int i = 0; i < localsSize(); i++) {
             ValueNode value = localAt(i);
             if (value != null) {
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/Loop07.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/Loop07.java	Wed Apr 16 19:00:14 2014 +0200
@@ -26,8 +26,6 @@
 
 import com.oracle.graal.jtt.*;
 
-/*
- */
 public class Loop07 extends JTTTest {
 
     public static String test(int arg) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/Loop07_2.java	Wed Apr 16 19:00:14 2014 +0200
@@ -0,0 +1,54 @@
+/*
+ * 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.jtt.loop;
+
+import org.junit.*;
+
+import com.oracle.graal.jtt.*;
+
+public class Loop07_2 extends JTTTest {
+
+    public static int test(int arg) {
+        int count = arg;
+        for (int i = 0; i < arg; i++) {
+            count++;
+        }
+        return count;
+    }
+
+    @Test
+    public void run0() throws Throwable {
+        runTest("test", 0);
+    }
+
+    @Test
+    public void run1() throws Throwable {
+        runTest("test", 10);
+    }
+
+    @Test
+    public void run2() throws Throwable {
+        runTest("test", 25);
+    }
+
+}
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMap.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMap.java	Wed Apr 16 19:00:14 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
 import com.oracle.graal.lir.*;
 
 /**
@@ -33,7 +34,7 @@
  *
  * <pre>
  *   Base       Contents
- *
+ * 
  *            :                                :  -----
  *   caller   | incoming overflow argument n   |    ^
  *   frame    :     ...                        :    | positive
@@ -88,8 +89,7 @@
 
     @Override
     protected int alignFrameSize(int size) {
-        int x = size + returnAddressSize() + (target.stackAlignment - 1);
-        return (x / target.stackAlignment) * target.stackAlignment - returnAddressSize();
+        return NumUtil.roundUp(size + returnAddressSize(), target.stackAlignment) - returnAddressSize();
     }
 
     @Override
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java	Wed Apr 16 19:00:14 2014 +0200
@@ -37,9 +37,9 @@
     private InductionVariable iv;
     private ValueNode end;
     private boolean oneOff;
-    private AbstractBeginNode body;
+    private BeginNode body;
 
-    CountedLoopInfo(LoopEx loop, InductionVariable iv, ValueNode end, boolean oneOff, AbstractBeginNode body) {
+    CountedLoopInfo(LoopEx loop, InductionVariable iv, ValueNode end, boolean oneOff, BeginNode body) {
         this.loop = loop;
         this.iv = iv;
         this.end = end;
@@ -117,7 +117,7 @@
         return oneOff;
     }
 
-    public AbstractBeginNode getBody() {
+    public BeginNode getBody() {
         return body;
     }
 
@@ -143,14 +143,14 @@
         CompareNode cond; // we use a negated guard with a < condition to achieve a >=
         ConstantNode one = ConstantNode.forIntegerStamp(stamp, 1, graph);
         if (iv.direction() == Direction.Up) {
-            IntegerArithmeticNode v1 = sub(graph, ConstantNode.forIntegerStamp(stamp, IntegerStamp.defaultMaxValue(stamp.getBits(), stamp.isUnsigned()), graph), sub(graph, iv.strideNode(), one));
+            IntegerArithmeticNode v1 = sub(graph, ConstantNode.forIntegerStamp(stamp, IntegerStamp.defaultMaxValue(stamp.getBits()), graph), sub(graph, iv.strideNode(), one));
             if (oneOff) {
                 v1 = sub(graph, v1, one);
             }
             cond = graph.unique(new IntegerLessThanNode(v1, end));
         } else {
             assert iv.direction() == Direction.Down;
-            IntegerArithmeticNode v1 = add(graph, ConstantNode.forIntegerStamp(stamp, IntegerStamp.defaultMinValue(stamp.getBits(), stamp.isUnsigned()), graph), sub(graph, one, iv.strideNode()));
+            IntegerArithmeticNode v1 = add(graph, ConstantNode.forIntegerStamp(stamp, IntegerStamp.defaultMinValue(stamp.getBits()), graph), sub(graph, one, iv.strideNode()));
             if (oneOff) {
                 v1 = add(graph, v1, one);
             }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Wed Apr 16 19:00:14 2014 +0200
@@ -36,19 +36,19 @@
 
 public class LoopEx {
 
-    private final Loop lirLoop;
+    private final Loop<Block> lirLoop;
     private LoopFragmentInside inside;
     private LoopFragmentWhole whole;
     private CountedLoopInfo counted; // TODO (gd) detect
     private LoopsData data;
     private InductionVariables ivs;
 
-    LoopEx(Loop lirLoop, LoopsData data) {
+    LoopEx(Loop<Block> lirLoop, LoopsData data) {
         this.lirLoop = lirLoop;
         this.data = data;
     }
 
-    public Loop lirLoop() {
+    public Loop<Block> lirLoop() {
         return lirLoop;
     }
 
@@ -88,7 +88,7 @@
     }
 
     public LoopBeginNode loopBegin() {
-        return lirLoop().loopBegin();
+        return (LoopBeginNode) lirLoop().header.getBeginNode();
     }
 
     public FixedNode predecessor() {
@@ -123,7 +123,7 @@
         return (isCounted() ? "CountedLoop [" + counted() + "] " : "Loop ") + "(depth=" + lirLoop().depth + ") " + loopBegin();
     }
 
-    private class InvariantPredicate extends NodePredicate {
+    private class InvariantPredicate implements NodePredicate {
 
         @Override
         public boolean apply(Node n) {
@@ -222,9 +222,9 @@
         return data;
     }
 
-    public NodeBitMap nodesInLoopFrom(AbstractBeginNode point, AbstractBeginNode until) {
-        Collection<AbstractBeginNode> blocks = new LinkedList<>();
-        Collection<AbstractBeginNode> exits = new LinkedList<>();
+    public NodeBitMap nodesInLoopFrom(BeginNode point, BeginNode until) {
+        Collection<BeginNode> blocks = new LinkedList<>();
+        Collection<LoopExitNode> exits = new LinkedList<>();
         Queue<Block> work = new LinkedList<>();
         ControlFlowGraph cfg = loopsData().controlFlowGraph();
         work.add(cfg.blockFor(point));
@@ -235,7 +235,7 @@
                 continue;
             }
             if (lirLoop().exits.contains(b)) {
-                exits.add(b.getBeginNode());
+                exits.add((LoopExitNode) b.getBeginNode());
             } else if (lirLoop().blocks.contains(b)) {
                 blocks.add(b.getBeginNode());
                 work.addAll(b.getDominated());
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Wed Apr 16 19:00:14 2014 +0200
@@ -31,7 +31,6 @@
 import com.oracle.graal.nodes.VirtualState.VirtualClosure;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.nodes.virtual.*;
 
 public abstract class LoopFragment {
@@ -79,6 +78,15 @@
         duplicationMap.put(oldNode, newNode);
     }
 
+    /**
+     * Gets the corresponding value in this fragment. Should be called on duplicate fragments with a
+     * node from the original fragment as argument.
+     *
+     * @param b original value
+     * @return corresponding value in the peel
+     */
+    protected abstract ValueNode prim(ValueNode b);
+
     public boolean isDuplicate() {
         return original != null;
     }
@@ -141,13 +149,13 @@
         }
     }
 
-    protected static NodeBitMap computeNodes(Graph graph, Iterable<AbstractBeginNode> blocks) {
-        return computeNodes(graph, blocks, Collections.<AbstractBeginNode> emptyList());
+    protected static NodeBitMap computeNodes(Graph graph, Iterable<BeginNode> blocks) {
+        return computeNodes(graph, blocks, Collections.emptyList());
     }
 
-    protected static NodeBitMap computeNodes(Graph graph, Iterable<AbstractBeginNode> blocks, Iterable<AbstractBeginNode> earlyExits) {
+    protected static NodeBitMap computeNodes(Graph graph, Iterable<BeginNode> blocks, Iterable<LoopExitNode> earlyExits) {
         final NodeBitMap nodes = graph.createNodeBitMap(true);
-        for (AbstractBeginNode b : blocks) {
+        for (BeginNode b : blocks) {
             if (b.isDeleted()) {
                 continue;
             }
@@ -165,7 +173,7 @@
                 nodes.mark(n);
             }
         }
-        for (AbstractBeginNode earlyExit : earlyExits) {
+        for (LoopExitNode earlyExit : earlyExits) {
             if (earlyExit.isDeleted()) {
                 continue;
             }
@@ -188,7 +196,7 @@
         }
 
         final NodeBitMap notloopNodes = graph.createNodeBitMap(true);
-        for (AbstractBeginNode b : blocks) {
+        for (BeginNode b : blocks) {
             if (b.isDeleted()) {
                 continue;
             }
@@ -245,19 +253,19 @@
         return false;
     }
 
-    public static NodeIterable<AbstractBeginNode> toHirBlocks(final Iterable<Block> blocks) {
-        return new AbstractNodeIterable<AbstractBeginNode>() {
+    public static NodeIterable<BeginNode> toHirBlocks(final Iterable<Block> blocks) {
+        return new NodeIterable<BeginNode>() {
 
-            public Iterator<AbstractBeginNode> iterator() {
+            public Iterator<BeginNode> iterator() {
                 final Iterator<Block> it = blocks.iterator();
-                return new Iterator<AbstractBeginNode>() {
+                return new Iterator<BeginNode>() {
 
                     @Override
                     public void remove() {
                         throw new UnsupportedOperationException();
                     }
 
-                    public AbstractBeginNode next() {
+                    public BeginNode next() {
                         return it.next().getBeginNode();
                     }
 
@@ -270,6 +278,31 @@
         };
     }
 
+    public static NodeIterable<LoopExitNode> toHirExits(final Iterable<Block> blocks) {
+        return new NodeIterable<LoopExitNode>() {
+
+            public Iterator<LoopExitNode> iterator() {
+                final Iterator<Block> it = blocks.iterator();
+                return new Iterator<LoopExitNode>() {
+
+                    @Override
+                    public void remove() {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public LoopExitNode next() {
+                        return (LoopExitNode) it.next().getBeginNode();
+                    }
+
+                    public boolean hasNext() {
+                        return it.hasNext();
+                    }
+                };
+            }
+
+        };
+    }
+
     /**
      * Merges the early exits (i.e. loop exits) that were duplicated as part of this fragment, with
      * the original fragment's exits.
@@ -277,38 +310,38 @@
     protected void mergeEarlyExits() {
         assert isDuplicate();
         StructuredGraph graph = graph();
-        for (AbstractBeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().lirLoop().exits)) {
-            FixedNode next = earlyExit.next();
-            if (earlyExit.isDeleted() || !this.original().contains(earlyExit)) {
+        for (BeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().lirLoop().exits)) {
+            LoopExitNode loopEarlyExit = (LoopExitNode) earlyExit;
+            FixedNode next = loopEarlyExit.next();
+            if (loopEarlyExit.isDeleted() || !this.original().contains(loopEarlyExit)) {
                 continue;
             }
-            AbstractBeginNode newEarlyExit = getDuplicatedNode(earlyExit);
+            BeginNode newEarlyExit = getDuplicatedNode(loopEarlyExit);
             if (newEarlyExit == null) {
                 continue;
             }
-            boolean newEarlyExitIsBegin = newEarlyExit instanceof BeginNode;
             MergeNode merge = graph.add(new MergeNode());
             AbstractEndNode originalEnd = graph.add(new EndNode());
             AbstractEndNode newEnd = graph.add(new EndNode());
             merge.addForwardEnd(originalEnd);
             merge.addForwardEnd(newEnd);
-            earlyExit.setNext(originalEnd);
+            loopEarlyExit.setNext(originalEnd);
             newEarlyExit.setNext(newEnd);
             merge.setNext(next);
 
-            FrameState exitState = earlyExit.stateAfter();
+            FrameState exitState = loopEarlyExit.stateAfter();
             FrameState state = null;
             if (exitState != null) {
                 state = exitState;
                 exitState = exitState.duplicateWithVirtualState();
-                earlyExit.setStateAfter(exitState);
+                loopEarlyExit.setStateAfter(exitState);
                 merge.setStateAfter(state);
                 /*
                  * Using the old exit's state as the merge's state is necessary because some of the
                  * VirtualState nodes contained in the old exit's state may be shared by other
                  * dominated VirtualStates. Those dominated virtual states need to see the
                  * proxy->phi update that are applied below.
-                 * 
+                 *
                  * We now update the original fragment's nodes accordingly:
                  */
                 state.applyToVirtual(new VirtualClosure() {
@@ -322,14 +355,19 @@
                     }
                 });
             }
+            FrameState finalExitState = exitState;
 
-            for (Node anchored : earlyExit.anchored().snapshot()) {
-                anchored.replaceFirstInput(earlyExit, merge);
+            for (Node anchored : loopEarlyExit.anchored().snapshot()) {
+                anchored.replaceFirstInput(loopEarlyExit, merge);
             }
 
-            for (final ProxyNode vpn : earlyExit.proxies().snapshot()) {
+            boolean newEarlyExitIsLoopExit = newEarlyExit instanceof LoopExitNode;
+            for (final ProxyNode vpn : loopEarlyExit.proxies().snapshot()) {
+                if (vpn.usages().isEmpty()) {
+                    continue;
+                }
                 final ValueNode replaceWith;
-                ProxyNode newVpn = getDuplicatedNode(vpn);
+                ValueNode newVpn = prim(newEarlyExitIsLoopExit ? vpn : vpn.value());
                 if (newVpn != null) {
                     PhiNode phi;
                     if (vpn instanceof ValueProxyNode) {
@@ -342,32 +380,23 @@
                         throw GraalInternalError.shouldNotReachHere();
                     }
                     phi.addInput(vpn);
-                    phi.addInput(newEarlyExitIsBegin ? newVpn.value() : newVpn);
+                    phi.addInput(newVpn);
                     replaceWith = phi;
                 } else {
                     replaceWith = vpn.value();
                 }
-                for (Node usage : vpn.usages().snapshot()) {
-                    if (!merge.isPhiAtMerge(usage)) {
-                        if (usage instanceof VirtualState) {
-                            VirtualState stateUsage = (VirtualState) usage;
-                            if (exitState.isPartOfThisState(stateUsage)) {
-                                continue;
-                            }
-                        }
-                        usage.replaceFirstInput(vpn, replaceWith);
+                vpn.replaceAtMatchingUsages(replaceWith, usage -> {
+                    if (merge.isPhiAtMerge(usage)) {
+                        return false;
                     }
-                }
-            }
-            if (newEarlyExitIsBegin) {
-                FrameState stateAtNewEarlyExit = newEarlyExit.stateAfter();
-                if (stateAtNewEarlyExit != null) {
-                    newEarlyExit.setStateAfter(null);
-                    GraphUtil.killWithUnusedFloatingInputs(stateAtNewEarlyExit);
-                }
-                for (ProxyNode proxy : newEarlyExit.proxies().snapshot()) {
-                    GraphUtil.killWithUnusedFloatingInputs(proxy);
-                }
+                    if (usage instanceof VirtualState) {
+                        VirtualState stateUsage = (VirtualState) usage;
+                        if (finalExitState.isPartOfThisState(stateUsage)) {
+                            return false;
+                        }
+                    }
+                    return true;
+                });
             }
         }
     }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Wed Apr 16 19:00:14 2014 +0200
@@ -29,7 +29,6 @@
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.VirtualState.NodeClosure;
-import com.oracle.graal.nodes.util.*;
 
 public class LoopFragmentInside extends LoopFragment {
 
@@ -88,18 +87,13 @@
 
         patchNodes(dataFixBefore);
 
-        AbstractBeginNode end = mergeEnds();
-
-        original().patchPeeling(this);
+        BeginNode end = mergeEnds();
 
         mergeEarlyExits();
 
-        AbstractBeginNode entry = getDuplicatedNode(loop.loopBegin());
-        FrameState state = entry.stateAfter();
-        if (state != null) {
-            entry.setStateAfter(null);
-            GraphUtil.killWithUnusedFloatingInputs(state);
-        }
+        original().patchPeeling(this);
+
+        BeginNode entry = getDuplicatedNode(loop.loopBegin());
         loop.entryPoint().replaceAtPredecessor(entry);
         end.setNext(loop.entryPoint());
     }
@@ -111,13 +105,27 @@
             whole.nodes(); // init nodes bitmap in whole
             nodes = whole.nodes.copy();
             // remove the phis
-            for (PhiNode phi : loop().loopBegin().phis()) {
+            LoopBeginNode loopBegin = loop().loopBegin();
+            for (PhiNode phi : loopBegin.phis()) {
                 nodes.clear(phi);
             }
+            for (LoopExitNode exit : exits()) {
+                FrameState exitState = exit.stateAfter();
+                if (exitState != null) {
+                    exitState.applyToVirtual(v -> nodes.clear(v));
+                }
+                for (ProxyNode proxy : exit.proxies()) {
+                    nodes.clear(proxy);
+                }
+            }
         }
         return nodes;
     }
 
+    public NodeIterable<LoopExitNode> exits() {
+        return loop().loopBegin().loopExits();
+    }
+
     @Override
     protected DuplicationReplacement getDuplicationReplacement() {
         final LoopBeginNode loopBegin = loop().loopBegin();
@@ -183,7 +191,22 @@
         LoopBeginNode loopBegin = loop().loopBegin();
         StructuredGraph graph = loopBegin.graph();
         List<PhiNode> newPhis = new LinkedList<>();
+
+        NodeBitMap usagesToPatch = nodes.copy();
+        for (LoopExitNode exit : exits()) {
+            FrameState exitState = exit.stateAfter();
+            if (exitState != null) {
+                exitState.applyToVirtual(v -> usagesToPatch.mark(v));
+            }
+            for (ProxyNode proxy : exit.proxies()) {
+                usagesToPatch.mark(proxy);
+            }
+        }
+
         for (PhiNode phi : loopBegin.phis().snapshot()) {
+            if (phi.usages().isEmpty()) {
+                continue;
+            }
             ValueNode first;
             if (loopBegin.loopEnds().count() == 1) {
                 ValueNode b = phi.valueAt(loopBegin.loopEnds().first()); // back edge value
@@ -201,9 +224,8 @@
             peel.putDuplicatedNode(phi, newPhi);
             newPhis.add(newPhi);
             for (Node usage : phi.usages().snapshot()) {
-                if (peel.getDuplicatedNode(usage) != null) { // patch only usages that should use
-                                                             // the new phi ie usages that were
-                                                             // peeled
+                // patch only usages that should use the new phi ie usages that were peeled
+                if (usagesToPatch.isMarked(usage)) {
                     usage.replaceFirstInput(phi, newPhi);
                 }
             }
@@ -229,7 +251,8 @@
      * @param b original value
      * @return corresponding value in the peel
      */
-    private ValueNode prim(ValueNode b) {
+    @Override
+    protected ValueNode prim(ValueNode b) {
         assert isDuplicate();
         LoopBeginNode loopBegin = original().loop().loopBegin();
         if (loopBegin.isPhiAtMerge(b)) {
@@ -246,7 +269,7 @@
         }
     }
 
-    private AbstractBeginNode mergeEnds() {
+    private BeginNode mergeEnds() {
         assert isDuplicate();
         List<AbstractEndNode> endsToMerge = new LinkedList<>();
         Map<AbstractEndNode, LoopEndNode> reverseEnds = new HashMap<>(); // map peel's exit to the
@@ -260,7 +283,7 @@
             }
         }
         mergedInitializers = new IdentityHashMap<>();
-        AbstractBeginNode newExit;
+        BeginNode newExit;
         StructuredGraph graph = graph();
         if (endsToMerge.size() == 1) {
             AbstractEndNode end = endsToMerge.get(0);
@@ -283,6 +306,9 @@
             }
 
             for (final PhiNode phi : loopBegin.phis().snapshot()) {
+                if (phi.usages().isEmpty()) {
+                    continue;
+                }
                 final PhiNode firstPhi = patchPhi(graph, phi, newExitMerge);
                 for (AbstractEndNode end : newExitMerge.forwardEnds()) {
                     LoopEndNode loopEnd = reverseEnds.get(end);
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java	Wed Apr 16 19:00:14 2014 +0200
@@ -56,13 +56,18 @@
     @Override
     public NodeIterable<Node> nodes() {
         if (nodes == null) {
-            Loop lirLoop = loop().lirLoop();
-            nodes = LoopFragment.computeNodes(graph(), LoopFragment.toHirBlocks(lirLoop.blocks), LoopFragment.toHirBlocks(lirLoop.exits));
+            Loop<Block> lirLoop = loop().lirLoop();
+            nodes = LoopFragment.computeNodes(graph(), LoopFragment.toHirBlocks(lirLoop.blocks), LoopFragment.toHirExits(lirLoop.exits));
         }
         return nodes;
     }
 
     @Override
+    protected ValueNode prim(ValueNode b) {
+        return getDuplicatedNode(b);
+    }
+
+    @Override
     protected DuplicationReplacement getDuplicationReplacement() {
         final FixedNode entry = loop().entryPoint();
         final Graph graph = this.graph();
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Wed Apr 16 19:00:14 2014 +0200
@@ -64,12 +64,12 @@
 
     public static boolean shouldUnswitch(LoopEx loop, ControlSplitNode controlSplit) {
         Block postDomBlock = loop.loopsData().controlFlowGraph().blockFor(controlSplit).getPostdominator();
-        AbstractBeginNode postDom = postDomBlock != null ? postDomBlock.getBeginNode() : null;
+        BeginNode postDom = postDomBlock != null ? postDomBlock.getBeginNode() : null;
         int loopTotal = loop.size();
         int inBranchTotal = 0;
         double maxProbability = 0;
         for (Node successor : controlSplit.successors()) {
-            AbstractBeginNode branch = (AbstractBeginNode) successor;
+            BeginNode branch = (BeginNode) successor;
             inBranchTotal += loop.nodesInLoopFrom(branch, postDom).cardinality(); // this may count
                                                                                   // twice because
                                                                                   // of fall-through
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Wed Apr 16 19:00:14 2014 +0200
@@ -63,6 +63,7 @@
             Mark mark = graph.getMark();
             peel(loop);
             canonicalizer.applyIncremental(graph, context, mark);
+            loopBegin.removeDeadPhis();
             loop.invalidateFragments();
             if (iterations++ > UNROLL_LIMIT || graph.getNodeCount() > MaximumDesiredSize.getValue() * 3) {
                 throw new BailoutException("FullUnroll : Graph seems to grow out of proportion");
@@ -81,19 +82,19 @@
         // original loop is used as first successor
         Position firstPosition = successors.nextPosition();
         NodeClass controlSplitClass = controlSplitNode.getNodeClass();
-        controlSplitClass.set(newControlSplit, firstPosition, AbstractBeginNode.begin(originalLoop.entryPoint()));
+        controlSplitClass.set(newControlSplit, firstPosition, BeginNode.begin(originalLoop.entryPoint()));
 
         StructuredGraph graph = controlSplitNode.graph();
         while (successors.hasNext()) {
             Position position = successors.nextPosition();
             // create a new loop duplicate, connect it and simplify it
             LoopFragmentWhole duplicateLoop = originalLoop.duplicate();
-            controlSplitClass.set(newControlSplit, position, AbstractBeginNode.begin(duplicateLoop.entryPoint()));
+            controlSplitClass.set(newControlSplit, position, BeginNode.begin(duplicateLoop.entryPoint()));
             ControlSplitNode duplicatedControlSplit = duplicateLoop.getDuplicatedNode(controlSplitNode);
-            graph.removeSplitPropagate(duplicatedControlSplit, (AbstractBeginNode) controlSplitClass.get(duplicatedControlSplit, position));
+            graph.removeSplitPropagate(duplicatedControlSplit, (BeginNode) controlSplitClass.get(duplicatedControlSplit, position));
         }
         // original loop is simplified last to avoid deleting controlSplitNode too early
-        graph.removeSplitPropagate(controlSplitNode, (AbstractBeginNode) controlSplitClass.get(controlSplitNode, firstPosition));
+        graph.removeSplitPropagate(controlSplitNode, (BeginNode) controlSplitClass.get(controlSplitNode, firstPosition));
         // TODO (gd) probabilities need some amount of fixup.. (probably also in other transforms)
     }
 
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java	Wed Apr 16 19:00:14 2014 +0200
@@ -31,7 +31,7 @@
 
 public class LoopsData {
 
-    private Map<Loop, LoopEx> lirLoopToEx = new IdentityHashMap<>();
+    private Map<Loop<Block>, LoopEx> lirLoopToEx = new IdentityHashMap<>();
     private Map<LoopBeginNode, LoopEx> loopBeginToEx = new IdentityHashMap<>();
     private ControlFlowGraph cfg;
 
@@ -42,14 +42,14 @@
             throw Debug.handle(e);
         }
 
-        for (Loop lirLoop : cfg.getLoops()) {
+        for (Loop<Block> lirLoop : cfg.getLoops()) {
             LoopEx ex = new LoopEx(lirLoop, this);
             lirLoopToEx.put(lirLoop, ex);
             loopBeginToEx.put(ex.loopBegin(), ex);
         }
     }
 
-    public LoopEx loop(Loop lirLoop) {
+    public LoopEx loop(Loop<?> lirLoop) {
         return lirLoopToEx.get(lirLoop);
     }
 
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Wed Apr 16 19:00:14 2014 +0200
@@ -78,7 +78,7 @@
         sb.append(loop).append(" at ").append(controlSplit).append(" [");
         NodeClassIterator it = controlSplit.successors().iterator();
         while (it.hasNext()) {
-            sb.append(controlSplit.probability((AbstractBeginNode) it.next()));
+            sb.append(controlSplit.probability((BeginNode) it.next()));
             if (it.hasNext()) {
                 sb.append(", ");
             }
--- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java	Wed Apr 16 19:00:14 2014 +0200
@@ -44,83 +44,83 @@
 
     @Test
     public void testBooleanConstant() {
-        assertEquals(new IntegerStamp(32, false, 1, 1, 0x1, 0x1), ConstantNode.forBoolean(true, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 0, 0, 0x0, 0x0), ConstantNode.forBoolean(false, graph).stamp());
+        assertEquals(new IntegerStamp(32, 1, 1, 0x1, 0x1), ConstantNode.forBoolean(true, graph).stamp());
+        assertEquals(new IntegerStamp(32, 0, 0, 0x0, 0x0), ConstantNode.forBoolean(false, graph).stamp());
     }
 
     @Test
     public void testByteConstant() {
-        assertEquals(new IntegerStamp(32, false, 0, 0, 0x0, 0x0), ConstantNode.forByte((byte) 0, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 16, 16, 0x10, 0x10), ConstantNode.forByte((byte) 16, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, -16, -16, 0xfffffff0L, 0xfffffff0L), ConstantNode.forByte((byte) -16, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 127, 127, 0x7f, 0x7f), ConstantNode.forByte((byte) 127, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forByte((byte) -128, graph).stamp());
+        assertEquals(new IntegerStamp(32, 0, 0, 0x0, 0x0), ConstantNode.forByte((byte) 0, graph).stamp());
+        assertEquals(new IntegerStamp(32, 16, 16, 0x10, 0x10), ConstantNode.forByte((byte) 16, graph).stamp());
+        assertEquals(new IntegerStamp(32, -16, -16, 0xfffffff0L, 0xfffffff0L), ConstantNode.forByte((byte) -16, graph).stamp());
+        assertEquals(new IntegerStamp(32, 127, 127, 0x7f, 0x7f), ConstantNode.forByte((byte) 127, graph).stamp());
+        assertEquals(new IntegerStamp(32, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forByte((byte) -128, graph).stamp());
     }
 
     @Test
     public void testShortConstant() {
-        assertEquals(new IntegerStamp(32, false, 0, 0, 0x0, 0x0), ConstantNode.forShort((short) 0, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 128, 128, 0x80, 0x80), ConstantNode.forShort((short) 128, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forShort((short) -128, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 32767, 32767, 0x7fff, 0x7fff), ConstantNode.forShort((short) 32767, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, -32768, -32768, 0xffff8000L, 0xffff8000L), ConstantNode.forShort((short) -32768, graph).stamp());
+        assertEquals(new IntegerStamp(32, 0, 0, 0x0, 0x0), ConstantNode.forShort((short) 0, graph).stamp());
+        assertEquals(new IntegerStamp(32, 128, 128, 0x80, 0x80), ConstantNode.forShort((short) 128, graph).stamp());
+        assertEquals(new IntegerStamp(32, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forShort((short) -128, graph).stamp());
+        assertEquals(new IntegerStamp(32, 32767, 32767, 0x7fff, 0x7fff), ConstantNode.forShort((short) 32767, graph).stamp());
+        assertEquals(new IntegerStamp(32, -32768, -32768, 0xffff8000L, 0xffff8000L), ConstantNode.forShort((short) -32768, graph).stamp());
     }
 
     @Test
     public void testCharConstant() {
-        assertEquals(new IntegerStamp(32, false, 0, 0, 0x0, 0x0), ConstantNode.forChar((char) 0, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 'A', 'A', 'A', 'A'), ConstantNode.forChar('A', graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 128, 128, 0x80, 0x80), ConstantNode.forChar((char) 128, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 65535, 65535, 0xffff, 0xffff), ConstantNode.forChar((char) 65535, graph).stamp());
+        assertEquals(new IntegerStamp(32, 0, 0, 0x0, 0x0), ConstantNode.forChar((char) 0, graph).stamp());
+        assertEquals(new IntegerStamp(32, 'A', 'A', 'A', 'A'), ConstantNode.forChar('A', graph).stamp());
+        assertEquals(new IntegerStamp(32, 128, 128, 0x80, 0x80), ConstantNode.forChar((char) 128, graph).stamp());
+        assertEquals(new IntegerStamp(32, 65535, 65535, 0xffff, 0xffff), ConstantNode.forChar((char) 65535, graph).stamp());
     }
 
     @Test
     public void testIntConstant() {
-        assertEquals(new IntegerStamp(32, false, 0, 0, 0x0, 0x0), ConstantNode.forInt(0, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 128, 128, 0x80, 0x80), ConstantNode.forInt(128, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forInt(-128, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, Integer.MAX_VALUE, Integer.MAX_VALUE, 0x7fffffff, 0x7fffffff), ConstantNode.forInt(Integer.MAX_VALUE, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, Integer.MIN_VALUE, Integer.MIN_VALUE, 0x80000000L, 0x80000000L), ConstantNode.forInt(Integer.MIN_VALUE, graph).stamp());
+        assertEquals(new IntegerStamp(32, 0, 0, 0x0, 0x0), ConstantNode.forInt(0, graph).stamp());
+        assertEquals(new IntegerStamp(32, 128, 128, 0x80, 0x80), ConstantNode.forInt(128, graph).stamp());
+        assertEquals(new IntegerStamp(32, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forInt(-128, graph).stamp());
+        assertEquals(new IntegerStamp(32, Integer.MAX_VALUE, Integer.MAX_VALUE, 0x7fffffff, 0x7fffffff), ConstantNode.forInt(Integer.MAX_VALUE, graph).stamp());
+        assertEquals(new IntegerStamp(32, Integer.MIN_VALUE, Integer.MIN_VALUE, 0x80000000L, 0x80000000L), ConstantNode.forInt(Integer.MIN_VALUE, graph).stamp());
     }
 
     @Test
     public void testLongConstant() {
-        assertEquals(new IntegerStamp(64, false, 0, 0, 0x0, 0x0), ConstantNode.forLong(0, graph).stamp());
-        assertEquals(new IntegerStamp(64, false, 128, 128, 0x80, 0x80), ConstantNode.forLong(128, graph).stamp());
-        assertEquals(new IntegerStamp(64, false, -128, -128, 0xffffffffffffff80L, 0xffffffffffffff80L), ConstantNode.forLong(-128, graph).stamp());
-        assertEquals(new IntegerStamp(64, false, Long.MAX_VALUE, Long.MAX_VALUE, 0x7fffffffffffffffL, 0x7fffffffffffffffL), ConstantNode.forLong(Long.MAX_VALUE, graph).stamp());
-        assertEquals(new IntegerStamp(64, false, Long.MIN_VALUE, Long.MIN_VALUE, 0x8000000000000000L, 0x8000000000000000L), ConstantNode.forLong(Long.MIN_VALUE, graph).stamp());
+        assertEquals(new IntegerStamp(64, 0, 0, 0x0, 0x0), ConstantNode.forLong(0, graph).stamp());
+        assertEquals(new IntegerStamp(64, 128, 128, 0x80, 0x80), ConstantNode.forLong(128, graph).stamp());
+        assertEquals(new IntegerStamp(64, -128, -128, 0xffffffffffffff80L, 0xffffffffffffff80L), ConstantNode.forLong(-128, graph).stamp());
+        assertEquals(new IntegerStamp(64, Long.MAX_VALUE, Long.MAX_VALUE, 0x7fffffffffffffffL, 0x7fffffffffffffffL), ConstantNode.forLong(Long.MAX_VALUE, graph).stamp());
+        assertEquals(new IntegerStamp(64, Long.MIN_VALUE, Long.MIN_VALUE, 0x8000000000000000L, 0x8000000000000000L), ConstantNode.forLong(Long.MIN_VALUE, graph).stamp());
     }
 
     @Test
     public void testPositiveRanges() {
-        assertEquals(new IntegerStamp(32, false, 0, 0, 0, 0), StampFactory.forInteger(Kind.Int, 0, 0));
-        assertEquals(new IntegerStamp(32, false, 0, 1, 0, 1), StampFactory.forInteger(Kind.Int, 0, 1));
-        assertEquals(new IntegerStamp(32, false, 0, 0x123, 0, 0x1ff), StampFactory.forInteger(Kind.Int, 0, 0x123));
-        assertEquals(new IntegerStamp(32, false, 0x120, 0x123, 0x120, 0x123), StampFactory.forInteger(Kind.Int, 0x120, 0x123));
-        assertEquals(new IntegerStamp(32, false, 10000, 15000, 0x2000, 0x3fff), StampFactory.forInteger(Kind.Int, 10000, 15000));
-        assertEquals(new IntegerStamp(64, false, 0, 1, 0, 1), StampFactory.forInteger(Kind.Long, 0, 1));
-        assertEquals(new IntegerStamp(64, false, 10000, 15000, 0x2000, 0x3fff), StampFactory.forInteger(Kind.Long, 10000, 15000));
-        assertEquals(new IntegerStamp(64, false, 140000000000L, 150000000000L, 0x2000000000L, 0x23ffffffffL), StampFactory.forInteger(Kind.Long, 140000000000L, 150000000000L));
+        assertEquals(new IntegerStamp(32, 0, 0, 0, 0), StampFactory.forInteger(Kind.Int, 0, 0));
+        assertEquals(new IntegerStamp(32, 0, 1, 0, 1), StampFactory.forInteger(Kind.Int, 0, 1));
+        assertEquals(new IntegerStamp(32, 0, 0x123, 0, 0x1ff), StampFactory.forInteger(Kind.Int, 0, 0x123));
+        assertEquals(new IntegerStamp(32, 0x120, 0x123, 0x120, 0x123), StampFactory.forInteger(Kind.Int, 0x120, 0x123));
+        assertEquals(new IntegerStamp(32, 10000, 15000, 0x2000, 0x3fff), StampFactory.forInteger(Kind.Int, 10000, 15000));
+        assertEquals(new IntegerStamp(64, 0, 1, 0, 1), StampFactory.forInteger(Kind.Long, 0, 1));
+        assertEquals(new IntegerStamp(64, 10000, 15000, 0x2000, 0x3fff), StampFactory.forInteger(Kind.Long, 10000, 15000));
+        assertEquals(new IntegerStamp(64, 140000000000L, 150000000000L, 0x2000000000L, 0x23ffffffffL), StampFactory.forInteger(Kind.Long, 140000000000L, 150000000000L));
     }
 
     @Test
     public void testNegativeRanges() {
-        assertEquals(new IntegerStamp(32, false, -2, -1, 0xfffffffeL, 0xffffffffL), StampFactory.forInteger(Kind.Int, -2, -1));
-        assertEquals(new IntegerStamp(32, false, -20, -10, 0xffffffe0L, 0xffffffffL), StampFactory.forInteger(Kind.Int, -20, -10));
-        assertEquals(new IntegerStamp(32, false, -10000, 0, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, 0));
-        assertEquals(new IntegerStamp(32, false, -10000, -1, 0xffffc000L, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, -1));
-        assertEquals(new IntegerStamp(32, false, -10010, -10000, 0xffffd8e0L, 0xffffd8ffL), StampFactory.forInteger(Kind.Int, -10010, -10000));
-        assertEquals(new IntegerStamp(64, false, -2, -1, 0xfffffffffffffffeL, 0xffffffffffffffffL), StampFactory.forInteger(Kind.Long, -2, -1));
-        assertEquals(new IntegerStamp(64, false, -10010, -10000, 0xffffffffffffd8e0L, 0xffffffffffffd8ffL), StampFactory.forInteger(Kind.Long, -10010, -10000));
-        assertEquals(new IntegerStamp(64, false, -150000000000L, -140000000000L, 0xffffffdc00000000L, 0xffffffdfffffffffL), StampFactory.forInteger(Kind.Long, -150000000000L, -140000000000L));
+        assertEquals(new IntegerStamp(32, -2, -1, 0xfffffffeL, 0xffffffffL), StampFactory.forInteger(Kind.Int, -2, -1));
+        assertEquals(new IntegerStamp(32, -20, -10, 0xffffffe0L, 0xffffffffL), StampFactory.forInteger(Kind.Int, -20, -10));
+        assertEquals(new IntegerStamp(32, -10000, 0, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, 0));
+        assertEquals(new IntegerStamp(32, -10000, -1, 0xffffc000L, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, -1));
+        assertEquals(new IntegerStamp(32, -10010, -10000, 0xffffd8e0L, 0xffffd8ffL), StampFactory.forInteger(Kind.Int, -10010, -10000));
+        assertEquals(new IntegerStamp(64, -2, -1, 0xfffffffffffffffeL, 0xffffffffffffffffL), StampFactory.forInteger(Kind.Long, -2, -1));
+        assertEquals(new IntegerStamp(64, -10010, -10000, 0xffffffffffffd8e0L, 0xffffffffffffd8ffL), StampFactory.forInteger(Kind.Long, -10010, -10000));
+        assertEquals(new IntegerStamp(64, -150000000000L, -140000000000L, 0xffffffdc00000000L, 0xffffffdfffffffffL), StampFactory.forInteger(Kind.Long, -150000000000L, -140000000000L));
     }
 
     @Test
     public void testMixedRanges() {
-        assertEquals(new IntegerStamp(32, false, -1, 0, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -1, 0));
-        assertEquals(new IntegerStamp(32, false, -10000, 1000, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, 1000));
-        assertEquals(new IntegerStamp(64, false, -10000, 1000, 0, 0xffffffffffffffffL), StampFactory.forInteger(Kind.Long, -10000, 1000));
+        assertEquals(new IntegerStamp(32, -1, 0, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -1, 0));
+        assertEquals(new IntegerStamp(32, -10000, 1000, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, 1000));
+        assertEquals(new IntegerStamp(64, -10000, 1000, 0, 0xffffffffffffffffL), StampFactory.forInteger(Kind.Long, -10000, 1000));
     }
 
     @Test
@@ -159,15 +159,15 @@
 
     @Test
     public void testXor() {
-        assertEquals(new IntegerStamp(32, false, 0, 0xff, 0, 0xff), StampTool.xor(new IntegerStamp(32, false, 0, 0, 0, 0), new IntegerStamp(32, false, 0, 0xff, 0, 0xff)));
-        assertEquals(new IntegerStamp(32, false, 0x10, 0x1f, 0x10, 0x1f), StampTool.xor(new IntegerStamp(32, false, 0, 0, 0, 0), new IntegerStamp(32, false, 0x10, 0x1f, 0x10, 0x1f)));
-        assertEquals(new IntegerStamp(32, false, 0x0, 0xf, 0x0, 0xf), StampTool.xor(new IntegerStamp(32, false, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(32, false, 0x10, 0x1f, 0x10, 0x1f)));
-        assertEquals(new IntegerStamp(32, false, 0x10, 0x1f, 0x10, 0x1f), StampTool.xor(new IntegerStamp(32, false, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(32, false, 0x0, 0xf, 0x0, 0xf)));
+        assertEquals(new IntegerStamp(32, 0, 0xff, 0, 0xff), StampTool.xor(new IntegerStamp(32, 0, 0, 0, 0), new IntegerStamp(32, 0, 0xff, 0, 0xff)));
+        assertEquals(new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f), StampTool.xor(new IntegerStamp(32, 0, 0, 0, 0), new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f)));
+        assertEquals(new IntegerStamp(32, 0x0, 0xf, 0x0, 0xf), StampTool.xor(new IntegerStamp(32, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f)));
+        assertEquals(new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f), StampTool.xor(new IntegerStamp(32, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(32, 0x0, 0xf, 0x0, 0xf)));
     }
 
     @Test
     public void testNot() {
-        assertEquals(new IntegerStamp(32, false, -11, -1, 0xffff_fff0L, 0xffff_ffffL), StampTool.not(new IntegerStamp(32, false, 0, 10, 0, 0xf)));
+        assertEquals(new IntegerStamp(32, -11, -1, 0xffff_fff0L, 0xffff_ffffL), StampTool.not(new IntegerStamp(32, 0, 10, 0, 0xf)));
     }
 
     @Test
@@ -258,13 +258,13 @@
 
     @Test
     public void testAnd() {
-        assertEquals(new IntegerStamp(32, false, Integer.MIN_VALUE, 0x40000000L, 0, 0xc0000000L), StampTool.and(StampFactory.forKind(Kind.Int), StampFactory.forConstant(Constant.forInt(0xc0000000))));
+        assertEquals(new IntegerStamp(32, Integer.MIN_VALUE, 0x40000000L, 0, 0xc0000000L), StampTool.and(StampFactory.forKind(Kind.Int), StampFactory.forConstant(Constant.forInt(0xc0000000))));
     }
 
     private static void testSignExtendShort(long lower, long upper) {
-        Stamp shortStamp = StampFactory.forInteger(16, false, lower, upper);
+        Stamp shortStamp = StampFactory.forInteger(16, lower, upper);
         Stamp intStamp = StampTool.signExtend(shortStamp, 32);
-        assertEquals(StampFactory.forInteger(32, false, lower, upper), intStamp);
+        assertEquals(StampFactory.forInteger(32, lower, upper), intStamp);
     }
 
     @Test
@@ -278,9 +278,9 @@
     }
 
     private static void testZeroExtendShort(long lower, long upper, long newLower, long newUpper) {
-        Stamp shortStamp = StampFactory.forInteger(16, false, lower, upper);
+        Stamp shortStamp = StampFactory.forInteger(16, lower, upper);
         Stamp intStamp = StampTool.zeroExtend(shortStamp, 32);
-        assertEquals(StampFactory.forInteger(32, false, newLower, newUpper), intStamp);
+        assertEquals(StampFactory.forInteger(32, newLower, newUpper), intStamp);
     }
 
     @Test
@@ -292,36 +292,4 @@
         testZeroExtendShort(-1, 1, 0, 0xFFFF);
         testZeroExtendShort(Short.MIN_VALUE, Short.MAX_VALUE, 0, 0xFFFF);
     }
-
-    private static void testSignExtendChar(long lower, long upper, long newLower, long newUpper) {
-        Stamp charStamp = StampFactory.forInteger(16, true, lower, upper);
-        Stamp uintStamp = StampTool.signExtend(charStamp, 32);
-        assertEquals(StampFactory.forInteger(32, true, newLower, newUpper), uintStamp);
-    }
-
-    @Test
-    public void testSignExtendUnsigned() {
-        testSignExtendChar(5, 7, 5, 7);
-        testSignExtendChar(0, 42, 0, 42);
-        testSignExtendChar(5, 0xF000, 5, 0xFFFFF000L);
-        testSignExtendChar(0, 0xF000, 0, 0xFFFFF000L);
-        testSignExtendChar(0xF000, Character.MAX_VALUE, 0xFFFFF000L, 0xFFFFFFFFL);
-        testSignExtendChar(Character.MIN_VALUE, Character.MAX_VALUE, 0, 0xFFFFFFFFL);
-    }
-
-    private static void testZeroExtendChar(long lower, long upper) {
-        Stamp charStamp = StampFactory.forInteger(16, true, lower, upper);
-        Stamp uintStamp = StampTool.zeroExtend(charStamp, 32);
-        assertEquals(StampFactory.forInteger(32, true, lower, upper), uintStamp);
-    }
-
-    @Test
-    public void testZeroExtendUnsigned() {
-        testZeroExtendChar(5, 7);
-        testZeroExtendChar(0, 42);
-        testZeroExtendChar(5, 0xF000);
-        testZeroExtendChar(0, 0xF000);
-        testZeroExtendChar(0xF000, Character.MAX_VALUE);
-        testZeroExtendChar(Character.MIN_VALUE, Character.MAX_VALUE);
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,194 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes;
-
-import static com.oracle.graal.graph.iterators.NodePredicates.*;
-
-import java.util.*;
-
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.iterators.*;
-import com.oracle.graal.graph.spi.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-
-@NodeInfo(allowedUsageTypes = {InputType.Guard, InputType.Anchor})
-public abstract class AbstractBeginNode extends FixedWithNextNode implements StateSplit, LIRLowerable, Simplifiable, GuardingNode, AnchoringNode, IterableNodeType {
-
-    @Input(InputType.State) private FrameState stateAfter;
-
-    public FrameState stateAfter() {
-        return stateAfter;
-    }
-
-    public void setStateAfter(FrameState x) {
-        assert x == null || x.isAlive() : "frame state must be in a graph";
-        updateUsages(stateAfter, x);
-        stateAfter = x;
-    }
-
-    public boolean hasSideEffect() {
-        return false;
-    }
-
-    protected AbstractBeginNode() {
-        super(StampFactory.forVoid());
-    }
-
-    protected AbstractBeginNode(Stamp stamp) {
-        super(stamp);
-    }
-
-    public static AbstractBeginNode begin(FixedNode with) {
-        if (with instanceof AbstractBeginNode) {
-            return (AbstractBeginNode) with;
-        }
-        AbstractBeginNode begin = with.graph().add(new BeginNode());
-        begin.setNext(with);
-        return begin;
-    }
-
-    @Override
-    public void simplify(SimplifierTool tool) {
-        FixedNode prev = (FixedNode) this.predecessor();
-        if (prev == null) {
-            // This is the start node.
-        } else if (prev instanceof ControlSplitNode) {
-            // This begin node is necessary.
-        } else {
-            // This begin node can be removed and all guards moved up to the preceding begin node.
-            prepareDelete();
-            tool.addToWorkList(next());
-            graph().removeFixed(this);
-        }
-    }
-
-    public static AbstractBeginNode prevBegin(FixedNode from) {
-        Node prevBegin = from;
-        while (prevBegin != null) {
-            if (prevBegin instanceof AbstractBeginNode) {
-                return (AbstractBeginNode) prevBegin;
-            }
-            prevBegin = prevBegin.predecessor();
-        }
-        return null;
-    }
-
-    private void evacuateGuards(FixedNode evacuateFrom) {
-        if (!usages().isEmpty()) {
-            AbstractBeginNode prevBegin = prevBegin(evacuateFrom);
-            assert prevBegin != null;
-            for (Node anchored : anchored().snapshot()) {
-                anchored.replaceFirstInput(this, prevBegin);
-            }
-        }
-    }
-
-    public void prepareDelete() {
-        prepareDelete((FixedNode) predecessor());
-    }
-
-    public void prepareDelete(FixedNode evacuateFrom) {
-        removeProxies();
-        evacuateGuards(evacuateFrom);
-    }
-
-    public void removeProxies() {
-        for (ProxyNode vpn : proxies().snapshot()) {
-            // can not use graph.replaceFloating because vpn.value may be null during killCFG
-            vpn.replaceAtUsages(vpn.value());
-            vpn.safeDelete();
-        }
-    }
-
-    @Override
-    public boolean verify() {
-        assertTrue(predecessor() != null || this == graph().start() || this instanceof MergeNode, "begin nodes must be connected");
-        return super.verify();
-    }
-
-    @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        // nop
-    }
-
-    public NodeIterable<GuardNode> guards() {
-        return usages().filter(GuardNode.class);
-    }
-
-    public NodeIterable<Node> anchored() {
-        return usages().filter(isNotA(ProxyNode.class));
-    }
-
-    public NodeIterable<ProxyNode> proxies() {
-        return usages().filter(ProxyNode.class);
-    }
-
-    public NodeIterable<FixedNode> getBlockNodes() {
-        return new AbstractNodeIterable<FixedNode>() {
-
-            @Override
-            public Iterator<FixedNode> iterator() {
-                return new BlockNodeIterator(AbstractBeginNode.this);
-            }
-        };
-    }
-
-    private class BlockNodeIterator implements Iterator<FixedNode> {
-
-        private FixedNode current;
-
-        public BlockNodeIterator(FixedNode next) {
-            this.current = next;
-        }
-
-        @Override
-        public boolean hasNext() {
-            return current != null;
-        }
-
-        @Override
-        public FixedNode next() {
-            FixedNode ret = current;
-            if (ret == null) {
-                throw new NoSuchElementException();
-            }
-            if (!(current instanceof FixedWithNextNode) || (current instanceof AbstractBeginNode && current != AbstractBeginNode.this)) {
-                current = null;
-            } else {
-                current = ((FixedWithNextNode) current).next();
-            }
-            return ret;
-        }
-
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    public FrameState getState() {
-        return stateAfter();
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -89,7 +89,7 @@
         DeoptimizeNode deopt = graph().add(new DeoptimizeNode(action, reason));
         deopt.setStateBefore(stateBefore());
         IfNode ifNode;
-        AbstractBeginNode noDeoptSuccessor;
+        BeginNode noDeoptSuccessor;
         if (negated) {
             ifNode = graph().add(new IfNode(condition, deopt, next, 0));
             noDeoptSuccessor = ifNode.falseSuccessor();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -22,11 +22,153 @@
  */
 package com.oracle.graal.nodes;
 
+import static com.oracle.graal.graph.iterators.NodePredicates.*;
+
+import java.util.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public final class BeginNode extends AbstractBeginNode {
+@NodeInfo(allowedUsageTypes = {InputType.Guard, InputType.Anchor})
+public class BeginNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, GuardingNode, AnchoringNode, IterableNodeType {
 
     public BeginNode() {
         super(StampFactory.forVoid());
     }
+
+    public BeginNode(Stamp stamp) {
+        super(stamp);
+    }
+
+    public static BeginNode begin(FixedNode with) {
+        if (with instanceof BeginNode) {
+            return (BeginNode) with;
+        }
+        BeginNode begin = with.graph().add(new BeginNode());
+        begin.setNext(with);
+        return begin;
+    }
+
+    @Override
+    public void simplify(SimplifierTool tool) {
+        FixedNode prev = (FixedNode) this.predecessor();
+        if (prev == null) {
+            // This is the start node.
+        } else if (prev instanceof ControlSplitNode) {
+            // This begin node is necessary.
+        } else {
+            // This begin node can be removed and all guards moved up to the preceding begin node.
+            prepareDelete();
+            tool.addToWorkList(next());
+            graph().removeFixed(this);
+        }
+    }
+
+    public static BeginNode prevBegin(FixedNode from) {
+        Node prevBegin = from;
+        while (prevBegin != null) {
+            if (prevBegin instanceof BeginNode) {
+                return (BeginNode) prevBegin;
+            }
+            prevBegin = prevBegin.predecessor();
+        }
+        return null;
+    }
+
+    private void evacuateGuards(FixedNode evacuateFrom) {
+        if (!usages().isEmpty()) {
+            BeginNode prevBegin = prevBegin(evacuateFrom);
+            assert prevBegin != null;
+            for (Node anchored : anchored().snapshot()) {
+                anchored.replaceFirstInput(this, prevBegin);
+            }
+        }
+    }
+
+    public void prepareDelete() {
+        prepareDelete((FixedNode) predecessor());
+    }
+
+    public void prepareDelete(FixedNode evacuateFrom) {
+        removeProxies();
+        evacuateGuards(evacuateFrom);
+    }
+
+    public void removeProxies() {
+        for (ProxyNode vpn : proxies().snapshot()) {
+            // can not use graph.replaceFloating because vpn.value may be null during killCFG
+            vpn.replaceAtUsages(vpn.value());
+            vpn.safeDelete();
+        }
+    }
+
+    @Override
+    public boolean verify() {
+        assertTrue(predecessor() != null || this == graph().start() || this instanceof MergeNode, "begin nodes must be connected");
+        return super.verify();
+    }
+
+    @Override
+    public void generate(NodeLIRBuilderTool gen) {
+        // nop
+    }
+
+    public NodeIterable<GuardNode> guards() {
+        return usages().filter(GuardNode.class);
+    }
+
+    public NodeIterable<Node> anchored() {
+        return usages().filter(isNotA(ProxyNode.class));
+    }
+
+    public NodeIterable<ProxyNode> proxies() {
+        return usages().filter(ProxyNode.class);
+    }
+
+    public NodeIterable<FixedNode> getBlockNodes() {
+        return new NodeIterable<FixedNode>() {
+
+            @Override
+            public Iterator<FixedNode> iterator() {
+                return new BlockNodeIterator(BeginNode.this);
+            }
+        };
+    }
+
+    private class BlockNodeIterator implements Iterator<FixedNode> {
+
+        private FixedNode current;
+
+        public BlockNodeIterator(FixedNode next) {
+            this.current = next;
+        }
+
+        @Override
+        public boolean hasNext() {
+            return current != null;
+        }
+
+        @Override
+        public FixedNode next() {
+            FixedNode ret = current;
+            if (ret == null) {
+                throw new NoSuchElementException();
+            }
+            if (!(current instanceof FixedWithNextNode) || (current instanceof BeginNode && current != BeginNode.this)) {
+                current = null;
+            } else {
+                current = ((FixedWithNextNode) current).next();
+            }
+            return ret;
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -22,16 +22,19 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.type.*;
 
 /**
- * Base class for {@link AbstractBeginNode}s that are associated with a frame state.
- * 
- * TODO (dnsimon) this not needed until {@link AbstractBeginNode} no longer implements
- * {@link StateSplit} which is not possible until loop peeling works without requiring begin nodes
- * to have frames states.
+ * Base class for {@link BeginNode}s that are associated with a frame state.
+ *
+ * TODO (dnsimon) this not needed until {@link BeginNode} no longer implements {@link StateSplit}
+ * which is not possible until loop peeling works without requiring begin nodes to have frames
+ * states.
  */
-public abstract class BeginStateSplitNode extends AbstractBeginNode implements StateSplit {
+public abstract class BeginStateSplitNode extends BeginNode implements StateSplit {
+
+    @Input(InputType.State) private FrameState stateAfter;
 
     public BeginStateSplitNode() {
     }
@@ -40,6 +43,16 @@
         super(stamp);
     }
 
+    public FrameState stateAfter() {
+        return stateAfter;
+    }
+
+    public void setStateAfter(FrameState x) {
+        assert x == null || x.isAlive() : "frame state must be in a graph";
+        updateUsages(stateAfter, x);
+        stateAfter = x;
+    }
+
     /**
      * A begin node has no side effect.
      */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -176,7 +176,7 @@
         if (stamp instanceof IntegerStamp) {
             assert constant.getKind().isNumericInteger() && stamp.getStackKind() == constant.getKind().getStackKind();
             IntegerStamp istamp = (IntegerStamp) stamp;
-            return forIntegerBits(istamp.getBits(), istamp.isUnsigned(), constant, graph);
+            return forIntegerBits(istamp.getBits(), constant, graph);
         } else {
             assert constant.getKind().isNumericFloat() && stamp.getStackKind() == constant.getKind();
             return forPrimitive(constant, graph);
@@ -267,23 +267,18 @@
         return graph.unique(node);
     }
 
-    private static ConstantNode forIntegerBits(int bits, boolean unsigned, Constant constant, StructuredGraph graph) {
+    private static ConstantNode forIntegerBits(int bits, Constant constant, StructuredGraph graph) {
         long value = constant.asLong();
-        long bounds;
-        if (unsigned) {
-            bounds = ZeroExtendNode.zeroExtend(value, bits);
-        } else {
-            bounds = SignExtendNode.signExtend(value, bits);
-        }
-        return unique(graph, new ConstantNode(constant, StampFactory.forInteger(bits, unsigned, bounds, bounds)));
+        long bounds = SignExtendNode.signExtend(value, bits);
+        return unique(graph, new ConstantNode(constant, StampFactory.forInteger(bits, bounds, bounds)));
     }
 
     /**
      * Returns a node for a constant integer that's not directly representable as Java primitive
      * (e.g. short).
      */
-    public static ConstantNode forIntegerBits(int bits, boolean unsigned, long value, StructuredGraph graph) {
-        return forIntegerBits(bits, unsigned, Constant.forPrimitiveInt(bits, value), graph);
+    public static ConstantNode forIntegerBits(int bits, long value, StructuredGraph graph) {
+        return forIntegerBits(bits, Constant.forPrimitiveInt(bits, value), graph);
     }
 
     /**
@@ -292,7 +287,7 @@
     public static ConstantNode forIntegerStamp(Stamp stamp, long value, StructuredGraph graph) {
         if (stamp instanceof IntegerStamp) {
             IntegerStamp intStamp = (IntegerStamp) stamp;
-            return forIntegerBits(intStamp.getBits(), intStamp.isUnsigned(), value, graph);
+            return forIntegerBits(intStamp.getBits(), value, graph);
         } else {
             return forIntegerKind(stamp.getStackKind(), value, graph);
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -35,7 +35,7 @@
         super(stamp);
     }
 
-    public abstract double probability(AbstractBeginNode successor);
+    public abstract double probability(BeginNode successor);
 
-    public abstract void setProbability(AbstractBeginNode successor, double value);
+    public abstract void setProbability(BeginNode successor, double value);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -31,7 +31,7 @@
  * by the graph builder.
  */
 @NodeInfo(allowedUsageTypes = {InputType.Association})
-public class EntryMarkerNode extends AbstractBeginNode implements IterableNodeType, Simplifiable, LIRLowerable {
+public class EntryMarkerNode extends BeginStateSplitNode implements IterableNodeType, Simplifiable, LIRLowerable {
 
     @Override
     public void simplify(SimplifierTool tool) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -32,7 +32,7 @@
 
     @Input(InputType.Guard) private GuardingNode value;
 
-    public GuardProxyNode(GuardingNode value, AbstractBeginNode proxyPoint) {
+    public GuardProxyNode(GuardingNode value, BeginNode proxyPoint) {
         super(StampFactory.forVoid(), proxyPoint);
         this.value = value;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -44,8 +44,8 @@
  */
 public final class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable, MemoryArithmeticLIRLowerable {
 
-    @Successor private AbstractBeginNode trueSuccessor;
-    @Successor private AbstractBeginNode falseSuccessor;
+    @Successor private BeginNode trueSuccessor;
+    @Successor private BeginNode falseSuccessor;
     @Input(InputType.Condition) private LogicNode condition;
     private double trueSuccessorProbability;
 
@@ -59,10 +59,10 @@
     }
 
     public IfNode(LogicNode condition, FixedNode trueSuccessor, FixedNode falseSuccessor, double trueSuccessorProbability) {
-        this(condition, AbstractBeginNode.begin(trueSuccessor), AbstractBeginNode.begin(falseSuccessor), trueSuccessorProbability);
+        this(condition, BeginNode.begin(trueSuccessor), BeginNode.begin(falseSuccessor), trueSuccessorProbability);
     }
 
-    public IfNode(LogicNode condition, AbstractBeginNode trueSuccessor, AbstractBeginNode falseSuccessor, double trueSuccessorProbability) {
+    public IfNode(LogicNode condition, BeginNode trueSuccessor, BeginNode falseSuccessor, double trueSuccessorProbability) {
         super(StampFactory.forVoid());
         this.condition = condition;
         this.falseSuccessor = falseSuccessor;
@@ -76,7 +76,7 @@
      *
      * @return the true successor
      */
-    public AbstractBeginNode trueSuccessor() {
+    public BeginNode trueSuccessor() {
         return trueSuccessor;
     }
 
@@ -85,16 +85,16 @@
      *
      * @return the false successor
      */
-    public AbstractBeginNode falseSuccessor() {
+    public BeginNode falseSuccessor() {
         return falseSuccessor;
     }
 
-    public void setTrueSuccessor(AbstractBeginNode node) {
+    public void setTrueSuccessor(BeginNode node) {
         updatePredecessor(trueSuccessor, node);
         trueSuccessor = node;
     }
 
-    public void setFalseSuccessor(AbstractBeginNode node) {
+    public void setFalseSuccessor(BeginNode node) {
         updatePredecessor(falseSuccessor, node);
         falseSuccessor = node;
     }
@@ -105,7 +105,7 @@
      * @param istrue {@code true} if the true successor is requested, {@code false} otherwise
      * @return the corresponding successor
      */
-    public AbstractBeginNode successor(boolean istrue) {
+    public BeginNode successor(boolean istrue) {
         return istrue ? trueSuccessor : falseSuccessor;
     }
 
@@ -115,12 +115,12 @@
     }
 
     @Override
-    public double probability(AbstractBeginNode successor) {
+    public double probability(BeginNode successor) {
         return successor == trueSuccessor ? trueSuccessorProbability : 1 - trueSuccessorProbability;
     }
 
     @Override
-    public void setProbability(AbstractBeginNode successor, double value) {
+    public void setProbability(BeginNode successor, double value) {
         assert successor == trueSuccessor || successor == falseSuccessor;
         setTrueSuccessorProbability(successor == trueSuccessor ? value : 1 - value);
     }
@@ -146,8 +146,8 @@
     @Override
     public void simplify(SimplifierTool tool) {
         if (condition() instanceof LogicNegationNode) {
-            AbstractBeginNode trueSucc = trueSuccessor();
-            AbstractBeginNode falseSucc = falseSuccessor();
+            BeginNode trueSucc = trueSuccessor();
+            BeginNode falseSucc = falseSuccessor();
             setTrueSuccessor(null);
             setFalseSuccessor(null);
             LogicNegationNode negation = (LogicNegationNode) condition();
@@ -182,7 +182,7 @@
         }
 
         if (falseSuccessor().usages().isEmpty() && (!(falseSuccessor() instanceof LoopExitNode)) && falseSuccessor().next() instanceof IfNode) {
-            AbstractBeginNode intermediateBegin = falseSuccessor();
+            BeginNode intermediateBegin = falseSuccessor();
             IfNode nextIf = (IfNode) intermediateBegin.next();
             double probabilityB = (1.0 - this.trueSuccessorProbability) * nextIf.trueSuccessorProbability;
             if (this.trueSuccessorProbability < probabilityB) {
@@ -191,7 +191,7 @@
                 if (prepareForSwap(tool.getConstantReflection(), condition(), nextIf.condition(), this.trueSuccessorProbability, probabilityB)) {
                     // Reording is allowed from (if1 => begin => if2) to (if2 => begin => if1).
                     assert intermediateBegin.next() == nextIf;
-                    AbstractBeginNode bothFalseBegin = nextIf.falseSuccessor();
+                    BeginNode bothFalseBegin = nextIf.falseSuccessor();
                     nextIf.setFalseSuccessor(null);
                     intermediateBegin.setNext(null);
                     this.setFalseSuccessor(null);
@@ -547,8 +547,8 @@
         List<AbstractEndNode> trueEnds = new ArrayList<>(mergePredecessors.size());
         Map<AbstractEndNode, ValueNode> phiValues = new HashMap<>(mergePredecessors.size());
 
-        AbstractBeginNode oldFalseSuccessor = falseSuccessor();
-        AbstractBeginNode oldTrueSuccessor = trueSuccessor();
+        BeginNode oldFalseSuccessor = falseSuccessor();
+        BeginNode oldTrueSuccessor = trueSuccessor();
 
         setFalseSuccessor(null);
         setTrueSuccessor(null);
@@ -637,7 +637,7 @@
      * @param oldMerge the merge being removed
      * @param phiValues the values of the phi at the merge, keyed by the merge ends
      */
-    private void connectEnds(List<AbstractEndNode> ends, Map<AbstractEndNode, ValueNode> phiValues, AbstractBeginNode successor, MergeNode oldMerge, SimplifierTool tool) {
+    private void connectEnds(List<AbstractEndNode> ends, Map<AbstractEndNode, ValueNode> phiValues, BeginNode successor, MergeNode oldMerge, SimplifierTool tool) {
         if (!ends.isEmpty()) {
             if (ends.size() == 1) {
                 AbstractEndNode end = ends.get(0);
@@ -703,8 +703,8 @@
     }
 
     private void removeEmptyIf(SimplifierTool tool) {
-        AbstractBeginNode originalTrueSuccessor = trueSuccessor();
-        AbstractBeginNode originalFalseSuccessor = falseSuccessor();
+        BeginNode originalTrueSuccessor = trueSuccessor();
+        BeginNode originalFalseSuccessor = falseSuccessor();
         assert originalTrueSuccessor.next() instanceof AbstractEndNode && originalFalseSuccessor.next() instanceof AbstractEndNode;
 
         AbstractEndNode trueEnd = (AbstractEndNode) originalTrueSuccessor.next();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -36,7 +36,7 @@
 
     private static final double EXCEPTION_PROBA = 1e-5;
 
-    @Successor private AbstractBeginNode next;
+    @Successor private BeginNode next;
     @Successor private DispatchBeginNode exceptionEdge;
     @Input(InputType.Extension) private CallTargetNode callTarget;
     @Input(InputType.State) private FrameState stateDuring;
@@ -66,11 +66,11 @@
         exceptionEdge = x;
     }
 
-    public AbstractBeginNode next() {
+    public BeginNode next() {
         return next;
     }
 
-    public void setNext(AbstractBeginNode x) {
+    public void setNext(BeginNode x) {
         updatePredecessor(next, x);
         next = x;
     }
@@ -163,7 +163,7 @@
     }
 
     public void killExceptionEdge() {
-        AbstractBeginNode edge = exceptionEdge();
+        BeginNode edge = exceptionEdge();
         setExceptionEdge(null);
         GraphUtil.killCFG(edge);
     }
@@ -196,12 +196,12 @@
     }
 
     @Override
-    public double probability(AbstractBeginNode successor) {
+    public double probability(BeginNode successor) {
         return successor == next ? 1 - exceptionProbability : exceptionProbability;
     }
 
     @Override
-    public void setProbability(AbstractBeginNode successor, double value) {
+    public void setProbability(BeginNode successor, double value) {
         assert successor == next || successor == exceptionEdge;
         this.exceptionProbability = successor == next ? 1 - value : value;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -27,7 +27,7 @@
 import com.oracle.graal.nodes.extended.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
-public class KillingBeginNode extends AbstractBeginNode implements MemoryCheckpoint.Single {
+public class KillingBeginNode extends BeginNode implements MemoryCheckpoint.Single {
 
     private LocationIdentity locationIdentity;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -178,7 +178,7 @@
         // nothing yet
     }
 
-    public boolean isLoopExit(AbstractBeginNode begin) {
+    public boolean isLoopExit(BeginNode begin) {
         return begin instanceof LoopExitNode && ((LoopExitNode) begin).loopBegin() == this;
     }
 
@@ -201,4 +201,27 @@
         updateUsagesInterface(this.overflowGuard, overflowGuard);
         this.overflowGuard = overflowGuard;
     }
+
+    /**
+     * Removes dead {@linkplain PhiNode phi nodes} hanging from this node.
+     *
+     * This method uses the heuristic that any node which not a phi node of this LoopBeginNode is
+     * alive. This allows the removal of dead phi loops.
+     */
+    public void removeDeadPhis() {
+        Set<PhiNode> alive = new HashSet<>();
+        for (PhiNode phi : phis()) {
+            NodePredicate isAlive = u -> !isPhiAtMerge(u) || alive.contains(u);
+            if (phi.usages().filter(isAlive).isNotEmpty()) {
+                alive.add(phi);
+                for (PhiNode keptAlive : phi.values().filter(PhiNode.class).filter(isAlive.negate())) {
+                    alive.add(keptAlive);
+                }
+            }
+        }
+        for (PhiNode phi : phis().filter(((NodePredicate) alive::contains).negate()).snapshot()) {
+            phi.replaceAtUsages(null);
+            phi.safeDelete();
+        }
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -34,7 +34,7 @@
     @Input(InputType.Memory) private MemoryNode value;
     private final LocationIdentity identity;
 
-    public MemoryProxyNode(MemoryNode value, AbstractBeginNode exit, LocationIdentity identity) {
+    public MemoryProxyNode(MemoryNode value, BeginNode exit, LocationIdentity identity) {
         super(StampFactory.forVoid(), exit);
         this.value = value;
         this.identity = identity;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -124,24 +124,12 @@
     }
 
     public NodeIterable<PhiNode> phis() {
-        return this.usages().filter(PhiNode.class).filter(new NodePredicate() {
-
-            @Override
-            public boolean apply(Node n) {
-                return ((PhiNode) n).merge() == MergeNode.this;
-            }
-        });
+        return this.usages().filter(PhiNode.class).filter(this::isPhiAtMerge);
     }
 
     @Override
     public NodeIterable<Node> anchored() {
-        return super.anchored().filter(isNotA(PhiNode.class).or(new NodePredicate() {
-
-            @Override
-            public boolean apply(Node n) {
-                return ((PhiNode) n).merge() != MergeNode.this;
-            }
-        }));
+        return super.anchored().filter(n -> !isPhiAtMerge(n));
     }
 
     @Override
@@ -163,10 +151,8 @@
                 return;
             }
             for (PhiNode phi : phis()) {
-                for (Node usage : phi.usages().filter(isNotA(FrameState.class))) {
-                    if (!merge.isPhiAtMerge(usage)) {
-                        return;
-                    }
+                if (phi.usages().filter(isNotA(FrameState.class)).and(node -> !merge.isPhiAtMerge(node)).isNotEmpty()) {
+                    return;
                 }
             }
             Debug.log("Split %s into ends for %s.", this, merge);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -35,9 +35,9 @@
  */
 public abstract class ProxyNode extends FloatingNode implements IterableNodeType, ValueNumberable {
 
-    @Input(InputType.Association) private AbstractBeginNode proxyPoint;
+    @Input(InputType.Association) private BeginNode proxyPoint;
 
-    public ProxyNode(Stamp stamp, AbstractBeginNode proxyPoint) {
+    public ProxyNode(Stamp stamp, BeginNode proxyPoint) {
         super(stamp);
         assert proxyPoint != null;
         this.proxyPoint = proxyPoint;
@@ -45,7 +45,7 @@
 
     public abstract ValueNode value();
 
-    public AbstractBeginNode proxyPoint() {
+    public BeginNode proxyPoint() {
         return proxyPoint;
     }
 
@@ -57,15 +57,15 @@
         return super.verify();
     }
 
-    public static MemoryProxyNode forMemory(MemoryNode value, AbstractBeginNode exit, LocationIdentity location, StructuredGraph graph) {
+    public static MemoryProxyNode forMemory(MemoryNode value, BeginNode exit, LocationIdentity location, StructuredGraph graph) {
         return graph.unique(new MemoryProxyNode(value, exit, location));
     }
 
-    public static ValueProxyNode forValue(ValueNode value, AbstractBeginNode exit, StructuredGraph graph) {
+    public static ValueProxyNode forValue(ValueNode value, BeginNode exit, StructuredGraph graph) {
         return graph.unique(new ValueProxyNode(value, exit));
     }
 
-    public static GuardProxyNode forGuard(GuardingNode value, AbstractBeginNode exit, StructuredGraph graph) {
+    public static GuardProxyNode forGuard(GuardingNode value, BeginNode exit, StructuredGraph graph) {
         return graph.unique(new GuardProxyNode(value, exit));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Wed Apr 16 19:00:14 2014 +0200
@@ -79,16 +79,14 @@
     private boolean isAfterFloatingReadPhase = false;
 
     /**
-     * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start()
-     * start} node.
+     * Creates a new Graph containing a single {@link BeginNode} as the {@link #start() start} node.
      */
     public StructuredGraph() {
         this(null, null);
     }
 
     /**
-     * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start()
-     * start} node.
+     * Creates a new Graph containing a single {@link BeginNode} as the {@link #start() start} node.
      */
     public StructuredGraph(String name, ResolvedJavaMethod method) {
         this(name, method, uniqueGraphIds.incrementAndGet(), INVOCATION_ENTRY_BCI);
@@ -255,8 +253,8 @@
      */
     public void removeFixed(FixedWithNextNode node) {
         assert node != null;
-        if (node instanceof AbstractBeginNode) {
-            ((AbstractBeginNode) node).prepareDelete();
+        if (node instanceof BeginNode) {
+            ((BeginNode) node).prepareDelete();
         }
         assert node.usages().isEmpty() : node + " " + node.usages();
         FixedNode next = node.next();
@@ -295,7 +293,7 @@
         node.safeDelete();
     }
 
-    public void removeSplit(ControlSplitNode node, AbstractBeginNode survivingSuccessor) {
+    public void removeSplit(ControlSplitNode node, BeginNode survivingSuccessor) {
         assert node != null;
         assert node.usages().isEmpty();
         assert survivingSuccessor != null;
@@ -304,7 +302,7 @@
         node.safeDelete();
     }
 
-    public void removeSplitPropagate(ControlSplitNode node, AbstractBeginNode survivingSuccessor) {
+    public void removeSplitPropagate(ControlSplitNode node, BeginNode survivingSuccessor) {
         assert node != null;
         assert node.usages().isEmpty();
         assert survivingSuccessor != null;
@@ -321,7 +319,7 @@
         }
     }
 
-    public void replaceSplit(ControlSplitNode node, Node replacement, AbstractBeginNode survivingSuccessor) {
+    public void replaceSplit(ControlSplitNode node, Node replacement, BeginNode survivingSuccessor) {
         if (replacement instanceof FixedWithNextNode) {
             replaceSplitWithFixed(node, (FixedWithNextNode) replacement, survivingSuccessor);
         } else {
@@ -331,7 +329,7 @@
         }
     }
 
-    public void replaceSplitWithFixed(ControlSplitNode node, FixedWithNextNode replacement, AbstractBeginNode survivingSuccessor) {
+    public void replaceSplitWithFixed(ControlSplitNode node, FixedWithNextNode replacement, BeginNode survivingSuccessor) {
         assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement;
         assert survivingSuccessor != null;
         node.clearSuccessors();
@@ -339,7 +337,7 @@
         node.replaceAndDelete(replacement);
     }
 
-    public void replaceSplitWithFloating(ControlSplitNode node, FloatingNode replacement, AbstractBeginNode survivingSuccessor) {
+    public void replaceSplitWithFloating(ControlSplitNode node, FloatingNode replacement, BeginNode survivingSuccessor) {
         assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement;
         assert survivingSuccessor != null;
         node.clearSuccessors();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -92,13 +92,7 @@
         return this instanceof ConstantNode;
     }
 
-    private static final NodePredicate IS_CONSTANT = new NodePredicate() {
-
-        @Override
-        public boolean apply(Node n) {
-            return n instanceof ValueNode && ((ValueNode) n).isConstant();
-        }
-    };
+    private static final NodePredicate IS_CONSTANT = node -> node instanceof ConstantNode;
 
     public static NodePredicate isConstantPredicate() {
         return IS_CONSTANT;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -30,7 +30,7 @@
 
     @Input private ValueNode value;
 
-    public ValueProxyNode(ValueNode value, AbstractBeginNode proxyPoint) {
+    public ValueProxyNode(ValueNode value, BeginNode proxyPoint) {
         super(value.stamp(), proxyPoint);
         this.value = value;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -88,8 +88,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitAnd(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitAnd(builder.operand(x()), builder.operand(y())));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -65,20 +65,20 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        Value op1 = gen.operand(x());
-        Value op2 = gen.operand(y());
-        if (!y().isConstant() && !livesLonger(this, y(), gen)) {
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        Value op1 = builder.operand(x());
+        Value op2 = builder.operand(y());
+        if (!y().isConstant() && !livesLonger(this, y(), builder)) {
             Value op = op1;
             op1 = op2;
             op2 = op;
         }
-        gen.setResult(this, gen.getLIRGeneratorTool().emitAdd(op1, op2));
+        builder.setResult(this, gen.emitAdd(op1, op2));
     }
 
-    public static boolean livesLonger(ValueNode after, ValueNode value, NodeLIRBuilderTool gen) {
+    public static boolean livesLonger(ValueNode after, ValueNode value, NodeMappableLIRBuilder builder) {
         for (Node usage : value.usages()) {
-            if (usage != after && usage instanceof ValueNode && gen.hasOperand(((ValueNode) usage))) {
+            if (usage != after && usage instanceof ValueNode && builder.hasOperand(((ValueNode) usage))) {
                 return true;
             }
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -201,8 +201,8 @@
         tool.getLowerer().lower(this, tool);
     }
 
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitFloatConvert(op, gen.operand(getInput())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitFloatConvert(op, builder.operand(getInput())));
     }
 
     public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -57,8 +57,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitDiv(gen.operand(x()), gen.operand(y()), null));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitDiv(builder.operand(x()), builder.operand(y()), null));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -60,15 +60,15 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        Value op1 = gen.operand(x());
-        Value op2 = gen.operand(y());
-        if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), gen)) {
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        Value op1 = builder.operand(x());
+        Value op2 = builder.operand(y());
+        if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), builder)) {
             Value op = op1;
             op1 = op2;
             op2 = op;
         }
-        gen.setResult(this, gen.getLIRGeneratorTool().emitMul(op1, op2));
+        builder.setResult(this, gen.emitMul(op1, op2));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -57,8 +57,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitRem(gen.operand(x()), gen.operand(y()), null));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitRem(builder.operand(x()), builder.operand(y()), null));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -76,8 +76,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitSub(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitSub(builder.operand(x()), builder.operand(y())));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -89,16 +89,16 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        Value op1 = gen.operand(x());
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        Value op1 = builder.operand(x());
         assert op1 != null : x() + ", this=" + this;
-        Value op2 = gen.operand(y());
-        if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), gen)) {
+        Value op2 = builder.operand(y());
+        if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), builder)) {
             Value op = op1;
             op1 = op2;
             op2 = op;
         }
-        gen.setResult(this, gen.getLIRGeneratorTool().emitAdd(op1, op2));
+        builder.setResult(this, gen.emitAdd(op1, op2));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -67,7 +67,7 @@
                 return getInput();
             } else if (getInput().isConstant()) {
                 Constant ret = evalConst(getInput().asConstant());
-                return ConstantNode.forIntegerBits(resultBits, false, ret.asLong(), graph());
+                return ConstantNode.forIntegerBits(resultBits, ret.asLong(), graph());
             }
         }
 
@@ -86,19 +86,11 @@
             result = graph.unique(new NarrowNode(input, toStamp.getBits()));
         } else {
             // toStamp.getBits() > fromStamp.getBits()
-            if (fromStamp.isUnsigned()) {
-                result = graph.unique(new ZeroExtendNode(input, toStamp.getBits()));
-            } else {
-                result = graph.unique(new SignExtendNode(input, toStamp.getBits()));
-            }
+            result = graph.unique(new SignExtendNode(input, toStamp.getBits()));
         }
 
         IntegerStamp resultStamp = (IntegerStamp) result.stamp();
         assert toStamp.getBits() == resultStamp.getBits();
-        if (toStamp.isUnsigned() == resultStamp.isUnsigned()) {
-            return result;
-        } else {
-            return graph.unique(new ReinterpretNode(toStamp, result));
-        }
+        return result;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -75,15 +75,15 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        Value op1 = gen.operand(x());
-        Value op2 = gen.operand(y());
-        if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), gen)) {
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        Value op1 = builder.operand(x());
+        Value op2 = builder.operand(y());
+        if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), builder)) {
             Value op = op1;
             op1 = op2;
             op2 = op;
         }
-        gen.setResult(this, gen.getLIRGeneratorTool().emitMul(op1, op2));
+        builder.setResult(this, gen.emitMul(op1, op2));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -117,8 +117,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitSub(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitSub(builder.operand(x()), builder.operand(y())));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -92,7 +92,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitShl(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitShl(builder.operand(x()), builder.operand(y())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -50,13 +50,7 @@
 
     @Override
     public Constant reverse(Constant input) {
-        IntegerStamp stamp = (IntegerStamp) stamp();
-        long result;
-        if (stamp.isUnsigned()) {
-            result = ZeroExtendNode.zeroExtend(input.asLong(), getResultBits());
-        } else {
-            result = SignExtendNode.signExtend(input.asLong(), getResultBits());
-        }
+        long result = SignExtendNode.signExtend(input.asLong(), getResultBits());
         return Constant.forPrimitiveInt(getInputBits(), result);
     }
 
@@ -110,8 +104,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitNarrow(gen.operand(getInput()), getResultBits()));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitNarrow(builder.operand(getInput()), getResultBits()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -88,7 +88,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitNegate(gen.operand(x())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitNegate(builder.operand(x())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -73,7 +73,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitNot(gen.operand(x())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitNot(builder.operand(x())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -73,8 +73,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitOr(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitOr(builder.operand(x()), builder.operand(y())));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -102,9 +102,9 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        PlatformKind kind = gen.getLIRGeneratorTool().getPlatformKind(stamp());
-        gen.setResult(this, gen.getLIRGeneratorTool().emitReinterpret(kind, gen.operand(value())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        PlatformKind kind = gen.getPlatformKind(stamp());
+        builder.setResult(this, gen.emitReinterpret(kind, builder.operand(value())));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -98,7 +98,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitShr(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitShr(builder.operand(x()), builder.operand(y())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -105,8 +105,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitSignExtend(gen.operand(getInput()), getInputBits(), getResultBits()));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitSignExtend(builder.operand(getInput()), getInputBits(), getResultBits()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -92,7 +92,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitUShr(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitUShr(builder.operand(x()), builder.operand(y())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -72,8 +72,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitXor(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitXor(builder.operand(x()), builder.operand(y())));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -98,8 +98,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitZeroExtend(gen.operand(getInput()), getInputBits(), getResultBits()));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitZeroExtend(builder.operand(getInput()), getInputBits(), getResultBits()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractBlock.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractBlock.java	Wed Apr 16 19:00:14 2014 +0200
@@ -24,11 +24,11 @@
 
 import java.util.*;
 
-public interface AbstractBlock<T extends AbstractBlock<?>> {
+public interface AbstractBlock<T extends AbstractBlock<T>> {
 
     int getId();
 
-    Loop getLoop();
+    Loop<T> getLoop();
 
     int getLoopDepth();
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractControlFlowGraph.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractControlFlowGraph.java	Wed Apr 16 19:00:14 2014 +0200
@@ -22,11 +22,13 @@
  */
 package com.oracle.graal.nodes.cfg;
 
+import java.util.*;
+
 public interface AbstractControlFlowGraph<T extends AbstractBlock<T>> {
 
     T[] getBlocks();
 
-    Loop[] getLoops();
+    Collection<Loop<T>> getLoops();
 
     T getStartBlock();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java	Wed Apr 16 19:00:14 2014 +0200
@@ -29,19 +29,19 @@
 
 public final class Block extends AbstractBlockBase<Block> {
 
-    protected final AbstractBeginNode beginNode;
+    protected final BeginNode beginNode;
 
     protected FixedNode endNode;
-    protected Loop loop;
+    protected Loop<Block> loop;
 
     protected List<Block> dominated;
     protected Block postdominator;
 
-    protected Block(AbstractBeginNode node) {
+    protected Block(BeginNode node) {
         this.beginNode = node;
     }
 
-    public AbstractBeginNode getBeginNode() {
+    public BeginNode getBeginNode() {
         return beginNode;
     }
 
@@ -49,7 +49,7 @@
         return endNode;
     }
 
-    public Loop getLoop() {
+    public Loop<Block> getLoop() {
         return loop;
     }
 
@@ -122,7 +122,7 @@
             } else {
                 cur = ((FixedWithNextNode) cur).next();
             }
-            assert !(cur instanceof AbstractBeginNode);
+            assert !(cur instanceof BeginNode);
             return result;
         }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/CFGVerifier.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/CFGVerifier.java	Wed Apr 16 19:00:14 2014 +0200
@@ -84,13 +84,13 @@
         }
 
         if (cfg.getLoops() != null) {
-            for (Loop loop : cfg.getLoops()) {
+            for (Loop<Block> loop : cfg.getLoops()) {
                 assert loop.header.isLoopHeader();
 
                 for (Block block : loop.blocks) {
                     assert block.getId() >= loop.header.getId();
 
-                    Loop blockLoop = block.getLoop();
+                    Loop<?> blockLoop = block.getLoop();
                     while (blockLoop != loop) {
                         assert blockLoop != null;
                         blockLoop = blockLoop.parent;
@@ -109,7 +109,7 @@
                 for (Block block : loop.exits) {
                     assert block.getId() >= loop.header.getId();
 
-                    Loop blockLoop = block.getLoop();
+                    Loop<?> blockLoop = block.getLoop();
                     while (blockLoop != null) {
                         blockLoop = blockLoop.parent;
                         assert blockLoop != loop;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Wed Apr 16 19:00:14 2014 +0200
@@ -34,7 +34,7 @@
 
     private final NodeMap<Block> nodeToBlock;
     private Block[] reversePostOrder;
-    private Loop[] loops;
+    private List<Loop<Block>> loops;
 
     public static ControlFlowGraph compute(StructuredGraph graph, boolean connectBlocks, boolean computeLoops, boolean computeDominators, boolean computePostdominators) {
         ControlFlowGraph cfg = new ControlFlowGraph(graph);
@@ -106,7 +106,7 @@
         return nodeToBlock.get(node);
     }
 
-    public Loop[] getLoops() {
+    public List<Loop<Block>> getLoops() {
         return loops;
     }
 
@@ -125,7 +125,7 @@
         Node last;
 
         // assign proxies of a loop exit to this block
-        if (cur instanceof AbstractBeginNode) {
+        if (cur instanceof BeginNode) {
             for (Node usage : cur.usages()) {
                 if (usage instanceof ProxyNode) {
                     nodeToBlock.set(usage, block);
@@ -146,7 +146,7 @@
 
             last = cur;
             cur = cur.successors().first();
-        } while (cur != null && !(cur instanceof AbstractBeginNode));
+        } while (cur != null && !(cur instanceof BeginNode));
 
         block.endNode = (FixedNode) last;
     }
@@ -154,7 +154,7 @@
     private void identifyBlocks() {
         // Find all block headers
         int numBlocks = 0;
-        for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.class)) {
+        for (BeginNode begin : graph.getNodes(BeginNode.class)) {
             Block block = new Block(begin);
             numBlocks++;
             identifyBlock(block);
@@ -233,12 +233,12 @@
     }
 
     private void computeLoopInformation() {
-        ArrayList<Loop> loopsList = new ArrayList<>();
+        loops = new ArrayList<>();
         for (Block block : reversePostOrder) {
             Node beginNode = block.getBeginNode();
             if (beginNode instanceof LoopBeginNode) {
-                Loop loop = new Loop(block.getLoop(), loopsList.size(), block);
-                loopsList.add(loop);
+                Loop<Block> loop = new HIRLoop(block.getLoop(), loops.size(), block);
+                loops.add(loop);
 
                 LoopBeginNode loopBegin = (LoopBeginNode) beginNode;
                 for (LoopEndNode end : loopBegin.loopEnds()) {
@@ -256,7 +256,7 @@
                 for (Block b : loop.blocks) {
                     for (Block sux : b.getSuccessors()) {
                         if (sux.loop != loop) {
-                            AbstractBeginNode begin = sux.getBeginNode();
+                            BeginNode begin = sux.getBeginNode();
                             if (!(begin instanceof LoopExitNode && ((LoopExitNode) begin).loopBegin() == loopBegin)) {
                                 Debug.log("Unexpected loop exit with %s, including whole branch in the loop", sux);
                                 unexpected.add(sux);
@@ -269,10 +269,9 @@
                 }
             }
         }
-        loops = loopsList.toArray(new Loop[loopsList.size()]);
     }
 
-    private static void addBranchToLoop(Loop l, Block b) {
+    private static void addBranchToLoop(Loop<Block> l, Block b) {
         if (l.blocks.contains(b)) {
             return;
         }
@@ -283,7 +282,7 @@
         }
     }
 
-    private static void computeLoopBlocks(Block block, Loop loop) {
+    private static void computeLoopBlocks(Block block, Loop<Block> loop) {
         if (block.getLoop() == loop) {
             return;
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/HIRLoop.java	Wed Apr 16 19:00:14 2014 +0200
@@ -0,0 +1,37 @@
+/*
+ * 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;
+
+import com.oracle.graal.nodes.*;
+
+public class HIRLoop extends Loop<Block> {
+
+    protected HIRLoop(Loop<Block> parent, int index, Block header) {
+        super(parent, index, header);
+    }
+
+    @Override
+    public long numBackedges() {
+        return ((LoopBeginNode) header.getBeginNode()).loopEnds().count();
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Loop.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Loop.java	Wed Apr 16 19:00:14 2014 +0200
@@ -24,20 +24,18 @@
 
 import java.util.*;
 
-import com.oracle.graal.nodes.*;
+public abstract class Loop<T extends AbstractBlock<T>> {
 
-public class Loop {
-
-    public final Loop parent;
-    public final List<Loop> children;
+    public final Loop<T> parent;
+    public final List<Loop<T>> children;
 
     public final int depth;
     public final int index;
-    public final Block header;
-    public final List<Block> blocks;
-    public final List<Block> exits;
+    public final T header;
+    public final List<T> blocks;
+    public final List<T> exits;
 
-    protected Loop(Loop parent, int index, Block header) {
+    protected Loop(Loop<T> parent, int index, T header) {
         this.parent = parent;
         if (parent != null) {
             this.depth = parent.depth + 1;
@@ -52,12 +50,10 @@
         this.exits = new ArrayList<>();
     }
 
+    public abstract long numBackedges();
+
     @Override
     public String toString() {
         return "loop " + index + " depth " + depth + (parent != null ? " outer " + parent.index : "");
     }
-
-    public LoopBeginNode loopBegin() {
-        return (LoopBeginNode) header.getBeginNode();
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -107,9 +107,9 @@
     }
 
     @Override
-    public Value generateAddress(NodeLIRBuilderTool gen, Value base) {
-        Value xAddr = getX().generateAddress(gen, base);
-        return getY().generateAddress(gen, xAddr);
+    public Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base) {
+        Value xAddr = getX().generateAddress(builder, gen, base);
+        return getY().generateAddress(builder, gen, xAddr);
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -50,7 +50,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        Value addr = getLocation().generateAddress(gen, gen.operand(getObject()));
+        Value addr = getLocation().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(getObject()));
         gen.setResult(this, addr);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -65,7 +65,7 @@
     }
 
     @Override
-    public Value generateAddress(NodeLIRBuilderTool gen, Value base) {
-        return gen.getLIRGeneratorTool().emitAddress(base, getDisplacement(), Value.ILLEGAL, 0);
+    public Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base) {
+        return gen.emitAddress(base, getDisplacement(), Value.ILLEGAL, 0);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -61,7 +61,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        Value address = location().generateAddress(gen, gen.operand(object()));
+        Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object()));
         PlatformKind readKind = gen.getLIRGeneratorTool().getPlatformKind(stamp());
         gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, address, this));
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -96,7 +96,7 @@
     }
 
     @Override
-    public Value generateAddress(NodeLIRBuilderTool gen, Value base) {
-        return gen.getLIRGeneratorTool().emitAddress(base, displacement, gen.operand(getIndex()), getIndexScaling());
+    public Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base) {
+        return gen.emitAddress(base, displacement, builder.operand(getIndex()), getIndexScaling());
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -49,7 +49,7 @@
      * @param keyProbabilities the probabilities of the keys
      * @param keySuccessors the successor index for each key
      */
-    public IntegerSwitchNode(ValueNode value, AbstractBeginNode[] successors, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
+    public IntegerSwitchNode(ValueNode value, BeginNode[] successors, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
         super(value, successors, keySuccessors, keyProbabilities);
         assert keySuccessors.length == keys.length + 1;
         assert keySuccessors.length == keyProbabilities.length;
@@ -76,7 +76,7 @@
      * @param keySuccessors the successor index for each key
      */
     public IntegerSwitchNode(ValueNode value, int successorCount, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
-        this(value, new AbstractBeginNode[successorCount], keys, keyProbabilities, keySuccessors);
+        this(value, new BeginNode[successorCount], keys, keyProbabilities, keySuccessors);
     }
 
     @Override
@@ -139,7 +139,7 @@
                     tool.addToWorkList(defaultSuccessor());
                     graph().removeSplitPropagate(this, defaultSuccessor());
                 } else if (validKeys != keys.length) {
-                    ArrayList<AbstractBeginNode> newSuccessors = new ArrayList<>(blockSuccessorCount());
+                    ArrayList<BeginNode> newSuccessors = new ArrayList<>(blockSuccessorCount());
                     int[] newKeys = new int[validKeys];
                     int[] newKeySuccessors = new int[validKeys + 1];
                     double[] newKeyProbabilities = new double[validKeys + 1];
@@ -172,14 +172,14 @@
                     }
 
                     for (int i = 0; i < blockSuccessorCount(); i++) {
-                        AbstractBeginNode successor = blockSuccessor(i);
+                        BeginNode successor = blockSuccessor(i);
                         if (!newSuccessors.contains(successor)) {
                             tool.deleteBranch(successor);
                         }
                         setBlockSuccessor(i, null);
                     }
 
-                    AbstractBeginNode[] successorsArray = newSuccessors.toArray(new AbstractBeginNode[newSuccessors.size()]);
+                    BeginNode[] successorsArray = newSuccessors.toArray(new BeginNode[newSuccessors.size()]);
                     IntegerSwitchNode newSwitch = graph().add(new IntegerSwitchNode(value(), successorsArray, newKeys, newKeyProbabilities, newKeySuccessors));
                     ((FixedWithNextNode) predecessor()).setNext(newSwitch);
                     GraphUtil.killWithUnusedFloatingInputs(this);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -62,5 +62,5 @@
         // nothing to do...
     }
 
-    public abstract Value generateAddress(NodeLIRBuilderTool gen, Value base);
+    public abstract Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -54,7 +54,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        Value address = location().generateAddress(gen, gen.operand(object()));
+        Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object()));
         PlatformKind readKind = gen.getLIRGeneratorTool().getPlatformKind(stamp());
         gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, address, this));
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -34,7 +34,7 @@
  */
 public abstract class SwitchNode extends ControlSplitNode {
 
-    @Successor private final NodeSuccessorList<AbstractBeginNode> successors;
+    @Successor private final NodeSuccessorList<BeginNode> successors;
     @Input private ValueNode value;
     private double[] keyProbabilities;
     private int[] keySuccessors;
@@ -45,7 +45,7 @@
      * @param value the instruction that provides the value to be switched over
      * @param successors the list of successors of this switch
      */
-    public SwitchNode(ValueNode value, AbstractBeginNode[] successors, int[] keySuccessors, double[] keyProbabilities) {
+    public SwitchNode(ValueNode value, BeginNode[] successors, int[] keySuccessors, double[] keyProbabilities) {
         super(StampFactory.forVoid());
         assert value.getKind() == Kind.Int || value.getKind() == Kind.Long || value.getKind() == Kind.Object : value.getKind() + " key not supported by SwitchNode";
         assert keySuccessors.length == keyProbabilities.length;
@@ -76,7 +76,7 @@
     }
 
     @Override
-    public double probability(AbstractBeginNode successor) {
+    public double probability(BeginNode successor) {
         double sum = 0;
         for (int i = 0; i < keySuccessors.length; i++) {
             if (successors.get(keySuccessors[i]) == successor) {
@@ -87,7 +87,7 @@
     }
 
     @Override
-    public void setProbability(AbstractBeginNode successor, double value) {
+    public void setProbability(BeginNode successor, double value) {
         double changeInProbability = 0;
         int nonZeroProbabilityCases = 0;
         for (int i = 0; i < keySuccessors.length; i++) {
@@ -139,7 +139,7 @@
     /**
      * Returns the successor for the key at the given index.
      */
-    public AbstractBeginNode keySuccessor(int i) {
+    public BeginNode keySuccessor(int i) {
         return successors.get(keySuccessors[i]);
     }
 
@@ -157,11 +157,11 @@
         return keySuccessors[keySuccessors.length - 1];
     }
 
-    public AbstractBeginNode blockSuccessor(int i) {
+    public BeginNode blockSuccessor(int i) {
         return successors.get(i);
     }
 
-    public void setBlockSuccessor(int i, AbstractBeginNode s) {
+    public void setBlockSuccessor(int i, BeginNode s) {
         successors.set(i, s);
     }
 
@@ -174,7 +174,7 @@
      * 
      * @return the default successor
      */
-    public AbstractBeginNode defaultSuccessor() {
+    public BeginNode defaultSuccessor() {
         if (defaultSuccessorIndex() == -1) {
             throw new GraalInternalError("unexpected");
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -91,7 +91,7 @@
 
     @Override
     public void virtualize(VirtualizerTool tool) {
-        if (anchored != null && !(anchored instanceof AbstractBeginNode)) {
+        if (anchored != null && !(anchored instanceof BeginNode)) {
             State state = tool.getObjectState(anchored);
             if (state == null || state.getState() != EscapeState.Virtual) {
                 return;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -44,7 +44,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        Value address = location().generateAddress(gen, gen.operand(object()));
+        Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), 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;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -22,11 +22,12 @@
  */
 package com.oracle.graal.nodes.java;
 
+import static com.oracle.graal.graph.iterators.NodePredicates.*;
+
 import java.lang.reflect.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -97,7 +98,7 @@
     }
 
     private PhiNode asPhi(MetaAccessProvider metaAccess) {
-        if (!isStatic() && Modifier.isFinal(field.getModifiers()) && object() instanceof ValuePhiNode && ((ValuePhiNode) object()).values().filter(NodePredicates.isNotA(ConstantNode.class)).isEmpty()) {
+        if (!isStatic() && Modifier.isFinal(field.getModifiers()) && object() instanceof ValuePhiNode && ((ValuePhiNode) object()).values().filter(isNotA(ConstantNode.class)).isEmpty()) {
             PhiNode phi = (PhiNode) object();
             Constant[] constants = new Constant[phi.valueCount()];
             for (int i = 0; i < phi.valueCount(); i++) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -80,7 +80,7 @@
     @Override
     public void generate(NodeLIRBuilderTool gen) {
         assert getNewValue().stamp().isCompatible(getExpectedValue().stamp());
-        Value address = location().generateAddress(gen, gen.operand(object()));
+        Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object()));
         Value result = gen.getLIRGeneratorTool().emitCompareAndSwap(address, gen.operand(getExpectedValue()), gen.operand(getNewValue()), Constant.INT_1, Constant.INT_0);
         gen.setResult(this, result);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -51,7 +51,7 @@
      * @param keyProbabilities the probabilities of the keys
      * @param keySuccessors the successor index for each key
      */
-    public TypeSwitchNode(ValueNode value, AbstractBeginNode[] successors, ResolvedJavaType[] keys, double[] keyProbabilities, int[] keySuccessors) {
+    public TypeSwitchNode(ValueNode value, BeginNode[] successors, ResolvedJavaType[] keys, double[] keyProbabilities, int[] keySuccessors) {
         super(value, successors, keySuccessors, keyProbabilities);
         assert successors.length <= keys.length + 1;
         assert keySuccessors.length == keyProbabilities.length;
@@ -134,7 +134,7 @@
                     tool.addToWorkList(defaultSuccessor());
                     graph().removeSplitPropagate(this, defaultSuccessor());
                 } else if (validKeys != keys.length) {
-                    ArrayList<AbstractBeginNode> newSuccessors = new ArrayList<>(blockSuccessorCount());
+                    ArrayList<BeginNode> newSuccessors = new ArrayList<>(blockSuccessorCount());
                     ResolvedJavaType[] newKeys = new ResolvedJavaType[validKeys];
                     int[] newKeySuccessors = new int[validKeys + 1];
                     double[] newKeyProbabilities = new double[validKeys + 1];
@@ -167,14 +167,14 @@
                     }
 
                     for (int i = 0; i < blockSuccessorCount(); i++) {
-                        AbstractBeginNode successor = blockSuccessor(i);
+                        BeginNode successor = blockSuccessor(i);
                         if (!newSuccessors.contains(successor)) {
                             tool.deleteBranch(successor);
                         }
                         setBlockSuccessor(i, null);
                     }
 
-                    AbstractBeginNode[] successorsArray = newSuccessors.toArray(new AbstractBeginNode[newSuccessors.size()]);
+                    BeginNode[] successorsArray = newSuccessors.toArray(new BeginNode[newSuccessors.size()]);
                     TypeSwitchNode newSwitch = graph().add(new TypeSwitchNode(value(), successorsArray, newKeys, newKeyProbabilities, newKeySuccessors));
                     ((FixedWithNextNode) predecessor()).setNext(newSwitch);
                     GraphUtil.killWithUnusedFloatingInputs(this);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRLowerable.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRLowerable.java	Wed Apr 16 19:00:14 2014 +0200
@@ -26,5 +26,5 @@
 
 public interface ArithmeticLIRLowerable extends ArithmeticOperation {
 
-    void generate(NodeLIRBuilderTool gen);
+    void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRTypeTool.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRTypeTool.java	Wed Apr 16 19:00:14 2014 +0200
@@ -29,7 +29,7 @@
  */
 public interface LIRTypeTool {
 
-    PlatformKind getIntegerKind(int bits, boolean unsigned);
+    PlatformKind getIntegerKind(int bits);
 
     PlatformKind getFloatingKind(int bits);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java	Wed Apr 16 19:00:14 2014 +0200
@@ -59,7 +59,7 @@
 
     LIRGeneratorTool getLIRGeneratorTool();
 
-    void emitOverflowCheckBranch(AbstractBeginNode overflowSuccessor, AbstractBeginNode next, double probability);
+    void emitOverflowCheckBranch(BeginNode overflowSuccessor, BeginNode next, double probability);
 
     Value[] visitInvokeArguments(CallingConvention cc, Collection<ValueNode> arguments);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Wed Apr 16 19:00:14 2014 +0200
@@ -37,43 +37,36 @@
  */
 public class IntegerStamp extends PrimitiveStamp {
 
-    private final boolean unsigned;
-
     private final long lowerBound;
     private final long upperBound;
     private final long downMask;
     private final long upMask;
 
-    public IntegerStamp(int bits, boolean unsigned, long lowerBound, long upperBound, long downMask, long upMask) {
+    public IntegerStamp(int bits, long lowerBound, long upperBound, long downMask, long upMask) {
         super(bits);
-        this.unsigned = unsigned;
         this.lowerBound = lowerBound;
         this.upperBound = upperBound;
         this.downMask = downMask;
         this.upMask = upMask;
-        assert lowerBound >= defaultMinValue(bits, unsigned) : this;
-        assert upperBound <= defaultMaxValue(bits, unsigned) : this;
+        assert lowerBound >= defaultMinValue(bits) : this;
+        assert upperBound <= defaultMaxValue(bits) : this;
         assert (downMask & defaultMask(bits)) == downMask : this;
         assert (upMask & defaultMask(bits)) == upMask : this;
     }
 
     @Override
     public Stamp unrestricted() {
-        return new IntegerStamp(getBits(), unsigned, defaultMinValue(getBits(), unsigned), defaultMaxValue(getBits(), unsigned), 0, defaultMask(getBits()));
+        return new IntegerStamp(getBits(), defaultMinValue(getBits()), defaultMaxValue(getBits()), 0, defaultMask(getBits()));
     }
 
     @Override
     public Stamp illegal() {
-        return new IntegerStamp(getBits(), unsigned, defaultMaxValue(getBits(), unsigned), defaultMinValue(getBits(), unsigned), defaultMask(getBits()), 0);
+        return new IntegerStamp(getBits(), defaultMaxValue(getBits()), defaultMinValue(getBits()), defaultMask(getBits()), 0);
     }
 
     @Override
     public boolean isLegal() {
-        if (unsigned) {
-            return Long.compareUnsigned(lowerBound, upperBound) <= 0;
-        } else {
-            return lowerBound <= upperBound;
-        }
+        return lowerBound <= upperBound;
     }
 
     @Override
@@ -87,29 +80,21 @@
 
     @Override
     public PlatformKind getPlatformKind(LIRTypeTool tool) {
-        return tool.getIntegerKind(getBits(), unsigned);
+        return tool.getIntegerKind(getBits());
     }
 
     @Override
     public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
         switch (getBits()) {
             case 1:
-                assert unsigned;
                 return metaAccess.lookupJavaType(Boolean.TYPE);
             case 8:
-                assert !unsigned;
                 return metaAccess.lookupJavaType(Byte.TYPE);
             case 16:
-                if (unsigned) {
-                    return metaAccess.lookupJavaType(Character.TYPE);
-                } else {
-                    return metaAccess.lookupJavaType(Short.TYPE);
-                }
+                return metaAccess.lookupJavaType(Short.TYPE);
             case 32:
-                assert !unsigned;
                 return metaAccess.lookupJavaType(Integer.TYPE);
             case 64:
-                assert !unsigned;
                 return metaAccess.lookupJavaType(Long.TYPE);
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -117,21 +102,14 @@
     }
 
     /**
-     * Check whether the value described by this stamp is unsigned.
-     */
-    public boolean isUnsigned() {
-        return unsigned;
-    }
-
-    /**
-     * The (inclusive) lower bound on the value described by this stamp.
+     * The signed inclusive lower bound on the value described by this stamp.
      */
     public long lowerBound() {
         return lowerBound;
     }
 
     /**
-     * The (inclusive) upper bound on the value described by this stamp.
+     * The signed inclusive upper bound on the value described by this stamp.
      */
     public long upperBound() {
         return upperBound;
@@ -152,7 +130,7 @@
     }
 
     public boolean isUnrestricted() {
-        return lowerBound == defaultMinValue(getBits(), unsigned) && upperBound == defaultMaxValue(getBits(), unsigned) && downMask == 0 && upMask == defaultMask(getBits());
+        return lowerBound == defaultMinValue(getBits()) && upperBound == defaultMaxValue(getBits()) && downMask == 0 && upMask == defaultMask(getBits());
     }
 
     public boolean contains(long value) {
@@ -186,11 +164,11 @@
     @Override
     public String toString() {
         StringBuilder str = new StringBuilder();
-        str.append(unsigned ? 'u' : 'i');
+        str.append('i');
         str.append(getBits());
         if (lowerBound == upperBound) {
             str.append(" [").append(lowerBound).append(']');
-        } else if (lowerBound != defaultMinValue(getBits(), unsigned) || upperBound != defaultMaxValue(getBits(), unsigned)) {
+        } else if (lowerBound != defaultMinValue(getBits()) || upperBound != defaultMaxValue(getBits())) {
             str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']');
         }
         if (downMask != 0) {
@@ -205,7 +183,7 @@
     }
 
     private Stamp createStamp(IntegerStamp other, long newUpperBound, long newLowerBound, long newDownMask, long newUpMask) {
-        assert getBits() == other.getBits() && unsigned == other.unsigned;
+        assert getBits() == other.getBits();
         if (newLowerBound > newUpperBound || (newDownMask & (~newUpMask)) != 0) {
             return illegal();
         } else if (newLowerBound == lowerBound && newUpperBound == upperBound && newDownMask == downMask && newUpMask == upMask) {
@@ -213,7 +191,7 @@
         } else if (newLowerBound == other.lowerBound && newUpperBound == other.upperBound && newDownMask == other.downMask && newUpMask == other.upMask) {
             return other;
         } else {
-            return new IntegerStamp(getBits(), unsigned, newLowerBound, newUpperBound, newDownMask, newUpMask);
+            return new IntegerStamp(getBits(), newLowerBound, newUpperBound, newDownMask, newUpMask);
         }
     }
 
@@ -250,7 +228,7 @@
         }
         if (stamp instanceof IntegerStamp) {
             IntegerStamp other = (IntegerStamp) stamp;
-            return getBits() == other.getBits() && unsigned == other.unsigned;
+            return getBits() == other.getBits();
         }
         return false;
     }
@@ -283,7 +261,7 @@
     }
 
     public static long defaultMask(int bits) {
-        assert 0 < bits && bits <= 64;
+        assert 0 <= bits && bits <= 64;
         if (bits == 64) {
             return 0xffffffffffffffffL;
         } else {
@@ -291,16 +269,12 @@
         }
     }
 
-    public static long defaultMinValue(int bits, boolean unsigned) {
-        if (unsigned) {
-            return 0;
-        } else {
-            return -1L << (bits - 1);
-        }
+    public static long defaultMinValue(int bits) {
+        return -1L << (bits - 1);
     }
 
-    public static long defaultMaxValue(int bits, boolean unsigned) {
-        return defaultMask(unsigned ? bits : bits - 1);
+    public static long defaultMaxValue(int bits) {
+        return defaultMask(bits - 1);
     }
 
     public static long upMaskFor(int bits, long lowerBound, long upperBound) {
@@ -332,11 +306,7 @@
                 case 8:
                     return Constant.forByte((byte) lowerBound);
                 case 16:
-                    if (unsigned) {
-                        return Constant.forChar((char) lowerBound);
-                    } else {
-                        return Constant.forShort((short) lowerBound);
-                    }
+                    return Constant.forShort((short) lowerBound);
                 case 32:
                     return Constant.forInt((int) lowerBound);
                 case 64:
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Wed Apr 16 19:00:14 2014 +0200
@@ -49,7 +49,7 @@
         } else {
             mask = IntegerStamp.defaultMask(bits);
         }
-        setCache(kind, new IntegerStamp(bits, false, kind.getMinValue(), kind.getMaxValue(), 0, mask));
+        setCache(kind, new IntegerStamp(bits, kind.getMinValue(), kind.getMaxValue(), 0, mask));
     }
 
     private static void setFloatCache(Kind kind) {
@@ -120,21 +120,21 @@
     }
 
     public static IntegerStamp forInteger(Kind kind, long lowerBound, long upperBound, long downMask, long upMask) {
-        return new IntegerStamp(kind.getBitCount(), kind.isUnsigned(), lowerBound, upperBound, downMask, upMask);
+        return new IntegerStamp(kind.getBitCount(), lowerBound, upperBound, downMask, upMask);
     }
 
     public static IntegerStamp forInteger(Kind kind, long lowerBound, long upperBound) {
-        return forInteger(kind.getBitCount(), kind.isUnsigned(), lowerBound, upperBound);
+        return forInteger(kind.getBitCount(), lowerBound, upperBound);
     }
 
-    public static IntegerStamp forInteger(int bits, boolean unsigned) {
-        return new IntegerStamp(bits, unsigned, IntegerStamp.defaultMinValue(bits, unsigned), IntegerStamp.defaultMaxValue(bits, unsigned), 0, IntegerStamp.defaultMask(bits));
+    public static IntegerStamp forInteger(int bits) {
+        return new IntegerStamp(bits, IntegerStamp.defaultMinValue(bits), IntegerStamp.defaultMaxValue(bits), 0, IntegerStamp.defaultMask(bits));
     }
 
-    public static IntegerStamp forInteger(int bits, boolean unsigned, long lowerBound, long upperBound) {
+    public static IntegerStamp forInteger(int bits, long lowerBound, long upperBound) {
         long defaultMask = IntegerStamp.defaultMask(bits);
         if (lowerBound == upperBound) {
-            return new IntegerStamp(bits, unsigned, lowerBound, lowerBound, lowerBound & defaultMask, lowerBound & defaultMask);
+            return new IntegerStamp(bits, lowerBound, lowerBound, lowerBound & defaultMask, lowerBound & defaultMask);
         }
         final long downMask;
         final long upMask;
@@ -158,7 +158,7 @@
                 downMask = lowerBound & ~(-1L >>> (lowerBoundLeadingOnes + sameBitCount)) | ~(-1L >>> lowerBoundLeadingOnes);
             }
         }
-        return new IntegerStamp(bits, unsigned, lowerBound, upperBound, downMask & defaultMask, upMask & defaultMask);
+        return new IntegerStamp(bits, lowerBound, upperBound, downMask & defaultMask, upMask & defaultMask);
     }
 
     public static FloatStamp forFloat(Kind kind, double lowerBound, double upperBound, boolean nonNaN) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java	Wed Apr 16 19:00:14 2014 +0200
@@ -36,9 +36,9 @@
         if (stamp instanceof IntegerStamp) {
             IntegerStamp integerStamp = (IntegerStamp) stamp;
             int bits = integerStamp.getBits();
-            if (integerStamp.lowerBound() != IntegerStamp.defaultMinValue(bits, false)) {
+            if (integerStamp.lowerBound() != IntegerStamp.defaultMinValue(bits)) {
                 // TODO(ls) check if the mask calculation is correct...
-                return StampFactory.forInteger(bits, false, -integerStamp.upperBound(), -integerStamp.lowerBound());
+                return StampFactory.forInteger(bits, -integerStamp.upperBound(), -integerStamp.lowerBound());
             }
         } else if (stamp instanceof FloatStamp) {
             FloatStamp floatStamp = (FloatStamp) stamp;
@@ -53,8 +53,7 @@
             IntegerStamp integerStamp = (IntegerStamp) stamp;
             int bits = integerStamp.getBits();
             long defaultMask = IntegerStamp.defaultMask(bits);
-            return new IntegerStamp(bits, integerStamp.isUnsigned(), ~integerStamp.upperBound(), ~integerStamp.lowerBound(), (~integerStamp.upMask()) & defaultMask, (~integerStamp.downMask()) &
-                            defaultMask);
+            return new IntegerStamp(bits, ~integerStamp.upperBound(), ~integerStamp.lowerBound(), (~integerStamp.upMask()) & defaultMask, (~integerStamp.downMask()) & defaultMask);
         }
         return stamp.unrestricted();
     }
@@ -95,45 +94,36 @@
     }
 
     public static Stamp div(IntegerStamp stamp1, IntegerStamp stamp2) {
-        assert stamp1.getBits() == stamp2.getBits() && stamp1.isUnsigned() == stamp2.isUnsigned();
+        assert stamp1.getBits() == stamp2.getBits();
         if (stamp2.isStrictlyPositive()) {
             long lowerBound = stamp1.lowerBound() / stamp2.lowerBound();
             long upperBound = stamp1.upperBound() / stamp2.lowerBound();
-            return StampFactory.forInteger(stamp1.getBits(), stamp1.isUnsigned(), lowerBound, upperBound);
+            return StampFactory.forInteger(stamp1.getBits(), lowerBound, upperBound);
         }
         return stamp1.unrestricted();
     }
 
-    private static boolean addOverflowsPositively(long x, long y, int bits, boolean unsigned) {
+    private static boolean addOverflowsPositively(long x, long y, int bits) {
         long result = x + y;
         if (bits == 64) {
-            if (unsigned) {
-                return ((x | y) & ~result) < 0;
-            } else {
-                return (~x & ~y & result) < 0;
-            }
+            return (~x & ~y & result) < 0;
         } else {
-            return result > IntegerStamp.defaultMaxValue(bits, unsigned);
+            return result > IntegerStamp.defaultMaxValue(bits);
         }
     }
 
-    private static boolean addOverflowsNegatively(long x, long y, int bits, boolean unsigned) {
-        if (unsigned) {
-            return false;
-        }
-
+    private static boolean addOverflowsNegatively(long x, long y, int bits) {
         long result = x + y;
         if (bits == 64) {
             return (x & y & ~result) < 0;
         } else {
-            return result < IntegerStamp.defaultMinValue(bits, unsigned);
+            return result < IntegerStamp.defaultMinValue(bits);
         }
     }
 
     public static IntegerStamp add(IntegerStamp stamp1, IntegerStamp stamp2) {
         int bits = stamp1.getBits();
-        boolean unsigned = stamp1.isUnsigned();
-        assert bits == stamp2.getBits() && unsigned == stamp2.isUnsigned();
+        assert bits == stamp2.getBits();
 
         if (stamp1.isUnrestricted()) {
             return stamp1;
@@ -151,30 +141,23 @@
 
         long lowerBound;
         long upperBound;
-        boolean lowerOverflowsPositively = addOverflowsPositively(stamp1.lowerBound(), stamp2.lowerBound(), bits, unsigned);
-        boolean upperOverflowsPositively = addOverflowsPositively(stamp1.upperBound(), stamp2.upperBound(), bits, unsigned);
-        boolean lowerOverflowsNegatively = addOverflowsNegatively(stamp1.lowerBound(), stamp2.lowerBound(), bits, unsigned);
-        boolean upperOverflowsNegatively = addOverflowsNegatively(stamp1.upperBound(), stamp2.upperBound(), bits, unsigned);
+        boolean lowerOverflowsPositively = addOverflowsPositively(stamp1.lowerBound(), stamp2.lowerBound(), bits);
+        boolean upperOverflowsPositively = addOverflowsPositively(stamp1.upperBound(), stamp2.upperBound(), bits);
+        boolean lowerOverflowsNegatively = addOverflowsNegatively(stamp1.lowerBound(), stamp2.lowerBound(), bits);
+        boolean upperOverflowsNegatively = addOverflowsNegatively(stamp1.upperBound(), stamp2.upperBound(), bits);
         if ((lowerOverflowsNegatively && !upperOverflowsNegatively) || (!lowerOverflowsPositively && upperOverflowsPositively)) {
-            lowerBound = IntegerStamp.defaultMinValue(bits, unsigned);
-            upperBound = IntegerStamp.defaultMaxValue(bits, unsigned);
+            lowerBound = IntegerStamp.defaultMinValue(bits);
+            upperBound = IntegerStamp.defaultMaxValue(bits);
         } else {
-            lowerBound = (stamp1.lowerBound() + stamp2.lowerBound()) & defaultMask;
-            upperBound = (stamp1.upperBound() + stamp2.upperBound()) & defaultMask;
-            if (!unsigned) {
-                lowerBound = SignExtendNode.signExtend(lowerBound, bits);
-                upperBound = SignExtendNode.signExtend(upperBound, bits);
-            }
+            lowerBound = SignExtendNode.signExtend((stamp1.lowerBound() + stamp2.lowerBound()) & defaultMask, bits);
+            upperBound = SignExtendNode.signExtend((stamp1.upperBound() + stamp2.upperBound()) & defaultMask, bits);
         }
-        IntegerStamp limit = StampFactory.forInteger(bits, unsigned, lowerBound, upperBound);
+        IntegerStamp limit = StampFactory.forInteger(bits, lowerBound, upperBound);
         newUpMask &= limit.upMask();
-        upperBound &= newUpMask;
-        if (!unsigned) {
-            upperBound = SignExtendNode.signExtend(upperBound, bits);
-        }
+        upperBound = SignExtendNode.signExtend(upperBound & newUpMask, bits);
         newDownMask |= limit.downMask();
         lowerBound |= newDownMask;
-        return new IntegerStamp(bits, unsigned, lowerBound, upperBound, newDownMask, newUpMask);
+        return new IntegerStamp(bits, lowerBound, upperBound, newDownMask, newUpMask);
     }
 
     public static Stamp sub(IntegerStamp stamp1, IntegerStamp stamp2) {
@@ -195,11 +178,11 @@
             upperBound = upMask;
         } else {
             lowerBound = downMask | (-1L << (bits - 1));
-            upperBound = IntegerStamp.defaultMaxValue(bits, false) & upMask;
+            upperBound = IntegerStamp.defaultMaxValue(bits) & upMask;
         }
         lowerBound = IntegerConvertNode.convert(lowerBound, bits, false);
         upperBound = IntegerConvertNode.convert(upperBound, bits, false);
-        return new IntegerStamp(bits, false, lowerBound, upperBound, downMask, upMask);
+        return new IntegerStamp(bits, lowerBound, upperBound, downMask, upMask);
     }
 
     public static Stamp and(Stamp stamp1, Stamp stamp2) {
@@ -265,7 +248,7 @@
                     lowerBound = value.lowerBound() >>> shiftCount;
                     upperBound = value.upperBound() >>> shiftCount;
                 }
-                return new IntegerStamp(bits, value.isUnsigned(), lowerBound, upperBound, downMask, upMask);
+                return new IntegerStamp(bits, lowerBound, upperBound, downMask, upMask);
             }
         }
         long mask = IntegerStamp.upMaskFor(bits, value.lowerBound(), value.upperBound());
@@ -312,17 +295,7 @@
             long downMask = SignExtendNode.signExtend(inputStamp.downMask(), inputBits) & defaultMask;
             long upMask = SignExtendNode.signExtend(inputStamp.upMask(), inputBits) & defaultMask;
 
-            long lowerBound;
-            long upperBound;
-            if (inputStamp.isUnsigned()) {
-                lowerBound = SignExtendNode.signExtend(inputStamp.lowerBound(), inputBits) & defaultMask;
-                upperBound = SignExtendNode.signExtend(inputStamp.upperBound(), inputBits) & defaultMask;
-            } else {
-                lowerBound = inputStamp.lowerBound();
-                upperBound = inputStamp.upperBound();
-            }
-
-            return new IntegerStamp(resultBits, inputStamp.isUnsigned(), lowerBound, upperBound, downMask, upMask);
+            return new IntegerStamp(resultBits, inputStamp.lowerBound(), inputStamp.upperBound(), downMask, upMask);
         } else {
             return input.illegal();
         }
@@ -346,7 +319,7 @@
             long lowerBound = ZeroExtendNode.zeroExtend(inputStamp.lowerBound(), inputBits);
             long upperBound = ZeroExtendNode.zeroExtend(inputStamp.upperBound(), inputBits);
 
-            return new IntegerStamp(resultBits, inputStamp.isUnsigned(), lowerBound, upperBound, downMask, upMask);
+            return new IntegerStamp(resultBits, lowerBound, upperBound, downMask, upMask);
         } else {
             return input.illegal();
         }
@@ -355,7 +328,6 @@
     public static Stamp narrowingConversion(Stamp input, int resultBits) {
         if (input instanceof IntegerStamp) {
             IntegerStamp inputStamp = (IntegerStamp) input;
-            boolean unsigned = inputStamp.isUnsigned();
             int inputBits = inputStamp.getBits();
             assert resultBits <= inputBits;
             if (resultBits == inputBits) {
@@ -363,28 +335,24 @@
             }
 
             final long upperBound;
-            if (inputStamp.lowerBound() < IntegerStamp.defaultMinValue(resultBits, unsigned)) {
-                upperBound = IntegerStamp.defaultMaxValue(resultBits, unsigned);
+            if (inputStamp.lowerBound() < IntegerStamp.defaultMinValue(resultBits)) {
+                upperBound = IntegerStamp.defaultMaxValue(resultBits);
             } else {
-                upperBound = saturate(inputStamp.upperBound(), resultBits, unsigned);
+                upperBound = saturate(inputStamp.upperBound(), resultBits);
             }
             final long lowerBound;
-            if (inputStamp.upperBound() > IntegerStamp.defaultMaxValue(resultBits, unsigned)) {
-                lowerBound = IntegerStamp.defaultMinValue(resultBits, unsigned);
+            if (inputStamp.upperBound() > IntegerStamp.defaultMaxValue(resultBits)) {
+                lowerBound = IntegerStamp.defaultMinValue(resultBits);
             } else {
-                lowerBound = saturate(inputStamp.lowerBound(), resultBits, unsigned);
+                lowerBound = saturate(inputStamp.lowerBound(), resultBits);
             }
 
             long defaultMask = IntegerStamp.defaultMask(resultBits);
             long newDownMask = inputStamp.downMask() & defaultMask;
             long newUpMask = inputStamp.upMask() & defaultMask;
-            long newLowerBound = (lowerBound | newDownMask) & newUpMask;
-            long newUpperBound = (upperBound | newDownMask) & newUpMask;
-            if (!unsigned) {
-                newLowerBound = SignExtendNode.signExtend(newLowerBound, resultBits);
-                newUpperBound = SignExtendNode.signExtend(newUpperBound, resultBits);
-            }
-            return new IntegerStamp(resultBits, unsigned, newLowerBound, newUpperBound, newDownMask, newUpMask);
+            long newLowerBound = SignExtendNode.signExtend((lowerBound | newDownMask) & newUpMask, resultBits);
+            long newUpperBound = SignExtendNode.signExtend((upperBound | newDownMask) & newUpMask, resultBits);
+            return new IntegerStamp(resultBits, newLowerBound, newUpperBound, newDownMask, newUpMask);
         } else {
             return input.illegal();
         }
@@ -409,7 +377,7 @@
         long intMask = IntegerStamp.defaultMask(32);
         long newUpMask = signExtend(fromStamp.upMask() & defaultMask, toKind) & intMask;
         long newDownMask = signExtend(fromStamp.downMask() & defaultMask, toKind) & intMask;
-        return new IntegerStamp(toKind.getStackKind().getBitCount(), false, (int) ((lowerBound | newDownMask) & newUpMask), (int) ((upperBound | newDownMask) & newUpMask), newDownMask, newUpMask);
+        return new IntegerStamp(toKind.getStackKind().getBitCount(), (int) ((lowerBound | newDownMask) & newUpMask), (int) ((upperBound | newDownMask) & newUpMask), newDownMask, newUpMask);
     }
 
     private static long signExtend(long value, Kind valueKind) {
@@ -420,13 +388,13 @@
         }
     }
 
-    private static long saturate(long v, int bits, boolean unsigned) {
+    private static long saturate(long v, int bits) {
         if (bits < 64) {
-            long max = IntegerStamp.defaultMaxValue(bits, unsigned);
+            long max = IntegerStamp.defaultMaxValue(bits);
             if (v > max) {
                 return max;
             }
-            long min = IntegerStamp.defaultMinValue(bits, unsigned);
+            long min = IntegerStamp.defaultMinValue(bits);
             if (v < min) {
                 return min;
             }
@@ -471,14 +439,14 @@
                 }
                 // If the test succeeds then this proves that n is at greater than c so the bounds
                 // are [c+1..-n.upperBound)].
-                return StampFactory.forInteger(x.getBits(), false, x.lowerBound() + 1, y.upperBound());
+                return StampFactory.forInteger(x.getBits(), x.lowerBound() + 1, y.upperBound());
             }
             return null;
         }
         // n <| c, where c is a strictly positive constant
         if (y.lowerBound() == y.upperBound() && y.isStrictlyPositive()) {
             // The test proves that n is positive and less than c, [0..c-1]
-            return StampFactory.forInteger(y.getBits(), false, 0, y.lowerBound() - 1);
+            return StampFactory.forInteger(y.getBits(), 0, y.lowerBound() - 1);
         }
         return null;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Wed Apr 16 19:00:14 2014 +0200
@@ -38,7 +38,6 @@
 
         @Override
         public final boolean apply(Node n) {
-            // isA(FloatingNode.class).or(VirtualState.class).or(CallTargetNode.class)
             return n instanceof FloatingNode || n instanceof VirtualState || n instanceof CallTargetNode;
         }
     };
@@ -164,7 +163,7 @@
     }
 
     public static void checkRedundantProxy(ProxyNode vpn) {
-        AbstractBeginNode proxyPoint = vpn.proxyPoint();
+        BeginNode proxyPoint = vpn.proxyPoint();
         if (proxyPoint instanceof LoopExitNode) {
             LoopExitNode exit = (LoopExitNode) proxyPoint;
             LoopBeginNode loopBegin = exit.loopBegin();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/NodeIterators.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/NodeIterators.java	Wed Apr 16 19:00:14 2014 +0200
@@ -30,7 +30,7 @@
 public class NodeIterators {
 
     public static NodeIterable<FixedNode> dominators(final FixedNode n) {
-        return new AbstractNodeIterable<FixedNode>() {
+        return new NodeIterable<FixedNode>() {
 
             @Override
             public Iterator<FixedNode> iterator() {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Wed Apr 16 19:00:14 2014 +0200
@@ -407,7 +407,7 @@
             }
         }
 
-        private void registerControlSplitInfo(Node pred, AbstractBeginNode begin) {
+        private void registerControlSplitInfo(Node pred, BeginNode begin) {
             assert pred != null && begin != null;
             if (begin instanceof LoopExitNode) {
                 state.clear();
@@ -656,8 +656,8 @@
 
         @Override
         protected void node(FixedNode node) {
-            if (node instanceof AbstractBeginNode) {
-                AbstractBeginNode begin = (AbstractBeginNode) node;
+            if (node instanceof BeginNode) {
+                BeginNode begin = (BeginNode) node;
                 Node pred = node.predecessor();
 
                 if (pred != null) {
@@ -742,7 +742,7 @@
 
                 LogicNode replacement = null;
                 ValueNode replacementAnchor = null;
-                AbstractBeginNode survivingSuccessor = null;
+                BeginNode survivingSuccessor = null;
                 if (state.trueConditions.containsKey(compare)) {
                     replacement = trueConstant;
                     replacementAnchor = state.trueConditions.get(compare);
@@ -764,7 +764,7 @@
                 }
 
                 if (replacement != null) {
-                    if (!(replacementAnchor instanceof AbstractBeginNode)) {
+                    if (!(replacementAnchor instanceof BeginNode)) {
                         ValueAnchorNode anchor = graph.add(new ValueAnchorNode(replacementAnchor));
                         graph.addBeforeFixed(ifNode, anchor);
                     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Wed Apr 16 19:00:14 2014 +0200
@@ -47,11 +47,11 @@
  */
 public class ConvertDeoptimizeToGuardPhase extends Phase {
 
-    private static AbstractBeginNode findBeginNode(FixedNode startNode) {
+    private static BeginNode findBeginNode(FixedNode startNode) {
         Node n = startNode;
         while (true) {
-            if (n instanceof AbstractBeginNode) {
-                return (AbstractBeginNode) n;
+            if (n instanceof BeginNode) {
+                return (BeginNode) n;
             } else {
                 n = n.predecessor();
             }
@@ -71,7 +71,7 @@
 
         for (FixedGuardNode fixedGuard : graph.getNodes(FixedGuardNode.class)) {
 
-            AbstractBeginNode pred = BeginNode.prevBegin(fixedGuard);
+            BeginNode pred = BeginNode.prevBegin(fixedGuard);
             if (pred instanceof MergeNode) {
                 MergeNode merge = (MergeNode) pred;
                 if (fixedGuard.condition() instanceof CompareNode) {
@@ -109,17 +109,17 @@
         new DeadCodeEliminationPhase().apply(graph);
     }
 
-    private void visitDeoptBegin(AbstractBeginNode deoptBegin, DeoptimizationAction deoptAction, DeoptimizationReason deoptReason, StructuredGraph graph) {
+    private void visitDeoptBegin(BeginNode deoptBegin, DeoptimizationAction deoptAction, DeoptimizationReason deoptReason, StructuredGraph graph) {
         if (deoptBegin instanceof MergeNode) {
             MergeNode mergeNode = (MergeNode) deoptBegin;
             Debug.log("Visiting %s", mergeNode);
-            List<AbstractBeginNode> begins = new ArrayList<>();
+            List<BeginNode> begins = new ArrayList<>();
             for (AbstractEndNode end : mergeNode.forwardEnds()) {
-                AbstractBeginNode newBeginNode = findBeginNode(end);
+                BeginNode newBeginNode = findBeginNode(end);
                 assert !begins.contains(newBeginNode);
                 begins.add(newBeginNode);
             }
-            for (AbstractBeginNode begin : begins) {
+            for (BeginNode begin : begins) {
                 assert !begin.isDeleted();
                 visitDeoptBegin(begin, deoptAction, deoptReason, graph);
             }
@@ -127,11 +127,11 @@
             return;
         } else if (deoptBegin.predecessor() instanceof IfNode) {
             IfNode ifNode = (IfNode) deoptBegin.predecessor();
-            AbstractBeginNode otherBegin = ifNode.trueSuccessor();
+            BeginNode otherBegin = ifNode.trueSuccessor();
             LogicNode conditionNode = ifNode.condition();
             FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deoptReason, deoptAction, deoptBegin == ifNode.trueSuccessor()));
             FixedWithNextNode pred = (FixedWithNextNode) ifNode.predecessor();
-            AbstractBeginNode survivingSuccessor;
+            BeginNode survivingSuccessor;
             if (deoptBegin == ifNode.trueSuccessor()) {
                 survivingSuccessor = ifNode.falseSuccessor();
             } else {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Wed Apr 16 19:00:14 2014 +0200
@@ -92,9 +92,9 @@
 
     private static void exitLoops(AbstractDeoptimizeNode deopt, EndNode end, ControlFlowGraph cfg) {
         Block block = cfg.blockFor(deopt);
-        Loop loop = block.getLoop();
+        Loop<Block> loop = block.getLoop();
         while (loop != null) {
-            end.graph().addBeforeFixed(end, end.graph().add(new LoopExitNode(loop.loopBegin())));
+            end.graph().addBeforeFixed(end, end.graph().add(new LoopExitNode((LoopBeginNode) loop.header.getBeginNode())));
             loop = loop.parent;
         }
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java	Wed Apr 16 19:00:14 2014 +0200
@@ -54,8 +54,8 @@
     }
 
     private static void processIf(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, IfNode ifNode, double shortCircuitProbability) {
-        AbstractBeginNode trueTarget = ifNode.trueSuccessor();
-        AbstractBeginNode falseTarget = ifNode.falseSuccessor();
+        BeginNode trueTarget = ifNode.trueSuccessor();
+        BeginNode falseTarget = ifNode.falseSuccessor();
         double firstIfProbability = shortCircuitProbability;
         /*
          * P(Y | not(X)) = P(Y inter not(X)) / P(not(X)) = (P(X union Y) - P(X)) / (1 - P(X))
@@ -77,9 +77,9 @@
         EndNode secondTrueEnd = graph.add(new EndNode());
         trueTargetMerge.addForwardEnd(firstTrueEnd);
         trueTargetMerge.addForwardEnd(secondTrueEnd);
-        AbstractBeginNode firstTrueTarget = AbstractBeginNode.begin(firstTrueEnd);
-        AbstractBeginNode secondTrueTarget = AbstractBeginNode.begin(secondTrueEnd);
-        AbstractBeginNode secondIf = AbstractBeginNode.begin(graph.add(new IfNode(y, yNegated ? falseTarget : secondTrueTarget, yNegated ? secondTrueTarget : falseTarget, secondIfProbability)));
+        BeginNode firstTrueTarget = BeginNode.begin(firstTrueEnd);
+        BeginNode secondTrueTarget = BeginNode.begin(secondTrueEnd);
+        BeginNode secondIf = BeginNode.begin(graph.add(new IfNode(y, yNegated ? falseTarget : secondTrueTarget, yNegated ? secondTrueTarget : falseTarget, secondIfProbability)));
         IfNode firstIf = graph.add(new IfNode(x, xNegated ? secondIf : firstTrueTarget, xNegated ? firstTrueTarget : secondIf, firstIfProbability));
         ifNode.replaceAtPredecessor(firstIf);
         ifNode.safeDelete();
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Wed Apr 16 19:00:14 2014 +0200
@@ -191,7 +191,7 @@
         }
 
         @Override
-        protected Set<LocationIdentity> afterSplit(AbstractBeginNode node, Set<LocationIdentity> oldState) {
+        protected Set<LocationIdentity> afterSplit(BeginNode node, Set<LocationIdentity> oldState) {
             return new HashSet<>(oldState);
         }
 
@@ -292,7 +292,7 @@
         }
 
         @Override
-        protected MemoryMapImpl afterSplit(AbstractBeginNode node, MemoryMapImpl oldState) {
+        protected MemoryMapImpl afterSplit(BeginNode node, MemoryMapImpl oldState) {
             MemoryMapImpl result = new MemoryMapImpl(oldState);
             if (node.predecessor() instanceof InvokeWithExceptionNode) {
                 /*
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java	Wed Apr 16 19:00:14 2014 +0200
@@ -92,7 +92,7 @@
         }
 
         @Override
-        protected FrameState afterSplit(AbstractBeginNode node, FrameState oldState) {
+        protected FrameState afterSplit(BeginNode node, FrameState oldState) {
             return oldState;
         }
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Wed Apr 16 19:00:14 2014 +0200
@@ -154,12 +154,12 @@
 
         private void lowerToIf(GuardNode guard) {
             StructuredGraph graph = guard.graph();
-            AbstractBeginNode fastPath = graph.add(new BeginNode());
+            BeginNode fastPath = graph.add(new BeginNode());
             @SuppressWarnings("deprecation")
             DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.action(), guard.reason(), useGuardIdAsDebugId ? guard.getId() : 0, guard.getSpeculation()));
-            AbstractBeginNode deoptBranch = AbstractBeginNode.begin(deopt);
-            AbstractBeginNode trueSuccessor;
-            AbstractBeginNode falseSuccessor;
+            BeginNode deoptBranch = BeginNode.begin(deopt);
+            BeginNode trueSuccessor;
+            BeginNode falseSuccessor;
             insertLoopExits(deopt);
             if (guard.negated()) {
                 trueSuccessor = deoptBranch;
@@ -174,10 +174,10 @@
         }
 
         private void insertLoopExits(DeoptimizeNode deopt) {
-            Loop loop = block.getLoop();
+            Loop<Block> loop = block.getLoop();
             StructuredGraph graph = deopt.graph();
             while (loop != null) {
-                LoopExitNode exit = graph.add(new LoopExitNode(loop.loopBegin()));
+                LoopExitNode exit = graph.add(new LoopExitNode((LoopBeginNode) loop.header.getBeginNode()));
                 graph.addBeforeFixed(deopt, exit);
                 loop = loop.parent;
             }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Wed Apr 16 19:00:14 2014 +0200
@@ -646,7 +646,7 @@
             }
 
             // create one separate block for each invoked method
-            AbstractBeginNode[] successors = new AbstractBeginNode[numberOfMethods + 1];
+            BeginNode[] successors = new BeginNode[numberOfMethods + 1];
             for (int i = 0; i < numberOfMethods; i++) {
                 successors[i] = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, true);
             }
@@ -658,7 +658,7 @@
             } else {
                 unknownTypeSux = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated));
             }
-            successors[successors.length - 1] = AbstractBeginNode.begin(unknownTypeSux);
+            successors[successors.length - 1] = BeginNode.begin(unknownTypeSux);
 
             // replace the invoke exception edge
             if (invoke instanceof InvokeWithExceptionNode) {
@@ -684,7 +684,7 @@
 
             // do the actual inlining for every invoke
             for (int i = 0; i < numberOfMethods; i++) {
-                AbstractBeginNode node = successors[i];
+                BeginNode node = successors[i];
                 Invoke invokeForInlining = (Invoke) node.next();
 
                 ResolvedJavaType commonType;
@@ -770,10 +770,10 @@
         private void inlineSingleMethod(StructuredGraph graph, MetaAccessProvider metaAccess, Assumptions assumptions) {
             assert concretes.size() == 1 && inlineableElements.length == 1 && ptypes.size() > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0;
 
-            AbstractBeginNode calleeEntryNode = graph.add(new BeginNode());
+            BeginNode calleeEntryNode = graph.add(new BeginNode());
 
-            AbstractBeginNode unknownTypeSux = createUnknownTypeSuccessor(graph);
-            AbstractBeginNode[] successors = new AbstractBeginNode[]{calleeEntryNode, unknownTypeSux};
+            BeginNode unknownTypeSux = createUnknownTypeSuccessor(graph);
+            BeginNode[] successors = new BeginNode[]{calleeEntryNode, unknownTypeSux};
             createDispatchOnTypeBeforeInvoke(graph, successors, false, metaAccess);
 
             calleeEntryNode.setNext(invoke.asNode());
@@ -781,7 +781,7 @@
             inline(invoke, methodAt(0), inlineableElementAt(0), assumptions, false);
         }
 
-        private boolean createDispatchOnTypeBeforeInvoke(StructuredGraph graph, AbstractBeginNode[] successors, boolean invokeIsOnlySuccessor, MetaAccessProvider metaAccess) {
+        private boolean createDispatchOnTypeBeforeInvoke(StructuredGraph graph, BeginNode[] successors, boolean invokeIsOnlySuccessor, MetaAccessProvider metaAccess) {
             assert ptypes.size() >= 1;
             ValueNode nonNullReceiver = nonNullReceiver(invoke);
             Kind hubKind = ((MethodCallTargetNode) invoke.callTarget()).targetMethod().getDeclaringClass().getEncoding(Representation.ObjectHub).getKind();
@@ -891,10 +891,10 @@
             return costEstimateMethodDispatch < costEstimateTypeDispatch;
         }
 
-        private static AbstractBeginNode createInvocationBlock(StructuredGraph graph, Invoke invoke, MergeNode returnMerge, PhiNode returnValuePhi, MergeNode exceptionMerge,
-                        PhiNode exceptionObjectPhi, boolean useForInlining) {
+        private static BeginNode createInvocationBlock(StructuredGraph graph, Invoke invoke, MergeNode returnMerge, PhiNode returnValuePhi, MergeNode exceptionMerge, PhiNode exceptionObjectPhi,
+                        boolean useForInlining) {
             Invoke duplicatedInvoke = duplicateInvokeForInlining(graph, invoke, exceptionMerge, exceptionObjectPhi, useForInlining);
-            AbstractBeginNode calleeEntryNode = graph.add(new BeginNode());
+            BeginNode calleeEntryNode = graph.add(new BeginNode());
             calleeEntryNode.setNext(duplicatedInvoke.asNode());
 
             AbstractEndNode endNode = graph.add(new EndNode());
@@ -969,9 +969,9 @@
         }
 
         private void devirtualizeWithTypeSwitch(StructuredGraph graph, InvokeKind kind, ResolvedJavaMethod target, MetaAccessProvider metaAccess) {
-            AbstractBeginNode invocationEntry = graph.add(new BeginNode());
-            AbstractBeginNode unknownTypeSux = createUnknownTypeSuccessor(graph);
-            AbstractBeginNode[] successors = new AbstractBeginNode[]{invocationEntry, unknownTypeSux};
+            BeginNode invocationEntry = graph.add(new BeginNode());
+            BeginNode unknownTypeSux = createUnknownTypeSuccessor(graph);
+            BeginNode[] successors = new BeginNode[]{invocationEntry, unknownTypeSux};
             createDispatchOnTypeBeforeInvoke(graph, successors, true, metaAccess);
 
             invocationEntry.setNext(invoke.asNode());
@@ -981,8 +981,8 @@
             replaceInvokeCallTarget(invoke, graph, kind, target);
         }
 
-        private static AbstractBeginNode createUnknownTypeSuccessor(StructuredGraph graph) {
-            return AbstractBeginNode.begin(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated)));
+        private static BeginNode createUnknownTypeSuccessor(StructuredGraph graph) {
+            return BeginNode.begin(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated)));
         }
 
         @Override
@@ -1347,7 +1347,7 @@
             }
         }
 
-        final AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(invokeNode);
+        final BeginNode prevBegin = BeginNode.prevBegin(invokeNode);
         DuplicationReplacement localReplacement = new DuplicationReplacement() {
 
             public Node replacement(Node node) {
@@ -1386,7 +1386,7 @@
             }
 
             // get rid of memory kill
-            AbstractBeginNode begin = invokeWithException.next();
+            BeginNode begin = invokeWithException.next();
             if (begin instanceof KillingBeginNode) {
                 BeginNode newBegin = new BeginNode();
                 graph.addAfterFixed(begin, graph.add(newBegin));
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java	Wed Apr 16 19:00:14 2014 +0200
@@ -55,11 +55,11 @@
     @Override
     protected void run(StructuredGraph graph) {
         LazyCFG cfg = new LazyCFG(graph);
-        for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.class)) {
+        for (BeginNode begin : graph.getNodes(BeginNode.class)) {
             if (!(begin instanceof StartNode || begin.predecessor() instanceof ControlSplitNode)) {
                 NodeIterable<GuardNode> guards = begin.guards();
                 if (guards.isNotEmpty()) {
-                    AbstractBeginNode newAnchor = computeOptimalAnchor(cfg.get(), begin);
+                    BeginNode newAnchor = computeOptimalAnchor(cfg.get(), begin);
                     // newAnchor == begin is possible because postdominator computation assumes that
                     // loops never end
                     if (newAnchor != begin) {
@@ -76,14 +76,14 @@
         }
     }
 
-    public static AbstractBeginNode getOptimalAnchor(LazyCFG cfg, AbstractBeginNode begin) {
+    public static BeginNode getOptimalAnchor(LazyCFG cfg, BeginNode begin) {
         if (begin instanceof StartNode || begin.predecessor() instanceof ControlSplitNode) {
             return begin;
         }
         return computeOptimalAnchor(cfg.get(), begin);
     }
 
-    private static AbstractBeginNode computeOptimalAnchor(ControlFlowGraph cfg, AbstractBeginNode begin) {
+    private static BeginNode computeOptimalAnchor(ControlFlowGraph cfg, BeginNode begin) {
         Block anchor = cfg.blockFor(begin);
         while (anchor.getDominator() != null && anchor.getDominator().getPostdominator() == anchor) {
             anchor = anchor.getDominator();
@@ -92,7 +92,7 @@
     }
 
     private static void optimizeAtControlSplit(ControlSplitNode controlSplit, LazyCFG cfg) {
-        AbstractBeginNode successor = findMinimumUsagesSuccessor(controlSplit);
+        BeginNode successor = findMinimumUsagesSuccessor(controlSplit);
         int successorCount = controlSplit.successors().count();
         List<GuardNode> otherGuards = new ArrayList<>(successorCount - 1);
         for (GuardNode guard : successor.guards().snapshot()) {
@@ -109,7 +109,7 @@
             }
 
             if (otherGuards.size() == successorCount - 1) {
-                AbstractBeginNode anchor = computeOptimalAnchor(cfg.get(), AbstractBeginNode.prevBegin(controlSplit));
+                BeginNode anchor = computeOptimalAnchor(cfg.get(), BeginNode.prevBegin(controlSplit));
                 GuardNode newGuard = controlSplit.graph().unique(new GuardNode(guard.condition(), anchor, guard.reason(), guard.action(), guard.negated(), guard.getSpeculation()));
                 for (GuardNode otherGuard : otherGuards) {
                     otherGuard.replaceAndDelete(newGuard);
@@ -126,12 +126,12 @@
                         conditonGuard.getSpeculation().equals(guard.getSpeculation());
     }
 
-    private static AbstractBeginNode findMinimumUsagesSuccessor(ControlSplitNode controlSplit) {
+    private static BeginNode findMinimumUsagesSuccessor(ControlSplitNode controlSplit) {
         NodeClassIterator successors = controlSplit.successors().iterator();
-        AbstractBeginNode min = (AbstractBeginNode) successors.next();
+        BeginNode min = (BeginNode) successors.next();
         int minUsages = min.usages().count();
         while (successors.hasNext()) {
-            AbstractBeginNode successor = (AbstractBeginNode) successors.next();
+            BeginNode successor = (BeginNode) successors.next();
             int count = successor.usages().count();
             if (count < minUsages) {
                 minUsages = count;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java	Wed Apr 16 19:00:14 2014 +0200
@@ -43,11 +43,11 @@
  * for each node would be too costly, so this phase takes the compromise that it trusts split
  * probabilities, but not loop frequencies. This means that it will insert counters at the start of
  * a method and at each loop header.
- * 
+ *
  * A schedule is created so that floating nodes can also be taken into account. The weight of a node
  * is determined heuristically in the
  * {@link ProfileCompiledMethodsPhase#getNodeWeight(ScheduledNode)} method.
- * 
+ *
  * Additionally, there's a second counter that's only increased for code sections without invokes.
  */
 public class ProfileCompiledMethodsPhase extends Phase {
@@ -65,18 +65,18 @@
         schedule.apply(graph, false);
 
         ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true);
-        for (Loop loop : cfg.getLoops()) {
-            double loopProbability = probabilities.get(loop.loopBegin());
+        for (Loop<Block> loop : cfg.getLoops()) {
+            double loopProbability = probabilities.get(loop.header.getBeginNode());
             if (loopProbability > (1D / Integer.MAX_VALUE)) {
-                addSectionCounters(loop.loopBegin(), loop.blocks, loop.children, schedule, probabilities);
+                addSectionCounters(loop.header.getBeginNode(), loop.blocks, loop.children, schedule, probabilities);
             }
         }
-        addSectionCounters(graph.start(), Arrays.asList(cfg.getBlocks()), Arrays.asList(cfg.getLoops()), schedule, probabilities);
+        addSectionCounters(graph.start(), Arrays.asList(cfg.getBlocks()), cfg.getLoops(), schedule, probabilities);
     }
 
-    private static void addSectionCounters(FixedWithNextNode start, Collection<Block> sectionBlocks, Collection<Loop> childLoops, SchedulePhase schedule, NodesToDoubles probabilities) {
+    private static void addSectionCounters(FixedWithNextNode start, Collection<Block> sectionBlocks, Collection<Loop<Block>> childLoops, SchedulePhase schedule, NodesToDoubles probabilities) {
         HashSet<Block> blocks = new HashSet<>(sectionBlocks);
-        for (Loop loop : childLoops) {
+        for (Loop<?> loop : childLoops) {
             blocks.removeAll(loop.blocks);
         }
         double weight = getSectionWeight(schedule, probabilities, blocks) / probabilities.get(start);
@@ -108,7 +108,7 @@
     private static double getNodeWeight(ScheduledNode node) {
         if (node instanceof MergeNode) {
             return ((MergeNode) node).phiPredecessorCount();
-        } else if (node instanceof AbstractBeginNode || node instanceof AbstractEndNode || node instanceof MonitorIdNode || node instanceof ConstantNode || node instanceof ParameterNode ||
+        } else if (node instanceof BeginNode || node instanceof AbstractEndNode || node instanceof MonitorIdNode || node instanceof ConstantNode || node instanceof ParameterNode ||
                         node instanceof CallTargetNode || node instanceof ValueProxy || node instanceof VirtualObjectNode || node instanceof ReinterpretNode) {
             return 0;
         } else if (node instanceof AccessMonitorNode) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Wed Apr 16 19:00:14 2014 +0200
@@ -293,7 +293,7 @@
                 // EndNode
                 FixedWithNextNode anchorDuplicate = (FixedWithNextNode) duplicates.get(anchor);
                 // move dependencies on the ValueAnchorNode to the previous BeginNode
-                AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(forwardEnd);
+                BeginNode prevBegin = BeginNode.prevBegin(forwardEnd);
                 anchorDuplicate.replaceAtUsages(InputType.Guard, prevBegin);
                 anchorDuplicate.replaceAtUsages(InputType.Anchor, prevBegin);
                 assert anchorDuplicate.usages().isEmpty();
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Wed Apr 16 19:00:14 2014 +0200
@@ -55,7 +55,7 @@
         }
         Node predecessor = deopt.predecessor();
         Node branch = null;
-        while (predecessor instanceof AbstractBeginNode) {
+        while (predecessor instanceof BeginNode) {
             branch = predecessor;
             predecessor = predecessor.predecessor();
         }
@@ -73,8 +73,8 @@
 
     private static void replaceWithTrappingNullCheck(DeoptimizeNode deopt, IfNode ifNode, LogicNode condition) {
         IsNullNode isNullNode = (IsNullNode) condition;
-        AbstractBeginNode nonTrappingContinuation = ifNode.falseSuccessor();
-        AbstractBeginNode trappingContinuation = ifNode.trueSuccessor();
+        BeginNode nonTrappingContinuation = ifNode.falseSuccessor();
+        BeginNode trappingContinuation = ifNode.trueSuccessor();
         NullCheckNode trappingNullCheck = deopt.graph().add(new NullCheckNode(isNullNode.object()));
         trappingNullCheck.setStateBefore(deopt.stateBefore());
         deopt.graph().replaceSplit(ifNode, trappingNullCheck, nonTrappingContinuation);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeInliningRelevanceClosure.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeInliningRelevanceClosure.java	Wed Apr 16 19:00:14 2014 +0200
@@ -105,26 +105,26 @@
         private Scope[] computeScopes() {
             ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, false, false);
 
-            Loop[] loops = cfg.getLoops();
-            HashMap<Loop, Scope> processedScopes = new HashMap<>();
-            Scope[] result = new Scope[loops.length + 1];
+            List<Loop<Block>> loops = cfg.getLoops();
+            HashMap<Loop<Block>, Scope> processedScopes = new HashMap<>();
+            Scope[] result = new Scope[loops.size() + 1];
             Scope methodScope = new Scope(graph.start(), null);
             processedScopes.put(null, methodScope);
 
             result[0] = methodScope;
-            for (int i = 0; i < loops.length; i++) {
-                result[i + 1] = createScope(loops[i], processedScopes);
+            for (int i = 0; i < loops.size(); i++) {
+                result[i + 1] = createScope(loops.get(i), processedScopes);
             }
 
             return result;
         }
 
-        private Scope createScope(Loop loop, HashMap<Loop, Scope> processedLoops) {
+        private Scope createScope(Loop<Block> loop, HashMap<Loop<Block>, Scope> processedLoops) {
             Scope parent = processedLoops.get(loop.parent);
             if (parent == null) {
                 parent = createScope(loop.parent, processedLoops);
             }
-            Scope result = new Scope(loop.loopBegin(), parent);
+            Scope result = new Scope(loop.header.getBeginNode(), parent);
             processedLoops.put(loop, result);
             return result;
         }
@@ -171,7 +171,7 @@
         int pathBeginCount = pathBeginNodes.size();
 
         for (Node sux : controlSplit.successors()) {
-            double probability = controlSplit.probability((AbstractBeginNode) sux);
+            double probability = controlSplit.probability((BeginNode) sux);
             if (probability > maxProbability) {
                 maxProbability = probability;
                 maxSux = sux;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java	Wed Apr 16 19:00:14 2014 +0200
@@ -223,7 +223,7 @@
         }
 
         @Override
-        public void afterSplit(AbstractBeginNode node) {
+        public void afterSplit(BeginNode node) {
             assert node.predecessor() != null;
             Node pred = node.predecessor();
             ControlSplitNode x = (ControlSplitNode) pred;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java	Wed Apr 16 19:00:14 2014 +0200
@@ -58,7 +58,7 @@
      * 
      * @param node the successor of the control split that is about to be visited
      */
-    public void afterSplit(AbstractBeginNode node) {
+    public void afterSplit(BeginNode node) {
         // empty default implementation
     }
 }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java	Wed Apr 16 19:00:14 2014 +0200
@@ -43,7 +43,7 @@
 public abstract class PostOrderNodeIterator<T extends MergeableState<T>> {
 
     private final NodeBitMap visitedEnds;
-    private final Deque<AbstractBeginNode> nodeQueue;
+    private final Deque<BeginNode> nodeQueue;
     private final IdentityHashMap<FixedNode, T> nodeStates;
     private final FixedNode start;
 
@@ -109,13 +109,13 @@
             for (Node node : successors) {
                 if (node != null) {
                     nodeStates.put((FixedNode) node.predecessor(), state);
-                    nodeQueue.addFirst((AbstractBeginNode) node);
+                    nodeQueue.addFirst((BeginNode) node);
                 }
             }
         } else {
             for (Node node : x.successors()) {
                 if (node != null) {
-                    nodeQueue.addFirst((AbstractBeginNode) node);
+                    nodeQueue.addFirst((BeginNode) node);
                 }
             }
         }
@@ -124,7 +124,7 @@
     private FixedNode nextQueuedNode() {
         int maxIterations = nodeQueue.size();
         while (maxIterations-- > 0) {
-            AbstractBeginNode node = nodeQueue.removeFirst();
+            BeginNode node = nodeQueue.removeFirst();
             if (node instanceof MergeNode) {
                 MergeNode merge = (MergeNode) node;
                 state = nodeStates.get(merge.forwardEndAt(0)).clone();
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java	Wed Apr 16 19:00:14 2014 +0200
@@ -45,14 +45,14 @@
 
         protected abstract StateT cloneState(StateT oldState);
 
-        protected abstract List<StateT> processLoop(Loop loop, StateT initialState);
+        protected abstract List<StateT> processLoop(Loop<Block> loop, StateT initialState);
     }
 
     private ReentrantBlockIterator() {
         // no instances allowed
     }
 
-    public static <StateT> LoopInfo<StateT> processLoop(BlockIteratorClosure<StateT> closure, Loop loop, StateT initialState) {
+    public static <StateT> LoopInfo<StateT> processLoop(BlockIteratorClosure<StateT> closure, Loop<Block> loop, StateT initialState) {
         IdentityHashMap<FixedNode, StateT> blockEndStates = apply(closure, loop.header, initialState, new HashSet<>(loop.blocks));
 
         LoopInfo<StateT> info = new LoopInfo<>();
@@ -101,8 +101,8 @@
                             states.put(current.getEndNode(), state);
                         } else {
                             // recurse into the loop
-                            Loop loop = successor.getLoop();
-                            LoopBeginNode loopBegin = loop.loopBegin();
+                            Loop<Block> loop = successor.getLoop();
+                            LoopBeginNode loopBegin = (LoopBeginNode) loop.header.getBeginNode();
                             assert successor.getBeginNode() == loopBegin;
 
                             List<StateT> exitStates = closure.processLoop(loop, state);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java	Wed Apr 16 19:00:14 2014 +0200
@@ -41,7 +41,7 @@
 
         protected abstract StateT merge(MergeNode merge, List<StateT> states);
 
-        protected abstract StateT afterSplit(AbstractBeginNode node, StateT oldState);
+        protected abstract StateT afterSplit(BeginNode node, StateT oldState);
 
         protected abstract Map<LoopExitNode, StateT> processLoop(LoopBeginNode loop, StateT initialState);
 
@@ -81,7 +81,7 @@
     }
 
     public static <StateT> Map<FixedNode, StateT> apply(NodeIteratorClosure<StateT> closure, FixedNode start, StateT initialState, Set<FixedNode> boundary) {
-        Deque<AbstractBeginNode> nodeQueue = new ArrayDeque<>();
+        Deque<BeginNode> nodeQueue = new ArrayDeque<>();
         IdentityHashMap<FixedNode, StateT> blockEndStates = new IdentityHashMap<>();
 
         StateT state = initialState;
@@ -146,14 +146,14 @@
                             continue;
                         } else {
                             while (successors.hasNext()) {
-                                AbstractBeginNode successor = (AbstractBeginNode) successors.next();
+                                BeginNode successor = (BeginNode) successors.next();
                                 StateT successorState = closure.afterSplit(successor, state);
                                 if (closure.continueIteration(successorState)) {
                                     blockEndStates.put(successor, successorState);
                                     nodeQueue.add(successor);
                                 }
                             }
-                            state = closure.afterSplit((AbstractBeginNode) firstSuccessor, state);
+                            state = closure.afterSplit((BeginNode) firstSuccessor, state);
                             current = closure.continueIteration(state) ? firstSuccessor : null;
                             continue;
                         }
@@ -167,7 +167,7 @@
             } else {
                 current = nodeQueue.removeFirst();
                 state = blockEndStates.get(current);
-                assert !(current instanceof MergeNode) && current instanceof AbstractBeginNode;
+                assert !(current instanceof MergeNode) && current instanceof BeginNode;
             }
         } while (true);
     }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/StatelessPostOrderNodeIterator.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/StatelessPostOrderNodeIterator.java	Wed Apr 16 19:00:14 2014 +0200
@@ -36,7 +36,7 @@
 public abstract class StatelessPostOrderNodeIterator {
 
     private final NodeBitMap visitedEnds;
-    private final Deque<AbstractBeginNode> nodeQueue;
+    private final Deque<BeginNode> nodeQueue;
     private final FixedNode start;
 
     public StatelessPostOrderNodeIterator(FixedNode start) {
@@ -76,7 +76,7 @@
                 controlSplit((ControlSplitNode) current);
                 for (Node node : current.successors()) {
                     if (node != null) {
-                        nodeQueue.addFirst((AbstractBeginNode) node);
+                        nodeQueue.addFirst((BeginNode) node);
                     }
                 }
                 current = nodeQueue.pollFirst();
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Wed Apr 16 19:00:14 2014 +0200
@@ -152,7 +152,7 @@
         }
 
         @Override
-        protected List<KillSet> processLoop(Loop loop, KillSet state) {
+        protected List<KillSet> processLoop(Loop<Block> loop, KillSet state) {
             LoopInfo<KillSet> info = ReentrantBlockIterator.processLoop(this, loop, cloneState(state));
 
             assert loop.header.getBeginNode() instanceof LoopBeginNode;
@@ -201,7 +201,7 @@
             }
         }
 
-        AbstractBeginNode startNode = cfg.getStartBlock().getBeginNode();
+        BeginNode startNode = cfg.getStartBlock().getBeginNode();
         assert startNode instanceof StartNode;
 
         KillSet accm = foundExcludeNode ? set : excludedLocations;
@@ -649,7 +649,7 @@
          * implies that the inputs' blocks have a total ordering via their dominance relation. So in
          * order to find the earliest block placement for this node we need to find the input block
          * that is dominated by all other input blocks.
-         * 
+         *
          * While iterating over the inputs a set of dominator blocks of the current earliest
          * placement is maintained. When the block of an input is not within this set, it becomes
          * the current earliest placement and the list of dominator blocks is updated.
@@ -753,7 +753,7 @@
                     // If a FrameState is an outer FrameState this method behaves as if the inner
                     // FrameState was the actual usage, by recursing.
                     blocksForUsage(node, unscheduledUsage, closure, strategy);
-                } else if (unscheduledUsage instanceof AbstractBeginNode) {
+                } else if (unscheduledUsage instanceof BeginNode) {
                     // Only FrameStates can be connected to BeginNodes.
                     if (!(usage instanceof FrameState)) {
                         throw new SchedulingError(usage.toString());
@@ -1047,7 +1047,7 @@
                 }
             }
 
-            if (instruction instanceof AbstractBeginNode) {
+            if (instruction instanceof BeginNode) {
                 ArrayList<ProxyNode> proxies = (instruction instanceof LoopExitNode) ? new ArrayList<>() : null;
                 for (ScheduledNode inBlock : blockToNodesMap.get(b)) {
                     if (!visited.isMarked(inBlock)) {
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Wed Apr 16 19:00:14 2014 +0200
@@ -140,7 +140,7 @@
             BlockIteratorClosure<NodeBitMap> closure = new BlockIteratorClosure<NodeBitMap>() {
 
                 @Override
-                protected List<NodeBitMap> processLoop(Loop loop, NodeBitMap initialState) {
+                protected List<NodeBitMap> processLoop(Loop<Block> loop, NodeBitMap initialState) {
                     return ReentrantBlockIterator.processLoop(this, loop, initialState).exitStates;
                 }
 
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Wed Apr 16 19:00:14 2014 +0200
@@ -488,7 +488,7 @@
             return "-";
         }
         String prefix;
-        if (node instanceof AbstractBeginNode && (lir == null && schedule == null)) {
+        if (node instanceof BeginNode && (lir == null && schedule == null)) {
             prefix = "B";
         } else if (node instanceof ValueNode) {
             ValueNode value = (ValueNode) node;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Wed Apr 16 19:00:14 2014 +0200
@@ -171,7 +171,7 @@
                     printProperty(bit, "true");
                 }
             }
-            if (node.getClass() == AbstractBeginNode.class) {
+            if (node.getClass() == BeginNode.class) {
                 printProperty("shortName", "B");
             } else if (node.getClass() == AbstractEndNode.class) {
                 printProperty("shortName", "E");
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -51,7 +51,7 @@
         throw GraalInternalError.shouldNotReachHere();
     }
 
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitFloatConvert(op, gen.operand(value)));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitFloatConvert(op, builder.operand(value)));
     }
 }
--- a/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -49,7 +49,7 @@
 
     /**
      * Gets the parameter passed to the math operation that this node represents.
-     * 
+     *
      * @return the parameter
      */
     public ValueNode getParameter() {
@@ -58,7 +58,7 @@
 
     /**
      * Returns the math operation represented by this node.
-     * 
+     *
      * @return the operation
      */
     public HSAILArithmetic operation() {
@@ -67,7 +67,7 @@
 
     /**
      * Creates a new HSAILMathIntrinsicNode.
-     * 
+     *
      * @param x the argument to the math operation
      * @param op the math operation
      */
@@ -81,30 +81,30 @@
      * Generates the LIR instructions for the math operation represented by this node.
      */
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        Value input = gen.operand(getParameter());
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        Value input = builder.operand(getParameter());
         Value result;
         switch (operation()) {
             case ABS:
-                result = gen.getLIRGeneratorTool().emitMathAbs(input);
+                result = gen.emitMathAbs(input);
                 break;
             case CEIL:
-                result = ((HSAILLIRGenerator) (gen.getLIRGeneratorTool())).emitMathCeil(input);
+                result = ((HSAILLIRGenerator) gen).emitMathCeil(input);
                 break;
             case FLOOR:
-                result = ((HSAILLIRGenerator) (gen.getLIRGeneratorTool())).emitMathFloor(input);
+                result = ((HSAILLIRGenerator) gen).emitMathFloor(input);
                 break;
             case RINT:
-                result = ((HSAILLIRGenerator) (gen.getLIRGeneratorTool())).emitMathRint(input);
+                result = ((HSAILLIRGenerator) gen).emitMathRint(input);
                 break;
             case SQRT:
-                result = gen.getLIRGeneratorTool().emitMathSqrt(input);
+                result = gen.emitMathSqrt(input);
                 break;
 
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
-        gen.setResult(this, result);
+        builder.setResult(this, result);
     }
 
     /**
@@ -132,7 +132,7 @@
 
     /**
      * Node intrinsic for {@link Math} routines taking a single int parameter.
-     * 
+     *
      * @param value
      * @param op the math operation
      * @return the result of the operation
@@ -142,7 +142,7 @@
 
     /**
      * Node intrinsic for {@link Math} routines taking a single double parameter.
-     * 
+     *
      * @param value the input parameter
      * @param op the math operation
      * @return the result of the operation
@@ -152,7 +152,7 @@
 
     /**
      * Node intrinsic for {@link Math} routines taking a single float parameter.
-     * 
+     *
      * @param value the input parameter
      * @param op the math operation
      * @return the result of the operation
@@ -162,10 +162,10 @@
 
     /**
      * Node intrinsic for {@link Math} routines taking a single double parameter.
-     * 
+     *
      * @param value the input parameter
      * @param op the math operation
-     * 
+     *
      * @return the result of the operation
      */
     @NodeIntrinsic
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java	Wed Apr 16 19:00:14 2014 +0200
@@ -65,7 +65,7 @@
             return new IterationState(this, sideEffect.asNode(), null, true);
         }
 
-        public IterationState addBranch(AbstractBeginNode begin) {
+        public IterationState addBranch(BeginNode begin) {
             return new IterationState(this, begin, null, this.invalid);
         }
 
@@ -192,7 +192,7 @@
         }
 
         @Override
-        protected IterationState afterSplit(AbstractBeginNode node, IterationState oldState) {
+        protected IterationState afterSplit(BeginNode node, IterationState oldState) {
             return oldState.addBranch(node);
         }
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -61,35 +61,35 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        Value input = gen.operand(x());
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        Value input = builder.operand(x());
         Value result;
         switch (operation()) {
             case ABS:
-                result = gen.getLIRGeneratorTool().emitMathAbs(input);
+                result = gen.emitMathAbs(input);
                 break;
             case SQRT:
-                result = gen.getLIRGeneratorTool().emitMathSqrt(input);
+                result = gen.emitMathSqrt(input);
                 break;
             case LOG:
-                result = gen.getLIRGeneratorTool().emitMathLog(input, false);
+                result = gen.emitMathLog(input, false);
                 break;
             case LOG10:
-                result = gen.getLIRGeneratorTool().emitMathLog(input, true);
+                result = gen.emitMathLog(input, true);
                 break;
             case SIN:
-                result = gen.getLIRGeneratorTool().emitMathSin(input);
+                result = gen.emitMathSin(input);
                 break;
             case COS:
-                result = gen.getLIRGeneratorTool().emitMathCos(input);
+                result = gen.emitMathCos(input);
                 break;
             case TAN:
-                result = gen.getLIRGeneratorTool().emitMathTan(input);
+                result = gen.emitMathTan(input);
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
-        gen.setResult(this, result);
+        builder.setResult(this, result);
     }
 
     public Constant evalConst(Constant... inputs) {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Wed Apr 16 19:00:14 2014 +0200
@@ -80,7 +80,7 @@
 
     // tracing
     @Option(help = "")
-    public static final OptionValue<Boolean> TraceTruffleCompilation = new OptionValue<>(true);
+    public static final OptionValue<Boolean> TraceTruffleCompilation = new OptionValue<>(false);
     @Option(help = "")
     public static final OptionValue<Boolean> TraceTruffleCompilationDetails = new OptionValue<>(false);
     @Option(help = "")
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -77,7 +77,7 @@
     }
 
     @Override
-    public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) {
+    public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) {
         return graph().add(new IntegerAddExactSplitNode(stamp(), x(), y(), next, deopt));
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -29,7 +29,7 @@
 
 public class IntegerAddExactSplitNode extends IntegerExactArithmeticSplitNode {
 
-    public IntegerAddExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) {
+    public IntegerAddExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) {
         super(stamp, x, y, next, overflowSuccessor);
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -28,5 +28,5 @@
 
 interface IntegerExactArithmeticNode extends Lowerable, IterableNodeType {
 
-    IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt);
+    IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt);
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -30,12 +30,12 @@
 
 public abstract class IntegerExactArithmeticSplitNode extends ControlSplitNode implements LIRLowerable {
 
-    @Successor private AbstractBeginNode overflowSuccessor;
-    @Successor private AbstractBeginNode next;
+    @Successor private BeginNode overflowSuccessor;
+    @Successor private BeginNode next;
     @Input private ValueNode x;
     @Input private ValueNode y;
 
-    public IntegerExactArithmeticSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) {
+    public IntegerExactArithmeticSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) {
         super(stamp);
         this.x = x;
         this.y = y;
@@ -44,20 +44,20 @@
     }
 
     @Override
-    public double probability(AbstractBeginNode successor) {
+    public double probability(BeginNode successor) {
         return successor == next ? 1 : 0;
     }
 
     @Override
-    public void setProbability(AbstractBeginNode successor, double value) {
+    public void setProbability(BeginNode successor, double value) {
         assert probability(successor) == value;
     }
 
-    public AbstractBeginNode getNext() {
+    public BeginNode getNext() {
         return next;
     }
 
-    public AbstractBeginNode getOverflowSuccessor() {
+    public BeginNode getOverflowSuccessor() {
         return overflowSuccessor;
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -74,7 +74,7 @@
     }
 
     @Override
-    public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) {
+    public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) {
         return graph().add(new IntegerMulExactSplitNode(stamp(), x(), y(), next, deopt));
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -29,7 +29,7 @@
 
 public class IntegerMulExactSplitNode extends IntegerExactArithmeticSplitNode {
 
-    public IntegerMulExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) {
+    public IntegerMulExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) {
         super(stamp, x, y, next, overflowSuccessor);
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -77,7 +77,7 @@
     }
 
     @Override
-    public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) {
+    public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) {
         return graph().add(new IntegerSubExactSplitNode(stamp(), x(), y(), next, deopt));
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -29,7 +29,7 @@
 
 public class IntegerSubExactSplitNode extends IntegerExactArithmeticSplitNode {
 
-    public IntegerSubExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) {
+    public IntegerSubExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) {
         super(stamp, x, y, next, overflowSuccessor);
     }
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Wed Apr 16 19:00:14 2014 +0200
@@ -43,7 +43,7 @@
 
     protected final NodeMap<ValueNode> aliases;
     protected final BlockMap<GraphEffectList> blockEffects;
-    private final IdentityHashMap<Loop, GraphEffectList> loopMergeEffects = new IdentityHashMap<>();
+    private final IdentityHashMap<Loop<Block>, GraphEffectList> loopMergeEffects = new IdentityHashMap<>();
     private final IdentityHashMap<LoopBeginNode, BlockT> loopEntryStates = new IdentityHashMap<>();
 
     private boolean changed;
@@ -105,7 +105,7 @@
             }
 
             @Override
-            protected List<Void> processLoop(Loop loop, Void initialState) {
+            protected List<Void> processLoop(Loop<Block> loop, Void initialState) {
                 LoopInfo<Void> info = ReentrantBlockIterator.processLoop(this, loop, initialState);
                 apply(loopMergeEffects.get(loop), loop);
                 return info.exitStates;
@@ -150,7 +150,7 @@
     }
 
     @Override
-    protected final List<BlockT> processLoop(Loop loop, BlockT initialState) {
+    protected final List<BlockT> processLoop(Loop<Block> loop, BlockT initialState) {
         BlockT loopEntryState = initialState;
         BlockT lastMergedState = cloneState(initialState);
         MergeProcessor mergeProcessor = createMergeProcessor(loop.header);
@@ -174,7 +174,7 @@
                 loopMergeEffects.put(loop, mergeProcessor.afterMergeEffects);
 
                 assert info.exitStates.size() == loop.exits.size();
-                loopEntryStates.put(loop.loopBegin(), loopEntryState);
+                loopEntryStates.put((LoopBeginNode) loop.header.getBeginNode(), loopEntryState);
                 for (int i = 0; i < loop.exits.size(); i++) {
                     assert info.exitStates.get(i) != null : "no loop exit state at " + loop.exits.get(i) + " / " + loop.header;
                 }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java	Wed Apr 16 19:00:14 2014 +0200
@@ -107,7 +107,7 @@
     }
 
     @Override
-    public Value generateAddress(NodeLIRBuilderTool gen, Value base) {
+    public Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base) {
         throw new GraalInternalError("locationIdentity must be a constant so that this node can be canonicalized: " + locationIdentity);
     }
 
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Wed Apr 16 18:57:14 2014 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Wed Apr 16 19:00:14 2014 +0200
@@ -379,7 +379,7 @@
          * The read must not float outside its block otherwise it may float above an explicit zero
          * check on its base address.
          */
-        read.setGuard(AbstractBeginNode.prevBegin(invoke.asNode()));
+        read.setGuard(BeginNode.prevBegin(invoke.asNode()));
         return read;
     }
 
--- a/make/solaris/makefiles/mapfile-vers	Wed Apr 16 18:57:14 2014 +0200
+++ b/make/solaris/makefiles/mapfile-vers	Wed Apr 16 19:00:14 2014 +0200
@@ -223,8 +223,6 @@
                 JVM_SetLength;
                 JVM_SetNativeThreadName;
                 JVM_SetPrimitiveArrayElement;
-                # Preserved so that Graal repo can link against a JDK7 libjava.so works
-                JVM_SetProtectionDomain;
                 JVM_SetSockOpt;
                 JVM_SetThreadPriority;
                 JVM_Sleep;
--- a/mx/eclipse-settings/org.eclipse.jdt.core.prefs	Wed Apr 16 18:57:14 2014 +0200
+++ b/mx/eclipse-settings/org.eclipse.jdt.core.prefs	Wed Apr 16 19:00:14 2014 +0200
@@ -100,7 +100,6 @@
 org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
 org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
 org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
-org.eclipse.jdt.core.compiler.problem.tasks=ignore
 org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
 org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
 org.eclipse.jdt.core.compiler.problem.unclosedCloseable=ignore
--- a/mx/mx_graal.py	Wed Apr 16 18:57:14 2014 +0200
+++ b/mx/mx_graal.py	Wed Apr 16 19:00:14 2014 +0200
@@ -28,7 +28,7 @@
 
 import os, sys, shutil, zipfile, tempfile, re, time, datetime, platform, subprocess, multiprocessing, StringIO
 from os.path import join, exists, dirname, basename, getmtime
-from argparse import ArgumentParser, REMAINDER
+from argparse import ArgumentParser, RawDescriptionHelpFormatter, REMAINDER
 from outputparser import OutputParser, ValuesMatcher
 import mx
 import xml.dom.minidom
@@ -828,7 +828,7 @@
     else:
         return [], args
 
-def _run_tests(args, harness, annotations, testfile):
+def _run_tests(args, harness, annotations, testfile, whitelist):
 
 
     vmArgs, tests = _extract_VM_args(args)
@@ -860,6 +860,9 @@
                 mx.log('warning: no tests matched by substring "' + t)
         projectscp = mx.classpath(projs)
 
+    if whitelist:
+        classes = list(set(classes) & set(whitelist))
+
     if len(classes) != 0:
         f_testfile = open(testfile, 'w')
         for c in classes:
@@ -867,7 +870,7 @@
         f_testfile.close()
         harness(projectscp, vmArgs)
 
-def _unittest(args, annotations, prefixcp=""):
+def _unittest(args, annotations, prefixcp="", whitelist=None):
     mxdir = dirname(__file__)
     name = 'JUnitWrapper'
     javaSource = join(mxdir, name + '.java')
@@ -894,12 +897,20 @@
             vm(prefixArgs + vmArgs + ['-cp', prefixcp + projectscp + os.pathsep + mxdir, name] + [testfile])
 
     try:
-        _run_tests(args, harness, annotations, testfile)
+        _run_tests(args, harness, annotations, testfile, whitelist)
     finally:
         if os.environ.get('MX_TESTFILE') is None:
             os.remove(testfile)
 
 _unittestHelpSuffix = """
+    Unittest options:
+
+      --short-only           run short testcases only
+      --long-only            run long testcases only
+      --baseline-whitelist   run only testcases which are known to
+                             work with the baseline compiler
+
+    To avoid conflicts with VM options '--' can be used as delimiter.
 
     If filters are supplied, only tests whose fully qualified name
     includes a filter as a substring are run.
@@ -928,17 +939,64 @@
 def unittest(args):
     """run the JUnit tests (all testcases){0}"""
 
-    _unittest(args, ['@Test', '@LongTest', '@Parameters'])
+    parser = ArgumentParser(prog='mx unittest',
+          description='run the JUnit tests',
+          add_help=False,
+          formatter_class=RawDescriptionHelpFormatter,
+          epilog=_unittestHelpSuffix,
+        )
+    group = parser.add_mutually_exclusive_group()
+    group.add_argument('--short-only', action='store_true', help='run short testcases only')
+    group.add_argument('--long-only', action='store_true', help='run long testcases only')
+    parser.add_argument('--baseline-whitelist', action='store_true', help='run baseline testcases only')
+
+    ut_args = []
+    delimiter = False
+    # check for delimiter
+    while len(args) > 0:
+        arg = args.pop(0)
+        if arg == '--':
+            delimiter = True
+            break
+        ut_args.append(arg)
+
+    if delimiter:
+        # all arguments before '--' must be recognized
+        parsed_args = parser.parse_args(ut_args)
+    else:
+        # parse all know arguments
+        parsed_args, remaining_args = parser.parse_known_args(ut_args)
+        args = remaining_args + args
+
+    whitelist = None
+    if parsed_args.baseline_whitelist:
+        baseline_whitelist_file = 'test/baseline_whitelist.txt'
+        try:
+            with open(join(_graal_home, baseline_whitelist_file)) as fp:
+                whitelist = [l.rstrip() for l in fp.readlines()]
+        except IOError:
+            mx.log('warning: could not read baseline whitelist: ' + baseline_whitelist_file)
+
+    if parsed_args.long_only:
+        annotations = ['@LongTest', '@Parameters']
+    elif parsed_args.short_only:
+        annotations = ['@Test']
+    else:
+        annotations = ['@Test', '@LongTest', '@Parameters']
+
+    _unittest(args, annotations, whitelist=whitelist)
 
 def shortunittest(args):
-    """run the JUnit tests (short testcases only){0}"""
+    """alias for 'unittest --short-only'{0}"""
 
-    _unittest(args, ['@Test'])
+    args.insert(0, '--short-only')
+    unittest(args)
 
 def longunittest(args):
-    """run the JUnit tests (long testcases only){0}"""
+    """alias for 'unittest --long-only'{0}"""
 
-    _unittest(args, ['@LongTest', '@Parameters'])
+    args.insert(0, '--long-only')
+    unittest(args)
 
 def buildvms(args):
     """build one or more VMs in various configurations"""
@@ -1784,9 +1842,9 @@
         'specjbb2005': [specjbb2005, '[VM options] [-- [SPECjbb2005 options]]'],
         'gate' : [gate, '[-options]'],
         'bench' : [bench, '[-resultfile file] [all(default)|dacapo|specjvm2008|bootstrap]'],
-        'unittest' : [unittest, '[VM options] [filters...]', _unittestHelpSuffix],
-        'longunittest' : [longunittest, '[VM options] [filters...]', _unittestHelpSuffix],
-        'shortunittest' : [shortunittest, '[VM options] [filters...]', _unittestHelpSuffix],
+        'unittest' : [unittest, '[unittest options] [--] [VM options] [filters...]', _unittestHelpSuffix],
+        'longunittest' : [longunittest, '[unittest options] [--] [VM options] [filters...]', _unittestHelpSuffix],
+        'shortunittest' : [shortunittest, '[unittest options] [--] [VM options] [filters...]', _unittestHelpSuffix],
         'jacocoreport' : [jacocoreport, '[output directory]'],
         'site' : [site, '[-options]'],
         'vm': [vm, '[-options] class [args...]'],
--- a/mx/projects	Wed Apr 16 18:57:14 2014 +0200
+++ b/mx/projects	Wed Apr 16 19:00:14 2014 +0200
@@ -5,10 +5,21 @@
 library@JDK_TOOLS@path=${JAVA_HOME}/lib/tools.jar
 library@JDK_TOOLS@optional=true
 
-library@JUNIT@path=lib/junit-4.8.jar
-library@JUNIT@urls=http://repo1.maven.org/maven2/junit/junit/4.8/junit-4.8.jar
-library@JUNIT@sha1=4150c00c5706306ef0f8f1410e70c8ff12757922
+library@JUNIT@path=lib/junit-4.11.jar
+library@JUNIT@urls=http://repo1.maven.org/maven2/junit/junit/4.11/junit-4.11.jar
+library@JUNIT@sha1=4e031bb61df09069aeb2bffb4019e7a5034a4ee0
 library@JUNIT@eclipse.container=org.eclipse.jdt.junit.JUNIT_CONTAINER/4
+library@JUNIT@sourcePath=lib/junit-4.11-sources.jar
+library@JUNIT@sourceUrls=http://repo1.maven.org/maven2/junit/junit/4.11/junit-4.11-sources.jar
+library@JUNIT@sourceSha1=28e0ad201304e4a4abf999ca0570b7cffc352c3c
+library@JUNIT@dependencies=HAMCREST
+
+library@HAMCREST@path=lib/hamcrest-core-1.3.jar
+library@HAMCREST@urls=http://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar
+library@HAMCREST@sha1=42a25dc3219429f0e5d060061f71acb49bf010a0
+library@HAMCREST@sourcePath=lib/hamcrest-core-1.3-sources.jar
+library@HAMCREST@sourceUrls=http://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar
+library@HAMCREST@sourceSha1=1dc37250fbc78e23a65a67fbbaf71d2e9cbc3c0b
 
 library@CHECKSTYLE@path=lib/checkstyle-5.5-all.jar
 library@CHECKSTYLE@urls=jar:http://sourceforge.net/projects/checkstyle/files/checkstyle/5.5/checkstyle-5.5-bin.zip/download!/checkstyle-5.5/checkstyle-5.5-all.jar
--- a/mxtool/mx.py	Wed Apr 16 18:57:14 2014 +0200
+++ b/mxtool/mx.py	Wed Apr 16 19:00:14 2014 +0200
@@ -406,7 +406,7 @@
     return path
 
 class Library(Dependency):
-    def __init__(self, suite, name, path, mustExist, urls, sha1, sourcePath, sourceUrls, sourceSha1):
+    def __init__(self, suite, name, path, mustExist, urls, sha1, sourcePath, sourceUrls, sourceSha1, deps):
         Dependency.__init__(self, suite, name)
         self.path = path.replace('/', os.sep)
         self.urls = urls
@@ -415,6 +415,7 @@
         self.sourcePath = sourcePath
         self.sourceUrls = sourceUrls
         self.sourceSha1 = sourceSha1
+        self.deps = deps
         for url in urls:
             if url.endswith('/') != self.path.endswith(os.sep):
                 abort('Path for dependency directory must have a URL ending with "/": path=' + self.path + ' url=' + url)
@@ -448,9 +449,9 @@
 
 
     def get_source_path(self, resolve):
-        if self.path is None:
+        if self.sourcePath is None:
             return None
-        path = _make_absolute(self.path, self.suite.dir)
+        path = _make_absolute(self.sourcePath, self.suite.dir)
         sha1path = path + '.sha1'
 
         return _download_file_with_sha1(self.name, path, self.sourceUrls, self.sourceSha1, sha1path, resolve, len(self.sourceUrls) != 0, sources=True)
@@ -461,9 +462,21 @@
             cp.append(path)
 
     def all_deps(self, deps, includeLibs, includeSelf=True, includeAnnotationProcessors=False):
-        if not includeLibs or not includeSelf:
+        """
+        Add the transitive set of dependencies for this library to the 'deps' list.
+        """
+        if not includeLibs:
+            return deps
+        childDeps = list(self.deps)
+        if self in deps:
             return deps
-        deps.append(self)
+        for name in childDeps:
+            assert name != self.name
+            dep = library(name)
+            if not dep in deps:
+                dep.all_deps(deps, includeLibs=includeLibs, includeAnnotationProcessors=includeAnnotationProcessors)
+        if not self in deps and includeSelf:
+            deps.append(self)
         return deps
 
 class HgConfig:
@@ -620,7 +633,8 @@
             sourcePath = attrs.pop('sourcePath', None)
             sourceUrls = pop_list(attrs, 'sourceUrls')
             sourceSha1 = attrs.pop('sourceSha1', None)
-            l = Library(self, name, path, mustExist, urls, sha1, sourcePath, sourceUrls, sourceSha1)
+            deps = pop_list(attrs, 'dependencies')
+            l = Library(self, name, path, mustExist, urls, sha1, sourcePath, sourceUrls, sourceSha1, deps)
             l.__dict__.update(attrs)
             self.libs.append(l)
 
@@ -1694,6 +1708,7 @@
     parser.add_argument('--force-javac', action='store_true', dest='javac', help='use javac despite ecj.jar is found or not')
     parser.add_argument('--jdt', help='path to ecj.jar, the Eclipse batch compiler (default: ' + defaultEcjPath + ')', default=defaultEcjPath, metavar='<path>')
     parser.add_argument('--jdt-warning-as-error', action='store_true', help='convert all Eclipse batch compiler warnings to errors')
+    parser.add_argument('--jdt-show-task-tags', action='store_true', help='show task tags as Eclipse batch compiler warnings')
     parser.add_argument('--error-prone', dest='error_prone', help='path to error-prone.jar', metavar='<path>')
 
     if suppliedParser:
@@ -1919,11 +1934,15 @@
                 if not exists(jdtProperties):
                     log('JDT properties file {0} not found'.format(jdtProperties))
                 else:
-                    # convert all warnings to errors
-                    if args.jdt_warning_as_error:
+                    with open(jdtProperties) as fp:
+                        origContent = fp.read()
+                        content = origContent
+                        if args.jdt_warning_as_error:
+                            content = content.replace('=warning', '=error')
+                        if not args.jdt_show_task_tags:
+                            content = content + '\norg.eclipse.jdt.core.compiler.problem.tasks=ignore'
+                    if origContent != content:
                         jdtPropertiesTmp = jdtProperties + '.tmp'
-                        with open(jdtProperties) as fp:
-                            content = fp.read().replace('=warning', '=error')
                         with open(jdtPropertiesTmp, 'w') as fp:
                             fp.write(content)
                         toBeDeleted.append(jdtPropertiesTmp)
@@ -2854,35 +2873,47 @@
         if exists(join(p.dir, 'plugin.xml')):  # eclipse plugin project
             out.element('classpathentry', {'kind' : 'con', 'path' : 'org.eclipse.pde.core.requiredPlugins'})
 
+        containerDeps = set()
+        libraryDeps = set()
+        projectDeps = set()
+
         for dep in p.all_deps([], True):
             if dep == p:
                 continue
-
             if dep.isLibrary():
                 if hasattr(dep, 'eclipse.container'):
-                    out.element('classpathentry', {'exported' : 'true', 'kind' : 'con', 'path' : getattr(dep, 'eclipse.container')})
-                elif hasattr(dep, 'eclipse.project'):
-                    out.element('classpathentry', {'combineaccessrules' : 'false', 'exported' : 'true', 'kind' : 'src', 'path' : '/' + getattr(dep, 'eclipse.project')})
+                    container = getattr(dep, 'eclipse.container')
+                    containerDeps.add(container)
+                    libraryDeps -= set(dep.all_deps([], True))
                 else:
-                    path = dep.path
-                    dep.get_path(resolve=True)
-                    if not path or (not exists(path) and not dep.mustExist):
-                        continue
-
-                    # Relative paths for "lib" class path entries have various semantics depending on the Eclipse
-                    # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's
-                    # safest to simply use absolute paths.
-                    path = _make_absolute(path, p.suite.dir)
-
-                    attributes = {'exported' : 'true', 'kind' : 'lib', 'path' : path}
-
-                    sourcePath = dep.get_source_path(resolve=True)
-                    if sourcePath is not None:
-                        attributes['sourcepath'] = sourcePath
-                    out.element('classpathentry', attributes)
-                    libFiles.append(path)
+                    libraryDeps.add(dep)
             else:
-                out.element('classpathentry', {'combineaccessrules' : 'false', 'exported' : 'true', 'kind' : 'src', 'path' : '/' + dep.name})
+                projectDeps.add(dep)
+
+        for dep in containerDeps:
+            out.element('classpathentry', {'exported' : 'true', 'kind' : 'con', 'path' : dep})
+
+        for dep in libraryDeps:
+            path = dep.path
+            dep.get_path(resolve=True)
+            if not path or (not exists(path) and not dep.mustExist):
+                continue
+
+            # Relative paths for "lib" class path entries have various semantics depending on the Eclipse
+            # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's
+            # safest to simply use absolute paths.
+            path = _make_absolute(path, p.suite.dir)
+
+            attributes = {'exported' : 'true', 'kind' : 'lib', 'path' : path}
+
+            sourcePath = dep.get_source_path(resolve=True)
+            if sourcePath is not None:
+                attributes['sourcepath'] = sourcePath
+            out.element('classpathentry', attributes)
+            libFiles.append(path)
+
+        for dep in projectDeps:
+            out.element('classpathentry', {'combineaccessrules' : 'false', 'exported' : 'true', 'kind' : 'src', 'path' : '/' + dep.name})
 
         out.element('classpathentry', {'kind' : 'output', 'path' : getattr(p, 'eclipse.output', 'bin')})
         out.close('classpath')
@@ -3612,7 +3643,7 @@
         moduleXml.open('module', attributes={'type': 'JAVA_MODULE', 'version': '4'})
 
         moduleXml.open('component', attributes={'name': 'NewModuleRootManager', 'LANGUAGE_LEVEL': intellijLanguageLevel, 'inherit-compiler-output': 'false'})
-        moduleXml.element('output', attributes={'url': 'file://$MODULE_DIR$/bin'}) # TODO use p.output_dir() ?
+        moduleXml.element('output', attributes={'url': 'file://$MODULE_DIR$/bin'})
         moduleXml.element('exclude-output')
 
         moduleXml.open('content', attributes={'url': 'file://$MODULE_DIR$'})
@@ -3676,12 +3707,12 @@
         libraryXml.open('component', attributes={'name': 'libraryTable'})
         libraryXml.open('library', attributes={'name': library.name})
         libraryXml.open('CLASSES')
-        libraryXml.element('root', attributes={'url': 'jar://$PROJECT_DIR$/' + os.path.relpath(library.path, suite.dir) + '!/'})
+        libraryXml.element('root', attributes={'url': 'jar://$PROJECT_DIR$/' + os.path.relpath(library.get_path(True), suite.dir) + '!/'})
         libraryXml.close('CLASSES')
         libraryXml.element('JAVADOC')
         if library.sourcePath:
             libraryXml.open('SOURCES')
-            libraryXml.element('root', attributes={'url': 'jar://$PROJECT_DIR$/' + os.path.relpath(library.sourcePath, suite.dir) + '!/'})
+            libraryXml.element('root', attributes={'url': 'jar://$PROJECT_DIR$/' + os.path.relpath(library.get_source_path(True), suite.dir) + '!/'})
             libraryXml.close('SOURCES')
         else:
             libraryXml.element('SOURCES')
@@ -3733,7 +3764,7 @@
     # Wite misc.xml for global JDK config
     miscXml = XMLDoc()
     miscXml.open('project', attributes={'version': '4'})
-    miscXml.element('component', attributes={'name': 'ProjectRootManager', 'version': '2', 'languagelevel': _complianceToIntellijLanguageLevel(java().javaCompliance), 'project-jdk-name': str(java().javaCompliance), 'project-jdk-type': 'JavaSDK'})
+    miscXml.element('component', attributes={'name': 'ProjectRootManager', 'version': '2', 'languageLevel': _complianceToIntellijLanguageLevel(java().javaCompliance), 'project-jdk-name': str(java().javaCompliance), 'project-jdk-type': 'JavaSDK'})
     miscXml.close('project')
     miscFile = join(ideaProjectDirectory, 'misc.xml')
     update_file(miscFile, miscXml.xml(indent='  ', newl='\n'))
@@ -4332,9 +4363,9 @@
                     buf = f.read(4096)
                     if not buf:
                         break
-                d.update(buf)
+                    d.update(buf)
             with open(path + '.' + suffix, 'w') as fp:
-                fp.write(d.hexdigest())
+                print >> fp, d.hexdigest()
             log('created ' + path + '.' + suffix)
 
     digest(args.sha1, path, hashlib.sha1, 'sha1')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/sparc/vm/graalCodeInstaller_sparc.cpp	Wed Apr 16 19:00:14 2014 +0200
@@ -0,0 +1,146 @@
+/*
+ * 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.
+ */
+
+#include "graal/graalCodeInstaller.hpp"
+#include "graal/graalCompiler.hpp"
+#include "graal/graalCompilerToVM.hpp"
+#include "graal/graalJavaAccess.hpp"
+
+jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
+  if (inst->is_call() || inst->is_jump()) {
+    return pc_offset + NativeCall::instruction_size;
+  } else if (inst->is_call_reg()) {
+    return pc_offset + NativeCallReg::instruction_size;
+  } else if (inst->is_sethi()) {
+    return pc_offset + NativeFarCall::instruction_size;
+  } else {
+    fatal("unsupported type of instruction for call site");
+    return 0;
+  }
+}
+
+void CodeInstaller::pd_patch_OopData(int pc_offset, oop data) {
+  address pc = _instructions->start() + pc_offset;
+  Handle obj = OopData::object(data);
+  jobject value = JNIHandles::make_local(obj());
+  if (OopData::compressed(data)) {
+    fatal("unimplemented: narrow oop relocation");
+  } else {
+    NativeMovConstReg* move = nativeMovConstReg_at(pc);
+    move->set_data((intptr_t) value);
+
+    // We need two relocations:  one on the sethi and one on the add.
+    int oop_index = _oop_recorder->find_index(value);
+    RelocationHolder rspec = oop_Relocation::spec(oop_index);
+    _instructions->relocate(pc + NativeMovConstReg::sethi_offset, rspec);
+    _instructions->relocate(pc + NativeMovConstReg::add_offset, rspec);
+  }
+}
+
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, oop data) {
+  address pc = _instructions->start() + pc_offset;
+  jint offset = DataSectionReference::offset(data);
+
+  NativeMovRegMem* load = nativeMovRegMem_at(pc);
+  int disp = _constants_size + pc_offset - offset - BytesPerInstWord;
+  load->set_offset(-disp);
+}
+
+void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
+  fatal("CodeInstaller::pd_relocate_CodeBlob - sparc unimp");
+}
+
+void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
+  address pc = (address) inst;
+  if (inst->is_call()) {
+    NativeCall* call = nativeCall_at(pc);
+    call->set_destination((address) foreign_call_destination);
+    _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec());
+  } else if (inst->is_sethi()) {
+    NativeJump* jump = nativeJump_at(pc);
+    jump->set_jump_destination((address) foreign_call_destination);
+    _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec());
+  } else {
+    fatal(err_msg("unknown call or jump instruction at %p", pc));
+  }
+  TRACE_graal_3("relocating (foreign call) at %p", inst);
+}
+
+void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) {
+#ifdef ASSERT
+  Method* method = NULL;
+  // we need to check, this might also be an unresolved method
+  if (hotspot_method->is_a(HotSpotResolvedJavaMethod::klass())) {
+    method = getMethodFromHotSpotMethod(hotspot_method);
+  }
+#endif
+  switch (_next_call_type) {
+    case INLINE_INVOKE:
+      break;
+    case INVOKEVIRTUAL:
+    case INVOKEINTERFACE: {
+      assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_virtual_call_stub());
+      _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc));
+      break;
+    }
+    case INVOKESTATIC: {
+      assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_static_call_stub());
+      _instructions->relocate(call->instruction_address(), relocInfo::static_call_type);
+      break;
+    }
+    case INVOKESPECIAL: {
+      assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
+      _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type);
+      break;
+    }
+    default:
+      fatal("invalid _next_call_type value");
+      break;
+  }
+}
+
+void CodeInstaller::pd_relocate_poll(address pc, jint mark) {
+  switch (mark) {
+    case POLL_NEAR:
+      fatal("unimplemented");
+      break;
+    case POLL_FAR:
+      _instructions->relocate(pc, relocInfo::poll_type);
+      break;
+    case POLL_RETURN_NEAR:
+      fatal("unimplemented");
+      break;
+    case POLL_RETURN_FAR:
+      _instructions->relocate(pc, relocInfo::poll_return_type);
+      break;
+    default:
+      fatal("invalid mark value");
+      break;
+  }
+}
--- a/src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp	Wed Apr 16 18:57:14 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,151 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef CPU_SPARC_VM_CODEINSTALLER_SPARC_HPP
-#define CPU_SPARC_VM_CODEINSTALLER_SPARC_HPP
-
-#include "graal/graalCompiler.hpp"
-#include "graal/graalCompilerToVM.hpp"
-#include "graal/graalJavaAccess.hpp"
-
-inline jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
-  if (inst->is_call() || inst->is_jump()) {
-    return pc_offset + NativeCall::instruction_size;
-  } else if (inst->is_call_reg()) {
-    return pc_offset + NativeCallReg::instruction_size;
-  } else if (inst->is_sethi()) {
-    return pc_offset + NativeFarCall::instruction_size;
-  } else {
-    fatal("unsupported type of instruction for call site");
-    return 0;
-  }
-}
-
-inline void CodeInstaller::pd_patch_OopData(int pc_offset, oop data) {
-  if (OopData::compressed(obj)) {
-    fatal("unimplemented: narrow oop relocation");
-  } else {
-    address pc = _instructions->start() + pc_offset;
-    Handle obj = OopData::object(data);
-    jobject value = JNIHandles::make_local(obj());
-
-    NativeMovConstReg* move = nativeMovConstReg_at(pc);
-    move->set_data((intptr_t) value);
-
-    // We need two relocations:  one on the sethi and one on the add.
-    int oop_index = _oop_recorder->find_index(value);
-    RelocationHolder rspec = oop_Relocation::spec(oop_index);
-    _instructions->relocate(pc + NativeMovConstReg::sethi_offset, rspec);
-    _instructions->relocate(pc + NativeMovConstReg::add_offset, rspec);
-  }
-}
-
-inline void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, oop data) {
-  address pc = _instructions->start() + pc_offset;
-  jint offset = DataSectionReference::offset(data);
-
-  NativeMovRegMem* load = nativeMovRegMem_at(pc);
-  int disp = _constants_size + pc_offset - offset - BytesPerInstWord;
-  load->set_offset(-disp);
-}
-
-inline void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
-  fatal("CodeInstaller::pd_relocate_CodeBlob - sparc unimp");
-}
-
-inline void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
-  address pc = (address) inst;
-  if (inst->is_call()) {
-    NativeCall* call = nativeCall_at(pc);
-    call->set_destination((address) foreign_call_destination);
-    _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec());
-  } else if (inst->is_sethi()) {
-    NativeJump* jump = nativeJump_at(pc);
-    jump->set_jump_destination((address) foreign_call_destination);
-    _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec());
-  } else {
-    fatal(err_msg("unknown call or jump instruction at %p", pc));
-  }
-  TRACE_graal_3("relocating (foreign call) at %p", inst);
-}
-
-inline void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) {
-#ifdef ASSERT
-  Method* method = NULL;
-  // we need to check, this might also be an unresolved method
-  if (hotspot_method->is_a(HotSpotResolvedJavaMethod::klass())) {
-    method = getMethodFromHotSpotMethod(hotspot_method);
-  }
-#endif
-  switch (_next_call_type) {
-    case INLINE_INVOKE:
-      break;
-    case INVOKEVIRTUAL:
-    case INVOKEINTERFACE: {
-      assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
-      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
-      call->set_destination(SharedRuntime::get_resolve_virtual_call_stub());
-      _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc));
-      break;
-    }
-    case INVOKESTATIC: {
-      assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
-      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
-      call->set_destination(SharedRuntime::get_resolve_static_call_stub());
-      _instructions->relocate(call->instruction_address(), relocInfo::static_call_type);
-      break;
-    }
-    case INVOKESPECIAL: {
-      assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
-      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
-      call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
-      _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type);
-      break;
-    }
-    default:
-      fatal("invalid _next_call_type value");
-      break;
-  }
-}
-
-inline void CodeInstaller::pd_relocate_poll(address pc, jint mark) {
-  switch (mark) {
-    case POLL_NEAR: {
-      fatal("unimplemented");
-    }
-    case POLL_FAR:
-      _instructions->relocate(pc, relocInfo::poll_type);
-      break;
-    case POLL_RETURN_NEAR: {
-      fatal("unimplemented");
-    }
-    case POLL_RETURN_FAR:
-      _instructions->relocate(pc, relocInfo::poll_return_type);
-      break;
-    default:
-      fatal("invalid mark value");
-      break;
-  }
-}
-
-#endif // CPU_SPARC_VM_CODEINSTALLER_SPARC_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/x86/vm/graalCodeInstaller_x86.cpp	Wed Apr 16 19:00:14 2014 +0200
@@ -0,0 +1,212 @@
+/*
+ * 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.
+ */
+
+#include "precompiled.hpp"
+#include "compiler/disassembler.hpp"
+#include "runtime/javaCalls.hpp"
+#include "graal/graalEnv.hpp"
+#include "graal/graalCompiler.hpp"
+#include "graal/graalCodeInstaller.hpp"
+#include "graal/graalJavaAccess.hpp"
+#include "graal/graalCompilerToVM.hpp"
+#include "graal/graalRuntime.hpp"
+#include "asm/register.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "code/vmreg.hpp"
+
+jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
+  if (inst->is_call() || inst->is_jump()) {
+    assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size");
+    return (pc_offset + NativeCall::instruction_size);
+  } else if (inst->is_mov_literal64()) {
+    // mov+call instruction pair
+    jint offset = pc_offset + NativeMovConstReg::instruction_size;
+    u_char* call = (u_char*) (_instructions->start() + offset);
+    assert((call[0] == 0x40 || call[0] == 0x41) && call[1] == 0xFF, "expected call with rex/rexb prefix byte");
+    offset += 3; /* prefix byte + opcode byte + modrm byte */
+    return (offset);
+  } else if (inst->is_call_reg()) {
+    // the inlined vtable stub contains a "call register" instruction
+    assert(method != NULL, "only valid for virtual calls");
+    return (pc_offset + ((NativeCallReg *) inst)->next_instruction_offset());
+  } else if (inst->is_cond_jump()) {
+    address pc = (address) (inst);
+    return pc_offset + (jint) (Assembler::locate_next_instruction(pc) - pc);
+  } else {
+    fatal("unsupported type of instruction for call site");
+    return 0;
+  }
+}
+
+void CodeInstaller::pd_patch_OopData(int pc_offset, oop data) {
+  address pc = _instructions->start() + pc_offset;
+  Handle obj = OopData::object(data);
+  jobject value = JNIHandles::make_local(obj());
+  if (OopData::compressed(data)) {
+    address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand);
+    int oop_index = _oop_recorder->find_index(value);
+    _instructions->relocate(pc, oop_Relocation::spec(oop_index), Assembler::narrow_oop_operand);
+    TRACE_graal_3("relocating (narrow oop constant) at %p/%p", pc, operand);
+  } else {
+    address operand = Assembler::locate_operand(pc, Assembler::imm_operand);
+    *((jobject*) operand) = value;
+    _instructions->relocate(pc, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
+    TRACE_graal_3("relocating (oop constant) at %p/%p", pc, operand);
+  }
+}
+
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, oop data) {
+  address pc = _instructions->start() + pc_offset;
+  jint offset = DataSectionReference::offset(data);
+
+  address operand = Assembler::locate_operand(pc, Assembler::disp32_operand);
+  address next_instruction = Assembler::locate_next_instruction(pc);
+  address dest = _constants->start() + offset;
+
+  long disp = dest - next_instruction;
+  assert(disp == (jint) disp, "disp doesn't fit in 32 bits");
+  *((jint*) operand) = (jint) disp;
+
+  _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand);
+  TRACE_graal_3("relocating at %p/%p with destination at %p (%d)", pc, operand, dest, offset);
+}
+
+void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
+  if (cb->is_nmethod()) {
+    nmethod* nm = (nmethod*) cb;
+    nativeJump_at((address)inst)->set_jump_destination(nm->verified_entry_point());
+  } else {
+    nativeJump_at((address)inst)->set_jump_destination(cb->code_begin());
+  }
+  _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
+}
+
+void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
+  address pc = (address) inst;
+  if (inst->is_call()) {
+    // NOTE: for call without a mov, the offset must fit a 32-bit immediate
+    //       see also CompilerToVM.getMaxCallTargetOffset()
+    NativeCall* call = nativeCall_at(pc);
+    call->set_destination((address) foreign_call_destination);
+    _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
+  } else if (inst->is_mov_literal64()) {
+    NativeMovConstReg* mov = nativeMovConstReg_at(pc);
+    mov->set_data((intptr_t) foreign_call_destination);
+    _instructions->relocate(mov->instruction_address(), runtime_call_Relocation::spec(), Assembler::imm_operand);
+  } else if (inst->is_jump()) {
+    NativeJump* jump = nativeJump_at(pc);
+    jump->set_jump_destination((address) foreign_call_destination);
+    _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
+  } else if (inst->is_cond_jump()) {
+    address old_dest = nativeGeneralJump_at(pc)->jump_destination();
+    address disp = Assembler::locate_operand(pc, Assembler::call32_operand);
+    *(jint*) disp += ((address) foreign_call_destination) - old_dest;
+    _instructions->relocate(pc, runtime_call_Relocation::spec(), Assembler::call32_operand);
+  } else {
+    fatal("unsupported relocation for foreign call");
+  }
+
+  TRACE_graal_3("relocating (foreign call)  at %p", inst);
+}
+
+void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) {
+#ifdef ASSERT
+  Method* method = NULL;
+  // we need to check, this might also be an unresolved method
+  if (hotspot_method->is_a(HotSpotResolvedJavaMethod::klass())) {
+    method = getMethodFromHotSpotMethod(hotspot_method);
+  }
+#endif
+  switch (_next_call_type) {
+    case INLINE_INVOKE:
+      break;
+    case INVOKEVIRTUAL:
+    case INVOKEINTERFACE: {
+      assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
+
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_virtual_call_stub());
+      _instructions->relocate(call->instruction_address(),
+                                             virtual_call_Relocation::spec(_invoke_mark_pc),
+                                             Assembler::call32_operand);
+      break;
+    }
+    case INVOKESTATIC: {
+      assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
+
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_static_call_stub());
+      _instructions->relocate(call->instruction_address(),
+                                             relocInfo::static_call_type, Assembler::call32_operand);
+      break;
+    }
+    case INVOKESPECIAL: {
+      assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
+      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+      call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
+      _instructions->relocate(call->instruction_address(),
+                              relocInfo::opt_virtual_call_type, Assembler::call32_operand);
+      break;
+    }
+    default:
+      break;
+  }
+}
+
+static void relocate_poll_near(address pc) {
+  NativeInstruction* ni = nativeInstruction_at(pc);
+  int32_t* disp = (int32_t*) Assembler::locate_operand(pc, Assembler::disp32_operand);
+  int32_t offset = *disp; // The Java code installed the polling page offset into the disp32 operand
+  intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni;
+  *disp = (int32_t)new_disp;
+}
+
+
+void CodeInstaller::pd_relocate_poll(address pc, jint mark) {
+  switch (mark) {
+    case POLL_NEAR: {
+      relocate_poll_near(pc);
+      _instructions->relocate(pc, relocInfo::poll_type, Assembler::disp32_operand);
+      break;
+    }
+    case POLL_FAR:
+      // This is a load from a register so there is no relocatable operand.
+      // We just have to ensure that the format is not disp32_operand
+      // so that poll_Relocation::fix_relocation_after_move does the right
+      // thing (i.e. ignores this relocation record)
+      _instructions->relocate(pc, relocInfo::poll_type, Assembler::imm_operand);
+      break;
+    case POLL_RETURN_NEAR: {
+      relocate_poll_near(pc);
+      _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::disp32_operand);
+      break;
+    }
+    case POLL_RETURN_FAR:
+      // see comment above for POLL_FAR
+      _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::imm_operand);
+      break;
+    default:
+      fatal("invalid mark value");
+      break;
+  }
+}
--- a/src/cpu/x86/vm/graalCodeInstaller_x86.hpp	Wed Apr 16 18:57:14 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,228 +0,0 @@
-/*
- * 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.
- */
-#ifndef CPU_X86_VM_CODEINSTALLER_X86_HPP
-#define CPU_X86_VM_CODEINSTALLER_X86_HPP
-
-#include "compiler/disassembler.hpp"
-#include "runtime/javaCalls.hpp"
-#include "graal/graalEnv.hpp"
-#include "graal/graalCompiler.hpp"
-#include "graal/graalCodeInstaller.hpp"
-#include "graal/graalJavaAccess.hpp"
-#include "graal/graalCompilerToVM.hpp"
-#include "graal/graalRuntime.hpp"
-#include "asm/register.hpp"
-#include "classfile/vmSymbols.hpp"
-#include "code/vmreg.hpp"
-
-inline jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
-  if (inst->is_call() || inst->is_jump()) {
-    assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size");
-    return (pc_offset + NativeCall::instruction_size);
-  } else if (inst->is_mov_literal64()) {
-    // mov+call instruction pair
-    jint offset = pc_offset + NativeMovConstReg::instruction_size;
-    u_char* call = (u_char*) (_instructions->start() + offset);
-    assert((call[0] == 0x40 || call[0] == 0x41) && call[1] == 0xFF, "expected call with rex/rexb prefix byte");
-    offset += 3; /* prefix byte + opcode byte + modrm byte */
-    return (offset);
-  } else if (inst->is_call_reg()) {
-    // the inlined vtable stub contains a "call register" instruction
-    assert(method != NULL, "only valid for virtual calls");
-    return (pc_offset + ((NativeCallReg *) inst)->next_instruction_offset());
-  } else if (inst->is_cond_jump()) {
-    address pc = (address) (inst);
-    return pc_offset + (jint) (Assembler::locate_next_instruction(pc) - pc);
-  } else {
-    fatal("unsupported type of instruction for call site");
-    return 0;
-  }
-}
-
-inline bool check_metaspace_data(address pc, oop data) {
-  jlong value = MetaspaceData::value(data);
-  address operand = Assembler::locate_operand(pc, Assembler::imm_operand);
-  if (MetaspaceData::compressed(data)) {
-    assert(*((jint*) operand) == value, err_msg("wrong compressed metaspace pointer: %p != %p", *((jint*) operand), value));
-  } else {
-    assert(*((jlong*) operand) == value, err_msg("wrong metaspace pointer: %p != %p", *((jlong*) operand), value));
-  }
-  return true;
-}
-
-inline void CodeInstaller::pd_patch_OopData(int pc_offset, oop data) {
-  address pc = _instructions->start() + pc_offset;
-
-  Handle obj = OopData::object(data);
-  jobject value = JNIHandles::make_local(obj());
-  if (OopData::compressed(data)) {
-    address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand);
-    int oop_index = _oop_recorder->find_index(value);
-    _instructions->relocate(pc, oop_Relocation::spec(oop_index), Assembler::narrow_oop_operand);
-    TRACE_graal_3("relocating (narrow oop constant) at %p/%p", pc, operand);
-  } else {
-    address operand = Assembler::locate_operand(pc, Assembler::imm_operand);
-    *((jobject*) operand) = value;
-    _instructions->relocate(pc, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
-    TRACE_graal_3("relocating (oop constant) at %p/%p", pc, operand);
-  }
-}
-
-inline void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, oop data) {
-  address pc = _instructions->start() + pc_offset;
-  jint offset = DataSectionReference::offset(data);
-
-  address operand = Assembler::locate_operand(pc, Assembler::disp32_operand);
-  address next_instruction = Assembler::locate_next_instruction(pc);
-  address dest = _constants->start() + offset;
-
-  long disp = dest - next_instruction;
-  assert(disp == (jint) disp, "disp doesn't fit in 32 bits");
-  *((jint*) operand) = (jint) disp;
-
-  _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand);
-  TRACE_graal_3("relocating at %p/%p with destination at %p (%d)", pc, operand, dest, offset);
-}
-
-inline void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
-  if (cb->is_nmethod()) {
-    nmethod* nm = (nmethod*) cb;
-    nativeJump_at((address)inst)->set_jump_destination(nm->verified_entry_point());
-  } else {
-    nativeJump_at((address)inst)->set_jump_destination(cb->code_begin());
-  }
-  _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
-}
-
-inline void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
-  address pc = (address) inst;
-  if (inst->is_call()) {
-    // NOTE: for call without a mov, the offset must fit a 32-bit immediate
-    //       see also CompilerToVM.getMaxCallTargetOffset()
-    NativeCall* call = nativeCall_at(pc);
-    call->set_destination((address) foreign_call_destination);
-    _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
-  } else if (inst->is_mov_literal64()) {
-    NativeMovConstReg* mov = nativeMovConstReg_at(pc);
-    mov->set_data((intptr_t) foreign_call_destination);
-    _instructions->relocate(mov->instruction_address(), runtime_call_Relocation::spec(), Assembler::imm_operand);
-  } else if (inst->is_jump()) {
-    NativeJump* jump = nativeJump_at(pc);
-    jump->set_jump_destination((address) foreign_call_destination);
-    _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
-  } else if (inst->is_cond_jump()) {
-    address old_dest = nativeGeneralJump_at(pc)->jump_destination();
-    address disp = Assembler::locate_operand(pc, Assembler::call32_operand);
-    *(jint*) disp += ((address) foreign_call_destination) - old_dest;
-    _instructions->relocate(pc, runtime_call_Relocation::spec(), Assembler::call32_operand);
-  } else {
-    fatal("unsupported relocation for foreign call");
-  }
-
-  TRACE_graal_3("relocating (foreign call)  at %p", inst);
-}
-
-inline void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) {
-#ifdef ASSERT
-  Method* method = NULL;
-  // we need to check, this might also be an unresolved method
-  if (hotspot_method->is_a(HotSpotResolvedJavaMethod::klass())) {
-    method = getMethodFromHotSpotMethod(hotspot_method);
-  }
-#endif
-  switch (_next_call_type) {
-    case INLINE_INVOKE:
-      break;
-    case INVOKEVIRTUAL:
-    case INVOKEINTERFACE: {
-      assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
-
-      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
-      call->set_destination(SharedRuntime::get_resolve_virtual_call_stub());
-      _instructions->relocate(call->instruction_address(),
-                                             virtual_call_Relocation::spec(_invoke_mark_pc),
-                                             Assembler::call32_operand);
-      break;
-    }
-    case INVOKESTATIC: {
-      assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
-
-      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
-      call->set_destination(SharedRuntime::get_resolve_static_call_stub());
-      _instructions->relocate(call->instruction_address(),
-                                             relocInfo::static_call_type, Assembler::call32_operand);
-      break;
-    }
-    case INVOKESPECIAL: {
-      assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
-      NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
-      call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
-      _instructions->relocate(call->instruction_address(),
-                              relocInfo::opt_virtual_call_type, Assembler::call32_operand);
-      break;
-    }
-    default:
-      break;
-  }
-}
-
-static void relocate_poll_near(address pc) {
-  NativeInstruction* ni = nativeInstruction_at(pc);
-  int32_t* disp = (int32_t*) Assembler::locate_operand(pc, Assembler::disp32_operand);
-  int32_t offset = *disp; // The Java code installed the polling page offset into the disp32 operand
-  intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni;
-  *disp = (int32_t)new_disp;
-}
-
-
-inline void CodeInstaller::pd_relocate_poll(address pc, jint mark) {
-  switch (mark) {
-    case POLL_NEAR: {
-      relocate_poll_near(pc);
-      _instructions->relocate(pc, relocInfo::poll_type, Assembler::disp32_operand);
-      break;
-    }
-    case POLL_FAR:
-      // This is a load from a register so there is no relocatable operand.
-      // We just have to ensure that the format is not disp32_operand
-      // so that poll_Relocation::fix_relocation_after_move does the right
-      // thing (i.e. ignores this relocation record)
-      _instructions->relocate(pc, relocInfo::poll_type, Assembler::imm_operand);
-      break;
-    case POLL_RETURN_NEAR: {
-      relocate_poll_near(pc);
-      _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::disp32_operand);
-      break;
-    }
-    case POLL_RETURN_FAR:
-      // see comment above for MARK_POLL_FAR
-      _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::imm_operand);
-      break;
-    default:
-      fatal("invalid mark value");
-      break;
-  }
-}
-
-#endif // CPU_X86_VM_CODEINSTALLER_X86_HPP
-
--- a/src/share/vm/classfile/systemDictionary.hpp	Wed Apr 16 18:57:14 2014 +0200
+++ b/src/share/vm/classfile/systemDictionary.hpp	Wed Apr 16 19:00:14 2014 +0200
@@ -186,6 +186,9 @@
   /* Support for Graal */                                                                                                \
   do_klass(CompilerThread_klass,                  com_oracle_graal_compiler_CompilerThread,                     Opt) \
   do_klass(BitSet_klass,                          java_util_BitSet,                                             Opt) \
+  /* graal.graph */                                                                                                  \
+  do_klass(Node_klass,                            com_oracle_graal_graph_Node,                                  Opt) \
+  do_klass(NodeClass_klass,                       com_oracle_graal_graph_NodeClass,                             Opt) \
   /* graal.hotspot */                                                                                                \
   do_klass(HotSpotCompiledCode_klass,             com_oracle_graal_hotspot_HotSpotCompiledCode,                 Opt) \
   do_klass(HotSpotCompiledCode_Comment_klass,     com_oracle_graal_hotspot_HotSpotCompiledCode_Comment,         Opt) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Wed Apr 16 18:57:14 2014 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Wed Apr 16 19:00:14 2014 +0200
@@ -292,6 +292,9 @@
   /* Support for Graal */                                                                                                             \
   template(com_oracle_graal_compiler_CompilerThread,                 "com/oracle/graal/compiler/CompilerThread")                      \
   template(java_util_BitSet,	                                       "java/util/BitSet")                                              \
+  /* graal.graph */                                                                                                                   \
+  template(com_oracle_graal_graph_Node,                              "com/oracle/graal/graph/Node")                                   \
+  template(com_oracle_graal_graph_NodeClass,                         "com/oracle/graal/graph/NodeClass")                              \
   /* graal.hotspot */                                                                                                                 \
   template(com_oracle_graal_hotspot_HotSpotGraalRuntime,             "com/oracle/graal/hotspot/HotSpotGraalRuntime")                  \
   template(com_oracle_graal_hotspot_HotSpotKlassOop,                 "com/oracle/graal/hotspot/HotSpotKlassOop")                      \
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Wed Apr 16 18:57:14 2014 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Wed Apr 16 19:00:14 2014 +0200
@@ -130,20 +130,4 @@
  */
 Method* getMethodFromHotSpotMethod(oop hotspot_method);
 
-#ifdef TARGET_ARCH_x86
-# include "graalCodeInstaller_x86.hpp"
-#endif
-#ifdef TARGET_ARCH_sparc
-# include "graalCodeInstaller_sparc.hpp"
-#endif
-#ifdef TARGET_ARCH_zero
-# error
-#endif
-#ifdef TARGET_ARCH_arm
-# error
-#endif
-#ifdef TARGET_ARCH_ppc
-# error
-#endif
-
 #endif // SHARE_VM_GRAAL_GRAAL_CODE_INSTALLER_HPP
--- a/src/share/vm/graal/graalCompiler.cpp	Wed Apr 16 18:57:14 2014 +0200
+++ b/src/share/vm/graal/graalCompiler.cpp	Wed Apr 16 19:00:14 2014 +0200
@@ -101,12 +101,10 @@
       _external_deopt_i2c_entry = create_external_deopt_i2c();
 #ifdef COMPILERGRAAL
       bool bootstrap = FLAG_IS_DEFAULT(BootstrapGraal) ? !TieredCompilation : BootstrapGraal;
-      bool hostedOnly = false;
 #else
       bool bootstrap = false;
-      bool hostedOnly = true;
 #endif
-      VMToCompiler::startCompiler(bootstrap, hostedOnly);
+      VMToCompiler::startCompiler(bootstrap);
       _initialized = true;
       CompilationPolicy::completed_vm_startup();
       if (bootstrap) {
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Wed Apr 16 18:57:14 2014 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Wed Apr 16 19:00:14 2014 +0200
@@ -743,12 +743,6 @@
   return JNIHandles::make_local(klass->java_mirror());
 C2V_END
 
-C2V_VMENTRY(void, setNodeClass, (JNIEnv *env, jobject, jobject java_class_handle, jobject value))
-  oop java_class = JNIHandles::resolve(java_class_handle);
-  InstanceKlass* iklass = (InstanceKlass*) java_lang_Class::as_Klass(java_class);
-  iklass->set_graal_node_class(JNIHandles::resolve(value));
-C2V_END
-
 C2V_VMENTRY(jlong, readUnsafeKlassPointer, (JNIEnv *env, jobject, jobject o))
   oop resolved_o = JNIHandles::resolve(o);
   jlong klass = (jlong)(address)resolved_o->klass();
@@ -1102,7 +1096,6 @@
   {CC"reprofile",                                    CC"("METASPACE_METHOD")V",                                        FN_PTR(reprofile)},
   {CC"invalidateInstalledCode",                      CC"("INSTALLED_CODE")V",                                          FN_PTR(invalidateInstalledCode)},
   {CC"getJavaMirror",                                CC"("METASPACE_KLASS")"CLASS,                                     FN_PTR(getJavaMirror)},
-  {CC"setNodeClass",                                 CC"("CLASS NODE_CLASS")V",                                        FN_PTR(setNodeClass)},
   {CC"readUnsafeKlassPointer",                       CC"("OBJECT")J",                                                  FN_PTR(readUnsafeKlassPointer)},
   {CC"collectCounters",                              CC"()[J",                                                         FN_PTR(collectCounters)},
   {CC"getGPUs",                                      CC"()"STRING,                                                     FN_PTR(getGPUs)},
--- a/src/share/vm/graal/graalVMToCompiler.cpp	Wed Apr 16 18:57:14 2014 +0200
+++ b/src/share/vm/graal/graalVMToCompiler.cpp	Wed Apr 16 19:00:14 2014 +0200
@@ -144,15 +144,13 @@
   }
 }
 
-void VMToCompiler::startCompiler(jboolean bootstrap_enabled, jboolean hosted_only) {
+void VMToCompiler::startCompiler(jboolean bootstrap_enabled) {
   JavaThread* THREAD = JavaThread::current();
   JavaValue result(T_VOID);
   JavaCallArguments args;
   args.push_oop(instance());
   args.push_int(bootstrap_enabled);
-  args.push_int(hosted_only);
-  TempNewSymbol bool_bool_void = SymbolTable::new_symbol("(ZZ)V", CHECK);
-  JavaCalls::call_interface(&result, vmToCompilerKlass(), vmSymbols::startCompiler_name(), bool_bool_void, &args, THREAD);
+  JavaCalls::call_interface(&result, vmToCompilerKlass(), vmSymbols::startCompiler_name(), vmSymbols::bool_void_signature(), &args, THREAD);
   check_pending_exception("Error while calling startCompiler");
 }
 
--- a/src/share/vm/graal/graalVMToCompiler.hpp	Wed Apr 16 18:57:14 2014 +0200
+++ b/src/share/vm/graal/graalVMToCompiler.hpp	Wed Apr 16 19:00:14 2014 +0200
@@ -66,8 +66,8 @@
   // public abstract void shutdownCompiler();
   static void shutdownCompiler();
   
-  // public abstract void startCompiler(boolean bootstrapEnabled, boolean hostedOnly);
-  static void startCompiler(jboolean bootstrap_enabled, jboolean hosted_only);
+  // public abstract void startCompiler(boolean bootstrapEnabled);
+  static void startCompiler(jboolean bootstrap_enabled);
   
   // public abstract void bootstrap();
   static void bootstrap();
--- a/src/share/vm/oops/instanceKlass.cpp	Wed Apr 16 18:57:14 2014 +0200
+++ b/src/share/vm/oops/instanceKlass.cpp	Wed Apr 16 19:00:14 2014 +0200
@@ -1201,6 +1201,21 @@
     JavaValue result(T_VOID);
     JavaCalls::call(&result, h_method, &args, CHECK); // Static call (no args)
   }
+
+#ifdef GRAAL
+  if (this_oop->is_subtype_of(SystemDictionary::Node_klass())) {
+    if (this_oop() != SystemDictionary::Node_klass()) {
+      // Create the NodeClass for a Node subclass.
+      TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/Class;)Lcom/oracle/graal/graph/NodeClass;", CHECK);
+      JavaValue result(T_OBJECT);
+      JavaCalls::call_static(&result, SystemDictionary::NodeClass_klass(), vmSymbols::get_name(), sig, this_oop->java_mirror(), CHECK);
+      this_oop->set_graal_node_class((oop) result.get_jobject());
+    } else {
+      // A NodeClass cannot be created for Node due to checks in
+      // NodeClass.FieldScanner.scanField()
+    }
+  }
+#endif
 }
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/baseline_whitelist.txt	Wed Apr 16 19:00:14 2014 +0200
@@ -0,0 +1,19 @@
+com.oracle.graal.jtt.loop.Loop03
+com.oracle.graal.jtt.loop.Loop04
+com.oracle.graal.jtt.loop.Loop08
+com.oracle.graal.jtt.loop.Loop11
+com.oracle.graal.jtt.bytecode.BC_iadd
+com.oracle.graal.jtt.bytecode.BC_iadd2
+com.oracle.graal.jtt.bytecode.BC_iadd3
+com.oracle.graal.jtt.bytecode.BC_ifeq_2
+com.oracle.graal.jtt.bytecode.BC_ifeq_3
+com.oracle.graal.jtt.bytecode.BC_ifeq
+com.oracle.graal.jtt.bytecode.BC_aload_3
+com.oracle.graal.jtt.bytecode.BC_aload_2
+com.oracle.graal.jtt.bytecode.BC_aload_1
+com.oracle.graal.jtt.bytecode.BC_aload_0
+com.oracle.graal.jtt.bytecode.BC_areturn
+com.oracle.graal.jtt.bytecode.BC_freturn
+com.oracle.graal.jtt.bytecode.BC_iconst
+com.oracle.graal.jtt.bytecode.BC_ireturn
+com.oracle.graal.jtt.bytecode.BC_lreturn