changeset 19000:e7b6e7f19fd0

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Wed, 28 Jan 2015 03:28:31 +0100
parents 43baadc1913a (current diff) 9470dcef2d59 (diff)
children 5a79fa76b489
files graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/EdgesTest.java
diffstat 207 files changed, 1058 insertions(+), 927 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java	Wed Jan 28 03:28:31 2015 +0100
@@ -188,9 +188,6 @@
      */
     private static void checkClass(Class<?> c, MetaAccessProvider metaAccess) {
         if (Node.class.isAssignableFrom(c)) {
-            if (Modifier.isFinal(c.getModifiers())) {
-                throw new AssertionError(String.format("Node subclass %s must not be final", c.getName()));
-            }
             if (c.getAnnotation(NodeInfo.class) == null) {
                 throw new AssertionError(String.format("Node subclass %s requires %s annotation", c.getName(), NodeClass.class.getSimpleName()));
             }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NodePosIteratorTest.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NodePosIteratorTest.java	Wed Jan 28 03:28:31 2015 +0100
@@ -32,7 +32,7 @@
 public class NodePosIteratorTest extends GraalCompilerTest {
 
     @NodeInfo
-    static class TestNode extends Node {
+    static final class TestNode extends Node {
         @Successor Node s1;
         @Successor Node s2;
         @Successor NodeSuccessorList<Node> stail;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java	Wed Jan 28 03:28:31 2015 +0100
@@ -45,15 +45,15 @@
         AbstractEndNode trueEnd = graph.add(new EndNode());
         AbstractEndNode falseEnd = graph.add(new EndNode());
 
-        BeginNode trueBegin = graph.add(new BeginNode());
+        AbstractBeginNode trueBegin = graph.add(new BeginNode());
         trueBegin.setNext(trueEnd);
-        BeginNode falseBegin = graph.add(new BeginNode());
+        AbstractBeginNode falseBegin = graph.add(new BeginNode());
         falseBegin.setNext(falseEnd);
 
         IfNode ifNode = graph.add(new IfNode(null, trueBegin, falseBegin, 0.5));
         graph.start().setNext(ifNode);
 
-        MergeNode merge = graph.add(new MergeNode());
+        AbstractMergeNode merge = graph.add(new MergeNode());
         merge.addForwardEnd(trueEnd);
         merge.addForwardEnd(falseEnd);
         ReturnNode returnNode = graph.add(new ReturnNode(null));
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Wed Jan 28 03:28:31 2015 +0100
@@ -222,8 +222,8 @@
             TTY.print(" " + input.toString(Verbosity.Id));
         }
         TTY.println(")");
-        if (node instanceof MergeNode) {
-            for (PhiNode phi : ((MergeNode) node).phis()) {
+        if (node instanceof AbstractMergeNode) {
+            for (PhiNode phi : ((AbstractMergeNode) node).phis()) {
                 outputNode(phi);
             }
         }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Wed Jan 28 03:28:31 2015 +0100
@@ -177,7 +177,7 @@
     @SafeVarargs
     protected final void testPartialEscapeAnalysis(final String snippet, double expectedProbability, int expectedCount, Class<? extends Node>... invalidNodeClasses) {
         prepareGraph(snippet, false);
-        for (MergeNode merge : graph.getNodes(MergeNode.class)) {
+        for (AbstractMergeNode merge : graph.getNodes(AbstractMergeNode.class)) {
             merge.setStateAfter(null);
         }
         new DeadCodeEliminationPhase().apply(graph);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Wed Jan 28 03:28:31 2015 +0100
@@ -331,7 +331,7 @@
     }
 
     @Override
-    public void visitMerge(MergeNode x) {
+    public void visitMerge(AbstractMergeNode x) {
     }
 
     @Override
@@ -346,7 +346,7 @@
     public void visitLoopEnd(LoopEndNode x) {
     }
 
-    private void moveToPhi(MergeNode merge, AbstractEndNode pred) {
+    private void moveToPhi(AbstractMergeNode merge, AbstractEndNode pred) {
         if (Options.TraceLIRGeneratorLevel.getValue() >= 1) {
             TTY.println("MOVE TO PHI from " + pred + " to " + merge);
         }
@@ -592,7 +592,7 @@
     }
 
     @Override
-    public void emitOverflowCheckBranch(BeginNode overflowSuccessor, BeginNode next, Stamp stamp, double probability) {
+    public void emitOverflowCheckBranch(AbstractBeginNode overflowSuccessor, AbstractBeginNode next, Stamp stamp, double probability) {
         LIRKind cmpKind = getLIRGeneratorTool().getLIRKind(stamp);
         gen.emitOverflowCheckBranch(getLIRBlock(overflowSuccessor), getLIRBlock(next), cmpKind, probability);
     }
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeMapTest.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeMapTest.java	Wed Jan 28 03:28:31 2015 +0100
@@ -33,7 +33,7 @@
 public class NodeMapTest {
 
     @NodeInfo
-    static class TestNode extends Node {
+    static final class TestNode extends Node {
         protected TestNode() {
         }
     }
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeUsagesTests.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeUsagesTests.java	Wed Jan 28 03:28:31 2015 +0100
@@ -34,13 +34,13 @@
 public class NodeUsagesTests {
 
     @NodeInfo
-    static class Def extends Node {
+    static final class Def extends Node {
         protected Def() {
         }
     }
 
     @NodeInfo
-    static class Use extends Node {
+    static final class Use extends Node {
         @Input Def in0;
         @Input Def in1;
         @Input Def in2;
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Wed Jan 28 03:28:31 2015 +0100
@@ -624,7 +624,7 @@
 
     // Fully qualified annotation name is required to satisfy javac
     @com.oracle.graal.nodeinfo.NodeInfo
-    static class PlaceHolderNode extends Node {
+    static final class PlaceHolderNode extends Node {
         public PlaceHolderNode() {
         }
 
--- a/graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/DataPatchInConstantsTest.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/DataPatchInConstantsTest.java	Wed Jan 28 03:28:31 2015 +0100
@@ -153,7 +153,7 @@
     }
 
     @NodeInfo
-    private static class LoadThroughPatchNode extends FixedWithNextNode implements LIRLowerable {
+    private static final class LoadThroughPatchNode extends FixedWithNextNode implements LIRLowerable {
 
         @Input protected ValueNode input;
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -33,7 +33,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo
-public class AMD64RawNativeCallNode extends FixedWithNextNode implements LIRLowerable {
+public final class AMD64RawNativeCallNode extends FixedWithNextNode implements LIRLowerable {
 
     protected final JavaConstant functionPointer;
     @Input NodeInputList<ValueNode> args;
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/DataPatchTest.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/DataPatchTest.java	Wed Jan 28 03:28:31 2015 +0100
@@ -92,7 +92,7 @@
     }
 
     @NodeInfo
-    private static class ConstantFoldBarrier extends FloatingNode implements LIRLowerable {
+    private static final class ConstantFoldBarrier extends FloatingNode implements LIRLowerable {
 
         @Input protected ValueNode input;
 
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Wed Jan 28 03:28:31 2015 +0100
@@ -693,12 +693,12 @@
                 }
 
                 @Override
-                protected Boolean merge(MergeNode merge, List<Boolean> states) {
+                protected Boolean merge(AbstractMergeNode merge, List<Boolean> states) {
                     return false;
                 }
 
                 @Override
-                protected Boolean afterSplit(BeginNode node, Boolean oldState) {
+                protected Boolean afterSplit(AbstractBeginNode node, Boolean oldState) {
                     return false;
                 }
             };
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Wed Jan 28 03:28:31 2015 +0100
@@ -301,7 +301,7 @@
          * Anchor the read of the element klass to the cfg, because it is only valid when arrayClass
          * is an object class, which might not be the case in other parts of the compiled method.
          */
-        return graph.unique(new FloatingReadNode(arrayHub, location, null, KlassPointerStamp.klassNonNull(), BeginNode.prevBegin(anchor)));
+        return graph.unique(new FloatingReadNode(arrayHub, location, null, KlassPointerStamp.klassNonNull(), AbstractBeginNode.prevBegin(anchor)));
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -36,7 +36,7 @@
  * the entire execution of the associated method.
  */
 @NodeInfo
-public class AllocaNode extends FixedWithNextNode implements LIRLowerable {
+public final class AllocaNode extends FixedWithNextNode implements LIRLowerable {
 
     /**
      * The number of slots in block.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -38,7 +38,7 @@
  * check on the object.
  */
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
-public class BeginLockScopeNode extends AbstractMemoryCheckpoint implements LIRLowerable, MonitorEnter, MemoryCheckpoint.Single {
+public final class BeginLockScopeNode extends AbstractMemoryCheckpoint implements LIRLowerable, MonitorEnter, MemoryCheckpoint.Single {
 
     protected int lockDepth;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -32,7 +32,7 @@
  * Converts a compile-time constant Java string into a C string installed with the generated code.
  */
 @NodeInfo
-public class CStringNode extends FloatingNode implements LIRLowerable {
+public final class CStringNode extends FloatingNode implements LIRLowerable {
 
     protected final String string;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -36,7 +36,7 @@
  * @see ClassSubstitutions#cast(Class, Object)
  */
 @NodeInfo
-public class ClassCastNode extends MacroStateSplitNode implements Canonicalizable.Binary<ValueNode> {
+public final class ClassCastNode extends MacroStateSplitNode implements Canonicalizable.Binary<ValueNode> {
 
     public ClassCastNode(Invoke invoke) {
         super(invoke);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetClassLoader0Node.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetClassLoader0Node.java	Wed Jan 28 03:28:31 2015 +0100
@@ -38,7 +38,7 @@
  */
 @SuppressWarnings("javadoc")
 @NodeInfo
-public class ClassGetClassLoader0Node extends MacroStateSplitNode implements Canonicalizable {
+public final class ClassGetClassLoader0Node extends MacroStateSplitNode implements Canonicalizable {
 
     public ClassGetClassLoader0Node(Invoke invoke) {
         super(invoke);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetComponentTypeNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetComponentTypeNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -37,7 +37,7 @@
  * @see ClassSubstitutions#getComponentType(Class)
  */
 @NodeInfo
-public class ClassGetComponentTypeNode extends MacroNode implements Canonicalizable {
+public final class ClassGetComponentTypeNode extends MacroNode implements Canonicalizable {
 
     public ClassGetComponentTypeNode(Invoke invoke) {
         super(invoke);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetModifiersNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetModifiersNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -36,7 +36,7 @@
  * @see ClassSubstitutions#getModifiers(Class)
  */
 @NodeInfo
-public class ClassGetModifiersNode extends MacroNode implements Canonicalizable {
+public final class ClassGetModifiersNode extends MacroNode implements Canonicalizable {
 
     public ClassGetModifiersNode(Invoke invoke) {
         super(invoke);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetSuperclassNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetSuperclassNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -37,7 +37,7 @@
  * @see ClassSubstitutions#getSuperclass(Class)
  */
 @NodeInfo
-public class ClassGetSuperclassNode extends MacroNode implements Canonicalizable {
+public final class ClassGetSuperclassNode extends MacroNode implements Canonicalizable {
 
     public ClassGetSuperclassNode(Invoke invoke) {
         super(invoke);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsArrayNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsArrayNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -36,7 +36,7 @@
  * @see ClassSubstitutions#isArray(Class)
  */
 @NodeInfo
-public class ClassIsArrayNode extends MacroNode implements Canonicalizable {
+public final class ClassIsArrayNode extends MacroNode implements Canonicalizable {
 
     public ClassIsArrayNode(Invoke invoke) {
         super(invoke);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsAssignableFromNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsAssignableFromNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -36,7 +36,7 @@
  * @see ClassSubstitutions#isAssignableFrom(Class, Class)
  */
 @NodeInfo
-public class ClassIsAssignableFromNode extends MacroStateSplitNode implements Canonicalizable {
+public final class ClassIsAssignableFromNode extends MacroStateSplitNode implements Canonicalizable {
     public ClassIsAssignableFromNode(Invoke invoke) {
         super(invoke);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInstanceNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInstanceNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -38,7 +38,7 @@
  * @see ClassSubstitutions#isInstance(Class, Object)
  */
 @NodeInfo
-public class ClassIsInstanceNode extends MacroNode implements Canonicalizable {
+public final class ClassIsInstanceNode extends MacroNode implements Canonicalizable {
 
     public ClassIsInstanceNode(Invoke invoke) {
         super(invoke);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInterfaceNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInterfaceNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -36,7 +36,7 @@
  * @see ClassSubstitutions#isInterface(Class)
  */
 @NodeInfo
-public class ClassIsInterfaceNode extends MacroNode implements Canonicalizable {
+public final class ClassIsInterfaceNode extends MacroNode implements Canonicalizable {
 
     public ClassIsInterfaceNode(Invoke invoke) {
         super(invoke);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsPrimitiveNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsPrimitiveNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -36,7 +36,7 @@
  * @see ClassSubstitutions#isPrimitive(Class)
  */
 @NodeInfo
-public class ClassIsPrimitiveNode extends MacroNode implements Canonicalizable {
+public final class ClassIsPrimitiveNode extends MacroNode implements Canonicalizable {
 
     public ClassIsPrimitiveNode(Invoke invoke) {
         super(invoke);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -40,7 +40,7 @@
  * Compress or uncompress an oop or metaspace pointer.
  */
 @NodeInfo(nameTemplate = "{p#op/s}")
-public class CompressionNode extends UnaryNode implements ConvertNode, LIRLowerable {
+public final class CompressionNode extends UnaryNode implements ConvertNode, LIRLowerable {
 
     public enum CompressionOp {
         Compress,
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -38,7 +38,7 @@
  * Gets the address of the C++ JavaThread object for the current thread.
  */
 @NodeInfo
-public class CurrentJavaThreadNode extends FloatingNode implements LIRLowerable {
+public final class CurrentJavaThreadNode extends FloatingNode implements LIRLowerable {
 
     protected LIRKind wordKind;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -34,7 +34,7 @@
  * Intrinsic for getting the lock in the current {@linkplain BeginLockScopeNode lock scope}.
  */
 @NodeInfo
-public class CurrentLockNode extends FixedWithNextNode implements LIRLowerable {
+public final class CurrentLockNode extends FixedWithNextNode implements LIRLowerable {
 
     protected int lockDepth;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -39,7 +39,7 @@
  * A call to the runtime code {@code Deoptimization::fetch_unroll_info}.
  */
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
-public class DeoptimizationFetchUnrollInfoCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Multi {
+public final class DeoptimizationFetchUnrollInfoCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Multi {
 
     @Input SaveAllRegistersNode registerSaver;
     protected final ForeignCallsProvider foreignCalls;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -33,7 +33,7 @@
  * Removes the current frame and tail calls the uncommon trap routine.
  */
 @NodeInfo(shortName = "DeoptCaller", nameTemplate = "DeoptCaller {p#reason/s}")
-public class DeoptimizeCallerNode extends ControlSinkNode implements LIRLowerable {
+public final class DeoptimizeCallerNode extends ControlSinkNode implements LIRLowerable {
 
     protected final DeoptimizationAction action;
     protected final DeoptimizationReason reason;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -39,7 +39,7 @@
  * instruction.
  */
 @NodeInfo
-public class DimensionsNode extends FixedWithNextNode implements LIRLowerable {
+public final class DimensionsNode extends FixedWithNextNode implements LIRLowerable {
 
     protected final int rank;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -38,7 +38,7 @@
  * expected value or the compared against value instead of a boolean.
  */
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
-public class DirectCompareAndSwapNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single {
+public final class DirectCompareAndSwapNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single {
 
     @Input ValueNode object;
     @Input ValueNode offset;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePreWriteBarrier.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePreWriteBarrier.java	Wed Jan 28 03:28:31 2015 +0100
@@ -26,7 +26,7 @@
 import com.oracle.graal.nodes.*;
 
 @NodeInfo
-public class G1ArrayRangePreWriteBarrier extends ArrayRangeWriteBarrier {
+public final class G1ArrayRangePreWriteBarrier extends ArrayRangeWriteBarrier {
 
     public G1ArrayRangePreWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) {
         super(object, startIndex, length);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java	Wed Jan 28 03:28:31 2015 +0100
@@ -27,7 +27,7 @@
 import com.oracle.graal.nodes.extended.*;
 
 @NodeInfo
-public class G1PreWriteBarrier extends WriteBarrier implements DeoptimizingNode.DeoptBefore {
+public final class G1PreWriteBarrier extends WriteBarrier implements DeoptimizingNode.DeoptBefore {
 
     @OptionalInput(InputType.State) FrameState stateBefore;
     protected final boolean nullCheck;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ReferentFieldReadBarrier.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ReferentFieldReadBarrier.java	Wed Jan 28 03:28:31 2015 +0100
@@ -33,7 +33,7 @@
  * read barrier and consequently is added to the SATB queue if the concurrent marker is enabled.
  */
 @NodeInfo
-public class G1ReferentFieldReadBarrier extends WriteBarrier {
+public final class G1ReferentFieldReadBarrier extends WriteBarrier {
 
     protected final boolean doLoad;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -34,7 +34,7 @@
  * this is if the usage is not an attempt to dereference the value.
  */
 @NodeInfo
-public class GetObjectAddressNode extends FixedWithNextNode implements LIRLowerable {
+public final class GetObjectAddressNode extends FixedWithNextNode implements LIRLowerable {
 
     @Input ValueNode object;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -31,7 +31,7 @@
 import com.oracle.graal.nodes.*;
 
 @NodeInfo
-public class HotSpotIndirectCallTargetNode extends IndirectCallTargetNode {
+public final class HotSpotIndirectCallTargetNode extends IndirectCallTargetNode {
 
     @Input ValueNode metaspaceMethod;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LoadIndexedPointerNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LoadIndexedPointerNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -29,7 +29,7 @@
 import com.oracle.graal.nodes.java.*;
 
 @NodeInfo
-public class LoadIndexedPointerNode extends LoadIndexedNode {
+public final class LoadIndexedPointerNode extends LoadIndexedNode {
 
     public LoadIndexedPointerNode(Stamp stamp, ValueNode array, ValueNode index) {
         super(stamp, array, index, Kind.Illegal);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -35,7 +35,7 @@
  * Node that is used to maintain a stack based counter of how many locks are currently held.
  */
 @NodeInfo
-public class MonitorCounterNode extends FloatingNode implements LIRLowerable {
+public final class MonitorCounterNode extends FloatingNode implements LIRLowerable {
 
     public MonitorCounterNode() {
         super(null);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java	Wed Jan 28 03:28:31 2015 +0100
@@ -38,7 +38,7 @@
  * A call to the {@link NewArrayStub}.
  */
 @NodeInfo
-public class NewArrayStubCall extends DeoptimizingStubCall implements LIRLowerable {
+public final class NewArrayStubCall extends DeoptimizingStubCall implements LIRLowerable {
 
     private static final Stamp defaultStamp = StampFactory.objectNonNull();
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Wed Jan 28 03:28:31 2015 +0100
@@ -38,7 +38,7 @@
  * A call to the {@link NewInstanceStub}.
  */
 @NodeInfo
-public class NewInstanceStubCall extends DeoptimizingStubCall implements LIRLowerable {
+public final class NewInstanceStubCall extends DeoptimizingStubCall implements LIRLowerable {
 
     private static final Stamp defaultStamp = StampFactory.objectNonNull();
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java	Wed Jan 28 03:28:31 2015 +0100
@@ -38,7 +38,7 @@
  * Node implementing a call to {@code GraalRuntime::new_multi_array}.
  */
 @NodeInfo
-public class NewMultiArrayStubCall extends ForeignCallNode {
+public final class NewMultiArrayStubCall extends ForeignCallNode {
 
     private static final Stamp defaultStamp = StampFactory.objectNonNull();
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetAnchorNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetAnchorNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -37,7 +37,7 @@
 
     @Override
     public void simplify(SimplifierTool tool) {
-        BeginNode prevBegin = BeginNode.prevBegin(this);
+        AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(this);
         replaceAtUsages(InputType.Anchor, prevBegin);
         replaceAtUsages(InputType.Guard, prevBegin);
         if (hasNoUsages()) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -33,7 +33,7 @@
 import com.oracle.graal.replacements.nodes.*;
 
 @NodeInfo
-public class CallSiteTargetNode extends MacroStateSplitNode implements Canonicalizable, Lowerable {
+public final class CallSiteTargetNode extends MacroStateSplitNode implements Canonicalizable, Lowerable {
 
     public CallSiteTargetNode(Invoke invoke) {
         super(invoke);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CardTableAddressNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CardTableAddressNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -30,7 +30,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo
-public class CardTableAddressNode extends FloatingNode implements LIRLowerable {
+public final class CardTableAddressNode extends FloatingNode implements LIRLowerable {
 
     public CardTableAddressNode() {
         super(StampFactory.forKind(Kind.Long));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CardTableShiftNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CardTableShiftNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -30,7 +30,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo
-public class CardTableShiftNode extends FloatingNode implements LIRLowerable {
+public final class CardTableShiftNode extends FloatingNode implements LIRLowerable {
 
     public CardTableShiftNode() {
         super(StampFactory.intValue());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassGetHubNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassGetHubNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -42,7 +42,7 @@
  * {@link ReadNode#canonicalizeRead(ValueNode, LocationNode, ValueNode, CanonicalizerTool)}.
  */
 @NodeInfo
-public class ClassGetHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, ConvertNode {
+public final class ClassGetHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, ConvertNode {
     @Input protected ValueNode clazz;
 
     public ClassGetHubNode(ValueNode clazz) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompositeValueClassSubstitutions.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompositeValueClassSubstitutions.java	Wed Jan 28 03:28:31 2015 +0100
@@ -45,7 +45,7 @@
      * {@link Class} parameter.
      */
     @NodeInfo
-    public static class CompositeValueClassGetNode extends PureFunctionMacroNode {
+    public static final class CompositeValueClassGetNode extends PureFunctionMacroNode {
 
         public CompositeValueClassGetNode(Invoke invoke) {
             super(invoke);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -43,7 +43,7 @@
  * Node for invocation methods defined on the class {@link MethodHandle}.
  */
 @NodeInfo
-public class MethodHandleNode extends MacroStateSplitNode implements Simplifiable {
+public final class MethodHandleNode extends MacroStateSplitNode implements Simplifiable {
 
     // Replacement method data
     protected ResolvedJavaMethod replacementTargetMethod;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyCallNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyCallNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -39,7 +39,7 @@
 import com.oracle.graal.runtime.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
-public class ArrayCopyCallNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
+public final class ArrayCopyCallNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
 
     @Input ValueNode src;
     @Input ValueNode srcPos;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -38,7 +38,7 @@
 import com.oracle.graal.replacements.nodes.*;
 
 @NodeInfo
-public class ArrayCopyNode extends BasicArrayCopyNode implements Virtualizable, Lowerable {
+public final class ArrayCopyNode extends BasicArrayCopyNode implements Virtualizable, Lowerable {
 
     public ArrayCopyNode(Invoke invoke) {
         super(invoke);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -38,7 +38,7 @@
 import com.oracle.graal.word.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Memory, InputType.Value})
-public class CheckcastArrayCopyCallNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
+public final class CheckcastArrayCopyCallNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
 
     @Input ValueNode src;
     @Input ValueNode srcPos;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/HotSpotWordTypeRewriterPhase.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/HotSpotWordTypeRewriterPhase.java	Wed Jan 28 03:28:31 2015 +0100
@@ -156,7 +156,7 @@
          * The read must not float outside its block otherwise it may float above an explicit zero
          * check on its base address.
          */
-        read.setGuard(BeginNode.prevBegin(invoke.asNode()));
+        read.setGuard(AbstractBeginNode.prevBegin(invoke.asNode()));
         return read;
     }
 
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/ComputeLoopFrequenciesClosure.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/ComputeLoopFrequenciesClosure.java	Wed Jan 28 03:28:31 2015 +0100
@@ -45,13 +45,13 @@
     }
 
     @Override
-    protected Double merge(MergeNode merge, List<Double> states) {
+    protected Double merge(AbstractMergeNode merge, List<Double> states) {
         // a merge has the sum of all predecessor probabilities
         return states.stream().collect(Collectors.summingDouble(d -> d));
     }
 
     @Override
-    protected Double afterSplit(BeginNode node, Double oldState) {
+    protected Double afterSplit(AbstractBeginNode node, Double oldState) {
         // a control split splits up the probability
         ControlSplitNode split = (ControlSplitNode) node.predecessor();
         return oldState * split.probability(node);
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Jan 28 03:28:31 2015 +0100
@@ -299,7 +299,7 @@
             @Override
             protected void handleUnresolvedInstanceOf(JavaType type, ValueNode object) {
                 assert !graphBuilderConfig.eagerResolving();
-                BeginNode successor = currentGraph.add(new BeginNode());
+                AbstractBeginNode successor = currentGraph.add(new BeginNode());
                 DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved));
                 append(new IfNode(currentGraph.unique(new IsNullNode(object)), successor, deopt, 1));
                 lastInstr = successor;
@@ -609,7 +609,7 @@
                     return;
                 }
                 BytecodeExceptionNode exception = currentGraph.add(new BytecodeExceptionNode(metaAccess, NullPointerException.class));
-                BeginNode falseSucc = currentGraph.add(new BeginNode());
+                AbstractBeginNode falseSucc = currentGraph.add(new BeginNode());
                 append(new IfNode(currentGraph.unique(new IsNullNode(receiver)), exception, falseSucc, 0.01));
                 lastInstr = falseSucc;
 
@@ -619,7 +619,7 @@
 
             @Override
             protected void emitBoundsCheck(ValueNode index, ValueNode length) {
-                BeginNode trueSucc = currentGraph.add(new BeginNode());
+                AbstractBeginNode trueSucc = currentGraph.add(new BeginNode());
                 BytecodeExceptionNode exception = currentGraph.add(new BytecodeExceptionNode(metaAccess, ArrayIndexOutOfBoundsException.class, index));
                 append(new IfNode(currentGraph.unique(new IntegerBelowNode(index, length)), trueSucc, exception, 0.99));
                 lastInstr = trueSucc;
@@ -795,7 +795,7 @@
                     createInvoke(callTarget, resultType);
                 } else {
                     InvokeWithExceptionNode invoke = createInvokeWithException(callTarget, resultType);
-                    BeginNode beginNode = currentGraph.add(new KillingBeginNode(LocationIdentity.ANY_LOCATION));
+                    AbstractBeginNode beginNode = currentGraph.add(new KillingBeginNode(LocationIdentity.ANY_LOCATION));
                     invoke.setNext(beginNode);
                     lastInstr = beginNode;
                 }
@@ -1077,18 +1077,18 @@
                 assert currentBlock == null || currentBlock.getId() < block.getId() : "must not be backward branch";
                 assert block.firstInstruction.next() == null : "bytecodes already parsed for block";
 
-                if (block.firstInstruction instanceof BeginNode && !(block.firstInstruction instanceof MergeNode)) {
+                if (block.firstInstruction instanceof AbstractBeginNode && !(block.firstInstruction instanceof AbstractMergeNode)) {
                     /*
                      * This is the second time we see this block. Create the actual MergeNode and
                      * the End Node for the already existing edge. For simplicity, we leave the
                      * placeholder in the graph and just append the new nodes after the placeholder.
                      */
-                    BeginNode placeholder = (BeginNode) block.firstInstruction;
+                    AbstractBeginNode placeholder = (AbstractBeginNode) block.firstInstruction;
 
                     // The EndNode for the already existing edge.
                     AbstractEndNode end = currentGraph.add(new EndNode());
                     // The MergeNode that replaces the placeholder.
-                    MergeNode mergeNode = currentGraph.add(new MergeNode());
+                    AbstractMergeNode mergeNode = currentGraph.add(new MergeNode());
                     FixedNode next = placeholder.next();
 
                     if (placeholder.predecessor() instanceof ControlSplitNode) {
@@ -1104,7 +1104,7 @@
                     block.firstInstruction = mergeNode;
                 }
 
-                MergeNode mergeNode = (MergeNode) block.firstInstruction;
+                AbstractMergeNode mergeNode = (AbstractMergeNode) block.firstInstruction;
 
                 // The EndNode for the newly merged edge.
                 AbstractEndNode newEnd = currentGraph.add(new EndNode());
@@ -1121,9 +1121,9 @@
              * Returns a block begin node with the specified state. If the specified probability is
              * 0, the block deoptimizes immediately.
              */
-            private BeginNode createBlockTarget(double probability, BciBlock block, HIRFrameStateBuilder stateAfter) {
+            private AbstractBeginNode createBlockTarget(double probability, BciBlock block, HIRFrameStateBuilder stateAfter) {
                 FixedNode target = createTarget(probability, block, stateAfter);
-                BeginNode begin = BeginNode.begin(target);
+                AbstractBeginNode begin = BeginNode.begin(target);
 
                 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.";
@@ -1151,12 +1151,12 @@
                     parser.setCurrentFrameState(frameState);
                     currentBlock = block;
 
-                    if (lastInstr instanceof MergeNode) {
+                    if (lastInstr instanceof AbstractMergeNode) {
                         int bci = block.startBci;
                         if (block instanceof ExceptionDispatchBlock) {
                             bci = ((ExceptionDispatchBlock) block).deoptBci;
                         }
-                        ((MergeNode) lastInstr).setStateAfter(frameState.create(bci));
+                        ((AbstractMergeNode) lastInstr).setStateAfter(frameState.create(bci));
                     }
 
                     if (block == returnBlock) {
@@ -1355,7 +1355,7 @@
                         frameState.clearNonLiveLocals(currentBlock, liveness, false);
                     }
                     if (lastInstr instanceof StateSplit) {
-                        if (lastInstr.getClass() == BeginNode.class) {
+                        if (lastInstr instanceof BeginNode) {
                             // 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	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java	Wed Jan 28 03:28:31 2015 +0100
@@ -193,7 +193,7 @@
         return true;
     }
 
-    public void merge(MergeNode block, HIRFrameStateBuilder other) {
+    public void merge(AbstractMergeNode block, HIRFrameStateBuilder other) {
         assert isCompatibleWith(other);
 
         for (int i = 0; i < localsSize(); i++) {
@@ -208,7 +208,7 @@
         }
     }
 
-    private ValueNode merge(ValueNode currentValue, ValueNode otherValue, MergeNode block) {
+    private ValueNode merge(ValueNode currentValue, ValueNode otherValue, AbstractMergeNode block) {
         if (currentValue == null || currentValue.isDeleted()) {
             return null;
 
@@ -294,7 +294,7 @@
         }
     }
 
-    public void insertProxies(BeginNode begin) {
+    public void insertProxies(AbstractBeginNode begin) {
         for (int i = 0; i < localsSize(); i++) {
             ValueNode value = localAt(i);
             if (value != null) {
@@ -318,7 +318,7 @@
         }
     }
 
-    private ValuePhiNode createLoopPhi(MergeNode block, ValueNode value) {
+    private ValuePhiNode createLoopPhi(AbstractMergeNode block, ValueNode value) {
         if (value == null) {
             return null;
         }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/UnsafeAccess01.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/UnsafeAccess01.java	Wed Jan 28 03:28:31 2015 +0100
@@ -34,16 +34,28 @@
  */
 public class UnsafeAccess01 extends JTTTest {
 
-    private static class TestClass {
-        @SuppressWarnings("unused") private int field = 42;
+    private static int randomValue = 100;
+    private static final Unsafe unsafe;
+    private static final long offset;
+    private static Object staticObject = new TestClass();
+
+    static {
+        unsafe = getUnsafe();
+        Field field = null;
+        try {
+            field = TestClass.class.getDeclaredField("field");
+        } catch (NoSuchFieldException e) {
+        } catch (SecurityException e) {
+        }
+        offset = unsafe.objectFieldOffset(field);
     }
 
-    public static int test() throws SecurityException, NoSuchFieldException {
-        final Unsafe unsafe = getUnsafe();
+    private static class TestClass {
+        private int field = 42;
+    }
 
+    public static int test() {
         final TestClass object = new TestClass();
-        final Field field = TestClass.class.getDeclaredField("field");
-        final long offset = unsafe.objectFieldOffset(field);
         final int value = unsafe.getInt(object, offset);
         return value;
     }
@@ -63,4 +75,22 @@
         runTest("test");
     }
 
+    @Test
+    public void runDiamond() throws Throwable {
+        runTest("testDiamond");
+    }
+
+    public static int testDiamond() {
+
+        final Object object = staticObject;
+        final int oldValue = ((TestClass) object).field;
+
+        if (randomValue == 100) {
+            unsafe.putInt(object, offset, 41);
+        } else {
+            unsafe.putInt(object, offset, 40);
+        }
+        unsafe.putInt(object, offset, 42);
+        return oldValue;
+    }
 }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java	Wed Jan 28 03:28:31 2015 +0100
@@ -38,9 +38,9 @@
     private InductionVariable iv;
     private ValueNode end;
     private boolean oneOff;
-    private BeginNode body;
+    private AbstractBeginNode body;
 
-    CountedLoopInfo(LoopEx loop, InductionVariable iv, ValueNode end, boolean oneOff, BeginNode body) {
+    CountedLoopInfo(LoopEx loop, InductionVariable iv, ValueNode end, boolean oneOff, AbstractBeginNode body) {
         this.loop = loop;
         this.iv = iv;
         this.end = end;
@@ -118,7 +118,7 @@
         return oneOff;
     }
 
-    public BeginNode getBody() {
+    public AbstractBeginNode getBody() {
         return body;
     }
 
@@ -157,7 +157,7 @@
             }
             cond = graph.unique(new IntegerLessThanNode(end, v1));
         }
-        overflowGuard = graph.unique(new GuardNode(cond, BeginNode.prevBegin(loop.entryPoint()), DeoptimizationReason.LoopLimitCheck, DeoptimizationAction.InvalidateRecompile, true,
+        overflowGuard = graph.unique(new GuardNode(cond, AbstractBeginNode.prevBegin(loop.entryPoint()), DeoptimizationReason.LoopLimitCheck, DeoptimizationAction.InvalidateRecompile, true,
                         JavaConstant.NULL_POINTER)); // TODO gd: use speculation
         loop.loopBegin().setOverflowGuard(overflowGuard);
         return overflowGuard;
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Wed Jan 28 03:28:31 2015 +0100
@@ -230,8 +230,8 @@
         return data;
     }
 
-    public NodeBitMap nodesInLoopFrom(BeginNode point, BeginNode until) {
-        Collection<BeginNode> blocks = new LinkedList<>();
+    public NodeBitMap nodesInLoopFrom(AbstractBeginNode point, AbstractBeginNode until) {
+        Collection<AbstractBeginNode> blocks = new LinkedList<>();
         Collection<LoopExitNode> exits = new LinkedList<>();
         Queue<Block> work = new LinkedList<>();
         ControlFlowGraph cfg = loopsData().controlFlowGraph();
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Wed Jan 28 03:28:31 2015 +0100
@@ -150,13 +150,13 @@
         }
     }
 
-    protected static NodeBitMap computeNodes(Graph graph, Iterable<BeginNode> blocks) {
+    protected static NodeBitMap computeNodes(Graph graph, Iterable<AbstractBeginNode> blocks) {
         return computeNodes(graph, blocks, Collections.emptyList());
     }
 
-    protected static NodeBitMap computeNodes(Graph graph, Iterable<BeginNode> blocks, Iterable<LoopExitNode> earlyExits) {
+    protected static NodeBitMap computeNodes(Graph graph, Iterable<AbstractBeginNode> blocks, Iterable<LoopExitNode> earlyExits) {
         final NodeBitMap nodes = graph.createNodeBitMap();
-        for (BeginNode b : blocks) {
+        for (AbstractBeginNode b : blocks) {
             if (b.isDeleted()) {
                 continue;
             }
@@ -188,7 +188,7 @@
         }
 
         final NodeBitMap notloopNodes = graph.createNodeBitMap();
-        for (BeginNode b : blocks) {
+        for (AbstractBeginNode b : blocks) {
             if (b.isDeleted()) {
                 continue;
             }
@@ -245,19 +245,19 @@
         return false;
     }
 
-    public static NodeIterable<BeginNode> toHirBlocks(final Iterable<Block> blocks) {
-        return new NodeIterable<BeginNode>() {
+    public static NodeIterable<AbstractBeginNode> toHirBlocks(final Iterable<Block> blocks) {
+        return new NodeIterable<AbstractBeginNode>() {
 
-            public Iterator<BeginNode> iterator() {
+            public Iterator<AbstractBeginNode> iterator() {
                 final Iterator<Block> it = blocks.iterator();
-                return new Iterator<BeginNode>() {
+                return new Iterator<AbstractBeginNode>() {
 
                     @Override
                     public void remove() {
                         throw new UnsupportedOperationException();
                     }
 
-                    public BeginNode next() {
+                    public AbstractBeginNode next() {
                         return it.next().getBeginNode();
                     }
 
@@ -302,17 +302,17 @@
     protected void mergeEarlyExits() {
         assert isDuplicate();
         StructuredGraph graph = graph();
-        for (BeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().loop().getExits())) {
+        for (AbstractBeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().loop().getExits())) {
             LoopExitNode loopEarlyExit = (LoopExitNode) earlyExit;
             FixedNode next = loopEarlyExit.next();
             if (loopEarlyExit.isDeleted() || !this.original().contains(loopEarlyExit)) {
                 continue;
             }
-            BeginNode newEarlyExit = getDuplicatedNode(loopEarlyExit);
+            AbstractBeginNode newEarlyExit = getDuplicatedNode(loopEarlyExit);
             if (newEarlyExit == null) {
                 continue;
             }
-            MergeNode merge = graph.add(new MergeNode());
+            AbstractMergeNode merge = graph.add(new MergeNode());
             AbstractEndNode originalEnd = graph.add(new EndNode());
             AbstractEndNode newEnd = graph.add(new EndNode());
             merge.addForwardEnd(originalEnd);
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Wed Jan 28 03:28:31 2015 +0100
@@ -89,13 +89,13 @@
 
         patchNodes(dataFixBefore);
 
-        BeginNode end = mergeEnds();
+        AbstractBeginNode end = mergeEnds();
 
         mergeEarlyExits();
 
         original().patchPeeling(this);
 
-        BeginNode entry = getDuplicatedNode(loop.loopBegin());
+        AbstractBeginNode entry = getDuplicatedNode(loop.loopBegin());
         loop.entryPoint().replaceAtPredecessor(entry);
         end.setNext(loop.entryPoint());
     }
@@ -152,7 +152,7 @@
                     if (value != null) {
                         return value;
                     }
-                    BeginNode newValue = graph.add(new BeginNode());
+                    AbstractBeginNode newValue = graph.add(new BeginNode());
                     seenNode.put(original, newValue);
                     return newValue;
                 }
@@ -161,7 +161,7 @@
                     if (value != null) {
                         return value;
                     }
-                    BeginNode newValue = graph.add(new BeginNode());
+                    AbstractBeginNode newValue = graph.add(new BeginNode());
                     seenNode.put(original, newValue);
                     return newValue;
                 }
@@ -184,7 +184,7 @@
         // TODO (gd) ?
     }
 
-    private static PhiNode patchPhi(StructuredGraph graph, PhiNode phi, MergeNode merge) {
+    private static PhiNode patchPhi(StructuredGraph graph, PhiNode phi, AbstractMergeNode merge) {
         PhiNode ret;
         if (phi instanceof ValuePhiNode) {
             ret = new ValuePhiNode(phi.stamp(), merge);
@@ -291,7 +291,7 @@
         }
     }
 
-    private BeginNode mergeEnds() {
+    private AbstractBeginNode mergeEnds() {
         assert isDuplicate();
         List<AbstractEndNode> endsToMerge = new LinkedList<>();
         // map peel exits to the corresponding loop exits
@@ -305,7 +305,7 @@
             }
         }
         mergedInitializers = Node.newIdentityMap();
-        BeginNode newExit;
+        AbstractBeginNode newExit;
         StructuredGraph graph = graph();
         if (endsToMerge.size() == 1) {
             AbstractEndNode end = endsToMerge.get(0);
@@ -315,7 +315,7 @@
             end.safeDelete();
         } else {
             assert endsToMerge.size() > 1;
-            MergeNode newExitMerge = graph.add(new MergeNode());
+            AbstractMergeNode newExitMerge = graph.add(new MergeNode());
             newExit = newExitMerge;
             FrameState state = loopBegin.stateAfter();
             FrameState duplicateState = null;
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Wed Jan 28 03:28:31 2015 +0100
@@ -70,9 +70,9 @@
         double maxProbability = 0;
         for (ControlSplitNode controlSplit : controlSplits) {
             Block postDomBlock = loop.loopsData().controlFlowGraph().blockFor(controlSplit).getPostdominator();
-            BeginNode postDom = postDomBlock != null ? postDomBlock.getBeginNode() : null;
+            AbstractBeginNode postDom = postDomBlock != null ? postDomBlock.getBeginNode() : null;
             for (Node successor : controlSplit.successors()) {
-                BeginNode branch = (BeginNode) successor;
+                AbstractBeginNode branch = (AbstractBeginNode) successor;
                 // this may count twice because of fall-through in switches
                 inBranchTotal += loop.nodesInLoopFrom(branch, postDom).count();
                 double probability = controlSplit.probability(branch);
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Wed Jan 28 03:28:31 2015 +0100
@@ -89,21 +89,21 @@
         assert successors.hasNext();
         // original loop is used as first successor
         Position firstPosition = successors.nextPosition();
-        BeginNode originalLoopBegin = BeginNode.begin(originalLoop.entryPoint());
+        AbstractBeginNode originalLoopBegin = BeginNode.begin(originalLoop.entryPoint());
         firstPosition.set(newControlSplit, originalLoopBegin);
 
         while (successors.hasNext()) {
             Position position = successors.nextPosition();
             // create a new loop duplicate and connect it.
             LoopFragmentWhole duplicateLoop = originalLoop.duplicate();
-            BeginNode newBegin = BeginNode.begin(duplicateLoop.entryPoint());
+            AbstractBeginNode newBegin = BeginNode.begin(duplicateLoop.entryPoint());
             position.set(newControlSplit, newBegin);
 
             // For each cloned ControlSplitNode, simplify the proper path
             for (ControlSplitNode controlSplitNode : controlSplitNodeSet) {
                 ControlSplitNode duplicatedControlSplit = duplicateLoop.getDuplicatedNode(controlSplitNode);
                 if (duplicatedControlSplit.isAlive()) {
-                    BeginNode survivingSuccessor = (BeginNode) position.get(duplicatedControlSplit);
+                    AbstractBeginNode survivingSuccessor = (AbstractBeginNode) position.get(duplicatedControlSplit);
                     survivingSuccessor.replaceAtUsages(InputType.Guard, newBegin);
                     graph.removeSplitPropagate(duplicatedControlSplit, survivingSuccessor);
                 }
@@ -112,7 +112,7 @@
         // original loop is simplified last to avoid deleting controlSplitNode too early
         for (ControlSplitNode controlSplitNode : controlSplitNodeSet) {
             if (controlSplitNode.isAlive()) {
-                BeginNode survivingSuccessor = (BeginNode) firstPosition.get(controlSplitNode);
+                AbstractBeginNode survivingSuccessor = (AbstractBeginNode) firstPosition.get(controlSplitNode);
                 survivingSuccessor.replaceAtUsages(InputType.Guard, originalLoopBegin);
                 graph.removeSplitPropagate(controlSplitNode, survivingSuccessor);
             }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Wed Jan 28 03:28:31 2015 +0100
@@ -86,7 +86,7 @@
             sb.append(controlSplit).append(" [");
             NodePosIterator it = controlSplit.successors().iterator();
             while (it.hasNext()) {
-                sb.append(controlSplit.probability((BeginNode) it.next()));
+                sb.append(controlSplit.probability((AbstractBeginNode) it.next()));
                 if (it.hasNext()) {
                     sb.append(", ");
                 }
--- a/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeProcessor.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeProcessor.java	Wed Jan 28 03:28:31 2015 +0100
@@ -126,12 +126,15 @@
 
                 TypeElement typeElement = (TypeElement) element;
 
-                if (typeElement.getModifiers().contains(Modifier.FINAL)) {
-                    errorMessage(element, "%s annotated class must not be final", NodeInfo.class.getSimpleName());
-                    continue;
+                Set<Modifier> modifiers = typeElement.getModifiers();
+                if (!modifiers.contains(Modifier.FINAL) && !modifiers.contains(Modifier.ABSTRACT)) {
+                    // TODO(thomaswue): Reenable this check.
+                    // errorMessage(element, "%s annotated class must be either final or abstract",
+                    // NodeInfo.class.getSimpleName());
+                    // continue;
                 }
 
-                if (!typeElement.equals(verifier.Node) && !typeElement.getModifiers().contains(Modifier.ABSTRACT)) {
+                if (!typeElement.equals(verifier.Node) && !modifiers.contains(Modifier.ABSTRACT)) {
                     verifier.verify(typeElement);
                 }
             } catch (ElementException ee) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -0,0 +1,163 @@
+/*
+ * 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.compiler.common.type.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.util.*;
+
+@NodeInfo(allowedUsageTypes = {InputType.Guard, InputType.Anchor})
+public abstract class AbstractBeginNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, GuardingNode, AnchoringNode, IterableNodeType {
+
+    public AbstractBeginNode() {
+        super(StampFactory.forVoid());
+    }
+
+    public AbstractBeginNode(Stamp stamp) {
+        super(stamp);
+    }
+
+    @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) {
+        for (AbstractBeginNode begin : GraphUtil.predecessorIterable(from).filter(AbstractBeginNode.class)) {
+            return begin;
+        }
+        return null;
+    }
+
+    private void evacuateGuards(FixedNode evacuateFrom) {
+        if (!hasNoUsages()) {
+            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 AbstractMergeNode, "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(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();
+        }
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -41,8 +41,8 @@
         gen.visitEndNode(this);
     }
 
-    public MergeNode merge() {
-        return (MergeNode) usages().first();
+    public AbstractMergeNode merge() {
+        return (AbstractMergeNode) usages().first();
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -90,7 +90,7 @@
         DeoptimizeNode deopt = graph().add(new DeoptimizeNode(action, reason));
         deopt.setStateBefore(stateBefore());
         IfNode ifNode;
-        BeginNode noDeoptSuccessor;
+        AbstractBeginNode noDeoptSuccessor;
         if (negated) {
             ifNode = graph().add(new IfNode(condition, deopt, currentNext, 0));
             noDeoptSuccessor = ifNode.falseSuccessor();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMergeNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import static com.oracle.graal.graph.iterators.NodePredicates.*;
+
+import java.util.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.util.*;
+
+/**
+ * Denotes the merging of multiple control-flow paths.
+ */
+@NodeInfo(allowedUsageTypes = {InputType.Association})
+public abstract class AbstractMergeNode extends BeginStateSplitNode implements IterableNodeType, LIRLowerable {
+    protected AbstractMergeNode() {
+    }
+
+    @Input(InputType.Association) protected NodeInputList<AbstractEndNode> ends = new NodeInputList<>(this);
+
+    @Override
+    public void generate(NodeLIRBuilderTool gen) {
+        gen.visitMerge(this);
+    }
+
+    public int forwardEndIndex(AbstractEndNode end) {
+        return ends.indexOf(end);
+    }
+
+    public void addForwardEnd(AbstractEndNode end) {
+        ends.add(end);
+    }
+
+    public int forwardEndCount() {
+        return ends.size();
+    }
+
+    public AbstractEndNode forwardEndAt(int index) {
+        return ends.get(index);
+    }
+
+    @Override
+    public NodeIterable<AbstractEndNode> cfgPredecessors() {
+        return ends;
+    }
+
+    /**
+     * Determines if a given node is a phi whose {@linkplain PhiNode#merge() merge} is this node.
+     *
+     * @param value the instruction to test
+     * @return {@code true} if {@code value} is a phi and its merge is {@code this}
+     */
+    public boolean isPhiAtMerge(Node value) {
+        return value instanceof PhiNode && ((PhiNode) value).merge() == this;
+    }
+
+    /**
+     * Removes the given end from the merge, along with the entries corresponding to this end in the
+     * phis connected to the merge.
+     *
+     * @param pred the end to remove
+     */
+    public void removeEnd(AbstractEndNode pred) {
+        int predIndex = phiPredecessorIndex(pred);
+        assert predIndex != -1;
+        deleteEnd(pred);
+        for (PhiNode phi : phis().snapshot()) {
+            if (phi.isDeleted()) {
+                continue;
+            }
+            ValueNode removedValue = phi.valueAt(predIndex);
+            phi.removeInput(predIndex);
+            if (removedValue != null && removedValue.isAlive() && removedValue.hasNoUsages() && GraphUtil.isFloatingNode().apply(removedValue)) {
+                GraphUtil.killWithUnusedFloatingInputs(removedValue);
+            }
+        }
+    }
+
+    protected void deleteEnd(AbstractEndNode end) {
+        ends.remove(end);
+    }
+
+    public void clearEnds() {
+        ends.clear();
+    }
+
+    public NodeInputList<AbstractEndNode> forwardEnds() {
+        return ends;
+    }
+
+    public int phiPredecessorCount() {
+        return forwardEndCount();
+    }
+
+    public int phiPredecessorIndex(AbstractEndNode pred) {
+        return forwardEndIndex(pred);
+    }
+
+    public AbstractEndNode phiPredecessorAt(int index) {
+        return forwardEndAt(index);
+    }
+
+    public NodeIterable<PhiNode> phis() {
+        return this.usages().filter(PhiNode.class).filter(this::isPhiAtMerge);
+    }
+
+    @Override
+    public NodeIterable<Node> anchored() {
+        return super.anchored().filter(n -> !isPhiAtMerge(n));
+    }
+
+    /**
+     * This simplify method can deal with a null value for tool, so that it can be used outside of
+     * canonicalization.
+     */
+    @Override
+    public void simplify(SimplifierTool tool) {
+        FixedNode currentNext = next();
+        if (currentNext instanceof AbstractEndNode) {
+            AbstractEndNode origLoopEnd = (AbstractEndNode) currentNext;
+            AbstractMergeNode merge = origLoopEnd.merge();
+            if (merge instanceof LoopBeginNode && !(origLoopEnd instanceof LoopEndNode)) {
+                return;
+            }
+            // in order to move anchored values to the other merge we would need to check if the
+            // anchors are used by phis of the other merge
+            if (this.anchored().isNotEmpty()) {
+                return;
+            }
+            if (merge.stateAfter() == null && this.stateAfter() != null) {
+                // We hold a state, but the succeeding merge does not => do not combine.
+                return;
+            }
+            for (PhiNode phi : phis()) {
+                if (phi.usages().filter(isNotA(VirtualState.class)).and(node -> !merge.isPhiAtMerge(node)).isNotEmpty()) {
+                    return;
+                }
+            }
+            Debug.log("Split %s into ends for %s.", this, merge);
+            int numEnds = this.forwardEndCount();
+            for (int i = 0; i < numEnds - 1; i++) {
+                AbstractEndNode end = forwardEndAt(numEnds - 1 - i);
+                if (tool != null) {
+                    tool.addToWorkList(end);
+                }
+                AbstractEndNode newEnd;
+                if (merge instanceof LoopBeginNode) {
+                    newEnd = graph().add(new LoopEndNode((LoopBeginNode) merge));
+                } else {
+                    newEnd = graph().add(new EndNode());
+                    merge.addForwardEnd(newEnd);
+                }
+                for (PhiNode phi : merge.phis()) {
+                    ValueNode v = phi.valueAt(origLoopEnd);
+                    ValueNode newInput;
+                    if (isPhiAtMerge(v)) {
+                        PhiNode endPhi = (PhiNode) v;
+                        newInput = endPhi.valueAt(end);
+                    } else {
+                        newInput = v;
+                    }
+                    phi.addInput(newInput);
+                }
+                this.removeEnd(end);
+                end.replaceAtPredecessor(newEnd);
+                end.safeDelete();
+                if (tool != null) {
+                    tool.addToWorkList(newEnd.predecessor());
+                }
+            }
+            graph().reduceTrivialMerge(this);
+        } else if (currentNext instanceof ReturnNode) {
+            ReturnNode returnNode = (ReturnNode) currentNext;
+            if (anchored().isNotEmpty() || returnNode.getMemoryMap() != null) {
+                return;
+            }
+            List<PhiNode> phis = phis().snapshot();
+            for (PhiNode phi : phis) {
+                for (Node usage : phi.usages().filter(isNotA(FrameState.class))) {
+                    if (usage != returnNode) {
+                        return;
+                    }
+                }
+            }
+
+            ValuePhiNode returnValuePhi = returnNode.result() == null || !isPhiAtMerge(returnNode.result()) ? null : (ValuePhiNode) returnNode.result();
+            List<AbstractEndNode> endNodes = forwardEnds().snapshot();
+            for (AbstractEndNode end : endNodes) {
+                ReturnNode newReturn = graph().add(new ReturnNode(returnValuePhi == null ? returnNode.result() : returnValuePhi.valueAt(end)));
+                if (tool != null) {
+                    tool.addToWorkList(end.predecessor());
+                }
+                end.replaceAtPredecessor(newReturn);
+            }
+            GraphUtil.killCFG(this);
+            for (AbstractEndNode end : endNodes) {
+                end.safeDelete();
+            }
+            for (PhiNode phi : phis) {
+                if (phi.isAlive() && phi.hasNoUsages()) {
+                    GraphUtil.killWithUnusedFloatingInputs(phi);
+                }
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -22,21 +22,11 @@
  */
 package com.oracle.graal.nodes;
 
-import static com.oracle.graal.graph.iterators.NodePredicates.*;
-
-import java.util.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 
-import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.iterators.*;
-import com.oracle.graal.graph.spi.*;
-import com.oracle.graal.nodeinfo.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.util.*;
-
-@NodeInfo(allowedUsageTypes = {InputType.Guard, InputType.Anchor})
-public class BeginNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, GuardingNode, AnchoringNode, IterableNodeType {
+@NodeInfo
+public final class BeginNode extends AbstractBeginNode {
 
     public BeginNode() {
         super(StampFactory.forVoid());
@@ -46,127 +36,12 @@
         super(stamp);
     }
 
-    public static BeginNode begin(FixedNode with) {
-        if (with instanceof BeginNode) {
-            return (BeginNode) with;
+    public static AbstractBeginNode begin(FixedNode with) {
+        if (with instanceof AbstractBeginNode) {
+            return (AbstractBeginNode) 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) {
-        for (BeginNode begin : GraphUtil.predecessorIterable(from).filter(BeginNode.class)) {
-            return begin;
-        }
-        return null;
-    }
-
-    private void evacuateGuards(FixedNode evacuateFrom) {
-        if (!hasNoUsages()) {
-            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	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -26,14 +26,14 @@
 import com.oracle.graal.nodeinfo.*;
 
 /**
- * Base class for {@link BeginNode}s that are associated with a frame state.
+ * Base class for {@link AbstractBeginNode}s that are associated with a frame state.
  *
- * TODO (dnsimon) this not needed until {@link BeginNode} no longer implements {@link StateSplit}
+ * 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.
  */
 @NodeInfo
-public abstract class BeginStateSplitNode extends BeginNode implements StateSplit {
+public abstract class BeginStateSplitNode extends AbstractBeginNode implements StateSplit {
 
     @OptionalInput(InputType.State) protected FrameState stateAfter;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -46,7 +46,7 @@
  * inspect in the native debugger when the breakpoint is hit.
  */
 @NodeInfo
-public class BreakpointNode extends FixedWithNextNode implements LIRLowerable {
+public final class BreakpointNode extends FixedWithNextNode implements LIRLowerable {
 
     @Input NodeInputList<ValueNode> arguments;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -30,7 +30,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(nameTemplate = "ConditionAnchor(!={p#negated})", allowedUsageTypes = {InputType.Guard})
-public class ConditionAnchorNode extends FixedWithNextNode implements Canonicalizable.Unary<Node>, Lowerable, GuardingNode {
+public final class ConditionAnchorNode extends FixedWithNextNode implements Canonicalizable.Unary<Node>, Lowerable, GuardingNode {
 
     @Input(InputType.Condition) LogicNode condition;
     protected boolean negated;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -39,7 +39,7 @@
  * The {@code ConstantNode} represents a {@link Constant constant}.
  */
 @NodeInfo(shortName = "Const", nameTemplate = "Const({p#rawvalue})")
-public class ConstantNode extends FloatingNode implements LIRLowerable {
+public final class ConstantNode extends FloatingNode implements LIRLowerable {
 
     private static final DebugMetric ConstantNodes = Debug.metric("ConstantNodes");
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -37,5 +37,5 @@
         super(stamp);
     }
 
-    public abstract double probability(BeginNode successor);
+    public abstract double probability(AbstractBeginNode successor);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -27,7 +27,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}")
-public class DeoptimizeNode extends AbstractDeoptimizeNode implements Lowerable, LIRLowerable {
+public final class DeoptimizeNode extends AbstractDeoptimizeNode implements Lowerable, LIRLowerable {
 
     protected final DeoptimizationAction action;
     protected final DeoptimizationReason reason;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -29,7 +29,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo
-public class DynamicDeoptimizeNode extends AbstractDeoptimizeNode implements LIRLowerable, Lowerable, Canonicalizable {
+public final class DynamicDeoptimizeNode extends AbstractDeoptimizeNode implements LIRLowerable, Lowerable, Canonicalizable {
     @Input ValueNode actionAndReason;
     @Input ValueNode speculation;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -33,7 +33,7 @@
  * by the graph builder.
  */
 @NodeInfo(allowedUsageTypes = {InputType.Association})
-public class EntryMarkerNode extends BeginStateSplitNode implements IterableNodeType, Simplifiable, LIRLowerable {
+public final class EntryMarkerNode extends BeginStateSplitNode implements IterableNodeType, Simplifiable, LIRLowerable {
 
     public EntryMarkerNode() {
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -30,7 +30,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(nameTemplate = "FixedGuard(!={p#negated}) {p#reason/s}", allowedUsageTypes = {InputType.Guard})
-public class FixedGuardNode extends AbstractFixedGuardNode implements Lowerable, IterableNodeType {
+public final class FixedGuardNode extends AbstractFixedGuardNode implements Lowerable, IterableNodeType {
 
     public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action) {
         this(condition, deoptReason, action, false);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -35,12 +35,12 @@
 
     @OptionalInput(InputType.Guard) NodeInputList<ValueNode> values;
 
-    public GuardPhiNode(MergeNode merge) {
+    public GuardPhiNode(AbstractMergeNode merge) {
         super(StampFactory.forVoid(), merge);
         this.values = new NodeInputList<>(this);
     }
 
-    public GuardPhiNode(MergeNode merge, ValueNode[] values) {
+    public GuardPhiNode(AbstractMergeNode merge, ValueNode[] values) {
         super(StampFactory.forVoid(), merge);
         this.values = new NodeInputList<>(this, values);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -33,7 +33,7 @@
 
     @Input(InputType.Guard) GuardingNode value;
 
-    public GuardProxyNode(GuardingNode value, BeginNode proxyPoint) {
+    public GuardProxyNode(GuardingNode value, AbstractBeginNode proxyPoint) {
         super(StampFactory.forVoid(), proxyPoint);
         this.value = value;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -36,7 +36,7 @@
  * A node that changes the stamp of its input based on some condition being true.
  */
 @NodeInfo(nameTemplate = "GuardingPi(!={p#negated}) {p#reason/s}")
-public class GuardingPiNode extends FixedWithNextNode implements Lowerable, Virtualizable, Canonicalizable, ValueProxy {
+public final class GuardingPiNode extends FixedWithNextNode implements Lowerable, Virtualizable, Canonicalizable, ValueProxy {
 
     @Input ValueNode object;
     @Input(InputType.Condition) LogicNode condition;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -51,8 +51,8 @@
 
     private static final DebugMetric CORRECTED_PROBABILITIES = Debug.metric("CorrectedProbabilities");
 
-    @Successor BeginNode trueSuccessor;
-    @Successor BeginNode falseSuccessor;
+    @Successor AbstractBeginNode trueSuccessor;
+    @Successor AbstractBeginNode falseSuccessor;
     @Input(InputType.Condition) LogicNode condition;
     protected double trueSuccessorProbability;
 
@@ -69,7 +69,7 @@
         this(condition, BeginNode.begin(trueSuccessor), BeginNode.begin(falseSuccessor), trueSuccessorProbability);
     }
 
-    public IfNode(LogicNode condition, BeginNode trueSuccessor, BeginNode falseSuccessor, double trueSuccessorProbability) {
+    public IfNode(LogicNode condition, AbstractBeginNode trueSuccessor, AbstractBeginNode falseSuccessor, double trueSuccessorProbability) {
         super(StampFactory.forVoid());
         this.condition = condition;
         this.falseSuccessor = falseSuccessor;
@@ -82,7 +82,7 @@
      *
      * @return the true successor
      */
-    public BeginNode trueSuccessor() {
+    public AbstractBeginNode trueSuccessor() {
         return trueSuccessor;
     }
 
@@ -91,16 +91,16 @@
      *
      * @return the false successor
      */
-    public BeginNode falseSuccessor() {
+    public AbstractBeginNode falseSuccessor() {
         return falseSuccessor;
     }
 
-    public void setTrueSuccessor(BeginNode node) {
+    public void setTrueSuccessor(AbstractBeginNode node) {
         updatePredecessor(trueSuccessor, node);
         trueSuccessor = node;
     }
 
-    public void setFalseSuccessor(BeginNode node) {
+    public void setFalseSuccessor(AbstractBeginNode node) {
         updatePredecessor(falseSuccessor, node);
         falseSuccessor = node;
     }
@@ -111,7 +111,7 @@
      * @param istrue {@code true} if the true successor is requested, {@code false} otherwise
      * @return the corresponding successor
      */
-    public BeginNode successor(boolean istrue) {
+    public AbstractBeginNode successor(boolean istrue) {
         return istrue ? trueSuccessor : falseSuccessor;
     }
 
@@ -121,7 +121,7 @@
     }
 
     @Override
-    public double probability(BeginNode successor) {
+    public double probability(AbstractBeginNode successor) {
         return successor == trueSuccessor ? trueSuccessorProbability : 1 - trueSuccessorProbability;
     }
 
@@ -153,8 +153,8 @@
         }
 
         if (condition() instanceof LogicNegationNode) {
-            BeginNode trueSucc = trueSuccessor();
-            BeginNode falseSucc = falseSuccessor();
+            AbstractBeginNode trueSucc = trueSuccessor();
+            AbstractBeginNode falseSucc = falseSuccessor();
             setTrueSuccessor(null);
             setFalseSuccessor(null);
             LogicNegationNode negation = (LogicNegationNode) condition();
@@ -190,7 +190,7 @@
         }
 
         if (falseSuccessor().hasNoUsages() && (!(falseSuccessor() instanceof LoopExitNode)) && falseSuccessor().next() instanceof IfNode) {
-            BeginNode intermediateBegin = falseSuccessor();
+            AbstractBeginNode intermediateBegin = falseSuccessor();
             IfNode nextIf = (IfNode) intermediateBegin.next();
             double probabilityB = (1.0 - this.trueSuccessorProbability) * nextIf.trueSuccessorProbability;
             if (this.trueSuccessorProbability < probabilityB) {
@@ -199,7 +199,7 @@
                 if (prepareForSwap(tool.getConstantReflection(), condition(), nextIf.condition(), this.trueSuccessorProbability, probabilityB)) {
                     // Reordering is allowed from (if1 => begin => if2) to (if2 => begin => if1).
                     assert intermediateBegin.next() == nextIf;
-                    BeginNode bothFalseBegin = nextIf.falseSuccessor();
+                    AbstractBeginNode bothFalseBegin = nextIf.falseSuccessor();
                     nextIf.setFalseSuccessor(null);
                     intermediateBegin.setNext(null);
                     this.setFalseSuccessor(null);
@@ -225,9 +225,9 @@
         assert trueSuccessor().hasNoUsages() && falseSuccessor().hasNoUsages();
         // push similar nodes upwards through the if, thereby deduplicating them
         do {
-            BeginNode trueSucc = trueSuccessor();
-            BeginNode falseSucc = falseSuccessor();
-            if (trueSucc.getClass() == BeginNode.class && falseSucc.getClass() == BeginNode.class && trueSucc.next() instanceof FixedWithNextNode && falseSucc.next() instanceof FixedWithNextNode) {
+            AbstractBeginNode trueSucc = trueSuccessor();
+            AbstractBeginNode falseSucc = falseSuccessor();
+            if (trueSucc instanceof BeginNode && falseSucc instanceof BeginNode && trueSucc.next() instanceof FixedWithNextNode && falseSucc.next() instanceof FixedWithNextNode) {
                 FixedWithNextNode trueNext = (FixedWithNextNode) trueSucc.next();
                 FixedWithNextNode falseNext = (FixedWithNextNode) falseSucc.next();
                 NodeClass nodeClass = trueNext.getNodeClass();
@@ -275,8 +275,8 @@
                 IfNode ifNode2 = (IfNode) falseSuccessor().next();
                 if (ifNode2.condition() instanceof IntegerLessThanNode) {
                     IntegerLessThanNode lessThan2 = (IntegerLessThanNode) ifNode2.condition();
-                    BeginNode falseSucc = ifNode2.falseSuccessor();
-                    BeginNode trueSucc = ifNode2.trueSuccessor();
+                    AbstractBeginNode falseSucc = ifNode2.falseSuccessor();
+                    AbstractBeginNode trueSucc = ifNode2.trueSuccessor();
                     IntegerBelowNode below = null;
                     /*
                      * Convert x >= 0 && x < positive which is represented as !(x < 0) && x <
@@ -286,7 +286,7 @@
                                     sameDestination(trueSuccessor(), ifNode2.falseSuccessor)) {
                         below = graph().unique(new IntegerBelowNode(lessThan2.getX(), lessThan2.getY()));
                         // swap direction
-                        BeginNode tmp = falseSucc;
+                        AbstractBeginNode tmp = falseSucc;
                         falseSucc = trueSucc;
                         trueSucc = tmp;
                     } else if (lessThan2.getY() == lessThan.getX() && sameDestination(trueSuccessor(), ifNode2.trueSuccessor)) {
@@ -326,7 +326,7 @@
      * Check it these two blocks end up at the same place. Meeting at the same merge, or
      * deoptimizing in the same way.
      */
-    private static boolean sameDestination(BeginNode succ1, BeginNode succ2) {
+    private static boolean sameDestination(AbstractBeginNode succ1, AbstractBeginNode succ2) {
         Node next1 = succ1.next();
         Node next2 = succ2.next();
         if (next1 instanceof EndNode && next2 instanceof EndNode) {
@@ -495,7 +495,7 @@
         if (trueSuccessor().next() instanceof AbstractEndNode && falseSuccessor().next() instanceof AbstractEndNode) {
             AbstractEndNode trueEnd = (AbstractEndNode) trueSuccessor().next();
             AbstractEndNode falseEnd = (AbstractEndNode) falseSuccessor().next();
-            MergeNode merge = trueEnd.merge();
+            AbstractMergeNode merge = trueEnd.merge();
             if (merge == falseEnd.merge() && trueSuccessor().anchored().isEmpty() && falseSuccessor().anchored().isEmpty()) {
                 PhiNode singlePhi = null;
                 int distinct = 0;
@@ -552,7 +552,7 @@
     }
 
     protected void removeThroughFalseBranch(SimplifierTool tool) {
-        BeginNode trueBegin = trueSuccessor();
+        AbstractBeginNode trueBegin = trueSuccessor();
         graph().removeSplitPropagate(this, trueBegin, tool);
         tool.addToWorkList(trueBegin);
     }
@@ -647,10 +647,10 @@
      * @return true if a transformation was made, false otherwise
      */
     private boolean removeIntermediateMaterialization(SimplifierTool tool) {
-        if (!(predecessor() instanceof MergeNode) || predecessor() instanceof LoopBeginNode) {
+        if (!(predecessor() instanceof AbstractMergeNode) || predecessor() instanceof LoopBeginNode) {
             return false;
         }
-        MergeNode merge = (MergeNode) predecessor();
+        AbstractMergeNode merge = (AbstractMergeNode) predecessor();
 
         if (!(condition() instanceof CompareNode)) {
             return false;
@@ -702,8 +702,8 @@
         List<AbstractEndNode> trueEnds = new ArrayList<>(mergePredecessors.size());
         Map<AbstractEndNode, ValueNode> phiValues = CollectionsFactory.newMap(mergePredecessors.size());
 
-        BeginNode oldFalseSuccessor = falseSuccessor();
-        BeginNode oldTrueSuccessor = trueSuccessor();
+        AbstractBeginNode oldFalseSuccessor = falseSuccessor();
+        AbstractBeginNode oldTrueSuccessor = trueSuccessor();
 
         setFalseSuccessor(null);
         setTrueSuccessor(null);
@@ -783,8 +783,8 @@
                 } else {
                     throw new GraalInternalError("Illegal state");
                 }
-            } else if (node instanceof MergeNode && !(node instanceof LoopBeginNode)) {
-                for (AbstractEndNode endNode : ((MergeNode) node).cfgPredecessors()) {
+            } else if (node instanceof AbstractMergeNode && !(node instanceof LoopBeginNode)) {
+                for (AbstractEndNode endNode : ((AbstractMergeNode) node).cfgPredecessors()) {
                     propagateZeroProbability(endNode);
                 }
                 return;
@@ -796,8 +796,8 @@
     private static boolean checkFrameState(FixedNode start) {
         FixedNode node = start;
         while (true) {
-            if (node instanceof MergeNode) {
-                MergeNode mergeNode = (MergeNode) node;
+            if (node instanceof AbstractMergeNode) {
+                AbstractMergeNode mergeNode = (AbstractMergeNode) node;
                 if (mergeNode.stateAfter() == null) {
                     return false;
                 } else {
@@ -840,7 +840,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, BeginNode successor, MergeNode oldMerge, SimplifierTool tool) {
+    private void connectEnds(List<AbstractEndNode> ends, Map<AbstractEndNode, ValueNode> phiValues, AbstractBeginNode successor, AbstractMergeNode oldMerge, SimplifierTool tool) {
         if (!ends.isEmpty()) {
             if (ends.size() == 1) {
                 AbstractEndNode end = ends.get(0);
@@ -850,7 +850,7 @@
             } else {
                 // Need a new phi in case the frame state is used by more than the merge being
                 // removed
-                MergeNode newMerge = graph().add(new MergeNode());
+                AbstractMergeNode newMerge = graph().add(new MergeNode());
                 PhiNode oldPhi = (PhiNode) oldMerge.usages().first();
                 PhiNode newPhi = graph().addWithoutUnique(new ValuePhiNode(oldPhi.stamp(), newMerge));
 
@@ -880,7 +880,7 @@
      * @return null if {@code node} is neither a {@link ConstantNode} nor a {@link PhiNode} whose
      *         input values are all constants
      */
-    public static Constant[] constantValues(ValueNode node, MergeNode merge, boolean allowNull) {
+    public static Constant[] constantValues(ValueNode node, AbstractMergeNode merge, boolean allowNull) {
         if (node.isConstant()) {
             JavaConstant[] result = new JavaConstant[merge.forwardEndCount()];
             Arrays.fill(result, node.asConstant());
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -37,8 +37,8 @@
 
     private static final double EXCEPTION_PROBA = 1e-5;
 
-    @Successor BeginNode next;
-    @Successor BeginNode exceptionEdge;
+    @Successor AbstractBeginNode next;
+    @Successor AbstractBeginNode exceptionEdge;
     @Input(InputType.Extension) CallTargetNode callTarget;
     @OptionalInput(InputType.State) FrameState stateDuring;
     @OptionalInput(InputType.State) FrameState stateAfter;
@@ -48,7 +48,7 @@
     protected boolean useForInlining;
     protected double exceptionProbability;
 
-    public InvokeWithExceptionNode(CallTargetNode callTarget, BeginNode exceptionEdge, int bci) {
+    public InvokeWithExceptionNode(CallTargetNode callTarget, AbstractBeginNode exceptionEdge, int bci) {
         super(callTarget.returnStamp());
         this.exceptionEdge = exceptionEdge;
         this.bci = bci;
@@ -58,20 +58,20 @@
         this.exceptionProbability = EXCEPTION_PROBA;
     }
 
-    public BeginNode exceptionEdge() {
+    public AbstractBeginNode exceptionEdge() {
         return exceptionEdge;
     }
 
-    public void setExceptionEdge(BeginNode x) {
+    public void setExceptionEdge(AbstractBeginNode x) {
         updatePredecessor(exceptionEdge, x);
         exceptionEdge = x;
     }
 
-    public BeginNode next() {
+    public AbstractBeginNode next() {
         return next;
     }
 
-    public void setNext(BeginNode x) {
+    public void setNext(AbstractBeginNode x) {
         updatePredecessor(next, x);
         next = x;
     }
@@ -164,7 +164,7 @@
     }
 
     public void killExceptionEdge() {
-        BeginNode edge = exceptionEdge();
+        AbstractBeginNode edge = exceptionEdge();
         setExceptionEdge(null);
         GraphUtil.killCFG(edge);
     }
@@ -201,7 +201,7 @@
     }
 
     @Override
-    public double probability(BeginNode successor) {
+    public double probability(AbstractBeginNode successor) {
         return successor == next ? 1 - exceptionProbability : exceptionProbability;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -27,7 +27,7 @@
 import com.oracle.graal.nodes.extended.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
-public class KillingBeginNode extends BeginNode implements MemoryCheckpoint.Single {
+public class KillingBeginNode extends AbstractBeginNode implements MemoryCheckpoint.Single {
 
     protected LocationIdentity locationIdentity;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -37,7 +37,7 @@
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo
-public class LoopBeginNode extends MergeNode implements IterableNodeType, LIRLowerable {
+public class LoopBeginNode extends AbstractMergeNode implements IterableNodeType, LIRLowerable {
 
     protected double loopFrequency;
     protected int nextEndIndex;
@@ -183,7 +183,7 @@
         canonicalizePhis(tool);
     }
 
-    public boolean isLoopExit(BeginNode begin) {
+    public boolean isLoopExit(AbstractBeginNode begin) {
         return begin instanceof LoopExitNode && ((LoopExitNode) begin).loopBegin() == this;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -44,7 +44,7 @@
     }
 
     @Override
-    public MergeNode merge() {
+    public AbstractMergeNode merge() {
         return loopBegin();
     }
 
@@ -80,7 +80,7 @@
 
     /**
      * Returns the 0-based index of this loop end. This is <b>not</b> the index into {@link PhiNode}
-     * values at the loop begin. Use {@link MergeNode#phiPredecessorIndex(AbstractEndNode)} for this
+     * values at the loop begin. Use {@link AbstractMergeNode#phiPredecessorIndex(AbstractEndNode)} for this
      * purpose.
      *
      * @return The 0-based index of this loop end.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopExitNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopExitNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -43,8 +43,8 @@
     @Override
     public void simplify(SimplifierTool tool) {
         Node prev = this.predecessor();
-        while (prev.getClass() == BeginNode.class && prev.hasNoUsages()) {
-            BeginNode begin = (BeginNode) prev;
+        while (prev instanceof BeginNode && prev.hasNoUsages()) {
+            AbstractBeginNode begin = (AbstractBeginNode) prev;
             prev = prev.predecessor();
             graph().removeFixed(begin);
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -36,7 +36,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Extension})
-public class MemoryMapNode extends FloatingNode implements MemoryMap, LIRLowerable {
+public final class MemoryMapNode extends FloatingNode implements MemoryMap, LIRLowerable {
 
     protected final List<LocationIdentity> locationIdentities;
     @Input(InputType.Memory) NodeInputList<ValueNode> nodes;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -32,18 +32,18 @@
  * Memory {@code PhiNode}s merge memory dependencies at control flow merges.
  */
 @NodeInfo(nameTemplate = "MemoryPhi({i#values}) {p#locationIdentity/s}", allowedUsageTypes = {InputType.Memory})
-public class MemoryPhiNode extends PhiNode implements MemoryNode {
+public final class MemoryPhiNode extends PhiNode implements MemoryNode {
 
     @Input(InputType.Memory) NodeInputList<ValueNode> values;
     protected final LocationIdentity locationIdentity;
 
-    public MemoryPhiNode(MergeNode merge, LocationIdentity locationIdentity) {
+    public MemoryPhiNode(AbstractMergeNode merge, LocationIdentity locationIdentity) {
         super(StampFactory.forVoid(), merge);
         this.locationIdentity = locationIdentity;
         this.values = new NodeInputList<>(this);
     }
 
-    public MemoryPhiNode(MergeNode merge, LocationIdentity locationIdentity, ValueNode[] values) {
+    public MemoryPhiNode(AbstractMergeNode merge, LocationIdentity locationIdentity, ValueNode[] values) {
         super(StampFactory.forVoid(), merge);
         this.locationIdentity = locationIdentity;
         this.values = new NodeInputList<>(this, values);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -22,211 +22,13 @@
  */
 package com.oracle.graal.nodes;
 
-import static com.oracle.graal.graph.iterators.NodePredicates.*;
-
-import java.util.*;
-
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.iterators.*;
-import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodeinfo.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.util.*;
 
 /**
  * Denotes the merging of multiple control-flow paths.
  */
-@NodeInfo(allowedUsageTypes = {InputType.Association})
-public class MergeNode extends BeginStateSplitNode implements IterableNodeType, LIRLowerable {
+@NodeInfo
+public final class MergeNode extends AbstractMergeNode {
     public MergeNode() {
     }
-
-    @Input(InputType.Association) protected NodeInputList<AbstractEndNode> ends = new NodeInputList<>(this);
-
-    @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.visitMerge(this);
-    }
-
-    public int forwardEndIndex(AbstractEndNode end) {
-        return ends.indexOf(end);
-    }
-
-    public void addForwardEnd(AbstractEndNode end) {
-        ends.add(end);
-    }
-
-    public int forwardEndCount() {
-        return ends.size();
-    }
-
-    public AbstractEndNode forwardEndAt(int index) {
-        return ends.get(index);
-    }
-
-    @Override
-    public NodeIterable<AbstractEndNode> cfgPredecessors() {
-        return ends;
-    }
-
-    /**
-     * Determines if a given node is a phi whose {@linkplain PhiNode#merge() merge} is this node.
-     *
-     * @param value the instruction to test
-     * @return {@code true} if {@code value} is a phi and its merge is {@code this}
-     */
-    public boolean isPhiAtMerge(Node value) {
-        return value instanceof PhiNode && ((PhiNode) value).merge() == this;
-    }
-
-    /**
-     * Removes the given end from the merge, along with the entries corresponding to this end in the
-     * phis connected to the merge.
-     *
-     * @param pred the end to remove
-     */
-    public void removeEnd(AbstractEndNode pred) {
-        int predIndex = phiPredecessorIndex(pred);
-        assert predIndex != -1;
-        deleteEnd(pred);
-        for (PhiNode phi : phis().snapshot()) {
-            if (phi.isDeleted()) {
-                continue;
-            }
-            ValueNode removedValue = phi.valueAt(predIndex);
-            phi.removeInput(predIndex);
-            if (removedValue != null && removedValue.isAlive() && removedValue.hasNoUsages() && GraphUtil.isFloatingNode().apply(removedValue)) {
-                GraphUtil.killWithUnusedFloatingInputs(removedValue);
-            }
-        }
-    }
-
-    protected void deleteEnd(AbstractEndNode end) {
-        ends.remove(end);
-    }
-
-    public void clearEnds() {
-        ends.clear();
-    }
-
-    public NodeInputList<AbstractEndNode> forwardEnds() {
-        return ends;
-    }
-
-    public int phiPredecessorCount() {
-        return forwardEndCount();
-    }
-
-    public int phiPredecessorIndex(AbstractEndNode pred) {
-        return forwardEndIndex(pred);
-    }
-
-    public AbstractEndNode phiPredecessorAt(int index) {
-        return forwardEndAt(index);
-    }
-
-    public NodeIterable<PhiNode> phis() {
-        return this.usages().filter(PhiNode.class).filter(this::isPhiAtMerge);
-    }
-
-    @Override
-    public NodeIterable<Node> anchored() {
-        return super.anchored().filter(n -> !isPhiAtMerge(n));
-    }
-
-    /**
-     * This simplify method can deal with a null value for tool, so that it can be used outside of
-     * canonicalization.
-     */
-    @Override
-    public void simplify(SimplifierTool tool) {
-        FixedNode currentNext = next();
-        if (currentNext instanceof AbstractEndNode) {
-            AbstractEndNode origLoopEnd = (AbstractEndNode) currentNext;
-            MergeNode merge = origLoopEnd.merge();
-            if (merge instanceof LoopBeginNode && !(origLoopEnd instanceof LoopEndNode)) {
-                return;
-            }
-            // in order to move anchored values to the other merge we would need to check if the
-            // anchors are used by phis of the other merge
-            if (this.anchored().isNotEmpty()) {
-                return;
-            }
-            if (merge.stateAfter() == null && this.stateAfter() != null) {
-                // We hold a state, but the succeeding merge does not => do not combine.
-                return;
-            }
-            for (PhiNode phi : phis()) {
-                if (phi.usages().filter(isNotA(VirtualState.class)).and(node -> !merge.isPhiAtMerge(node)).isNotEmpty()) {
-                    return;
-                }
-            }
-            Debug.log("Split %s into ends for %s.", this, merge);
-            int numEnds = this.forwardEndCount();
-            for (int i = 0; i < numEnds - 1; i++) {
-                AbstractEndNode end = forwardEndAt(numEnds - 1 - i);
-                if (tool != null) {
-                    tool.addToWorkList(end);
-                }
-                AbstractEndNode newEnd;
-                if (merge instanceof LoopBeginNode) {
-                    newEnd = graph().add(new LoopEndNode((LoopBeginNode) merge));
-                } else {
-                    newEnd = graph().add(new EndNode());
-                    merge.addForwardEnd(newEnd);
-                }
-                for (PhiNode phi : merge.phis()) {
-                    ValueNode v = phi.valueAt(origLoopEnd);
-                    ValueNode newInput;
-                    if (isPhiAtMerge(v)) {
-                        PhiNode endPhi = (PhiNode) v;
-                        newInput = endPhi.valueAt(end);
-                    } else {
-                        newInput = v;
-                    }
-                    phi.addInput(newInput);
-                }
-                this.removeEnd(end);
-                end.replaceAtPredecessor(newEnd);
-                end.safeDelete();
-                if (tool != null) {
-                    tool.addToWorkList(newEnd.predecessor());
-                }
-            }
-            graph().reduceTrivialMerge(this);
-        } else if (currentNext instanceof ReturnNode) {
-            ReturnNode returnNode = (ReturnNode) currentNext;
-            if (anchored().isNotEmpty() || returnNode.getMemoryMap() != null) {
-                return;
-            }
-            List<PhiNode> phis = phis().snapshot();
-            for (PhiNode phi : phis) {
-                for (Node usage : phi.usages().filter(isNotA(FrameState.class))) {
-                    if (usage != returnNode) {
-                        return;
-                    }
-                }
-            }
-
-            ValuePhiNode returnValuePhi = returnNode.result() == null || !isPhiAtMerge(returnNode.result()) ? null : (ValuePhiNode) returnNode.result();
-            List<AbstractEndNode> endNodes = forwardEnds().snapshot();
-            for (AbstractEndNode end : endNodes) {
-                ReturnNode newReturn = graph().add(new ReturnNode(returnValuePhi == null ? returnNode.result() : returnValuePhi.valueAt(end)));
-                if (tool != null) {
-                    tool.addToWorkList(end.predecessor());
-                }
-                end.replaceAtPredecessor(newReturn);
-            }
-            GraphUtil.killCFG(this);
-            for (AbstractEndNode end : endNodes) {
-                end.safeDelete();
-            }
-            for (PhiNode phi : phis) {
-                if (phi.isAlive() && phi.hasNoUsages()) {
-                    GraphUtil.killWithUnusedFloatingInputs(phi);
-                }
-            }
-        }
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -32,28 +32,28 @@
 import com.oracle.graal.nodes.calc.*;
 
 /**
- * {@code PhiNode}s represent the merging of edges at a control flow merges ({@link MergeNode} or
- * {@link LoopBeginNode}). For a {@link MergeNode}, the order of the values corresponds to the order
+ * {@code PhiNode}s represent the merging of edges at a control flow merges ({@link AbstractMergeNode} or
+ * {@link LoopBeginNode}). For a {@link AbstractMergeNode}, the order of the values corresponds to the order
  * of the ends. For {@link LoopBeginNode}s, the first value corresponds to the loop's predecessor,
  * while the rest of the values correspond to the {@link LoopEndNode}s.
  */
 @NodeInfo
 public abstract class PhiNode extends FloatingNode implements Simplifiable {
 
-    @Input(InputType.Association) protected MergeNode merge;
+    @Input(InputType.Association) protected AbstractMergeNode merge;
 
-    protected PhiNode(Stamp stamp, MergeNode merge) {
+    protected PhiNode(Stamp stamp, AbstractMergeNode merge) {
         super(stamp);
         this.merge = merge;
     }
 
     public abstract NodeInputList<ValueNode> values();
 
-    public MergeNode merge() {
+    public AbstractMergeNode merge() {
         return merge;
     }
 
-    public void setMerge(MergeNode x) {
+    public void setMerge(AbstractMergeNode x) {
         updateUsages(merge, x);
         merge = x;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -36,9 +36,9 @@
 @NodeInfo
 public abstract class ProxyNode extends FloatingNode implements IterableNodeType, ValueNumberable {
 
-    @Input(InputType.Association) BeginNode proxyPoint;
+    @Input(InputType.Association) AbstractBeginNode proxyPoint;
 
-    public ProxyNode(Stamp stamp, BeginNode proxyPoint) {
+    public ProxyNode(Stamp stamp, AbstractBeginNode proxyPoint) {
         super(stamp);
         assert proxyPoint != null;
         this.proxyPoint = proxyPoint;
@@ -46,7 +46,7 @@
 
     public abstract ValueNode value();
 
-    public BeginNode proxyPoint() {
+    public AbstractBeginNode proxyPoint() {
         return proxyPoint;
     }
 
@@ -58,11 +58,11 @@
         return super.verify();
     }
 
-    public static ValueProxyNode forValue(ValueNode value, BeginNode exit, StructuredGraph graph) {
+    public static ValueProxyNode forValue(ValueNode value, AbstractBeginNode exit, StructuredGraph graph) {
         return graph.unique(new ValueProxyNode(value, exit));
     }
 
-    public static GuardProxyNode forGuard(GuardingNode value, BeginNode exit, StructuredGraph graph) {
+    public static GuardProxyNode forGuard(GuardingNode value, AbstractBeginNode exit, StructuredGraph graph) {
         return graph.unique(new GuardProxyNode(value, exit));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Wed Jan 28 03:28:31 2015 +0100
@@ -94,14 +94,14 @@
     private boolean hasValueProxies = true;
 
     /**
-     * Creates a new Graph containing a single {@link BeginNode} as the {@link #start() start} node.
+     * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start() start} node.
      */
     public StructuredGraph() {
         this(null, null);
     }
 
     /**
-     * Creates a new Graph containing a single {@link BeginNode} as the {@link #start() start} node.
+     * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start() start} node.
      */
     public StructuredGraph(String name, ResolvedJavaMethod method) {
         this(name, method, uniqueGraphIds.incrementAndGet(), INVOCATION_ENTRY_BCI);
@@ -285,8 +285,8 @@
      */
     public void removeFixed(FixedWithNextNode node) {
         assert node != null;
-        if (node instanceof BeginNode) {
-            ((BeginNode) node).prepareDelete();
+        if (node instanceof AbstractBeginNode) {
+            ((AbstractBeginNode) node).prepareDelete();
         }
         assert node.hasNoUsages() : node + " " + node.usages();
         GraphUtil.unlinkFixedNode(node);
@@ -321,7 +321,7 @@
         node.safeDelete();
     }
 
-    public void removeSplit(ControlSplitNode node, BeginNode survivingSuccessor) {
+    public void removeSplit(ControlSplitNode node, AbstractBeginNode survivingSuccessor) {
         assert node != null;
         assert node.hasNoUsages();
         assert survivingSuccessor != null;
@@ -330,11 +330,11 @@
         node.safeDelete();
     }
 
-    public void removeSplitPropagate(ControlSplitNode node, BeginNode survivingSuccessor) {
+    public void removeSplitPropagate(ControlSplitNode node, AbstractBeginNode survivingSuccessor) {
         removeSplitPropagate(node, survivingSuccessor, null);
     }
 
-    public void removeSplitPropagate(ControlSplitNode node, BeginNode survivingSuccessor, SimplifierTool tool) {
+    public void removeSplitPropagate(ControlSplitNode node, AbstractBeginNode survivingSuccessor, SimplifierTool tool) {
         assert node != null;
         assert node.hasNoUsages();
         assert survivingSuccessor != null;
@@ -351,7 +351,7 @@
         }
     }
 
-    public void replaceSplit(ControlSplitNode node, Node replacement, BeginNode survivingSuccessor) {
+    public void replaceSplit(ControlSplitNode node, Node replacement, AbstractBeginNode survivingSuccessor) {
         if (replacement instanceof FixedWithNextNode) {
             replaceSplitWithFixed(node, (FixedWithNextNode) replacement, survivingSuccessor);
         } else {
@@ -361,7 +361,7 @@
         }
     }
 
-    public void replaceSplitWithFixed(ControlSplitNode node, FixedWithNextNode replacement, BeginNode survivingSuccessor) {
+    public void replaceSplitWithFixed(ControlSplitNode node, FixedWithNextNode replacement, AbstractBeginNode survivingSuccessor) {
         assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement;
         assert survivingSuccessor != null;
         node.clearSuccessors();
@@ -369,7 +369,7 @@
         node.replaceAndDelete(replacement);
     }
 
-    public void replaceSplitWithFloating(ControlSplitNode node, FloatingNode replacement, BeginNode survivingSuccessor) {
+    public void replaceSplitWithFloating(ControlSplitNode node, FloatingNode replacement, AbstractBeginNode survivingSuccessor) {
         assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement;
         assert survivingSuccessor != null;
         node.clearSuccessors();
@@ -404,12 +404,12 @@
         if (begin.forwardEndCount() == 1) { // bypass merge and remove
             reduceTrivialMerge(begin);
         } else { // convert to merge
-            MergeNode merge = this.add(new MergeNode());
+            AbstractMergeNode merge = this.add(new MergeNode());
             this.replaceFixedWithFixed(begin, merge);
         }
     }
 
-    public void reduceTrivialMerge(MergeNode merge) {
+    public void reduceTrivialMerge(AbstractMergeNode merge) {
         assert merge.forwardEndCount() == 1;
         assert !(merge instanceof LoopBeginNode) || ((LoopBeginNode) merge).loopEnds().isEmpty();
         for (PhiNode phi : merge.phis().snapshot()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -35,13 +35,13 @@
 
     @Input protected NodeInputList<ValueNode> values;
 
-    public ValuePhiNode(Stamp stamp, MergeNode merge) {
+    public ValuePhiNode(Stamp stamp, AbstractMergeNode merge) {
         super(stamp, merge);
         assert stamp != StampFactory.forVoid();
         values = new NodeInputList<>(this);
     }
 
-    public ValuePhiNode(Stamp stamp, MergeNode merge, ValueNode[] values) {
+    public ValuePhiNode(Stamp stamp, AbstractMergeNode merge, ValueNode[] values) {
         super(stamp, merge);
         assert stamp != StampFactory.forVoid();
         this.values = new NodeInputList<>(this, values);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -32,7 +32,7 @@
 
     @Input ValueNode value;
 
-    public ValueProxyNode(ValueNode value, BeginNode proxyPoint) {
+    public ValueProxyNode(ValueNode value, AbstractBeginNode proxyPoint) {
         super(value.stamp(), proxyPoint);
         this.value = value;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AbsNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AbsNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -34,7 +34,7 @@
  * Absolute value.
  */
 @NodeInfo
-public class AbsNode extends UnaryArithmeticNode<Abs> implements ArithmeticLIRLowerable, NarrowableArithmeticNode {
+public final class AbsNode extends UnaryArithmeticNode<Abs> implements ArithmeticLIRLowerable, NarrowableArithmeticNode {
 
     public AbsNode(ValueNode x) {
         super(ArithmeticOpTable::getAbs, x);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -34,7 +34,7 @@
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "&")
-public class AndNode extends BinaryArithmeticNode<And> implements NarrowableArithmeticNode {
+public final class AndNode extends BinaryArithmeticNode<And> implements NarrowableArithmeticNode {
 
     public AndNode(ValueNode x, ValueNode y) {
         super(ArithmeticOpTable::getAnd, x, y);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -38,7 +38,7 @@
  * that these nodes are not built directly from the bytecode but are introduced by canonicalization.
  */
 @NodeInfo
-public class ConditionalNode extends FloatingNode implements Canonicalizable, LIRLowerable {
+public final class ConditionalNode extends FloatingNode implements Canonicalizable, LIRLowerable {
 
     @Input(InputType.Condition) LogicNode condition;
     @Input ValueNode trueValue;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/DivNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/DivNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -33,7 +33,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "/")
-public class DivNode extends BinaryArithmeticNode<Div> {
+public final class DivNode extends BinaryArithmeticNode<Div> {
 
     public DivNode(ValueNode x, ValueNode y) {
         super(ArithmeticOpTable::getDiv, x, y);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -37,7 +37,7 @@
  * semantics.
  */
 @NodeInfo
-public class FloatConvertNode extends UnaryArithmeticNode<FloatConvertOp> implements ConvertNode, Lowerable, ArithmeticLIRLowerable {
+public final class FloatConvertNode extends UnaryArithmeticNode<FloatConvertOp> implements ConvertNode, Lowerable, ArithmeticLIRLowerable {
 
     protected final FloatConvert op;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -35,7 +35,7 @@
  * The {@code NarrowNode} converts an integer to a narrower integer.
  */
 @NodeInfo
-public class NarrowNode extends IntegerConvertNode<Narrow, SignExtend> {
+public final class NarrowNode extends IntegerConvertNode<Narrow, SignExtend> {
 
     public NarrowNode(ValueNode input, int resultBits) {
         this(input, PrimitiveStamp.getBits(input.stamp()), resultBits);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -34,7 +34,7 @@
  * The {@code NegateNode} node negates its operand.
  */
 @NodeInfo
-public class NegateNode extends UnaryArithmeticNode<Neg> implements NarrowableArithmeticNode {
+public final class NegateNode extends UnaryArithmeticNode<Neg> implements NarrowableArithmeticNode {
 
     public NegateNode(ValueNode value) {
         super(ArithmeticOpTable::getNeg, value);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java	Wed Jan 28 03:28:31 2015 +0100
@@ -30,7 +30,7 @@
 
 public final class Block extends AbstractBlockBase<Block> {
 
-    protected final BeginNode beginNode;
+    protected final AbstractBeginNode beginNode;
 
     protected FixedNode endNode;
 
@@ -39,11 +39,11 @@
 
     protected Block postdominator;
 
-    protected Block(BeginNode node) {
+    protected Block(AbstractBeginNode node) {
         this.beginNode = node;
     }
 
-    public BeginNode getBeginNode() {
+    public AbstractBeginNode getBeginNode() {
         return beginNode;
     }
 
@@ -122,7 +122,7 @@
             } else {
                 cur = ((FixedWithNextNode) cur).next();
             }
-            assert !(cur instanceof BeginNode);
+            assert !(cur instanceof AbstractBeginNode);
             return result;
         }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Wed Jan 28 03:28:31 2015 +0100
@@ -130,7 +130,7 @@
         Node last;
 
         // assign proxies of a loop exit to this block
-        if (cur instanceof BeginNode) {
+        if (cur instanceof AbstractBeginNode) {
             for (Node usage : cur.usages()) {
                 if (usage instanceof ProxyNode) {
                     nodeToBlock.set(usage, block);
@@ -143,15 +143,15 @@
 
             assert nodeToBlock.get(cur) == null;
             nodeToBlock.set(cur, block);
-            if (cur instanceof MergeNode) {
-                for (PhiNode phi : ((MergeNode) cur).phis()) {
+            if (cur instanceof AbstractMergeNode) {
+                for (PhiNode phi : ((AbstractMergeNode) cur).phis()) {
                     nodeToBlock.set(phi, block);
                 }
             }
 
             last = cur;
             cur = cur.successors().first();
-        } while (cur != null && !(cur instanceof BeginNode));
+        } while (cur != null && !(cur instanceof AbstractBeginNode));
 
         block.endNode = (FixedNode) last;
     }
@@ -159,7 +159,7 @@
     private void identifyBlocks() {
         // Find all block headers
         int numBlocks = 0;
-        for (BeginNode begin : graph.getNodes(BeginNode.class)) {
+        for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.class)) {
             Block block = new Block(begin);
             numBlocks++;
             identifyBlock(block);
@@ -252,7 +252,7 @@
     private void computeLoopInformation() {
         loops = new ArrayList<>();
         for (Block block : reversePostOrder) {
-            Node beginNode = block.getBeginNode();
+            AbstractBeginNode beginNode = block.getBeginNode();
             if (beginNode instanceof LoopBeginNode) {
                 Loop<Block> loop = new HIRLoop(block.getLoop(), loops.size(), block);
                 loops.add(loop);
@@ -273,7 +273,7 @@
                 for (Block b : loop.getBlocks()) {
                     for (Block sux : b.getSuccessors()) {
                         if (sux.loop != loop) {
-                            BeginNode begin = sux.getBeginNode();
+                            AbstractBeginNode 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);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -36,7 +36,7 @@
  * [(base + x) + y] where base is a node and x and y are location nodes.
  */
 @NodeInfo(nameTemplate = "AddLoc {p#locationIdentity/s}")
-public class AddLocationNode extends LocationNode implements Canonicalizable.Binary<LocationNode> {
+public final class AddLocationNode extends LocationNode implements Canonicalizable.Binary<LocationNode> {
 
     @Input(InputType.Association) ValueNode x;
     @Input(InputType.Association) ValueNode y;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -40,7 +40,7 @@
  * methods in Integer, Long, etc.
  */
 @NodeInfo
-public class BoxNode extends UnaryNode implements VirtualizableAllocation, Lowerable {
+public final class BoxNode extends UnaryNode implements VirtualizableAllocation, Lowerable {
 
     protected final Kind boxingKind;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -36,7 +36,7 @@
  * intended primarily for snippets, so that they can define their fast and slow paths.
  */
 @NodeInfo
-public class BranchProbabilityNode extends FloatingNode implements Simplifiable, Lowerable {
+public final class BranchProbabilityNode extends FloatingNode implements Simplifiable, Lowerable {
 
     public static final double LIKELY_PROBABILITY = 0.6;
     public static final double NOT_LIKELY_PROBABILITY = 1 - LIKELY_PROBABILITY;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BytecodeExceptionNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BytecodeExceptionNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -34,7 +34,7 @@
  * either a {@linkplain ForeignCallDescriptor foreign} call or a pre-allocated exception object.
  */
 @NodeInfo
-public class BytecodeExceptionNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
+public final class BytecodeExceptionNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
 
     protected final Class<? extends Throwable> exceptionClass;
     @Input NodeInputList<ValueNode> arguments;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -30,7 +30,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo
-public class ComputeAddressNode extends FloatingNode implements LIRLowerable {
+public final class ComputeAddressNode extends FloatingNode implements LIRLowerable {
 
     @Input ValueNode object;
     @Input(InputType.Association) ValueNode location;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -33,7 +33,7 @@
  * where base is a node and disp is a constant.
  */
 @NodeInfo(nameTemplate = "Loc {p#locationIdentity/s}")
-public class ConstantLocationNode extends LocationNode {
+public final class ConstantLocationNode extends LocationNode {
 
     protected final LocationIdentity locationIdentity;
     protected final long displacement;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -28,7 +28,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo
-public class FixedValueAnchorNode extends FixedWithNextNode implements LIRLowerable, ValueProxy {
+public final class FixedValueAnchorNode extends FixedWithNextNode implements LIRLowerable, ValueProxy {
 
     @Input ValueNode object;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -41,7 +41,7 @@
 
     protected final int[] keys;
 
-    public IntegerSwitchNode(ValueNode value, BeginNode[] successors, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
+    public IntegerSwitchNode(ValueNode value, AbstractBeginNode[] successors, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
         super(value, successors, keySuccessors, keyProbabilities);
         assert keySuccessors.length == keys.length + 1;
         assert keySuccessors.length == keyProbabilities.length;
@@ -58,7 +58,7 @@
     }
 
     public IntegerSwitchNode(ValueNode value, int successorCount, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
-        this(value, new BeginNode[successorCount], keys, keyProbabilities, keySuccessors);
+        this(value, new AbstractBeginNode[successorCount], keys, keyProbabilities, keySuccessors);
     }
 
     @Override
@@ -130,7 +130,7 @@
                     tool.addToWorkList(defaultSuccessor());
                     graph().removeSplitPropagate(this, defaultSuccessor());
                 } else if (validKeys != keys.length) {
-                    ArrayList<BeginNode> newSuccessors = new ArrayList<>(blockSuccessorCount());
+                    ArrayList<AbstractBeginNode> newSuccessors = new ArrayList<>(blockSuccessorCount());
                     int[] newKeys = new int[validKeys];
                     int[] newKeySuccessors = new int[validKeys + 1];
                     double[] newKeyProbabilities = new double[validKeys + 1];
@@ -163,14 +163,14 @@
                     }
 
                     for (int i = 0; i < blockSuccessorCount(); i++) {
-                        BeginNode successor = blockSuccessor(i);
+                        AbstractBeginNode successor = blockSuccessor(i);
                         if (!newSuccessors.contains(successor)) {
                             tool.deleteBranch(successor);
                         }
                         setBlockSuccessor(i, null);
                     }
 
-                    BeginNode[] successorsArray = newSuccessors.toArray(new BeginNode[newSuccessors.size()]);
+                    AbstractBeginNode[] successorsArray = newSuccessors.toArray(new AbstractBeginNode[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/LoadHubNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -33,7 +33,7 @@
  * Loads an object's hub. The object is not null-checked by this operation.
  */
 @NodeInfo
-public class LoadHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, Virtualizable {
+public final class LoadHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, Virtualizable {
 
     @Input ValueNode value;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -37,7 +37,7 @@
 @NodeInfo
 public abstract class SwitchNode extends ControlSplitNode {
 
-    @Successor protected NodeSuccessorList<BeginNode> successors;
+    @Successor protected NodeSuccessorList<AbstractBeginNode> successors;
     @Input protected ValueNode value;
 
     // do not change the contents of these arrays:
@@ -50,7 +50,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, BeginNode[] successors, int[] keySuccessors, double[] keyProbabilities) {
+    public SwitchNode(ValueNode value, AbstractBeginNode[] successors, int[] keySuccessors, double[] keyProbabilities) {
         super(StampFactory.forVoid());
         assert value.stamp().getStackKind().isNumericInteger() || value.stamp() instanceof AbstractPointerStamp : value.stamp() + " key not supported by SwitchNode";
         assert keySuccessors.length == keyProbabilities.length;
@@ -72,7 +72,7 @@
     }
 
     @Override
-    public double probability(BeginNode successor) {
+    public double probability(AbstractBeginNode successor) {
         double sum = 0;
         for (int i = 0; i < keySuccessors.length; i++) {
             if (successors.get(keySuccessors[i]) == successor) {
@@ -117,7 +117,7 @@
     /**
      * Returns the successor for the key at the given index.
      */
-    public BeginNode keySuccessor(int i) {
+    public AbstractBeginNode keySuccessor(int i) {
         return successors.get(keySuccessors[i]);
     }
 
@@ -135,11 +135,11 @@
         return keySuccessors[keySuccessors.length - 1];
     }
 
-    public BeginNode blockSuccessor(int i) {
+    public AbstractBeginNode blockSuccessor(int i) {
         return successors.get(i);
     }
 
-    public void setBlockSuccessor(int i, BeginNode s) {
+    public void setBlockSuccessor(int i, AbstractBeginNode s) {
         successors.set(i, s);
     }
 
@@ -152,7 +152,7 @@
      *
      * @return the default successor
      */
-    public BeginNode defaultSuccessor() {
+    public AbstractBeginNode defaultSuccessor() {
         if (defaultSuccessorIndex() == -1) {
             throw new GraalInternalError("unexpected");
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -91,7 +91,7 @@
 
     @Override
     public void virtualize(VirtualizerTool tool) {
-        if (anchored != null && !(anchored instanceof BeginNode)) {
+        if (anchored != null && !(anchored instanceof AbstractBeginNode)) {
             State state = tool.getObjectState(anchored);
             if (state == null || state.getState() != EscapeState.Virtual) {
                 return;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -32,7 +32,7 @@
  * The {@code AbstractNewArrayNode} is used for all 1-dimensional array allocations.
  */
 @NodeInfo
-public class AbstractNewArrayNode extends AbstractNewObjectNode implements ArrayLengthProvider {
+public abstract class AbstractNewArrayNode extends AbstractNewObjectNode implements ArrayLengthProvider {
 
     @Input protected ValueNode length;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -36,7 +36,7 @@
  * The {@code AbstractNewObjectNode} is the base class for the new instance and new array nodes.
  */
 @NodeInfo
-public class AbstractNewObjectNode extends DeoptimizingFixedWithNextNode implements Simplifiable, Lowerable {
+public abstract class AbstractNewObjectNode extends DeoptimizingFixedWithNextNode implements Simplifiable, Lowerable {
 
     protected final boolean fillContents;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -34,7 +34,7 @@
  * The {@code ArrayLength} instruction gets the length of an array.
  */
 @NodeInfo
-public class ArrayLengthNode extends FixedWithNextNode implements Canonicalizable.Unary<ValueNode>, Lowerable, Virtualizable {
+public final class ArrayLengthNode extends FixedWithNextNode implements Canonicalizable.Unary<ValueNode>, Lowerable, Virtualizable {
 
     @Input ValueNode array;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -36,7 +36,7 @@
  * Represents an atomic read-and-add operation like {@link Unsafe#getAndAddInt(Object, long, int)}.
  */
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
-public class AtomicReadAndAddNode extends AbstractMemoryCheckpoint implements LIRLowerable, MemoryCheckpoint.Single {
+public final class AtomicReadAndAddNode extends AbstractMemoryCheckpoint implements LIRLowerable, MemoryCheckpoint.Single {
 
     @Input ValueNode object;
     @Input ValueNode offset;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndWriteNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndWriteNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -37,7 +37,7 @@
  * .
  */
 @NodeInfo
-public class AtomicReadAndWriteNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
+public final class AtomicReadAndWriteNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
 
     @Input ValueNode object;
     @Input ValueNode offset;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -34,7 +34,7 @@
  * instance, to implement an object array store check.
  */
 @NodeInfo
-public class CheckCastDynamicNode extends FixedWithNextNode implements Canonicalizable.Binary<ValueNode>, Lowerable {
+public final class CheckCastDynamicNode extends FixedWithNextNode implements Canonicalizable.Binary<ValueNode>, Lowerable {
 
     @Input ValueNode object;
     @Input ValueNode hub;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -41,7 +41,7 @@
  * Implements a type check against a compile-time known type.
  */
 @NodeInfo
-public class CheckCastNode extends FixedWithNextNode implements Canonicalizable, Simplifiable, Lowerable, Virtualizable, ValueProxy {
+public final class CheckCastNode extends FixedWithNextNode implements Canonicalizable, Simplifiable, Lowerable, Virtualizable, ValueProxy {
 
     @Input protected ValueNode object;
     protected final ResolvedJavaType type;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -36,7 +36,7 @@
  * value matched the expected value.
  */
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
-public class CompareAndSwapNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
+public final class CompareAndSwapNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
 
     @Input ValueNode object;
     @Input ValueNode offset;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -30,7 +30,7 @@
 import com.oracle.graal.nodes.*;
 
 @NodeInfo
-public class DynamicNewInstanceNode extends AbstractNewObjectNode implements Canonicalizable {
+public final class DynamicNewInstanceNode extends AbstractNewObjectNode implements Canonicalizable {
 
     @Input ValueNode clazz;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -34,7 +34,7 @@
  * throw instruction or implicit exception).
  */
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
-public class ExceptionObjectNode extends DispatchBeginNode implements Lowerable, MemoryCheckpoint.Single {
+public final class ExceptionObjectNode extends DispatchBeginNode implements Lowerable, MemoryCheckpoint.Single {
 
     public ExceptionObjectNode(MetaAccessProvider metaAccess) {
         super(StampFactory.declaredNonNull(metaAccess.lookupJavaType(Throwable.class)));
@@ -53,7 +53,7 @@
              * deopts can float in between the begin node and the load exception node.
              */
             LocationIdentity locationsKilledByInvoke = ((InvokeWithExceptionNode) predecessor()).getLocationIdentity();
-            BeginNode entry = graph().add(new KillingBeginNode(locationsKilledByInvoke));
+            AbstractBeginNode entry = graph().add(new KillingBeginNode(locationsKilledByInvoke));
             LoadExceptionObjectNode loadException = graph().add(new LoadExceptionObjectNode(stamp()));
 
             loadException.setStateAfter(stateAfter());
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -37,7 +37,7 @@
  * The {@code LoadFieldNode} represents a read of a static or instance field.
  */
 @NodeInfo(nameTemplate = "LoadField#{p#field/s}")
-public class LoadFieldNode extends AccessFieldNode implements Canonicalizable.Unary<ValueNode>, VirtualizableRoot, UncheckedInterfaceProvider {
+public final class LoadFieldNode extends AccessFieldNode implements Canonicalizable.Unary<ValueNode>, VirtualizableRoot, UncheckedInterfaceProvider {
 
     public LoadFieldNode(ValueNode object, ResolvedJavaField field) {
         super(createStamp(field), object, field);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -185,8 +185,8 @@
                  */
                 LogicNode condition = graph().unique(new InstanceOfNode(singleImplementor, receiver, getProfile()));
                 GuardNode guard = graph().unique(
-                                new GuardNode(condition, BeginNode.prevBegin(invoke().asNode()), DeoptimizationReason.OptimizedTypeCheckViolated, DeoptimizationAction.InvalidateRecompile, false,
-                                                JavaConstant.NULL_POINTER));
+                                new GuardNode(condition, AbstractBeginNode.prevBegin(invoke().asNode()), DeoptimizationReason.OptimizedTypeCheckViolated, DeoptimizationAction.InvalidateRecompile,
+                                                false, JavaConstant.NULL_POINTER));
                 PiNode piNode = graph().unique(new PiNode(receiver, StampFactory.declaredNonNull(singleImplementor), guard));
                 arguments().set(0, piNode);
                 setInvokeKind(InvokeKind.Virtual);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -33,7 +33,7 @@
  * The {@code MonitorEnterNode} represents the acquisition of a monitor.
  */
 @NodeInfo
-public class MonitorEnterNode extends AccessMonitorNode implements Virtualizable, Lowerable, IterableNodeType, MonitorEnter, MemoryCheckpoint.Single {
+public final class MonitorEnterNode extends AccessMonitorNode implements Virtualizable, Lowerable, IterableNodeType, MonitorEnter, MemoryCheckpoint.Single {
 
     public MonitorEnterNode(ValueNode object, MonitorIdNode monitorId) {
         super(object, monitorId);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -37,7 +37,7 @@
  * materialized before releasing the monitor.
  */
 @NodeInfo
-public class MonitorExitNode extends AccessMonitorNode implements Virtualizable, Simplifiable, Lowerable, IterableNodeType, MonitorExit, MemoryCheckpoint.Single {
+public final class MonitorExitNode extends AccessMonitorNode implements Virtualizable, Simplifiable, Lowerable, IterableNodeType, MonitorExit, MemoryCheckpoint.Single {
 
     @OptionalInput ValueNode escapedReturnValue;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -36,7 +36,7 @@
  * The {@code NewInstanceNode} represents the allocation of an instance class object.
  */
 @NodeInfo(nameTemplate = "New {p#instanceClass/s}")
-public class NewInstanceNode extends AbstractNewObjectNode implements VirtualizableAllocation {
+public final class NewInstanceNode extends AbstractNewObjectNode implements VirtualizableAllocation {
 
     protected final ResolvedJavaType instanceClass;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -33,7 +33,7 @@
  * The {@code NewMultiArrayNode} represents an allocation of a multi-dimensional object array.
  */
 @NodeInfo
-public class NewMultiArrayNode extends DeoptimizingFixedWithNextNode implements Lowerable, ArrayLengthProvider {
+public final class NewMultiArrayNode extends DeoptimizingFixedWithNextNode implements Lowerable, ArrayLengthProvider {
 
     @Input protected NodeInputList<ValueNode> dimensions;
     protected final ResolvedJavaType type;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -42,7 +42,7 @@
 
     protected final ResolvedJavaType[] keys;
 
-    public TypeSwitchNode(ValueNode value, BeginNode[] successors, ResolvedJavaType[] keys, double[] keyProbabilities, int[] keySuccessors) {
+    public TypeSwitchNode(ValueNode value, AbstractBeginNode[] successors, ResolvedJavaType[] keys, double[] keyProbabilities, int[] keySuccessors) {
         super(value, successors, keySuccessors, keyProbabilities);
         assert successors.length <= keys.length + 1;
         assert keySuccessors.length == keyProbabilities.length;
@@ -150,7 +150,7 @@
                     tool.addToWorkList(defaultSuccessor());
                     graph().removeSplitPropagate(this, defaultSuccessor());
                 } else if (validKeys != keys.length) {
-                    ArrayList<BeginNode> newSuccessors = new ArrayList<>(blockSuccessorCount());
+                    ArrayList<AbstractBeginNode> newSuccessors = new ArrayList<>(blockSuccessorCount());
                     ResolvedJavaType[] newKeys = new ResolvedJavaType[validKeys];
                     int[] newKeySuccessors = new int[validKeys + 1];
                     double[] newKeyProbabilities = new double[validKeys + 1];
@@ -183,14 +183,14 @@
                     }
 
                     for (int i = 0; i < blockSuccessorCount(); i++) {
-                        BeginNode successor = blockSuccessor(i);
+                        AbstractBeginNode successor = blockSuccessor(i);
                         if (!newSuccessors.contains(successor)) {
                             tool.deleteBranch(successor);
                         }
                         setBlockSuccessor(i, null);
                     }
 
-                    BeginNode[] successorsArray = newSuccessors.toArray(new BeginNode[newSuccessors.size()]);
+                    AbstractBeginNode[] successorsArray = newSuccessors.toArray(new AbstractBeginNode[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/NodeLIRBuilderTool.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java	Wed Jan 28 03:28:31 2015 +0100
@@ -49,7 +49,7 @@
     void emitInvoke(Invoke i);
 
     // Handling of block-end nodes still needs to be unified in the LIRGenerator.
-    void visitMerge(MergeNode i);
+    void visitMerge(AbstractMergeNode i);
 
     void visitEndNode(AbstractEndNode i);
 
@@ -67,7 +67,7 @@
 
     LIRGeneratorTool getLIRGeneratorTool();
 
-    void emitOverflowCheckBranch(BeginNode overflowSuccessor, BeginNode next, Stamp compareStamp, double probability);
+    void emitOverflowCheckBranch(AbstractBeginNode overflowSuccessor, AbstractBeginNode next, Stamp compareStamp, double probability);
 
     Value[] visitInvokeArguments(CallingConvention cc, Collection<ValueNode> arguments);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Wed Jan 28 03:28:31 2015 +0100
@@ -71,7 +71,7 @@
     }
 
     private static void killEnd(AbstractEndNode end, SimplifierTool tool) {
-        MergeNode merge = end.merge();
+        AbstractMergeNode merge = end.merge();
         if (merge != null) {
             merge.removeEnd(end);
             StructuredGraph graph = end.graph();
@@ -158,7 +158,7 @@
     }
 
     public static void unlinkFixedNode(FixedWithNextNode fixed) {
-        assert fixed.next() != null && fixed.predecessor() != null && fixed.isAlive();
+        assert fixed.next() != null && fixed.predecessor() != null && fixed.isAlive() : fixed;
         FixedNode next = fixed.next();
         fixed.setNext(null);
         fixed.replaceAtPredecessor(next);
@@ -187,7 +187,7 @@
         if (vpn.isDeleted()) {
             return;
         }
-        BeginNode proxyPoint = vpn.proxyPoint();
+        AbstractBeginNode 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/virtual/AllocatedObjectNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -33,7 +33,7 @@
  * {@link VirtualObjectNode}.
  */
 @NodeInfo
-public class AllocatedObjectNode extends FloatingNode implements Virtualizable, ArrayLengthProvider {
+public final class AllocatedObjectNode extends FloatingNode implements Virtualizable, ArrayLengthProvider {
 
     @Input VirtualObjectNode virtualObject;
     @Input(InputType.Extension) CommitAllocationNode commit;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -33,7 +33,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(nameTemplate = "Alloc {i#virtualObjects}", allowedUsageTypes = {InputType.Extension})
-public class CommitAllocationNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Simplifiable {
+public final class CommitAllocationNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Simplifiable {
 
     @Input NodeInputList<VirtualObjectNode> virtualObjects = new NodeInputList<>(this);
     @Input NodeInputList<ValueNode> values = new NodeInputList<>(this);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Wed Jan 28 03:28:31 2015 +0100
@@ -321,7 +321,7 @@
                         graph.removeFloating((FloatingNode) node);
                     } else {
                         // case 2
-                        assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode || canonical instanceof MergeNode) : node + " -> " + canonical +
+                        assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode || canonical instanceof AbstractMergeNode) : node + " -> " + canonical +
                                         " : replacement should be floating or fixed and connected";
                         graph.replaceFloating((FloatingNode) node, canonical);
                     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Wed Jan 28 03:28:31 2015 +0100
@@ -124,7 +124,7 @@
         }
 
         @Override
-        public boolean merge(MergeNode merge, List<State> withStates) {
+        public boolean merge(AbstractMergeNode merge, List<State> withStates) {
             Map<ValueNode, ResolvedJavaType> newKnownTypes = Node.newIdentityMap();
             Map<LogicNode, GuardingNode> newTrueConditions = Node.newIdentityMap();
             Map<LogicNode, GuardingNode> newFalseConditions = Node.newIdentityMap();
@@ -405,7 +405,7 @@
             }
         }
 
-        private void registerControlSplitInfo(Node pred, BeginNode begin) {
+        private void registerControlSplitInfo(Node pred, AbstractBeginNode begin) {
             assert pred != null && begin != null;
             /*
              * We does not create value proxies for values it may connect accross loop exit node so
@@ -640,8 +640,8 @@
 
         @Override
         protected void node(FixedNode node) {
-            if (node instanceof BeginNode) {
-                BeginNode begin = (BeginNode) node;
+            if (node instanceof AbstractBeginNode) {
+                AbstractBeginNode begin = (AbstractBeginNode) node;
                 Node pred = node.predecessor();
 
                 if (pred != null) {
@@ -694,7 +694,7 @@
                         replacementAnchor = searchAnchor(GraphUtil.unproxify(object), type);
                     }
                     if (replacementAnchor == null) {
-                        replacementAnchor = BeginNode.prevBegin(checkCast);
+                        replacementAnchor = AbstractBeginNode.prevBegin(checkCast);
                     }
                     PiNode piNode;
                     if (isNull) {
@@ -730,7 +730,7 @@
 
                 LogicNode replacement = null;
                 GuardingNode replacementAnchor = null;
-                BeginNode survivingSuccessor = null;
+                AbstractBeginNode survivingSuccessor = null;
                 if (state.trueConditions.containsKey(compare)) {
                     replacement = trueConstant;
                     replacementAnchor = state.trueConditions.get(compare);
@@ -752,7 +752,7 @@
                 }
 
                 if (replacement != null) {
-                    if (replacementAnchor != null && !(replacementAnchor instanceof BeginNode)) {
+                    if (replacementAnchor != null && !(replacementAnchor instanceof AbstractBeginNode)) {
                         ValueAnchorNode anchor = graph.add(new ValueAnchorNode(replacementAnchor.asNode()));
                         graph.addBeforeFixed(ifNode, anchor);
                     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Wed Jan 28 03:28:31 2015 +0100
@@ -51,8 +51,8 @@
 public class ConvertDeoptimizeToGuardPhase extends Phase {
     private SimplifierTool simplifierTool = GraphUtil.getDefaultSimplifier(null, null, null, false);
 
-    private static BeginNode findBeginNode(FixedNode startNode) {
-        return GraphUtil.predecessorIterable(startNode).filter(BeginNode.class).first();
+    private static AbstractBeginNode findBeginNode(FixedNode startNode) {
+        return GraphUtil.predecessorIterable(startNode).filter(AbstractBeginNode.class).first();
     }
 
     @Override
@@ -63,14 +63,14 @@
         }
         for (DeoptimizeNode d : graph.getNodes(DeoptimizeNode.class)) {
             assert d.isAlive();
-            visitDeoptBegin(BeginNode.prevBegin(d), d.action(), d.reason(), graph);
+            visitDeoptBegin(AbstractBeginNode.prevBegin(d), d.action(), d.reason(), graph);
         }
 
         for (FixedGuardNode fixedGuard : graph.getNodes(FixedGuardNode.class)) {
 
-            BeginNode pred = BeginNode.prevBegin(fixedGuard);
-            if (pred instanceof MergeNode) {
-                MergeNode merge = (MergeNode) pred;
+            AbstractBeginNode pred = AbstractBeginNode.prevBegin(fixedGuard);
+            if (pred instanceof AbstractMergeNode) {
+                AbstractMergeNode merge = (AbstractMergeNode) pred;
                 if (fixedGuard.condition() instanceof CompareNode) {
                     CompareNode compare = (CompareNode) fixedGuard.condition();
                     List<AbstractEndNode> mergePredecessors = merge.cfgPredecessors().snapshot();
@@ -96,7 +96,7 @@
                         }
                         if (xs[i] instanceof PrimitiveConstant && ys[i] instanceof PrimitiveConstant &&
                                         compare.condition().foldCondition(xs[i], ys[i], null, compare.unorderedIsTrue()) == fixedGuard.isNegated()) {
-                            visitDeoptBegin(BeginNode.prevBegin(mergePredecessor), fixedGuard.getAction(), fixedGuard.getReason(), graph);
+                            visitDeoptBegin(AbstractBeginNode.prevBegin(mergePredecessor), fixedGuard.getAction(), fixedGuard.getReason(), graph);
                         }
                     }
                 }
@@ -106,27 +106,27 @@
         new DeadCodeEliminationPhase(Optional).apply(graph);
     }
 
-    private void visitDeoptBegin(BeginNode deoptBegin, DeoptimizationAction deoptAction, DeoptimizationReason deoptReason, StructuredGraph graph) {
-        if (deoptBegin instanceof MergeNode) {
-            MergeNode mergeNode = (MergeNode) deoptBegin;
+    private void visitDeoptBegin(AbstractBeginNode deoptBegin, DeoptimizationAction deoptAction, DeoptimizationReason deoptReason, StructuredGraph graph) {
+        if (deoptBegin instanceof AbstractMergeNode) {
+            AbstractMergeNode mergeNode = (AbstractMergeNode) deoptBegin;
             Debug.log("Visiting %s", mergeNode);
             FixedNode next = mergeNode.next();
             while (mergeNode.isAlive()) {
                 AbstractEndNode end = mergeNode.forwardEnds().first();
-                BeginNode newBeginNode = findBeginNode(end);
+                AbstractBeginNode newBeginNode = findBeginNode(end);
                 visitDeoptBegin(newBeginNode, deoptAction, deoptReason, graph);
             }
             assert next.isAlive();
-            BeginNode newBeginNode = findBeginNode(next);
+            AbstractBeginNode newBeginNode = findBeginNode(next);
             visitDeoptBegin(newBeginNode, deoptAction, deoptReason, graph);
             return;
         } else if (deoptBegin.predecessor() instanceof IfNode) {
             IfNode ifNode = (IfNode) deoptBegin.predecessor();
-            BeginNode otherBegin = ifNode.trueSuccessor();
+            AbstractBeginNode otherBegin = ifNode.trueSuccessor();
             LogicNode conditionNode = ifNode.condition();
             FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deoptReason, deoptAction, deoptBegin == ifNode.trueSuccessor()));
             FixedWithNextNode pred = (FixedWithNextNode) ifNode.predecessor();
-            BeginNode survivingSuccessor;
+            AbstractBeginNode survivingSuccessor;
             if (deoptBegin == ifNode.trueSuccessor()) {
                 survivingSuccessor = ifNode.falseSuccessor();
             } else {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java	Wed Jan 28 03:28:31 2015 +0100
@@ -79,7 +79,7 @@
         deleteNodes(flood, graph);
 
         // remove chained Merges
-        for (MergeNode merge : graph.getNodes(MergeNode.class)) {
+        for (AbstractMergeNode merge : graph.getNodes(AbstractMergeNode.class)) {
             if (merge.forwardEndCount() == 1 && !(merge instanceof LoopBeginNode)) {
                 graph.reduceTrivialMerge(merge);
             }
@@ -102,7 +102,7 @@
     private static void disconnectCFGNodes(NodeFlood flood, StructuredGraph graph) {
         for (AbstractEndNode node : graph.getNodes(AbstractEndNode.class)) {
             if (!flood.isMarked(node)) {
-                MergeNode merge = node.merge();
+                AbstractMergeNode merge = node.merge();
                 if (merge != null && flood.isMarked(merge)) {
                     // We are a dead end node leading to a live merge.
                     merge.removeEnd(node);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Wed Jan 28 03:28:31 2015 +0100
@@ -52,7 +52,7 @@
                     if (cfg == null) {
                         cfg = ControlFlowGraph.compute(graph, true, true, false, false);
                     }
-                    MergeNode merge;
+                    AbstractMergeNode merge;
                     if (target instanceof AbstractDeoptimizeNode) {
                         merge = graph.add(new MergeNode());
                         EndNode firstEnd = graph.add(new EndNode());
@@ -72,7 +72,7 @@
                         obsoletes.add((AbstractDeoptimizeNode) target);
                         target = merge;
                     } else {
-                        merge = (MergeNode) target;
+                        merge = (AbstractMergeNode) target;
                     }
                     EndNode newEnd = graph.add(new EndNode());
                     merge.addForwardEnd(newEnd);
@@ -84,7 +84,7 @@
                 }
             }
             if (obsoletes != null) {
-                ((DynamicDeoptimizeNode) ((MergeNode) target).next()).setStateBefore(fs);
+                ((DynamicDeoptimizeNode) ((AbstractMergeNode) target).next()).setStateBefore(fs);
                 for (AbstractDeoptimizeNode obsolete : obsoletes) {
                     obsolete.safeDelete();
                 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java	Wed Jan 28 03:28:31 2015 +0100
@@ -55,14 +55,14 @@
     }
 
     private static void processIf(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, IfNode ifNode, double shortCircuitProbability) {
-        BeginNode trueTarget = ifNode.trueSuccessor();
-        BeginNode falseTarget = ifNode.falseSuccessor();
+        AbstractBeginNode trueTarget = ifNode.trueSuccessor();
+        AbstractBeginNode 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))
-         * 
+         *
          * P(X) = shortCircuitProbability
-         * 
+         *
          * P(X union Y) = ifNode.probability(trueTarget)
          */
         double secondIfProbability = (ifNode.probability(trueTarget) - shortCircuitProbability) / (1 - shortCircuitProbability);
@@ -72,15 +72,15 @@
         }
         ifNode.clearSuccessors();
         Graph graph = ifNode.graph();
-        MergeNode trueTargetMerge = graph.add(new MergeNode());
+        AbstractMergeNode trueTargetMerge = graph.add(new MergeNode());
         trueTargetMerge.setNext(trueTarget);
         EndNode firstTrueEnd = graph.add(new EndNode());
         EndNode secondTrueEnd = graph.add(new EndNode());
         trueTargetMerge.addForwardEnd(firstTrueEnd);
         trueTargetMerge.addForwardEnd(secondTrueEnd);
-        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)));
+        AbstractBeginNode firstTrueTarget = BeginNode.begin(firstTrueEnd);
+        AbstractBeginNode secondTrueTarget = BeginNode.begin(secondTrueEnd);
+        AbstractBeginNode 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	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Wed Jan 28 03:28:31 2015 +0100
@@ -150,7 +150,7 @@
         }
     }
 
-    public static MemoryMapImpl mergeMemoryMaps(MergeNode merge, List<? extends MemoryMap> states, boolean updateExistingPhis) {
+    public static MemoryMapImpl mergeMemoryMaps(AbstractMergeNode merge, List<? extends MemoryMap> states, boolean updateExistingPhis) {
         MemoryMapImpl newState = new MemoryMapImpl();
 
         Set<LocationIdentity> keys = CollectionsFactory.newSet();
@@ -237,7 +237,7 @@
         }
 
         @Override
-        protected Set<LocationIdentity> merge(MergeNode merge, List<Set<LocationIdentity>> states) {
+        protected Set<LocationIdentity> merge(AbstractMergeNode merge, List<Set<LocationIdentity>> states) {
             Set<LocationIdentity> result = CollectionsFactory.newSet();
             for (Set<LocationIdentity> other : states) {
                 result.addAll(other);
@@ -246,7 +246,7 @@
         }
 
         @Override
-        protected Set<LocationIdentity> afterSplit(BeginNode node, Set<LocationIdentity> oldState) {
+        protected Set<LocationIdentity> afterSplit(AbstractBeginNode node, Set<LocationIdentity> oldState) {
             return CollectionsFactory.newSet(oldState);
         }
 
@@ -346,12 +346,12 @@
         }
 
         @Override
-        protected MemoryMapImpl merge(MergeNode merge, List<MemoryMapImpl> states) {
+        protected MemoryMapImpl merge(AbstractMergeNode merge, List<MemoryMapImpl> states) {
             return mergeMemoryMaps(merge, states, updateExistingPhis);
         }
 
         @Override
-        protected MemoryMapImpl afterSplit(BeginNode node, MemoryMapImpl oldState) {
+        protected MemoryMapImpl afterSplit(AbstractBeginNode 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	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java	Wed Jan 28 03:28:31 2015 +0100
@@ -88,13 +88,13 @@
         }
 
         @Override
-        protected FrameState merge(MergeNode merge, List<FrameState> states) {
+        protected FrameState merge(AbstractMergeNode merge, List<FrameState> states) {
             FrameState singleFrameState = singleFrameState(states);
             return singleFrameState == null ? merge.stateAfter() : singleFrameState;
         }
 
         @Override
-        protected FrameState afterSplit(BeginNode node, FrameState oldState) {
+        protected FrameState afterSplit(AbstractBeginNode node, FrameState oldState) {
             return oldState;
         }
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Wed Jan 28 03:28:31 2015 +0100
@@ -161,12 +161,12 @@
 
         private void lowerToIf(GuardNode guard) {
             StructuredGraph graph = guard.graph();
-            BeginNode fastPath = graph.add(new BeginNode());
+            AbstractBeginNode fastPath = graph.add(new BeginNode());
             @SuppressWarnings("deprecation")
             DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.action(), guard.reason(), useGuardIdAsDebugId ? guard.getId() : 0, guard.getSpeculation(), null));
-            BeginNode deoptBranch = BeginNode.begin(deopt);
-            BeginNode trueSuccessor;
-            BeginNode falseSuccessor;
+            AbstractBeginNode deoptBranch = BeginNode.begin(deopt);
+            AbstractBeginNode trueSuccessor;
+            AbstractBeginNode falseSuccessor;
             insertLoopExits(deopt);
             if (guard.isNegated()) {
                 trueSuccessor = deoptBranch;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Wed Jan 28 03:28:31 2015 +0100
@@ -319,7 +319,7 @@
                     if (loweringTool.guardAnchor.asNode().isDeleted()) {
                         // TODO nextNode could be deleted but this is not currently supported
                         assert nextNode.isAlive();
-                        loweringTool.guardAnchor = BeginNode.prevBegin(nextNode);
+                        loweringTool.guardAnchor = AbstractBeginNode.prevBegin(nextNode);
                     }
                     assert checkPostNodeLowering(node, loweringTool, preLoweringMark, unscheduledUsages);
                 }
@@ -336,7 +336,7 @@
                         // FixedWithNextNode is followed by some kind of BeginNode.
                         // For example the when a FixedGuard followed by a loop exit is lowered to a
                         // control-split + deopt.
-                        BeginNode begin = node.graph().add(new BeginNode());
+                        AbstractBeginNode begin = node.graph().add(new BeginNode());
                         nextLastFixed.replaceFirstSuccessor(nextNode, begin);
                         begin.setNext(nextNode);
                         nextLastFixed = begin;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java	Wed Jan 28 03:28:31 2015 +0100
@@ -55,11 +55,11 @@
     @Override
     protected void run(StructuredGraph graph) {
         LazyCFG cfg = new LazyCFG(graph);
-        for (BeginNode begin : graph.getNodes(BeginNode.class)) {
+        for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.class)) {
             if (!(begin instanceof StartNode || begin.predecessor() instanceof ControlSplitNode)) {
                 NodeIterable<GuardNode> guards = begin.guards();
                 if (guards.isNotEmpty()) {
-                    BeginNode newAnchor = computeOptimalAnchor(cfg.get(), begin);
+                    AbstractBeginNode 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 BeginNode getOptimalAnchor(LazyCFG cfg, BeginNode begin) {
+    public static AbstractBeginNode getOptimalAnchor(LazyCFG cfg, AbstractBeginNode begin) {
         if (begin instanceof StartNode || begin.predecessor() instanceof ControlSplitNode) {
             return begin;
         }
         return computeOptimalAnchor(cfg.get(), begin);
     }
 
-    private static BeginNode computeOptimalAnchor(ControlFlowGraph cfg, BeginNode begin) {
+    private static AbstractBeginNode computeOptimalAnchor(ControlFlowGraph cfg, AbstractBeginNode 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) {
-        BeginNode successor = findMinimumUsagesSuccessor(controlSplit);
+        AbstractBeginNode 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) {
-                BeginNode anchor = computeOptimalAnchor(cfg.get(), BeginNode.prevBegin(controlSplit));
+                AbstractBeginNode anchor = computeOptimalAnchor(cfg.get(), AbstractBeginNode.prevBegin(controlSplit));
                 GuardNode newGuard = controlSplit.graph().unique(new GuardNode(guard.condition(), anchor, guard.reason(), guard.action(), guard.isNegated(), guard.getSpeculation()));
                 for (GuardNode otherGuard : otherGuards) {
                     otherGuard.replaceAndDelete(newGuard);
@@ -126,12 +126,12 @@
                         conditonGuard.getSpeculation().equals(guard.getSpeculation());
     }
 
-    private static BeginNode findMinimumUsagesSuccessor(ControlSplitNode controlSplit) {
+    private static AbstractBeginNode findMinimumUsagesSuccessor(ControlSplitNode controlSplit) {
         NodePosIterator successors = controlSplit.successors().iterator();
-        BeginNode min = (BeginNode) successors.next();
+        AbstractBeginNode min = (AbstractBeginNode) successors.next();
         int minUsages = min.getUsageCount();
         while (successors.hasNext()) {
-            BeginNode successor = (BeginNode) successors.next();
+            AbstractBeginNode successor = (AbstractBeginNode) successors.next();
             int count = successor.getUsageCount();
             if (count < minUsages) {
                 minUsages = count;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java	Wed Jan 28 03:28:31 2015 +0100
@@ -125,9 +125,9 @@
     }
 
     private static double getNodeWeight(ValueNode node) {
-        if (node instanceof MergeNode) {
-            return ((MergeNode) node).phiPredecessorCount();
-        } else if (node instanceof BeginNode || node instanceof AbstractEndNode || node instanceof MonitorIdNode || node instanceof ConstantNode || node instanceof ParameterNode ||
+        if (node instanceof AbstractMergeNode) {
+            return ((AbstractMergeNode) node).phiPredecessorCount();
+        } else if (node instanceof AbstractBeginNode || 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	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Wed Jan 28 03:28:31 2015 +0100
@@ -47,7 +47,7 @@
 
 /**
  * This class is a phase that looks for opportunities for tail duplication. The static method
- * {@link #tailDuplicate(MergeNode, TailDuplicationDecision, List, PhaseContext, CanonicalizerPhase)}
+ * {@link #tailDuplicate(AbstractMergeNode, TailDuplicationDecision, List, PhaseContext, CanonicalizerPhase)}
  * can also be used to drive tail duplication from other places, e.g., inlining.
  */
 public class TailDuplicationPhase extends BasePhase<PhaseContext> {
@@ -84,7 +84,7 @@
          *            duplicated set of nodes.
          * @return true if the tail duplication should be performed, false otherwise.
          */
-        boolean doTransform(MergeNode merge, int fixedNodeCount);
+        boolean doTransform(AbstractMergeNode merge, int fixedNodeCount);
     }
 
     /**
@@ -94,7 +94,7 @@
      */
     public static final TailDuplicationDecision DEFAULT_DECISION = new TailDuplicationDecision() {
 
-        public boolean doTransform(MergeNode merge, int fixedNodeCount) {
+        public boolean doTransform(AbstractMergeNode merge, int fixedNodeCount) {
             if (fixedNodeCount < TailDuplicationTrivialSize.getValue()) {
                 return true;
             }
@@ -144,7 +144,7 @@
     public static final TailDuplicationDecision TRUE_DECISION = new TailDuplicationDecision() {
 
         @Override
-        public boolean doTransform(MergeNode merge, int fixedNodeCount) {
+        public boolean doTransform(AbstractMergeNode merge, int fixedNodeCount) {
             return true;
         }
     };
@@ -155,12 +155,12 @@
 
     @Override
     protected void run(StructuredGraph graph, PhaseContext phaseContext) {
-        if (graph.hasNode(MergeNode.class)) {
+        if (graph.hasNode(AbstractMergeNode.class)) {
             ToDoubleFunction<FixedNode> nodeProbabilities = new FixedNodeProbabilityCache();
 
             // A snapshot is taken here, so that new MergeNode instances aren't considered for tail
             // duplication.
-            for (MergeNode merge : graph.getNodes(MergeNode.class).snapshot()) {
+            for (AbstractMergeNode merge : graph.getNodes(AbstractMergeNode.class).snapshot()) {
                 if (!(merge instanceof LoopBeginNode) && nodeProbabilities.applyAsDouble(merge) >= TailDuplicationProbability.getValue()) {
                     tailDuplicate(merge, DEFAULT_DECISION, null, phaseContext, canonicalizer);
                 }
@@ -172,7 +172,7 @@
      * This method attempts to duplicate the tail of the given merge. The merge must not be a
      * {@link LoopBeginNode}. If the merge is eligible for duplication (at least one fixed node in
      * its tail, no {@link MonitorEnterNode}/ {@link MonitorExitNode}, non-null
-     * {@link MergeNode#stateAfter()}) then the decision callback is used to determine whether the
+     * {@link AbstractMergeNode#stateAfter()}) then the decision callback is used to determine whether the
      * tail duplication should actually be performed. If replacements is non-null, then this list of
      * {@link PiNode}s is used to replace one value per merge end.
      *
@@ -185,7 +185,7 @@
      *            {@link PiNode} in the duplicated branch that corresponds to the entry.
      * @param phaseContext
      */
-    public static boolean tailDuplicate(MergeNode merge, TailDuplicationDecision decision, List<GuardedValueNode> replacements, PhaseContext phaseContext, CanonicalizerPhase canonicalizer) {
+    public static boolean tailDuplicate(AbstractMergeNode merge, TailDuplicationDecision decision, List<GuardedValueNode> replacements, PhaseContext phaseContext, CanonicalizerPhase canonicalizer) {
         assert !(merge instanceof LoopBeginNode);
         assert replacements == null || replacements.size() == merge.forwardEndCount();
         FixedNode fixed = merge;
@@ -209,11 +209,11 @@
     }
 
     /**
-     * This class encapsulates one tail duplication operation on a specific {@link MergeNode}.
+     * This class encapsulates one tail duplication operation on a specific {@link AbstractMergeNode}.
      */
     private static class DuplicationOperation {
 
-        private final MergeNode merge;
+        private final AbstractMergeNode merge;
         private final StructuredGraph graph;
 
         private final Map<ValueNode, PhiNode> bottomPhis = Node.newMap();
@@ -228,7 +228,7 @@
          * @param replacements A list of replacement {@link PiNode}s, or null. If this is non-null,
          *            then the size of the list needs to match the number of end nodes at the merge.
          */
-        public DuplicationOperation(MergeNode merge, List<GuardedValueNode> replacements, CanonicalizerPhase canonicalizer) {
+        public DuplicationOperation(AbstractMergeNode merge, List<GuardedValueNode> replacements, CanonicalizerPhase canonicalizer) {
             this.merge = merge;
             this.replacements = replacements;
             this.graph = merge.graph();
@@ -270,7 +270,7 @@
             }
 
             AbstractEndNode endAfter = createNewMerge(fixed, stateAfter);
-            MergeNode mergeAfter = endAfter.merge();
+            AbstractMergeNode mergeAfter = endAfter.merge();
             fixedNodes.add(endAfter);
             final Set<Node> duplicatedNodes = buildDuplicatedNodeSet(fixedNodes, stateAfter);
             mergeAfter.clearEnds();
@@ -298,7 +298,7 @@
                 // EndNode
                 FixedWithNextNode anchorDuplicate = (FixedWithNextNode) duplicates.get(anchor);
                 // move dependencies on the ValueAnchorNode to the previous BeginNode
-                BeginNode prevBegin = BeginNode.prevBegin(forwardEnd);
+                AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(forwardEnd);
                 anchorDuplicate.replaceAtUsages(InputType.Guard, prevBegin);
                 anchorDuplicate.replaceAtUsages(InputType.Anchor, prevBegin);
                 assert anchorDuplicate.hasNoUsages();
@@ -448,7 +448,7 @@
          * @return The newly created end node.
          */
         private AbstractEndNode createNewMerge(FixedNode successor, FrameState stateAfterMerge) {
-            MergeNode newBottomMerge = graph.add(new MergeNode());
+            AbstractMergeNode newBottomMerge = graph.add(new MergeNode());
             AbstractEndNode newBottomEnd = graph.add(new EndNode());
             newBottomMerge.addForwardEnd(newBottomEnd);
             newBottomMerge.setStateAfter(stateAfterMerge);
@@ -477,7 +477,7 @@
          *            for newly created phis and to as a target for dependencies that pointed into
          *            the duplicated set of nodes.
          */
-        private void expandDuplicated(Set<Node> duplicatedNodes, MergeNode newBottomMerge) {
+        private void expandDuplicated(Set<Node> duplicatedNodes, AbstractMergeNode newBottomMerge) {
             Deque<Node> worklist = new ArrayDeque<>(duplicatedNodes);
 
             while (!worklist.isEmpty()) {
@@ -487,7 +487,7 @@
             }
         }
 
-        private void processUsages(Node duplicated, Set<Node> duplicatedNodes, MergeNode newBottomMerge, Deque<Node> worklist) {
+        private void processUsages(Node duplicated, Set<Node> duplicatedNodes, AbstractMergeNode newBottomMerge, Deque<Node> worklist) {
             Set<Node> unique = Node.newSet();
             duplicated.usages().snapshotTo(unique);
             Node newOutsideClone = null;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Wed Jan 28 03:28:31 2015 +0100
@@ -58,8 +58,8 @@
 
     private static void tryUseTrappingNullCheck(MetaAccessProvider metaAccessProvider, DynamicDeoptimizeNode deopt) {
         Node predecessor = deopt.predecessor();
-        if (predecessor instanceof MergeNode) {
-            MergeNode merge = (MergeNode) predecessor;
+        if (predecessor instanceof AbstractMergeNode) {
+            AbstractMergeNode merge = (AbstractMergeNode) predecessor;
 
             // Process each predecessor at the merge, unpacking the reasons and speculations as
             // needed.
@@ -115,23 +115,23 @@
         if (speculation != null && !speculation.equals(JavaConstant.NULL_POINTER)) {
             return;
         }
-        if (predecessor instanceof MergeNode) {
-            MergeNode merge = (MergeNode) predecessor;
+        if (predecessor instanceof AbstractMergeNode) {
+            AbstractMergeNode merge = (AbstractMergeNode) predecessor;
             if (merge.phis().isEmpty()) {
                 for (AbstractEndNode end : merge.cfgPredecessors().snapshot()) {
                     checkPredecessor(deopt, end.predecessor(), deoptimizationReason);
                 }
             }
-        } else if (predecessor instanceof BeginNode) {
+        } else if (predecessor instanceof AbstractBeginNode) {
             checkPredecessor(deopt, predecessor, deoptimizationReason);
         }
     }
 
     private static void checkPredecessor(AbstractDeoptimizeNode deopt, Node predecessor, DeoptimizationReason deoptimizationReason) {
         Node current = predecessor;
-        BeginNode branch = null;
-        while (current instanceof BeginNode) {
-            branch = (BeginNode) current;
+        AbstractBeginNode branch = null;
+        while (current instanceof AbstractBeginNode) {
+            branch = (AbstractBeginNode) current;
             if (branch.anchored().isNotEmpty()) {
                 // some input of the deopt framestate is anchored to this branch
                 return;
@@ -159,8 +159,8 @@
             metricTrappingNullCheckUnreached.increment();
         }
         IsNullNode isNullNode = (IsNullNode) condition;
-        BeginNode nonTrappingContinuation = ifNode.falseSuccessor();
-        BeginNode trappingContinuation = ifNode.trueSuccessor();
+        AbstractBeginNode nonTrappingContinuation = ifNode.falseSuccessor();
+        AbstractBeginNode trappingContinuation = ifNode.trueSuccessor();
         NullCheckNode trappingNullCheck = deopt.graph().add(new NullCheckNode(isNullNode.getValue()));
         trappingNullCheck.setStateBefore(deopt.stateBefore());
         deopt.graph().replaceSplit(ifNode, trappingNullCheck, nonTrappingContinuation);
@@ -171,7 +171,7 @@
          * then remove the Begin from the graph.
          */
         nonTrappingContinuation.replaceAtUsages(InputType.Guard, trappingNullCheck);
-        if (nonTrappingContinuation.getClass() == BeginNode.class) {
+        if (nonTrappingContinuation instanceof BeginNode) {
             FixedNode next = nonTrappingContinuation.next();
             nonTrappingContinuation.clearSuccessors();
             trappingNullCheck.setNext(next);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ValueAnchorCleanupPhase.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ValueAnchorCleanupPhase.java	Wed Jan 28 03:28:31 2015 +0100
@@ -50,7 +50,7 @@
         }
 
         @Override
-        public boolean merge(MergeNode merge, List<State> withStates) {
+        public boolean merge(AbstractMergeNode merge, List<State> withStates) {
             for (State other : withStates) {
                 anchoredValues.retainAll(other.anchoredValues);
             }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java	Wed Jan 28 03:28:31 2015 +0100
@@ -265,7 +265,7 @@
             }
         }
 
-        final BeginNode prevBegin = BeginNode.prevBegin(invokeNode);
+        final AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(invokeNode);
         DuplicationReplacement localReplacement = new DuplicationReplacement() {
 
             public Node replacement(Node node) {
@@ -303,9 +303,9 @@
             }
 
             // get rid of memory kill
-            BeginNode begin = invokeWithException.next();
+            AbstractBeginNode begin = invokeWithException.next();
             if (begin instanceof KillingBeginNode) {
-                BeginNode newBegin = new BeginNode();
+                AbstractBeginNode newBegin = new BeginNode();
                 graph.addAfterFixed(begin, graph.add(newBegin));
                 begin.replaceAtUsages(newBegin);
                 graph.removeFixed(begin);
@@ -344,7 +344,7 @@
                 for (ReturnNode returnNode : returnNodes) {
                     returnDuplicates.add((ReturnNode) duplicates.get(returnNode));
                 }
-                MergeNode merge = graph.add(new MergeNode());
+                AbstractMergeNode merge = graph.add(new MergeNode());
                 merge.setStateAfter(stateAfter);
                 ValueNode returnValue = mergeReturns(merge, returnDuplicates, canonicalizedNodes);
                 invokeNode.replaceAtUsages(returnValue);
@@ -448,8 +448,8 @@
                 } else {
                     StateSplit stateSplit = (StateSplit) usage;
                     FixedNode fixedStateSplit = stateSplit.asNode();
-                    if (fixedStateSplit instanceof MergeNode) {
-                        MergeNode merge = (MergeNode) fixedStateSplit;
+                    if (fixedStateSplit instanceof AbstractMergeNode) {
+                        AbstractMergeNode merge = (AbstractMergeNode) fixedStateSplit;
                         while (merge.isAlive()) {
                             AbstractEndNode end = merge.forwardEnds().first();
                             DeoptimizeNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler));
@@ -458,7 +458,7 @@
                         }
                     } else {
                         FixedNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler));
-                        if (fixedStateSplit instanceof BeginNode) {
+                        if (fixedStateSplit instanceof AbstractBeginNode) {
                             deoptimizeNode = BeginNode.begin(deoptimizeNode);
                         }
                         fixedStateSplit.replaceAtPredecessor(deoptimizeNode);
@@ -469,7 +469,7 @@
         }
     }
 
-    public static ValueNode mergeReturns(MergeNode merge, List<? extends ReturnNode> returnNodes, List<Node> canonicalizedNodes) {
+    public static ValueNode mergeReturns(AbstractMergeNode merge, List<? extends ReturnNode> returnNodes, List<Node> canonicalizedNodes) {
         PhiNode returnValuePhi = null;
 
         for (ReturnNode returnNode : returnNodes) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Wed Jan 28 03:28:31 2015 +0100
@@ -173,7 +173,7 @@
 
         ValueNode originalReceiver = ((MethodCallTargetNode) invoke.callTarget()).receiver();
         // setup merge and phi nodes for results and exceptions
-        MergeNode returnMerge = graph.add(new MergeNode());
+        AbstractMergeNode returnMerge = graph.add(new MergeNode());
         returnMerge.setStateAfter(invoke.stateAfter());
 
         PhiNode returnValuePhi = null;
@@ -181,7 +181,7 @@
             returnValuePhi = graph.addWithoutUnique(new ValuePhiNode(invoke.asNode().stamp().unrestricted(), returnMerge));
         }
 
-        MergeNode exceptionMerge = null;
+        AbstractMergeNode exceptionMerge = null;
         PhiNode exceptionObjectPhi = null;
         if (invoke instanceof InvokeWithExceptionNode) {
             InvokeWithExceptionNode invokeWithException = (InvokeWithExceptionNode) invoke;
@@ -196,7 +196,7 @@
         }
 
         // create one separate block for each invoked method
-        BeginNode[] successors = new BeginNode[numberOfMethods + 1];
+        AbstractBeginNode[] successors = new AbstractBeginNode[numberOfMethods + 1];
         for (int i = 0; i < numberOfMethods; i++) {
             successors[i] = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, true);
         }
@@ -234,7 +234,7 @@
 
         // prepare the anchors for the invokes
         for (int i = 0; i < numberOfMethods; i++) {
-            BeginNode node = successors[i];
+            AbstractBeginNode node = successors[i];
             Invoke invokeForInlining = (Invoke) node.next();
 
             ResolvedJavaType commonType;
@@ -330,10 +330,10 @@
     private Collection<Node> inlineSingleMethod(StructuredGraph graph, MetaAccessProvider metaAccess, Assumptions assumptions, StampProvider stampProvider) {
         assert concretes.size() == 1 && inlineableElements.length == 1 && ptypes.size() > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0;
 
-        BeginNode calleeEntryNode = graph.add(new BeginNode());
+        AbstractBeginNode calleeEntryNode = graph.add(new BeginNode());
 
-        BeginNode unknownTypeSux = createUnknownTypeSuccessor(graph);
-        BeginNode[] successors = new BeginNode[]{calleeEntryNode, unknownTypeSux};
+        AbstractBeginNode unknownTypeSux = createUnknownTypeSuccessor(graph);
+        AbstractBeginNode[] successors = new AbstractBeginNode[]{calleeEntryNode, unknownTypeSux};
         createDispatchOnTypeBeforeInvoke(graph, successors, false, metaAccess, stampProvider);
 
         calleeEntryNode.setNext(invoke.asNode());
@@ -341,7 +341,7 @@
         return inline(invoke, methodAt(0), inlineableElementAt(0), assumptions, false);
     }
 
-    private boolean createDispatchOnTypeBeforeInvoke(StructuredGraph graph, BeginNode[] successors, boolean invokeIsOnlySuccessor, MetaAccessProvider metaAccess, StampProvider stampProvider) {
+    private boolean createDispatchOnTypeBeforeInvoke(StructuredGraph graph, AbstractBeginNode[] successors, boolean invokeIsOnlySuccessor, MetaAccessProvider metaAccess, StampProvider stampProvider) {
         assert ptypes.size() >= 1;
         ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke);
         LoadHubNode hub = graph.unique(new LoadHubNode(stampProvider, nonNullReceiver));
@@ -459,10 +459,10 @@
         return costEstimateMethodDispatch < costEstimateTypeDispatch;
     }
 
-    private static BeginNode createInvocationBlock(StructuredGraph graph, Invoke invoke, MergeNode returnMerge, PhiNode returnValuePhi, MergeNode exceptionMerge, PhiNode exceptionObjectPhi,
+    private static AbstractBeginNode createInvocationBlock(StructuredGraph graph, Invoke invoke, AbstractMergeNode returnMerge, PhiNode returnValuePhi, AbstractMergeNode exceptionMerge, PhiNode exceptionObjectPhi,
                     boolean useForInlining) {
         Invoke duplicatedInvoke = duplicateInvokeForInlining(graph, invoke, exceptionMerge, exceptionObjectPhi, useForInlining);
-        BeginNode calleeEntryNode = graph.add(new BeginNode());
+        AbstractBeginNode calleeEntryNode = graph.add(new BeginNode());
         calleeEntryNode.setNext(duplicatedInvoke.asNode());
 
         AbstractEndNode endNode = graph.add(new EndNode());
@@ -475,7 +475,7 @@
         return calleeEntryNode;
     }
 
-    private static Invoke duplicateInvokeForInlining(StructuredGraph graph, Invoke invoke, MergeNode exceptionMerge, PhiNode exceptionObjectPhi, boolean useForInlining) {
+    private static Invoke duplicateInvokeForInlining(StructuredGraph graph, Invoke invoke, AbstractMergeNode exceptionMerge, PhiNode exceptionObjectPhi, boolean useForInlining) {
         Invoke result = (Invoke) invoke.asNode().copyWithInputs();
         Node callTarget = result.callTarget().copyWithInputs();
         result.asNode().replaceFirstInput(result.callTarget(), callTarget);
@@ -538,9 +538,9 @@
     }
 
     private void devirtualizeWithTypeSwitch(StructuredGraph graph, InvokeKind kind, ResolvedJavaMethod target, MetaAccessProvider metaAccess, StampProvider stampProvider) {
-        BeginNode invocationEntry = graph.add(new BeginNode());
-        BeginNode unknownTypeSux = createUnknownTypeSuccessor(graph);
-        BeginNode[] successors = new BeginNode[]{invocationEntry, unknownTypeSux};
+        AbstractBeginNode invocationEntry = graph.add(new BeginNode());
+        AbstractBeginNode unknownTypeSux = createUnknownTypeSuccessor(graph);
+        AbstractBeginNode[] successors = new AbstractBeginNode[]{invocationEntry, unknownTypeSux};
         createDispatchOnTypeBeforeInvoke(graph, successors, true, metaAccess, stampProvider);
 
         invocationEntry.setNext(invoke.asNode());
@@ -550,7 +550,7 @@
         InliningUtil.replaceInvokeCallTarget(invoke, graph, kind, target);
     }
 
-    private static BeginNode createUnknownTypeSuccessor(StructuredGraph graph) {
+    private static AbstractBeginNode createUnknownTypeSuccessor(StructuredGraph graph) {
         return BeginNode.begin(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated)));
     }
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/ComputeInliningRelevance.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/ComputeInliningRelevance.java	Wed Jan 28 03:28:31 2015 +0100
@@ -114,9 +114,9 @@
                         parent = loops.get(null);
                         break;
                     } else {
-                        assert current.getClass() == MergeNode.class : current;
+                        assert current instanceof MergeNode : current;
                         // follow any path upwards - it doesn't matter which one
-                        current = ((MergeNode) current).forwardEndAt(0);
+                        current = ((AbstractMergeNode) current).forwardEndAt(0);
                     }
                 } else if (current instanceof LoopExitNode) {
                     // if we reach a loop exit then we follow this loop and have the same parent
@@ -278,7 +278,7 @@
         int pathBeginCount = pathBeginNodes.size();
 
         for (Node sux : controlSplit.successors()) {
-            double probability = controlSplit.probability((BeginNode) sux);
+            double probability = controlSplit.probability((AbstractBeginNode) sux);
             if (probability > maxProbability) {
                 maxProbability = probability;
                 maxSux = sux;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningIterator.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningIterator.java	Wed Jan 28 03:28:31 2015 +0100
@@ -67,7 +67,7 @@
                 queueSuccessors(current);
             } else if (current instanceof LoopEndNode) {
                 // nothing to do
-            } else if (current instanceof MergeNode) {
+            } else if (current instanceof AbstractMergeNode) {
                 queueSuccessors(current);
             } else if (current instanceof FixedWithNextNode) {
                 queueSuccessors(current);
@@ -114,14 +114,14 @@
     }
 
     private void queueMerge(AbstractEndNode end) {
-        MergeNode merge = end.merge();
+        AbstractMergeNode merge = end.merge();
         if (!queuedNodes.isMarked(merge) && visitedAllEnds(merge)) {
             queuedNodes.mark(merge);
             nodeQueue.add(merge);
         }
     }
 
-    private boolean visitedAllEnds(MergeNode merge) {
+    private boolean visitedAllEnds(AbstractMergeNode merge) {
         for (int i = 0; i < merge.forwardEndCount(); i++) {
             if (!queuedNodes.isMarked(merge.forwardEndAt(i))) {
                 return false;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java	Wed Jan 28 03:28:31 2015 +0100
@@ -30,7 +30,7 @@
 import com.oracle.graal.nodes.*;
 
 /**
- * Compute probabilities for fixed nodes on the fly and cache them at {@link BeginNode}s.
+ * Compute probabilities for fixed nodes on the fly and cache them at {@link AbstractBeginNode}s.
  */
 public class FixedNodeProbabilityCache implements ToDoubleFunction<FixedNode> {
 
@@ -40,7 +40,7 @@
 
     /**
      * <p>
-     * Given a {@link FixedNode} this method finds the most immediate {@link BeginNode} preceding it
+     * Given a {@link FixedNode} this method finds the most immediate {@link AbstractBeginNode} preceding it
      * that either:
      * <ul>
      * <li>has no predecessor (ie, the begin-node is a merge, in particular a loop-begin, or the
@@ -50,7 +50,7 @@
      * </p>
      *
      * <p>
-     * The thus found {@link BeginNode} is equi-probable with the {@link FixedNode} it was obtained
+     * The thus found {@link AbstractBeginNode} is equi-probable with the {@link FixedNode} it was obtained
      * from. When computed for the first time (afterwards a cache lookup returns it) that
      * probability is computed as follows, again depending on the begin-node's predecessor:
      * <ul>
@@ -77,7 +77,7 @@
         while (true) {
             assert current != null;
             Node predecessor = current.predecessor();
-            if (current instanceof BeginNode) {
+            if (current instanceof AbstractBeginNode) {
                 if (predecessor == null) {
                     break;
                 } else if (predecessor.successors().count() != 1) {
@@ -91,7 +91,7 @@
             current = (FixedNode) predecessor;
         }
 
-        assert current instanceof BeginNode;
+        assert current instanceof AbstractBeginNode;
         Double cachedValue = cache.get(current);
         if (cachedValue != null) {
             return cachedValue;
@@ -99,8 +99,8 @@
 
         double probability = 0.0;
         if (current.predecessor() == null) {
-            if (current instanceof MergeNode) {
-                MergeNode currentMerge = (MergeNode) current;
+            if (current instanceof AbstractMergeNode) {
+                AbstractMergeNode currentMerge = (AbstractMergeNode) current;
                 NodeInputList<AbstractEndNode> currentForwardEnds = currentMerge.forwardEnds();
                 /*
                  * Use simple iteration instead of streams, since the stream infrastructure adds
@@ -119,7 +119,7 @@
             }
         } else {
             ControlSplitNode split = (ControlSplitNode) current.predecessor();
-            probability = split.probability((BeginNode) current) * applyAsDouble(split);
+            probability = split.probability((AbstractBeginNode) current) * applyAsDouble(split);
         }
         assert !Double.isNaN(probability) && !Double.isInfinite(probability) : current + " " + probability;
         cache.put(current, probability);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java	Wed Jan 28 03:28:31 2015 +0100
@@ -38,7 +38,7 @@
      * @param merge the merge node
      * @param withStates the state at the the merge's end node except the first one.
      */
-    public abstract boolean merge(MergeNode merge, List<T> withStates);
+    public abstract boolean merge(AbstractMergeNode merge, List<T> withStates);
 
     /**
      * This method is called before a loop is entered (before the {@link LoopBeginNode} is visited).
@@ -65,7 +65,7 @@
      *
      * @param node the successor of the control split that is about to be visited
      */
-    public void afterSplit(BeginNode node) {
+    public void afterSplit(AbstractBeginNode node) {
         // empty default implementation
     }
 }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java	Wed Jan 28 03:28:31 2015 +0100
@@ -32,7 +32,7 @@
  * specified fixed node.
  * <p>
  * For this iterator the CFG is defined by the classical CFG nodes ({@link ControlSplitNode},
- * {@link MergeNode}...) and the {@link FixedWithNextNode#next() next} pointers of
+ * {@link AbstractMergeNode}...) and the {@link FixedWithNextNode#next() next} pointers of
  * {@link FixedWithNextNode}.
  * <p>
  * While iterating it maintains a user-defined state by calling the methods available in
@@ -43,7 +43,7 @@
 public abstract class PostOrderNodeIterator<T extends MergeableState<T>> {
 
     private final NodeBitMap visitedEnds;
-    private final Deque<BeginNode> nodeQueue;
+    private final Deque<AbstractBeginNode> nodeQueue;
     private final Map<FixedNode, T> nodeStates;
     private final FixedNode start;
 
@@ -77,9 +77,9 @@
                 loopEnd((LoopEndNode) current);
                 finishLoopEnds((LoopEndNode) current);
                 current = nextQueuedNode();
-            } else if (current instanceof MergeNode) {
-                merge((MergeNode) current);
-                current = ((MergeNode) current).next();
+            } else if (current instanceof AbstractMergeNode) {
+                merge((AbstractMergeNode) current);
+                current = ((AbstractMergeNode) current).next();
                 assert current != null;
             } else if (current instanceof FixedWithNextNode) {
                 FixedNode next = ((FixedWithNextNode) current).next();
@@ -110,13 +110,13 @@
             for (Node node : successors) {
                 if (node != null) {
                     nodeStates.put((FixedNode) node.predecessor(), state);
-                    nodeQueue.addFirst((BeginNode) node);
+                    nodeQueue.addFirst((AbstractBeginNode) node);
                 }
             }
         } else {
             for (Node node : x.successors()) {
                 if (node != null) {
-                    nodeQueue.addFirst((BeginNode) node);
+                    nodeQueue.addFirst((AbstractBeginNode) node);
                 }
             }
         }
@@ -125,9 +125,9 @@
     private FixedNode nextQueuedNode() {
         int maxIterations = nodeQueue.size();
         while (maxIterations-- > 0) {
-            BeginNode node = nodeQueue.removeFirst();
-            if (node instanceof MergeNode) {
-                MergeNode merge = (MergeNode) node;
+            AbstractBeginNode node = nodeQueue.removeFirst();
+            if (node instanceof AbstractMergeNode) {
+                AbstractMergeNode merge = (AbstractMergeNode) node;
                 state = nodeStates.get(merge.forwardEndAt(0)).clone();
                 ArrayList<T> states = new ArrayList<>(merge.forwardEndCount() - 1);
                 for (int i = 1; i < merge.forwardEndCount(); i++) {
@@ -181,7 +181,7 @@
         assert !nodeStates.containsKey(end);
         nodeStates.put(end, state);
         visitedEnds.mark(end);
-        MergeNode merge = end.merge();
+        AbstractMergeNode merge = end.merge();
         boolean endsVisited = true;
         for (int i = 0; i < merge.forwardEndCount(); i++) {
             if (!visitedEnds.isMarked(merge.forwardEndAt(i))) {
@@ -200,7 +200,7 @@
         node(endNode);
     }
 
-    protected void merge(MergeNode merge) {
+    protected void merge(AbstractMergeNode merge) {
         node(merge);
     }
 
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java	Wed Jan 28 03:28:31 2015 +0100
@@ -118,7 +118,7 @@
                         AbstractEndNode end = (AbstractEndNode) current.getEndNode();
 
                         // add the end node and see if the merge is ready for processing
-                        MergeNode merge = end.merge();
+                        AbstractMergeNode merge = end.merge();
                         if (allEndsVisited(states, current, merge)) {
                             ArrayList<StateT> mergedStates = mergeStates(states, state, current, successor, merge);
                             state = closure.merge(successor, mergedStates);
@@ -149,7 +149,7 @@
         }
     }
 
-    private static <StateT> boolean allEndsVisited(Map<FixedNode, StateT> states, Block current, MergeNode merge) {
+    private static <StateT> boolean allEndsVisited(Map<FixedNode, StateT> states, Block current, AbstractMergeNode merge) {
         for (AbstractEndNode forwardEnd : merge.forwardEnds()) {
             if (forwardEnd != current.getEndNode() && !states.containsKey(forwardEnd)) {
                 return false;
@@ -168,7 +168,7 @@
         return successors.get(0);
     }
 
-    private static <StateT> ArrayList<StateT> mergeStates(Map<FixedNode, StateT> states, StateT state, Block current, Block successor, MergeNode merge) {
+    private static <StateT> ArrayList<StateT> mergeStates(Map<FixedNode, StateT> states, StateT state, Block current, Block successor, AbstractMergeNode merge) {
         ArrayList<StateT> mergedStates = new ArrayList<>(merge.forwardEndCount());
         for (Block predecessor : successor.getPredecessors()) {
             assert predecessor == current || states.containsKey(predecessor.getEndNode());
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java	Wed Jan 28 03:28:31 2015 +0100
@@ -44,9 +44,9 @@
 
         protected abstract StateT processNode(FixedNode node, StateT currentState);
 
-        protected abstract StateT merge(MergeNode merge, List<StateT> states);
+        protected abstract StateT merge(AbstractMergeNode merge, List<StateT> states);
 
-        protected abstract StateT afterSplit(BeginNode node, StateT oldState);
+        protected abstract StateT afterSplit(AbstractBeginNode node, StateT oldState);
 
         protected abstract Map<LoopExitNode, StateT> processLoop(LoopBeginNode loop, StateT initialState);
 
@@ -87,7 +87,7 @@
 
     private static <StateT> Map<FixedNode, StateT> apply(NodeIteratorClosure<StateT> closure, FixedNode start, StateT initialState, LoopBeginNode boundary) {
         assert start != null;
-        Deque<BeginNode> nodeQueue = new ArrayDeque<>();
+        Deque<AbstractBeginNode> nodeQueue = new ArrayDeque<>();
         Map<FixedNode, StateT> blockEndStates = Node.newIdentityMap();
 
         StateT state = initialState;
@@ -114,7 +114,7 @@
                             blockEndStates.put(current, state);
                         } else if (current instanceof EndNode) {
                             // add the end node and see if the merge is ready for processing
-                            MergeNode merge = ((EndNode) current).merge();
+                            AbstractMergeNode merge = ((EndNode) current).merge();
                             if (merge instanceof LoopBeginNode) {
                                 Map<LoopExitNode, StateT> loopExitState = closure.processLoop((LoopBeginNode) merge, state);
                                 for (Map.Entry<LoopExitNode, StateT> entry : loopExitState.entrySet()) {
@@ -153,7 +153,7 @@
                             continue;
                         } else {
                             do {
-                                BeginNode successor = (BeginNode) successors.next();
+                                AbstractBeginNode successor = (AbstractBeginNode) successors.next();
                                 StateT successorState = closure.afterSplit(successor, state);
                                 if (closure.continueIteration(successorState)) {
                                     blockEndStates.put(successor, successorState);
@@ -161,7 +161,7 @@
                                 }
                             } while (successors.hasNext());
 
-                            state = closure.afterSplit((BeginNode) firstSuccessor, state);
+                            state = closure.afterSplit((AbstractBeginNode) firstSuccessor, state);
                             current = closure.continueIteration(state) ? firstSuccessor : null;
                             continue;
                         }
@@ -176,7 +176,7 @@
                 current = nodeQueue.removeFirst();
                 assert blockEndStates.containsKey(current);
                 state = blockEndStates.remove(current);
-                assert !(current instanceof MergeNode) && current instanceof BeginNode;
+                assert !(current instanceof AbstractMergeNode) && current instanceof AbstractBeginNode;
             }
         } while (true);
     }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScopedPostOrderNodeIterator.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScopedPostOrderNodeIterator.java	Wed Jan 28 03:28:31 2015 +0100
@@ -67,7 +67,7 @@
                 queueLoopExitSuccessors((LoopExitNode) current);
             } else if (current instanceof LoopEndNode) {
                 // nothing todo
-            } else if (current instanceof MergeNode) {
+            } else if (current instanceof AbstractMergeNode) {
                 queueSuccessors(current);
             } else if (current instanceof FixedWithNextNode) {
                 queueSuccessors(current);
@@ -142,13 +142,13 @@
     }
 
     private void queueMerge(AbstractEndNode end) {
-        MergeNode merge = end.merge();
+        AbstractMergeNode merge = end.merge();
         if (!queuedNodes.isMarked(merge) && visitedAllEnds(merge)) {
             queue(merge);
         }
     }
 
-    private boolean visitedAllEnds(MergeNode merge) {
+    private boolean visitedAllEnds(AbstractMergeNode merge) {
         for (int i = 0; i < merge.forwardEndCount(); i++) {
             if (!queuedNodes.isMarked(merge.forwardEndAt(i))) {
                 return false;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/SinglePassNodeIterator.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/SinglePassNodeIterator.java	Wed Jan 28 03:28:31 2015 +0100
@@ -32,16 +32,16 @@
  * start node. Unlike in iterative dataflow analysis, a single pass is performed, which allows
  * keeping a smaller working set of pending {@link MergeableState}. This iteration scheme requires:
  * <ul>
- * <li>{@link MergeableState#merge(MergeNode, List)} to always return <code>true</code> (an
+ * <li>{@link MergeableState#merge(AbstractMergeNode, List)} to always return <code>true</code> (an
  * assertion checks this)</li>
  * <li>{@link #controlSplit(ControlSplitNode)} to always return all successors (otherwise, not all
  * associated {@link EndNode} will be visited. In turn, visiting all the end nodes for a given
- * {@link MergeNode} is a precondition before that merge node can be visited)</li>
+ * {@link AbstractMergeNode} is a precondition before that merge node can be visited)</li>
  * </ul>
  *
  * <p>
  * For this iterator the CFG is defined by the classical CFG nodes (
- * {@link com.oracle.graal.nodes.ControlSplitNode}, {@link com.oracle.graal.nodes.MergeNode}...) and
+ * {@link com.oracle.graal.nodes.ControlSplitNode}, {@link com.oracle.graal.nodes.AbstractMergeNode}...) and
  * the {@link com.oracle.graal.nodes.FixedWithNextNode#next() next} pointers of
  * {@link com.oracle.graal.nodes.FixedWithNextNode}.
  * </p>
@@ -101,7 +101,7 @@
      * <p>
      * Correspondingly each item may stand for:
      * <ul>
-     * <li>a {@link MergeNode} whose pre-state results from merging those of its forward-ends, see
+     * <li>a {@link AbstractMergeNode} whose pre-state results from merging those of its forward-ends, see
      * {@link #nextQueuedNode()}</li>
      * <li>a successor of a control-split node, in which case the state on entry to it (the
      * successor) is also stored in the item, see {@link #nextQueuedNode()}</li>
@@ -109,10 +109,10 @@
      * </p>
      */
     private static final class PathStart<U> {
-        private final BeginNode node;
+        private final AbstractBeginNode node;
         private final U stateOnEntry;
 
-        private PathStart(BeginNode node, U stateOnEntry) {
+        private PathStart(AbstractBeginNode node, U stateOnEntry) {
             this.node = node;
             this.stateOnEntry = stateOnEntry;
             assert repOK();
@@ -125,7 +125,7 @@
             if (node == null) {
                 return false;
             }
-            if (node instanceof MergeNode) {
+            if (node instanceof AbstractMergeNode) {
                 return stateOnEntry == null;
             }
             return (stateOnEntry != null);
@@ -169,9 +169,9 @@
                 loopEnd((LoopEndNode) current);
                 finishLoopEnds((LoopEndNode) current);
                 current = nextQueuedNode();
-            } else if (current instanceof MergeNode) {
-                merge((MergeNode) current);
-                current = ((MergeNode) current).next();
+            } else if (current instanceof AbstractMergeNode) {
+                merge((AbstractMergeNode) current);
+                current = ((AbstractMergeNode) current).next();
                 assert current != null;
             } else if (current instanceof FixedWithNextNode) {
                 FixedNode next = ((FixedWithNextNode) current).next();
@@ -210,13 +210,13 @@
     private void queueSuccessors(FixedNode x) {
         Iterator<Node> iter = x.successors().nonNull().iterator();
         if (iter.hasNext()) {
-            BeginNode begin = (BeginNode) iter.next();
+            AbstractBeginNode begin = (AbstractBeginNode) iter.next();
             // the current state isn't cloned for the first successor
             // conceptually, the state is handed over to it
             nodeQueue.addFirst(new PathStart<>(begin, state));
         }
         while (iter.hasNext()) {
-            BeginNode begin = (BeginNode) iter.next();
+            AbstractBeginNode begin = (AbstractBeginNode) iter.next();
             // for all other successors it is cloned
             nodeQueue.addFirst(new PathStart<>(begin, state.clone()));
         }
@@ -228,7 +228,7 @@
      * the pre-state for that node.
      *
      * <p>
-     * Upon reaching a {@link MergeNode}, some entries are pruned from {@link #nodeStates} (ie, the
+     * Upon reaching a {@link AbstractMergeNode}, some entries are pruned from {@link #nodeStates} (ie, the
      * entries associated to forward-ends for that merge-node).
      * </p>
      */
@@ -237,8 +237,8 @@
             return null;
         }
         PathStart<T> elem = nodeQueue.removeFirst();
-        if (elem.node instanceof MergeNode) {
-            MergeNode merge = (MergeNode) elem.node;
+        if (elem.node instanceof AbstractMergeNode) {
+            AbstractMergeNode merge = (AbstractMergeNode) elem.node;
             state = pruneEntry(merge.forwardEndAt(0));
             ArrayList<T> states = new ArrayList<>(merge.forwardEndCount() - 1);
             for (int i = 1; i < merge.forwardEndCount(); i++) {
@@ -249,7 +249,7 @@
             assert ready : "Not a single-pass iterator after all";
             return merge;
         } else {
-            BeginNode begin = elem.node;
+            AbstractBeginNode begin = elem.node;
             assert begin.predecessor() != null;
             state = elem.stateOnEntry;
             state.afterSplit(begin);
@@ -309,7 +309,7 @@
         assert !visitedEnds.isMarked(end);
         visitedEnds.mark(end);
         keepForLater(end, state);
-        MergeNode merge = end.merge();
+        AbstractMergeNode merge = end.merge();
         boolean endsVisited = true;
         for (int i = 0; i < merge.forwardEndCount(); i++) {
             if (!visitedEnds.isMarked(merge.forwardEndAt(i))) {
@@ -328,7 +328,7 @@
         node(endNode);
     }
 
-    protected void merge(MergeNode merge) {
+    protected void merge(AbstractMergeNode merge) {
         node(merge);
     }
 
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/StatelessPostOrderNodeIterator.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/StatelessPostOrderNodeIterator.java	Wed Jan 28 03:28:31 2015 +0100
@@ -36,7 +36,7 @@
 public abstract class StatelessPostOrderNodeIterator {
 
     private final NodeBitMap visitedEnds;
-    private final Deque<BeginNode> nodeQueue;
+    private final Deque<AbstractBeginNode> nodeQueue;
     private final FixedNode start;
 
     public StatelessPostOrderNodeIterator(FixedNode start) {
@@ -58,9 +58,9 @@
                 assert !visitedEnds.isMarked(current);
                 visitedEnds.mark(current);
                 current = nodeQueue.pollFirst();
-            } else if (current instanceof MergeNode) {
-                merge((MergeNode) current);
-                current = ((MergeNode) current).next();
+            } else if (current instanceof AbstractMergeNode) {
+                merge((AbstractMergeNode) current);
+                current = ((AbstractMergeNode) current).next();
                 assert current != null;
             } else if (current instanceof FixedWithNextNode) {
                 node(current);
@@ -76,7 +76,7 @@
                 controlSplit((ControlSplitNode) current);
                 for (Node node : current.successors()) {
                     if (node != null) {
-                        nodeQueue.addFirst((BeginNode) node);
+                        nodeQueue.addFirst((AbstractBeginNode) node);
                     }
                 }
                 current = nodeQueue.pollFirst();
@@ -90,7 +90,7 @@
     private void queueMerge(EndNode end) {
         assert !visitedEnds.isMarked(end);
         visitedEnds.mark(end);
-        MergeNode merge = end.merge();
+        AbstractMergeNode merge = end.merge();
         boolean endsVisited = true;
         for (int i = 0; i < merge.forwardEndCount(); i++) {
             if (!visitedEnds.isMarked(merge.forwardEndAt(i))) {
@@ -111,7 +111,7 @@
         node(endNode);
     }
 
-    protected void merge(MergeNode merge) {
+    protected void merge(AbstractMergeNode merge) {
         node(merge);
     }
 
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Wed Jan 28 03:28:31 2015 +0100
@@ -77,60 +77,89 @@
         LATEST_OUT_OF_LOOPS
     }
 
-    private class KillSet implements Iterable<LocationIdentity> {
+    static int created;
+
+    private class LocationSet {
+        private LocationIdentity firstLocation;
         private List<LocationIdentity> list;
 
-        public KillSet() {
+        public LocationSet() {
             list = null;
         }
 
-        public KillSet(KillSet other) {
+        public LocationSet(LocationSet other) {
+            this.firstLocation = other.firstLocation;
             if (other.list != null && other.list.size() > 0) {
                 list = new ArrayList<>(other.list);
             }
         }
 
-        private void initSet() {
+        private void initList() {
             if (list == null) {
                 list = new ArrayList<>(4);
             }
         }
 
-        public void add(LocationIdentity locationIdentity) {
-            if (list == null || !list.contains(locationIdentity)) {
-                initSet();
-                list.add(locationIdentity);
+        public void add(LocationIdentity location) {
+            if (location == LocationIdentity.ANY_LOCATION) {
+                firstLocation = location;
+                list = null;
+            } else {
+                if (firstLocation == null) {
+                    firstLocation = location;
+                } else {
+                    initList();
+                    list.add(location);
+                }
             }
         }
 
-        public void addAll(KillSet other) {
-            if (other.list == null) {
-                return;
+        public void addAll(LocationSet other) {
+            if (other.firstLocation != null) {
+                add(other.firstLocation);
             }
-            initSet();
-            for (LocationIdentity locationIdentity : other) {
-                if (!list.contains(locationIdentity)) {
-                    list.add(locationIdentity);
+            List<LocationIdentity> otherList = other.list;
+            if (otherList != null) {
+                for (LocationIdentity l : otherList) {
+                    add(l);
                 }
             }
         }
 
-        public Iterator<LocationIdentity> iterator() {
-            if (list == null) {
-                return Collections.emptyIterator();
+        public boolean contains(LocationIdentity locationIdentity) {
+            assert locationIdentity != null;
+            assert locationIdentity != LocationIdentity.ANY_LOCATION;
+            assert locationIdentity != LocationIdentity.FINAL_LOCATION;
+            if (firstLocation == LocationIdentity.ANY_LOCATION) {
+                return true;
+            }
+            if (firstLocation == locationIdentity) {
+                return true;
             }
-            return list.iterator();
+            if (list != null) {
+                for (int i = 0; i < list.size(); ++i) {
+                    LocationIdentity value = list.get(i);
+                    if (value == locationIdentity) {
+                        return true;
+                    }
+                }
+            }
+            return false;
         }
 
-        public boolean isKilled(LocationIdentity locationIdentity) {
-            if (list == null) {
-                return false;
+        public List<LocationIdentity> getCopyAsList() {
+            ArrayList<LocationIdentity> result = new ArrayList<>();
+            if (firstLocation != null) {
+                result.add(firstLocation);
             }
-            return list.contains(locationIdentity);
+            if (list != null) {
+                result.addAll(list);
+            }
+            return result;
         }
     }
 
-    private class NewMemoryScheduleClosure extends BlockIteratorClosure<KillSet> {
+    private class NewMemoryScheduleClosure extends BlockIteratorClosure<LocationSet> {
         private Node excludeNode;
         private Block upperBoundBlock;
 
@@ -144,23 +173,23 @@
         }
 
         @Override
-        protected KillSet getInitialState() {
+        protected LocationSet getInitialState() {
             return cloneState(blockToKillSet.get(getCFG().getStartBlock()));
         }
 
         @Override
-        protected KillSet processBlock(Block block, KillSet currentState) {
+        protected LocationSet processBlock(Block block, LocationSet currentState) {
             assert block != null;
             currentState.addAll(computeKillSet(block, block == upperBoundBlock ? excludeNode : null));
             return currentState;
         }
 
         @Override
-        protected KillSet merge(Block merge, List<KillSet> states) {
-            assert merge.getBeginNode() instanceof MergeNode;
+        protected LocationSet merge(Block merge, List<LocationSet> states) {
+            assert merge.getBeginNode() instanceof AbstractMergeNode;
 
-            KillSet initKillSet = new KillSet();
-            for (KillSet state : states) {
+            LocationSet initKillSet = new LocationSet();
+            for (LocationSet state : states) {
                 initKillSet.addAll(state);
             }
 
@@ -168,16 +197,16 @@
         }
 
         @Override
-        protected KillSet cloneState(KillSet state) {
-            return new KillSet(state);
+        protected LocationSet cloneState(LocationSet state) {
+            return new LocationSet(state);
         }
 
         @Override
-        protected List<KillSet> processLoop(Loop<Block> loop, KillSet state) {
-            LoopInfo<KillSet> info = ReentrantBlockIterator.processLoop(this, loop, cloneState(state));
+        protected List<LocationSet> processLoop(Loop<Block> loop, LocationSet state) {
+            LoopInfo<LocationSet> info = ReentrantBlockIterator.processLoop(this, loop, cloneState(state));
 
             assert loop.getHeader().getBeginNode() instanceof LoopBeginNode;
-            KillSet headerState = merge(loop.getHeader(), info.endStates);
+            LocationSet headerState = merge(loop.getHeader(), info.endStates);
 
             // second iteration, for propagating information to loop exits
             info = ReentrantBlockIterator.processLoop(this, loop, cloneState(headerState));
@@ -196,10 +225,10 @@
      *            until we reach excludeNode.
      * @return all killed locations
      */
-    private KillSet computeKillSet(Block block, Node excludeNode) {
+    private LocationSet computeKillSet(Block block, Node excludeNode) {
         // cache is only valid if we don't potentially exclude kills from the set
         if (excludeNode == null) {
-            KillSet cachedSet = blockToKillSet.get(block);
+            LocationSet cachedSet = blockToKillSet.get(block);
             if (cachedSet != null) {
                 return cachedSet;
             }
@@ -208,10 +237,10 @@
         // add locations to excludedLocations until we reach the excluded node
         boolean foundExcludeNode = excludeNode == null;
 
-        KillSet set = new KillSet();
-        KillSet excludedLocations = new KillSet();
-        if (block.getBeginNode() instanceof MergeNode) {
-            MergeNode mergeNode = (MergeNode) block.getBeginNode();
+        LocationSet set = new LocationSet();
+        LocationSet excludedLocations = new LocationSet();
+        if (block.getBeginNode() instanceof AbstractMergeNode) {
+            AbstractMergeNode mergeNode = (AbstractMergeNode) block.getBeginNode();
             for (MemoryPhiNode phi : mergeNode.usages().filter(MemoryPhiNode.class)) {
                 if (foundExcludeNode) {
                     set.add(phi.getLocationIdentity());
@@ -222,10 +251,10 @@
             }
         }
 
-        BeginNode startNode = cfg.getStartBlock().getBeginNode();
+        AbstractBeginNode startNode = cfg.getStartBlock().getBeginNode();
         assert startNode instanceof StartNode;
 
-        KillSet accm = foundExcludeNode ? set : excludedLocations;
+        LocationSet accm = foundExcludeNode ? set : excludedLocations;
         for (Node node : block.getNodes()) {
             if (!foundExcludeNode && node == excludeNode) {
                 foundExcludeNode = true;
@@ -254,7 +283,7 @@
         return set;
     }
 
-    private KillSet computeKillSet(Block block) {
+    private LocationSet computeKillSet(Block block) {
         return computeKillSet(block, null);
     }
 
@@ -265,7 +294,7 @@
      * Map from blocks to the nodes in each block.
      */
     private BlockMap<List<ValueNode>> blockToNodesMap;
-    private BlockMap<KillSet> blockToKillSet;
+    private BlockMap<LocationSet> blockToKillSet;
     private final SchedulingStrategy selectedStrategy;
 
     public SchedulePhase() {
@@ -319,11 +348,11 @@
             buf.format("post-dom: %s. ", b.getPostdominator());
             buf.format("preds: %s. ", b.getPredecessors());
             buf.format("succs: %s ====%n", b.getSuccessors());
-            BlockMap<KillSet> killSets = blockToKillSet;
+            BlockMap<LocationSet> killSets = blockToKillSet;
             if (killSets != null) {
                 buf.format("X block kills: %n");
                 if (killSets.get(b) != null) {
-                    for (LocationIdentity locId : killSets.get(b)) {
+                    for (LocationIdentity locId : killSets.get(b).getCopyAsList()) {
                         buf.format("X %s killed by %s%n", locId, "dunno anymore");
                     }
                 }
@@ -519,7 +548,7 @@
             Block dominatedBlock = path.size() == 0 ? null : path.peek();
             if (dominatedBlock != null && !currentBlock.getSuccessors().contains(dominatedBlock)) {
                 // the dominated block is not a successor -> we have a split
-                assert dominatedBlock.getBeginNode() instanceof MergeNode;
+                assert dominatedBlock.getBeginNode() instanceof AbstractMergeNode;
 
                 NewMemoryScheduleClosure closure = null;
                 if (currentBlock == upperBoundBlock) {
@@ -529,11 +558,11 @@
                 } else {
                     closure = new NewMemoryScheduleClosure();
                 }
-                Map<FixedNode, KillSet> states;
-                states = ReentrantBlockIterator.apply(closure, currentBlock, new KillSet(), block -> block == dominatedBlock);
+                Map<FixedNode, LocationSet> states;
+                states = ReentrantBlockIterator.apply(closure, currentBlock, new LocationSet(), block -> block == dominatedBlock);
 
-                KillSet mergeState = states.get(dominatedBlock.getBeginNode());
-                if (mergeState.isKilled(locid)) {
+                LocationSet mergeState = states.get(dominatedBlock.getBeginNode());
+                if (mergeState.contains(locid)) {
                     // location got killed somewhere in the branches,
                     // thus we've to move the read above it
                     return currentBlock;
@@ -541,11 +570,11 @@
             } else {
                 if (currentBlock == upperBoundBlock) {
                     assert earliestBlock == upperBoundBlock;
-                    KillSet ks = computeKillSet(upperBoundBlock, ValueNodeUtil.asNode(n.getLastLocationAccess()));
-                    if (ks.isKilled(locid)) {
+                    LocationSet ks = computeKillSet(upperBoundBlock, ValueNodeUtil.asNode(n.getLastLocationAccess()));
+                    if (ks.contains(locid)) {
                         return upperBoundBlock;
                     }
-                } else if (dominatedBlock == null || computeKillSet(currentBlock).isKilled(locid)) {
+                } else if (dominatedBlock == null || computeKillSet(currentBlock).contains(locid)) {
                     return currentBlock;
                 }
             }
@@ -716,7 +745,7 @@
             // One PhiNode can use an input multiple times, the closure will be called for each
             // usage.
             PhiNode phi = (PhiNode) usage;
-            MergeNode merge = phi.merge();
+            AbstractMergeNode merge = phi.merge();
             Block mergeBlock = cfg.getNodeToBlock().get(merge);
             if (mergeBlock == null) {
                 throw new SchedulingError("no block for merge %s", merge.toString(Verbosity.Id));
@@ -742,7 +771,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 BeginNode) {
+                } else if (unscheduledUsage instanceof AbstractBeginNode) {
                     // Only FrameStates can be connected to BeginNodes.
                     if (!(usage instanceof FrameState)) {
                         throw new SchedulingError(usage.toString());
@@ -1108,7 +1137,7 @@
                 }
             }
 
-            if (instruction instanceof BeginNode) {
+            if (instruction instanceof AbstractBeginNode) {
                 for (ValueNode inBlock : blockToNodesMap.get(b)) {
                     if (!visited.isMarked(inBlock)) {
                         addToEarliestSorting(b, inBlock, sortedInstructions, visited);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/BlockWorkList.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/BlockWorkList.java	Wed Jan 28 03:28:31 2015 +0100
@@ -31,7 +31,7 @@
  */
 public class BlockWorkList {
 
-    MergeNode[] workList;
+    AbstractMergeNode[] workList;
     int[] workListNumbers;
     int workListIndex;
 
@@ -40,7 +40,7 @@
      * 
      * @param block the block to add
      */
-    public void add(MergeNode block) {
+    public void add(AbstractMergeNode block) {
         if (workList == null) {
             // worklist not allocated yet
             allocate();
@@ -59,7 +59,7 @@
      * @param block the block to add
      * @param number the number used to sort the block
      */
-    public void addSorted(MergeNode block, int number) {
+    public void addSorted(AbstractMergeNode block, int number) {
         if (workList == null) {
             // worklist not allocated yet
             allocate();
@@ -92,7 +92,7 @@
      * 
      * @return the next block in the list
      */
-    public MergeNode removeFromWorkList() {
+    public AbstractMergeNode removeFromWorkList() {
         if (workListIndex != 0) {
             return workList[--workListIndex];
         }
@@ -109,13 +109,13 @@
     }
 
     private void allocate() {
-        workList = new MergeNode[5];
+        workList = new AbstractMergeNode[5];
         workListNumbers = new int[5];
     }
 
     private void grow() {
         int prevLength = workList.length;
-        MergeNode[] nworkList = new MergeNode[prevLength * 3];
+        AbstractMergeNode[] nworkList = new AbstractMergeNode[prevLength * 3];
         System.arraycopy(workList, 0, nworkList, 0, prevLength);
         workList = nworkList;
 
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Wed Jan 28 03:28:31 2015 +0100
@@ -110,8 +110,8 @@
                     }
                 }
                 nodes.add(node);
-                if (node instanceof MergeNode) {
-                    for (PhiNode phi : ((MergeNode) node).phis()) {
+                if (node instanceof AbstractMergeNode) {
+                    for (PhiNode phi : ((AbstractMergeNode) node).phis()) {
                         visited.mark(phi);
                         nodes.add(phi);
                     }
@@ -172,9 +172,9 @@
                             pendingStateAfter = null;
                         }
 
-                        if (node instanceof MergeNode) {
+                        if (node instanceof AbstractMergeNode) {
                             // phis aren't scheduled, so they need to be added explicitly
-                            currentState.markAll(((MergeNode) node).phis());
+                            currentState.markAll(((AbstractMergeNode) node).phis());
                             if (node instanceof LoopBeginNode) {
                                 // remember the state at the loop entry, it's restored at exits
                                 loopEntryStates.put((LoopBeginNode) node, currentState.copy());
@@ -210,7 +210,7 @@
                             }
                         }
                         if (node instanceof AbstractEndNode) {
-                            MergeNode merge = ((AbstractEndNode) node).merge();
+                            AbstractMergeNode merge = ((AbstractEndNode) node).merge();
                             for (PhiNode phi : merge.phis()) {
                                 ValueNode phiValue = phi.valueAt((AbstractEndNode) node);
                                 assert phiValue == null || currentState.isMarked(phiValue) : phiValue + " not available at phi " + phi + " / end " + node + " in block " + block;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Wed Jan 28 03:28:31 2015 +0100
@@ -265,9 +265,9 @@
         out.println("HIR");
         out.disableIndentation();
 
-        if (block.getBeginNode() instanceof MergeNode) {
+        if (block.getBeginNode() instanceof AbstractMergeNode) {
             // Currently phi functions are not in the schedule, so print them separately here.
-            for (ValueNode phi : ((MergeNode) block.getBeginNode()).phis()) {
+            for (ValueNode phi : ((AbstractMergeNode) block.getBeginNode()).phis()) {
                 printNode(phi, false);
             }
         }
@@ -484,7 +484,7 @@
             return "-";
         }
         String prefix;
-        if (node instanceof BeginNode && (lir == null && schedule == null)) {
+        if (node instanceof AbstractBeginNode && (lir == null && schedule == null)) {
             prefix = "B";
         } else if (node instanceof ValueNode) {
             ValueNode value = (ValueNode) node;
@@ -585,9 +585,9 @@
         out.println("HIR");
         out.disableIndentation();
 
-        if (block.getBeginNode() instanceof MergeNode) {
+        if (block.getBeginNode() instanceof AbstractMergeNode) {
             // Currently phi functions are not in the schedule, so print them separately here.
-            for (ValueNode phi : ((MergeNode) block.getBeginNode()).phis()) {
+            for (ValueNode phi : ((AbstractMergeNode) block.getBeginNode()).phis()) {
                 printNode(phi, false);
             }
         }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Wed Jan 28 03:28:31 2015 +0100
@@ -173,7 +173,7 @@
                     printProperty(bit, "true");
                 }
             }
-            if (node.getClass() == BeginNode.class) {
+            if (node instanceof BeginNode) {
                 printProperty("shortName", "B");
             } else if (node.getClass() == EndNode.class) {
                 printProperty("shortName", "E");
@@ -276,8 +276,8 @@
                 if (node instanceof StateSplit && ((StateSplit) node).stateAfter() != null) {
                     nodes.add(((StateSplit) node).stateAfter());
                 }
-                if (node instanceof MergeNode) {
-                    for (PhiNode phi : ((MergeNode) node).phis()) {
+                if (node instanceof AbstractMergeNode) {
+                    for (PhiNode phi : ((AbstractMergeNode) node).phis()) {
                         nodes.add(phi);
                     }
                 }
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountLeadingZerosNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountLeadingZerosNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -35,7 +35,7 @@
  * Count the number of leading zeros.
  */
 @NodeInfo
-public class AMD64CountLeadingZerosNode extends UnaryNode implements LIRLowerable {
+public final class AMD64CountLeadingZerosNode extends UnaryNode implements LIRLowerable {
 
     public AMD64CountLeadingZerosNode(ValueNode value) {
         super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value);
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountTrailingZerosNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountTrailingZerosNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -35,7 +35,7 @@
  * Count the number of trailing zeros.
  */
 @NodeInfo
-public class AMD64CountTrailingZerosNode extends UnaryNode implements LIRLowerable {
+public final class AMD64CountTrailingZerosNode extends UnaryNode implements LIRLowerable {
 
     public AMD64CountTrailingZerosNode(ValueNode value) {
         super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value);
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -37,7 +37,7 @@
  * fixup code that handles the corner cases that differ between AMD64 and Java.
  */
 @NodeInfo
-public class AMD64FloatConvertNode extends UnaryArithmeticNode<FloatConvertOp> implements ArithmeticLIRLowerable {
+public final class AMD64FloatConvertNode extends UnaryArithmeticNode<FloatConvertOp> implements ArithmeticLIRLowerable {
 
     protected final FloatConvert op;
 
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/EdgesTest.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/EdgesTest.java	Wed Jan 28 03:28:31 2015 +0100
@@ -44,7 +44,7 @@
 public class EdgesTest extends GraalCompilerTest {
 
     @NodeInfo
-    static class TestNode extends Node {
+    static final class TestNode extends Node {
         @Input NodeInputList<ValueNode> itail;
         @Input ConstantNode i1;
         @Input FloatingNode i2;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java	Wed Jan 28 03:28:31 2015 +0100
@@ -68,11 +68,11 @@
             return new IterationState(this, sideEffect.asNode(), null, true);
         }
 
-        public IterationState addBranch(BeginNode begin) {
+        public IterationState addBranch(AbstractBeginNode begin) {
             return new IterationState(this, begin, null, this.invalid);
         }
 
-        public static IterationState merge(MergeNode merge, Collection<IterationState> before, boolean invalid) {
+        public static IterationState merge(AbstractMergeNode merge, Collection<IterationState> before, boolean invalid) {
             return new IterationState(null, merge, before, invalid);
         }
 
@@ -152,7 +152,7 @@
         }
 
         @Override
-        protected IterationState merge(MergeNode merge, List<IterationState> states) {
+        protected IterationState merge(AbstractMergeNode merge, List<IterationState> states) {
             boolean invalid = false;
             for (IterationState state : states) {
                 if (state.invalid) {
@@ -191,7 +191,7 @@
         }
 
         @Override
-        protected IterationState afterSplit(BeginNode node, IterationState oldState) {
+        protected IterationState afterSplit(AbstractBeginNode node, IterationState oldState) {
             return oldState.addBranch(node);
         }
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java	Wed Jan 28 03:28:31 2015 +0100
@@ -275,7 +275,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(BeginNode.prevBegin(load));
+            memoryRead.setGuard(AbstractBeginNode.prevBegin(load));
             graph.replaceFixedWithFixed(load, memoryRead);
         }
     }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java	Wed Jan 28 03:28:31 2015 +0100
@@ -246,8 +246,8 @@
      * @param trueProbability The estimated probability the the condition is true
      */
     public void startIf(LogicNode condition, double trueProbability) {
-        BeginNode thenSuccessor = graph.add(new BeginNode());
-        BeginNode elseSuccessor = graph.add(new BeginNode());
+        AbstractBeginNode thenSuccessor = graph.add(new BeginNode());
+        AbstractBeginNode elseSuccessor = graph.add(new BeginNode());
         append(new IfNode(condition, thenSuccessor, elseSuccessor, trueProbability));
         lastFixedNode = null;
 
@@ -303,7 +303,7 @@
             EndNode elseEnd = graph.add(new EndNode());
             graph.addAfterFixed(elsePart, elseEnd);
 
-            MergeNode merge = graph.add(new MergeNode());
+            AbstractMergeNode merge = graph.add(new MergeNode());
             merge.addForwardEnd(thenEnd);
             merge.addForwardEnd(elseEnd);
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Wed Jan 28 03:28:31 2015 +0100
@@ -737,7 +737,7 @@
         } else if (returnNodes.size() == 1) {
             this.returnNode = returnNodes.get(0);
         } else {
-            MergeNode merge = snippet.add(new MergeNode());
+            AbstractMergeNode merge = snippet.add(new MergeNode());
             List<MemoryMapNode> memMaps = returnNodes.stream().map(n -> n.getMemoryMap()).collect(Collectors.toList());
             ValueNode returnValue = InliningUtil.mergeReturns(merge, returnNodes, null);
             this.returnNode = snippet.add(new ReturnNode(returnValue));
@@ -1100,7 +1100,7 @@
             FixedNode firstCFGNode = entryPointNode.next();
             StructuredGraph replaceeGraph = replacee.graph();
             Map<Node, Node> replacements = bind(replaceeGraph, metaAccess, args);
-            replacements.put(entryPointNode, BeginNode.prevBegin(replacee));
+            replacements.put(entryPointNode, AbstractBeginNode.prevBegin(replacee));
             Map<Node, Node> duplicates = replaceeGraph.addDuplicates(nodes, snippet, snippet.getNodeCount(), replacements);
             Debug.dump(replaceeGraph, "After inlining snippet %s", snippet.method());
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -36,7 +36,7 @@
  * Compares two arrays with the same length.
  */
 @NodeInfo
-public class ArrayEqualsNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable, Virtualizable, MemoryAccess {
+public final class ArrayEqualsNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable, Virtualizable, MemoryAccess {
 
     /** {@link Kind} of the arrays to compare. */
     protected final Kind kind;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/AssertionNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/AssertionNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -36,7 +36,7 @@
  * may need to insert a check.
  */
 @NodeInfo
-public class AssertionNode extends FixedWithNextNode implements Lowerable, Canonicalizable, LIRLowerable {
+public final class AssertionNode extends FixedWithNextNode implements Lowerable, Canonicalizable, LIRLowerable {
 
     @Input ValueNode value;
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -32,7 +32,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo
-public class BitCountNode extends UnaryNode implements LIRLowerable {
+public final class BitCountNode extends UnaryNode implements LIRLowerable {
 
     public BitCountNode(ValueNode value) {
         super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -36,7 +36,7 @@
  * input is zero.
  */
 @NodeInfo
-public class BitScanForwardNode extends UnaryNode implements LIRLowerable {
+public final class BitScanForwardNode extends UnaryNode implements LIRLowerable {
 
     public BitScanForwardNode(ValueNode value) {
         super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -36,7 +36,7 @@
  * input is zero.
  */
 @NodeInfo
-public class BitScanReverseNode extends UnaryNode implements LIRLowerable {
+public final class BitScanReverseNode extends UnaryNode implements LIRLowerable {
 
     public BitScanReverseNode(ValueNode value) {
         super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BlackholeNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BlackholeNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -28,7 +28,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo
-public class BlackholeNode extends FixedWithNextNode implements LIRLowerable {
+public final class BlackholeNode extends FixedWithNextNode implements LIRLowerable {
 
     @Input ValueNode value;
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DeferredPiNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DeferredPiNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -39,7 +39,7 @@
  * is replaced by a {@link PiNode} once the type becomes constant (which <b>must</b> happen).
  */
 @NodeInfo
-public class DeferredPiNode extends FloatingNode implements Canonicalizable {
+public final class DeferredPiNode extends FloatingNode implements Canonicalizable {
 
     @Input ValueNode object;
     @Input ValueNode type;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -35,7 +35,7 @@
  * {@link StateSplit} and does not include a write barrier.
  */
 @NodeInfo
-public class DirectObjectStoreNode extends FixedWithNextNode implements Lowerable {
+public final class DirectObjectStoreNode extends FixedWithNextNode implements Lowerable {
 
     @Input ValueNode object;
     @Input ValueNode value;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ExplodeLoopNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ExplodeLoopNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -37,7 +37,7 @@
  * @see VarargsParameter
  */
 @NodeInfo
-public class ExplodeLoopNode extends FixedWithNextNode {
+public final class ExplodeLoopNode extends FixedWithNextNode {
 
     public ExplodeLoopNode() {
         super(StampFactory.forVoid());
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -35,7 +35,7 @@
 import com.oracle.graal.truffle.*;
 
 @NodeInfo
-public class AssumptionNode extends MacroNode implements Simplifiable {
+public final class AssumptionNode extends MacroNode implements Simplifiable {
 
     public AssumptionNode(Invoke invoke) {
         super(invoke);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -31,7 +31,7 @@
 import com.oracle.graal.replacements.nodes.*;
 
 @NodeInfo
-public class BailoutNode extends MacroNode implements Canonicalizable {
+public final class BailoutNode extends MacroNode implements Canonicalizable {
 
     public BailoutNode(Invoke invoke) {
         super(invoke);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -83,7 +83,7 @@
     }
 
     @Override
-    public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) {
+    public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) {
         return graph().add(new IntegerAddExactSplitNode(stamp(), getX(), getY(), next, deopt));
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -31,7 +31,7 @@
 @NodeInfo
 public class IntegerAddExactSplitNode extends IntegerExactArithmeticSplitNode {
 
-    public IntegerAddExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) {
+    public IntegerAddExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) {
         super(stamp, x, y, next, overflowSuccessor);
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -27,5 +27,5 @@
 
 interface IntegerExactArithmeticNode extends Lowerable {
 
-    IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt);
+    IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt);
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -32,12 +32,12 @@
 @NodeInfo
 public abstract class IntegerExactArithmeticSplitNode extends ControlSplitNode implements LIRLowerable {
 
-    @Successor BeginNode overflowSuccessor;
-    @Successor BeginNode next;
+    @Successor AbstractBeginNode overflowSuccessor;
+    @Successor AbstractBeginNode next;
     @Input ValueNode x;
     @Input ValueNode y;
 
-    public IntegerExactArithmeticSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) {
+    public IntegerExactArithmeticSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) {
         super(stamp);
         this.x = x;
         this.y = y;
@@ -46,15 +46,15 @@
     }
 
     @Override
-    public double probability(BeginNode successor) {
+    public double probability(AbstractBeginNode successor) {
         return successor == next ? 1 : 0;
     }
 
-    public BeginNode getNext() {
+    public AbstractBeginNode getNext() {
         return next;
     }
 
-    public BeginNode getOverflowSuccessor() {
+    public AbstractBeginNode getOverflowSuccessor() {
         return overflowSuccessor;
     }
 
@@ -81,7 +81,7 @@
             FixedNode next = previous.next();
             previous.setNext(null);
             DeoptimizeNode deopt = floatingNode.graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.ArithmeticException));
-            BeginNode normalBegin = floatingNode.graph().add(new BeginNode());
+            AbstractBeginNode normalBegin = floatingNode.graph().add(new BeginNode());
             normalBegin.setNext(next);
             IntegerExactArithmeticSplitNode split = node.createSplit(normalBegin, BeginNode.begin(deopt));
             previous.setNext(split);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -80,7 +80,7 @@
     }
 
     @Override
-    public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) {
+    public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) {
         return graph().add(new IntegerMulExactSplitNode(stamp(), getX(), getY(), next, deopt));
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -31,7 +31,7 @@
 @NodeInfo
 public class IntegerMulExactSplitNode extends IntegerExactArithmeticSplitNode {
 
-    public IntegerMulExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) {
+    public IntegerMulExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) {
         super(stamp, x, y, next, overflowSuccessor);
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -84,7 +84,7 @@
     }
 
     @Override
-    public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) {
+    public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) {
         return graph().add(new IntegerSubExactSplitNode(stamp(), getX(), getY(), next, deopt));
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -31,7 +31,7 @@
 @NodeInfo
 public class IntegerSubExactSplitNode extends IntegerExactArithmeticSplitNode {
 
-    public IntegerSubExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) {
+    public IntegerSubExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) {
         super(stamp, x, y, next, overflowSuccessor);
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/CompilationConstantNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/CompilationConstantNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -28,7 +28,7 @@
 import com.oracle.graal.nodes.*;
 
 @NodeInfo
-public class CompilationConstantNode extends NeverPartOfCompilationNode implements Canonicalizable {
+public final class CompilationConstantNode extends NeverPartOfCompilationNode implements Canonicalizable {
 
     public CompilationConstantNode(Invoke invoke) {
         super(invoke, "The value could not be reduced to a compile time constant.");
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -28,7 +28,7 @@
 import com.oracle.graal.replacements.nodes.*;
 
 @NodeInfo
-public class NeverInlineMacroNode extends MacroStateSplitNode implements com.oracle.graal.graph.IterableNodeType {
+public final class NeverInlineMacroNode extends MacroStateSplitNode implements com.oracle.graal.graph.IterableNodeType {
 
     public NeverInlineMacroNode(Invoke invoke) {
         super(invoke);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -46,7 +46,7 @@
  * class.
  */
 @NodeInfo
-public class NewFrameNode extends FixedWithNextNode implements IterableNodeType, VirtualizableAllocation, Canonicalizable {
+public final class NewFrameNode extends FixedWithNextNode implements IterableNodeType, VirtualizableAllocation, Canonicalizable {
 
     @Input ValueNode descriptor;
     @Input ValueNode arguments;
@@ -96,7 +96,7 @@
     }
 
     @NodeInfo
-    public static class VirtualOnlyInstanceNode extends VirtualInstanceNode {
+    public static final class VirtualOnlyInstanceNode extends VirtualInstanceNode {
 
         protected boolean allowMaterialization;
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -40,7 +40,7 @@
  * Substitution for method CompilerDirectives#unsafeGet*.
  */
 @NodeInfo
-public class CustomizedUnsafeLoadFinalNode extends FixedWithNextNode implements Canonicalizable, Virtualizable, Lowerable {
+public final class CustomizedUnsafeLoadFinalNode extends FixedWithNextNode implements Canonicalizable, Virtualizable, Lowerable {
     @Input ValueNode object;
     @Input ValueNode offset;
     @Input ValueNode condition;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -37,7 +37,7 @@
  * Macro node for CompilerDirectives#unsafeGetInt*.
  */
 @NodeInfo
-public class CustomizedUnsafeLoadMacroNode extends NeverPartOfCompilationNode implements Canonicalizable {
+public final class CustomizedUnsafeLoadMacroNode extends NeverPartOfCompilationNode implements Canonicalizable {
 
     private static final int ARGUMENT_COUNT = 4;
     private static final int OBJECT_ARGUMENT_INDEX = 0;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java	Wed Jan 28 03:28:31 2015 +0100
@@ -35,7 +35,7 @@
  * Macro node for method CompilerDirectives#unsafePut*.
  */
 @NodeInfo
-public class CustomizedUnsafeStoreMacroNode extends NeverPartOfCompilationNode implements Canonicalizable, StateSplit {
+public final class CustomizedUnsafeStoreMacroNode extends NeverPartOfCompilationNode implements Canonicalizable, StateSplit {
     private static final int ARGUMENT_COUNT = 4;
     private static final int OBJECT_ARGUMENT_INDEX = 0;
     private static final int OFFSET_ARGUMENT_INDEX = 1;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Wed Jan 28 03:28:31 2015 +0100
@@ -204,7 +204,7 @@
     protected class MergeProcessor {
 
         protected final Block mergeBlock;
-        protected final MergeNode merge;
+        protected final AbstractMergeNode merge;
 
         protected final GraphEffectList mergeEffects;
         protected final GraphEffectList afterMergeEffects;
@@ -212,7 +212,7 @@
 
         public MergeProcessor(Block mergeBlock) {
             this.mergeBlock = mergeBlock;
-            this.merge = (MergeNode) mergeBlock.getBeginNode();
+            this.merge = (AbstractMergeNode) mergeBlock.getBeginNode();
             this.mergeEffects = new GraphEffectList();
             this.afterMergeEffects = new GraphEffectList();
         }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Wed Jan 28 03:28:31 2015 +0100
@@ -405,7 +405,7 @@
          * The read must not float outside its block otherwise it may float above an explicit zero
          * check on its base address.
          */
-        read.setGuard(BeginNode.prevBegin(invoke.asNode()));
+        read.setGuard(AbstractBeginNode.prevBegin(invoke.asNode()));
         return read;
     }
 
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Tue Jan 27 15:47:34 2015 -0800
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Wed Jan 28 03:28:31 2015 +0100
@@ -86,7 +86,7 @@
                 } else if (usage instanceof ArrayLengthNode) {
                     verify(!isWord(node) || ((ArrayLengthNode) usage).array() != node, node, usage, "cannot get array length from word value");
                 } else if (usage instanceof ValuePhiNode) {
-                    if (!(node instanceof MergeNode)) {
+                    if (!(node instanceof AbstractMergeNode)) {
                         ValuePhiNode phi = (ValuePhiNode) usage;
                         for (ValueNode input : phi.values()) {
                             verify(isWord(node) == isWord(input), node, input, "cannot merge word and non-word values");