changeset 4506:ab7c258e1cef

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Sun, 05 Feb 2012 05:40:36 +0100
parents 5d9c4796912d (current diff) 0312460af9fc (diff)
children 9d640941c9c7
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/loop/Loop.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/loop/LoopInfo.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/loop/LoopUtil.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/RemovePlaceholderPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/NodeIterators.java graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/TypePredicate.java graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BlockMap.java graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/ArrayCopySnippets.java graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/IntrinsifyArrayCopyPhase.java graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/SystemSnippets.java graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/UnsafeSnippets.java
diffstat 115 files changed, 4102 insertions(+), 3989 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java	Sun Feb 05 05:40:36 2012 +0100
@@ -77,11 +77,11 @@
 
     XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, RiType type);
 
-    XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type);
+    XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact);
 
-    XirSnippet genInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, RiType type);
+    XirSnippet genInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact);
 
-    XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type);
+    XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type, RiResolvedType[] hints, boolean hintsExact);
 
     XirSnippet genArrayLoad(XirSite site, XirArgument array, XirArgument index, CiKind elementKind, RiType elementType);
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/AssignRegisters.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/AssignRegisters.java	Sun Feb 05 05:40:36 2012 +0100
@@ -28,6 +28,7 @@
 import com.oracle.max.criutils.*;
 import com.oracle.max.graal.alloc.util.*;
 import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
 
@@ -50,7 +51,7 @@
 
         assert trace("==== start assign registers ====");
         for (int i = lir.linearScanOrder().size() - 1; i >= 0; i--) {
-            LIRBlock block = lir.linearScanOrder().get(i);
+            Block block = lir.linearScanOrder().get(i);
             assert trace("start block %s", block);
             assert block.phis == null : "Register assignment must run after phi functions have been replaced by moves";
 
@@ -60,8 +61,8 @@
             // Put all values live at the end of the block into the reference map.
             locationsForBlockEnd(block).forEachLocation(setReferenceProc);
 
-            for (int j = block.lir().size() - 1; j >= 0; j--) {
-                LIRInstruction op = block.lir().get(j);
+            for (int j = block.lir.size() - 1; j >= 0; j--) {
+                LIRInstruction op = block.lir.get(j);
                 assert trace("  op %d %s", op.id(), op);
 
                 op.forEachOutput(defProc);
@@ -120,7 +121,7 @@
         return value;
     }
 
-    protected abstract LocationMap locationsForBlockEnd(LIRBlock block);
+    protected abstract LocationMap locationsForBlockEnd(Block block);
 
     private static boolean trace(String format, Object...args) {
         if (GraalOptions.TraceRegisterAllocation) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/DataFlowAnalysis.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/DataFlowAnalysis.java	Sun Feb 05 05:40:36 2012 +0100
@@ -32,10 +32,10 @@
 import com.oracle.max.criutils.*;
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.alloc.*;
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
 import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure;
-import com.oracle.max.graal.compiler.schedule.*;
 
 public class DataFlowAnalysis {
     private final LIR lir;
@@ -52,7 +52,7 @@
     }
 
 
-    private List<LIRBlock> blocks() {
+    private List<Block> blocks() {
         return lir.linearScanOrder();
     }
 
@@ -67,21 +67,21 @@
 
     private int[] definitions;
     private BitSet[] blockLiveIn;
-    private LIRBlock[] opIdBlock;
+    private Block[] opIdBlock;
     private Object[] opIdKilledValues;
 
 
     public BitSet liveIn(Block block) {
-        return blockLiveIn[block.blockID()];
+        return blockLiveIn[block.getId()];
     }
     private void setLiveIn(Block block, BitSet liveIn) {
-        blockLiveIn[block.blockID()] = liveIn;
+        blockLiveIn[block.getId()] = liveIn;
     }
 
-    private LIRBlock blockOf(int opId) {
+    private Block blockOf(int opId) {
         return opIdBlock[opId >> 1];
     }
-    private void setBlockOf(int opId, LIRBlock block) {
+    private void setBlockOf(int opId, Block block) {
         opIdBlock[opId >> 1] = block;
     }
 
@@ -121,22 +121,20 @@
         ValueProcedure defProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return setDef(value); } };
 
         int numInstructions = 0;
-        for (LIRBlock block : blocks()) {
-            numInstructions += block.lir().size();
+        for (Block block : blocks()) {
+            numInstructions += block.lir.size();
         }
-        opIdBlock = new LIRBlock[numInstructions];
+        opIdBlock = new Block[numInstructions];
         opIdKilledValues = new Object[numInstructions << 1];
         definitions = new int[numVariables()];
 
         curOpId = 0;
-        for (LIRBlock block : blocks()) {
-            block.setFirstLirInstructionId(curOpId);
-
+        for (Block block : blocks()) {
             if (block.phis != null) {
                 block.phis.forEachOutput(defProc);
             }
 
-            for (LIRInstruction op : block.lir()) {
+            for (LIRInstruction op : block.lir) {
                 op.setId(curOpId);
                 setBlockOf(curOpId, block);
 
@@ -145,7 +143,6 @@
 
                 curOpId += 2; // numbering of lirOps by two
             }
-            block.setLastLirInstructionId(curOpId - 2);
         }
         assert curOpId == numInstructions << 1;
     }
@@ -175,11 +172,11 @@
 
         assert trace("==== start backward data flow analysis ====");
         for (int i = blocks().size() - 1; i >= 0; i--) {
-            LIRBlock block = blocks().get(i);
-            assert trace("start block %s  loop %d depth %d", block, block.loopIndex(), block.loopDepth());
+            Block block = blocks().get(i);
+            assert trace("start block %s  loop %s", block, block.getLoop());
 
             variableLive = new BitSet();
-            for (LIRBlock sux : block.getLIRSuccessors()) {
+            for (Block sux : block.getSuccessors()) {
                 BitSet suxLive = liveIn(sux);
                 if (suxLive != null) {
                     assert trace("  sux %s  suxLive: %s", sux, suxLive);
@@ -187,7 +184,7 @@
                 }
 
                 if (sux.phis != null) {
-                    curOpId = block.lastLirInstructionId();
+                    curOpId = block.getLastLirInstructionId();
                     assert trace("  phis %d  variableLive: %s", curOpId, variableLive);
                     sux.phis.forEachInput(block, phiInputProc);
                 }
@@ -195,8 +192,8 @@
 
             assert registerLive.isEmpty() : "no fixed register must be alive before processing a block";
 
-            for (int j = block.lir().size() - 1; j >= 0; j--) {
-                LIRInstruction op = block.lir().get(j);
+            for (int j = block.lir.size() - 1; j >= 0; j--) {
+                LIRInstruction op = block.lir.get(j);
                 curOpId = op.id();
                 assert trace("  op %d %s  variableLive: %s  registerLive: %s", curOpId, op, variableLive, registerLive);
 
@@ -208,7 +205,7 @@
             }
 
             if (block.phis != null) {
-                curOpId = block.firstLirInstructionId();
+                curOpId = block.getFirstLirInstructionId();
                 assert trace("  phis %d  variableLive: %s  registerLive: %s", curOpId, variableLive, registerLive);
                 block.phis.forEachOutput(outputProc);
             }
@@ -221,7 +218,7 @@
                 assert trace("  loop header, propagating live set to loop blocks  variableLive: %s", variableLive);
                 // All variables that are live at the beginning of a loop are also live the whole loop.
                 // This is guaranteed by the SSA form.
-                for (Block loop : block.loopBlocks) {
+                for (Block loop : block.getLoop().blocks) {
                     BitSet loopLiveIn = liveIn(loop);
                     assert loopLiveIn != null : "All loop blocks must have been processed before the loop header";
                     loopLiveIn.or(variableLive);
@@ -292,13 +289,13 @@
             int defOpId = definitions[asVariable(value).index];
             assert defOpId > 0 && defOpId <= opId;
 
-            LIRBlock defBlock = blockOf(defOpId);
-            LIRBlock useBlock = blockOf(opId);
+            Block defBlock = blockOf(defOpId);
+            Block useBlock = blockOf(opId);
 
-            if (useBlock.loopDepth() > 0 && useBlock.loopIndex() != defBlock.loopIndex()) {
+            if (useBlock.getLoop() != null && useBlock.getLoop() != defBlock.getLoop()) {
                 // This is a value defined outside of the loop it is currently used in.  Therefore, it is live the whole loop
                 // and is not killed by the current instruction.
-                assert trace("      no kill because use in loop %d, definition in loop %d", useBlock.loopIndex(), defBlock.loopIndex());
+                assert trace("      no kill because use in %s, definition in %s", useBlock.getLoop(), defBlock.getLoop());
                 return;
             }
         }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/LinearScanAllocator.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/LinearScanAllocator.java	Sun Feb 05 05:40:36 2012 +0100
@@ -32,12 +32,12 @@
 import com.oracle.max.criutils.*;
 import com.oracle.max.graal.alloc.util.*;
 import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
 import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure;
-import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.debug.*;
 
@@ -85,12 +85,12 @@
         }
 
         @Override
-        protected LocationMap locationsForBlockBegin(LIRBlock block) {
+        protected LocationMap locationsForBlockBegin(Block block) {
             return beginLocationsFor(block);
         }
 
         @Override
-        protected LocationMap locationsForBlockEnd(LIRBlock block) {
+        protected LocationMap locationsForBlockEnd(Block block) {
             return endLocationsFor(block);
         }
     }
@@ -101,7 +101,7 @@
         }
 
         @Override
-        protected LocationMap locationsForBlockEnd(LIRBlock block) {
+        protected LocationMap locationsForBlockEnd(Block block) {
             return endLocationsFor(block);
         }
     }
@@ -119,19 +119,19 @@
     private final LocationMap[] blockBeginLocations;
 
     private LocationMap beginLocationsFor(Block block) {
-        return blockBeginLocations[block.blockID()];
+        return blockBeginLocations[block.getId()];
     }
     private void setBeginLocationsFor(Block block, LocationMap locations) {
-        blockBeginLocations[block.blockID()] = locations;
+        blockBeginLocations[block.getId()] = locations;
     }
 
     private final LocationMap[] blockEndLocations;
 
     private LocationMap endLocationsFor(Block block) {
-        return blockEndLocations[block.blockID()];
+        return blockEndLocations[block.getId()];
     }
     private void setEndLocationsFor(Block block, LocationMap locations) {
-        blockEndLocations[block.blockID()] = locations;
+        blockEndLocations[block.getId()] = locations;
     }
 
     private final int[] variableLastUse;
@@ -150,7 +150,7 @@
     private CiValue[] curOutRegisterState;
     private BitSet curLiveIn;
     private int curOpId;
-    private LIRBlock curPhiBlock;
+    private Block curPhiBlock;
 
     private LocationMap canonicalSpillLocations;
 
@@ -191,12 +191,12 @@
         canonicalSpillLocations = new LocationMap(lir.numVariables());
         curInRegisterState = new CiValue[maxRegisterNum()];
         curOutRegisterState = new CiValue[maxRegisterNum()];
-        for (LIRBlock block : lir.linearScanOrder()) {
-            assert trace("start block %s  loop %d depth %d", block, block.loopIndex(), block.loopDepth());
+        for (Block block : lir.linearScanOrder()) {
+            assert trace("start block %s %s", block, block.getLoop());
 
             Arrays.fill(curOutRegisterState, null);
-            if (block.dominator() != null) {
-                LocationMap dominatorState = endLocationsFor(block.dominator());
+            if (block.getDominator() != null) {
+                LocationMap dominatorState = endLocationsFor(block.getDominator());
                 curLocations = new LocationMap(dominatorState);
                 // Clear out all variables that are not live at the begin of this block
                 curLiveIn = dataFlow.liveIn(block);
@@ -210,7 +210,7 @@
             if (block.phis != null) {
                 assert trace("  phis");
                 curPhiBlock = block;
-                curOpId = block.firstLirInstructionId();
+                curOpId = block.getFirstLirInstructionId();
                 block.phis.forEachOutput(defProc);
                 curOpId = -1;
                 curPhiBlock = null;
@@ -218,8 +218,8 @@
 
             setBeginLocationsFor(block, new LocationMap(curLocations));
 
-            for (int opIdx = 0; opIdx < block.lir().size(); opIdx++) {
-                LIRInstruction op = block.lir().get(opIdx);
+            for (int opIdx = 0; opIdx < block.lir.size(); opIdx++) {
+                LIRInstruction op = block.lir.get(opIdx);
                 curOpId = op.id();
                 assert trace("  op %d %s", op.id(), op);
 
@@ -234,7 +234,7 @@
                 op.forEachInput(recordUseProc);
                 op.forEachAlive(recordUseProc);
 
-                moveResolver.init(block.lir(), opIdx);
+                moveResolver.init(block.lir, opIdx);
                 // Process Alive before Input because they are more restricted and the same variable can be Alive and Input.
                 op.forEachAlive(useProc);
                 op.forEachInput(useProc);
@@ -263,11 +263,11 @@
                 curOpId = -1;
             }
 
-            for (LIRBlock sux : block.getLIRSuccessors()) {
+            for (Block sux : block.getSuccessors()) {
                 if (sux.phis != null) {
                     assert trace("  phis of successor %s", sux);
                     System.arraycopy(curOutRegisterState, 0, curInRegisterState, 0, curOutRegisterState.length);
-                    curOpId = block.lastLirInstructionId() + 1;
+                    curOpId = block.getLastLirInstructionId() + 1;
                     sux.phis.forEachInput(block, useProc);
                     curOpId = -1;
                 }
@@ -463,6 +463,9 @@
         }
 
         if (bestSpillCandidate == null) {
+            if (curPhiBlock != null) {
+                return selectSpillSlot(variable, mode);
+            }
             // This should not happen as long as all LIR instructions have fulfillable register constraints. But be safe in product mode and bail out.
             assert false;
             throw new CiBailout("No register available");
@@ -554,7 +557,7 @@
         return loc;
     }
 
-    private boolean checkInputState(final LIRBlock block) {
+    private boolean checkInputState(final Block block) {
         final BitSet liveState = new BitSet();
         curLocations.forEachLocation(new ValueProcedure() {
             @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/ResolveDataFlow.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/ResolveDataFlow.java	Sun Feb 05 05:40:36 2012 +0100
@@ -30,6 +30,7 @@
 import com.oracle.max.criutils.*;
 import com.oracle.max.graal.alloc.util.*;
 import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
 import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure;
@@ -46,7 +47,7 @@
         this.dataFlow = dataFlow;
     }
 
-    private LIRBlock curToBlock;
+    private Block curToBlock;
     private LocationMap curFromLocations;
 
     public void execute() {
@@ -54,10 +55,10 @@
         PhiValueProcedure phiMappingProc = new PhiValueProcedure() { @Override public CiValue doValue(CiValue input, CiValue output) { return phiMapping(input, output); } };
 
         assert trace("==== start resolve data flow ====");
-        for (LIRBlock toBlock : lir.linearScanOrder()) {
+        for (Block toBlock : lir.linearScanOrder()) {
             curToBlock = toBlock;
 
-            for (LIRBlock fromBlock : toBlock.getLIRPredecessors()) {
+            for (Block fromBlock : toBlock.getPredecessors()) {
                 assert trace("start edge %s -> %s", fromBlock, toBlock);
                 findInsertPos(fromBlock, toBlock);
 
@@ -98,18 +99,18 @@
         return input;
     }
 
-    private void findInsertPos(LIRBlock fromBlock, LIRBlock toBlock) {
+    private void findInsertPos(Block fromBlock, Block toBlock) {
         assert fromBlock.getSuccessors().contains(toBlock) && toBlock.getPredecessors().contains(fromBlock);
 
         if (fromBlock.numberOfSux() == 1) {
-            List<LIRInstruction> instructions = fromBlock.lir();
+            List<LIRInstruction> instructions = fromBlock.lir;
             LIRInstruction instr = instructions.get(instructions.size() - 1);
             assert instr instanceof StandardOp.JumpOp : "block does not end with an unconditional jump";
             moveResolver.init(instructions, instructions.size() - 1);
             assert trace("  insert at end of %s before %d", fromBlock, instructions.size() - 1);
 
         } else if (toBlock.numberOfPreds() == 1) {
-            moveResolver.init(toBlock.lir(), 1);
+            moveResolver.init(toBlock.lir, 1);
             assert trace("  insert at beginning of %s before %d", toBlock, 1);
 
         } else {
@@ -117,8 +118,8 @@
         }
     }
 
-    protected abstract LocationMap locationsForBlockBegin(LIRBlock block);
-    protected abstract LocationMap locationsForBlockEnd(LIRBlock block);
+    protected abstract LocationMap locationsForBlockBegin(Block block);
+    protected abstract LocationMap locationsForBlockEnd(Block block);
 
 
     private static boolean trace(String format, Object...args) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java	Sun Feb 05 05:40:36 2012 +0100
@@ -32,12 +32,12 @@
 import com.oracle.max.criutils.*;
 import com.oracle.max.graal.alloc.util.*;
 import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
 import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure;
-import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.debug.*;
 
@@ -80,13 +80,13 @@
         }
 
         @Override
-        protected LocationMap locationsForBlockBegin(LIRBlock block) {
-            assert block.numberOfPreds() > 0 && block.dominator() != null;
-            return locationsFor(block.dominator());
+        protected LocationMap locationsForBlockBegin(Block block) {
+            assert block.numberOfPreds() > 0 && block.getDominator() != null;
+            return locationsFor(block.getDominator());
         }
 
         @Override
-        protected LocationMap locationsForBlockEnd(LIRBlock block) {
+        protected LocationMap locationsForBlockEnd(Block block) {
             return locationsFor(block);
         }
     }
@@ -97,7 +97,7 @@
         }
 
         @Override
-        protected LocationMap locationsForBlockEnd(LIRBlock block) {
+        protected LocationMap locationsForBlockEnd(Block block) {
             return locationsFor(block);
         }
     }
@@ -115,10 +115,10 @@
     private final LocationMap[] blockLocations;
 
     private LocationMap locationsFor(Block block) {
-        return blockLocations[block.blockID()];
+        return blockLocations[block.getId()];
     }
     private void setLocationsFor(Block block, LocationMap locations) {
-        blockLocations[block.blockID()] = locations;
+        blockLocations[block.getId()] = locations;
     }
 
     private MoveResolver moveResolver;
@@ -168,12 +168,12 @@
         curInRegisterState = new Object[maxRegisterNum()];
         curOutRegisterState = new Object[maxRegisterNum()];
         curRegisterLocations = new LocationMap(lir.numVariables());
-        for (LIRBlock block : lir.linearScanOrder()) {
-            assert trace("start block %s  loop %d depth %d", block, block.loopIndex(), block.loopDepth());
+        for (Block block : lir.linearScanOrder()) {
+            assert trace("start block %s %s", block, block.getLoop());
             assert checkEmpty(curOutRegisterState);
 
-            if (block.dominator() != null) {
-                LocationMap dominatorState = locationsFor(block.dominator());
+            if (block.getDominator() != null) {
+                LocationMap dominatorState = locationsFor(block.getDominator());
                 curStackLocations = new LocationMap(dominatorState);
                 // Clear out all variables that are not live at the begin of this block
                 curLiveIn = dataFlow.liveIn(block);
@@ -189,8 +189,8 @@
                 block.phis.forEachOutput(defSlotProc);
             }
 
-            for (int opIdx = 0; opIdx < block.lir().size(); opIdx++) {
-                LIRInstruction op = block.lir().get(opIdx);
+            for (int opIdx = 0; opIdx < block.lir.size(); opIdx++) {
+                LIRInstruction op = block.lir.get(opIdx);
                 curInstruction = op;
                 assert trace("  op %d %s", op.id(), op);
 
@@ -202,7 +202,7 @@
                 op.forEachTemp(blockProc);
                 op.forEachOutput(blockProc);
 
-                moveResolver.init(block.lir(), opIdx);
+                moveResolver.init(block.lir, opIdx);
                 // Process Alive before Input because they are more restricted and the same variable can be Alive and Input.
                 op.forEachAlive(loadProc);
                 op.forEachInput(loadProc);
@@ -212,7 +212,7 @@
                 dataFlow.forEachKilled(op, false, killBeginProc);
                 assert !op.hasCall() || checkNoCallerSavedRegister() : "caller saved register in use accross call site";
 
-                moveResolver.init(block.lir(), opIdx + 1);
+                moveResolver.init(block.lir, opIdx + 1);
                 op.forEachTemp(spillProc);
                 op.forEachOutput(spillProc);
                 moveResolver.resolve();
@@ -225,7 +225,7 @@
             }
             assert checkEmpty(curOutRegisterState);
 
-            for (LIRBlock sux : block.getLIRSuccessors()) {
+            for (Block sux : block.getSuccessors()) {
                 if (sux.phis != null) {
                     assert trace("  phis of successor %s", sux);
                     sux.phis.forEachInput(block, useSlotProc);
@@ -434,7 +434,7 @@
         return loc;
     }
 
-    private boolean checkInputState(final LIRBlock block) {
+    private boolean checkInputState(final Block block) {
         final BitSet liveState = new BitSet();
         curStackLocations.forEachLocation(new ValueProcedure() {
             @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/IntervalPrinter.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/IntervalPrinter.java	Sun Feb 05 05:40:36 2012 +0100
@@ -30,6 +30,7 @@
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.graal.alloc.simple.*;
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode;
@@ -126,11 +127,11 @@
     public Interval[] execute() {
         ValueProcedure varProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return var(value); } };
 
-        for (LIRBlock block : lir.linearScanOrder()) {
+        for (Block block : lir.linearScanOrder()) {
             if (block.phis != null) {
                 block.phis.forEachOutput(varProc);
             }
-            for (LIRInstruction op : block.lir()) {
+            for (LIRInstruction op : block.lir) {
                 op.forEachOutput(varProc);
             }
         }
@@ -142,29 +143,29 @@
         intervals.put("st", new Interval(-1, "st", "", "st", "hasState"));
 
         for (int i = lir.linearScanOrder().size() - 1; i >= 0; i--) {
-            LIRBlock block = lir.linearScanOrder().get(i);
+            Block block = lir.linearScanOrder().get(i);
 
-            curOpId = block.lastLirInstructionId() + 2;
-            for (LIRBlock sux : block.getLIRSuccessors()) {
+            curOpId = block.getLastLirInstructionId() + 2;
+            for (Block sux : block.getSuccessors()) {
                 BitSet suxIn = dataFlow.liveIn(sux);
                 for (int idx = suxIn.nextSetBit(0); idx >= 0; idx = suxIn.nextSetBit(idx + 1)) {
                     if (blockEndLocations != null) {
-                        out(blockEndLocations[block.blockID()].get(variables[idx]));
+                        out(blockEndLocations[block.getId()].get(variables[idx]));
                     } else {
                         out(variables[idx]);
                     }
                 }
             }
 
-            curOpId = block.lastLirInstructionId() + 1;
-            for (LIRBlock sux : block.getLIRSuccessors()) {
+            curOpId = block.getLastLirInstructionId() + 1;
+            for (Block sux : block.getSuccessors()) {
                 if (sux.phis != null) {
                     sux.phis.forEachInput(block, useProc);
                 }
             }
 
-            for (int j = block.lir().size() - 1; j >= 0; j--) {
-                LIRInstruction op = block.lir().get(j);
+            for (int j = block.lir.size() - 1; j >= 0; j--) {
+                LIRInstruction op = block.lir.get(j);
                 if (op.id() >= 0) {
                     curOpId = op.id();
                 } else {
@@ -188,13 +189,13 @@
             }
 
             if (block.phis != null) {
-                curOpId = block.firstLirInstructionId() + 1;
+                curOpId = block.getFirstLirInstructionId() + 1;
                 block.phis.forEachOutput(defProc);
             }
 
             for (Interval interval : intervals.values()) {
                 if (interval.lastTo != 0) {
-                    interval.ranges.add(new Range(block.firstLirInstructionId(), interval.lastTo));
+                    interval.ranges.add(new Range(block.getFirstLirInstructionId(), interval.lastTo));
                     interval.lastTo = 0;
                 }
             }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/RegisterVerifier.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/RegisterVerifier.java	Sun Feb 05 05:40:36 2012 +0100
@@ -30,6 +30,7 @@
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.criutils.*;
 import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.*;
 import com.oracle.max.graal.compiler.util.*;
@@ -40,7 +41,7 @@
     /**
      * All blocks that must be processed.
      */
-    private final List<LIRBlock> workList;
+    private final List<Block> workList;
 
     /**
      * Saved information of previous check.
@@ -51,18 +52,18 @@
      */
     private final Map<Object, CiValue>[] blockStates;
 
-    private void addToWorkList(LIRBlock block) {
+    private void addToWorkList(Block block) {
         if (!workList.contains(block)) {
             workList.add(block);
         }
     }
 
-    private Map<Object, CiValue> stateFor(LIRBlock block) {
-        return blockStates[block.blockID()];
+    private Map<Object, CiValue> stateFor(Block block) {
+        return blockStates[block.getId()];
     }
 
-    private void setStateFor(LIRBlock block, Map<Object, CiValue> savedState) {
-        blockStates[block.blockID()] = savedState;
+    private void setStateFor(Block block, Map<Object, CiValue> savedState) {
+        blockStates[block.getId()] = savedState;
     }
 
     private static Map<Object, CiValue> copy(Map<Object, CiValue> inputState) {
@@ -71,7 +72,7 @@
 
     public static boolean verify(LIR lir, FrameMap frameMap) {
         RegisterVerifier verifier = new RegisterVerifier(lir, frameMap);
-        verifier.verify(lir.startBlock());
+        verifier.verify(lir.cfg.getStartBlock());
         return true;
     }
 
@@ -84,7 +85,7 @@
 
     private Map<Object, CiValue> curInputState;
 
-    private void verify(LIRBlock startBlock) {
+    private void verify(Block startBlock) {
         ValueProcedure useProc =    new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, flags); } };
         ValueProcedure tempProc =   new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return temp(value); } };
         ValueProcedure outputProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return output(value); } };
@@ -95,15 +96,15 @@
 
         assert trace("==== start verify register allocation ====");
         do {
-            LIRBlock block = workList.remove(0);
+            Block block = workList.remove(0);
             assert block.phis == null : "phi functions must have been resolved with moves";
 
             // Must copy state because it is modified.
             curInputState = copy(stateFor(block));
-            assert trace("start block %s  loop %d depth %d", block, block.loopIndex(), block.loopDepth());
+            assert trace("start block %s %s", block, block.getLoop());
             assert traceState();
 
-            for (LIRInstruction op : block.lir()) {
+            for (LIRInstruction op : block.lir) {
                 assert trace("  op %d %s", op.id(), op);
 
                 op.forEachInput(useProc);
@@ -116,7 +117,7 @@
                 op.forEachOutput(outputProc);
             }
 
-            for (LIRBlock succ : block.getLIRSuccessors()) {
+            for (Block succ : block.getSuccessors()) {
                 processSuccessor(succ);
             }
 
@@ -125,7 +126,7 @@
         assert trace("==== end verify register allocation ====");
     }
 
-    private void processSuccessor(LIRBlock succ) {
+    private void processSuccessor(Block succ) {
         Map<Object, CiValue> savedState = stateFor(succ);
         if (savedState == null) {
             // Block was not processed before, so set initial inputState.
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java	Sun Feb 05 05:40:36 2012 +0100
@@ -33,6 +33,7 @@
 import com.oracle.max.graal.alloc.simple.*;
 import com.oracle.max.graal.compiler.alloc.*;
 import com.oracle.max.graal.compiler.asm.*;
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.gen.*;
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.phases.*;
@@ -41,7 +42,6 @@
 import com.oracle.max.graal.compiler.target.*;
 import com.oracle.max.graal.cri.*;
 import com.oracle.max.graal.debug.*;
-import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 
 public class GraalCompiler {
@@ -181,24 +181,17 @@
                 new ReadEliminationPhase().apply(graph);
             }
         }
-        new RemovePlaceholderPhase().apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
 
         plan.runPhases(PhasePosition.MID_LEVEL, graph);
 
         plan.runPhases(PhasePosition.LOW_LEVEL, graph);
 
-        final IdentifyBlocksPhase schedule = new IdentifyBlocksPhase(true, LIRBlock.FACTORY);
+        final SchedulePhase schedule = new SchedulePhase();
         schedule.apply(graph);
 
-        final List<Block> blocks = schedule.getBlocks();
-        final NodeMap<LIRBlock> valueToBlock = new NodeMap<>(graph);
-        for (Block b : blocks) {
-            for (Node i : b.getInstructions()) {
-                valueToBlock.set(i, (LIRBlock) b);
-            }
-        }
-        final LIRBlock startBlock = valueToBlock.get(graph.start());
+        final Block[] blocks = schedule.getCFG().getBlocks();
+        final Block startBlock = schedule.getCFG().getStartBlock();
         assert startBlock != null;
         assert startBlock.numberOfPreds() == 0;
 
@@ -206,16 +199,16 @@
 
             @Override
             public LIR call() {
-                ComputeLinearScanOrder clso = new ComputeLinearScanOrder(blocks.size(), schedule.loopCount(), startBlock);
-                List<LIRBlock> linearScanOrder = clso.linearScanOrder();
-                List<LIRBlock> codeEmittingOrder = clso.codeEmittingOrder();
+                ComputeLinearScanOrder clso = new ComputeLinearScanOrder(blocks.length, schedule.getCFG().getLoops().length, startBlock);
+                List<Block> linearScanOrder = clso.linearScanOrder();
+                List<Block> codeEmittingOrder = clso.codeEmittingOrder();
 
                 int z = 0;
-                for (LIRBlock b : linearScanOrder) {
-                    b.setLinearScanNumber(z++);
+                for (Block b : linearScanOrder) {
+                    b.linearScanNumber = z++;
                 }
 
-                LIR lir = new LIR(startBlock, linearScanOrder, codeEmittingOrder, valueToBlock, schedule.loopCount());
+                LIR lir = new LIR(schedule.getCFG(), schedule.getNodesFor(), linearScanOrder, codeEmittingOrder);
                 Debug.dump(lir, "After linear scan order");
                 return lir;
 
@@ -229,11 +222,11 @@
 
         Debug.scope("LIRGen", new Runnable() {
             public void run() {
-                for (LIRBlock b : lir.linearScanOrder()) {
+                for (Block b : lir.linearScanOrder()) {
                     lirGenerator.doBlock(b);
                 }
 
-                for (LIRBlock b : lir.linearScanOrder()) {
+                for (Block b : lir.linearScanOrder()) {
                     if (b.phis != null) {
                         b.phis.fillInputs(lirGenerator);
                     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Sun Feb 05 05:40:36 2012 +0100
@@ -126,6 +126,7 @@
     public static int     MatureInvocationCount              = 100;
     public static boolean GenSafepoints                      = true;
     public static boolean GenLoopSafepoints                  = true;
+    public static boolean UseInstanceOfHints                 = true;
 
     public static boolean GenAssertionCode                   = ____;
     public static boolean AlignCallsForPatching              = true;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ComputeLinearScanOrder.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ComputeLinearScanOrder.java	Sun Feb 05 05:40:36 2012 +0100
@@ -27,22 +27,22 @@
 
 import com.oracle.max.criutils.*;
 import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.graph.*;
 
 public final class ComputeLinearScanOrder {
 
     private int numBlocks; // total number of blocks (smaller than maxBlockId)
 
-    List<LIRBlock> linearScanOrder; // the resulting list of blocks in correct order
-    List<LIRBlock> codeEmittingOrder;
+    List<Block> linearScanOrder; // the resulting list of blocks in correct order
+    List<Block> codeEmittingOrder;
 
     final BitMap visitedBlocks; // used for recursive processing of blocks
     final BitMap activeBlocks; // used for recursive processing of blocks
     final BitMap dominatorBlocks; // temporary BitMap used for computation of dominator
     final int[] forwardBranches; // number of incoming forward branches for each block
-    final List<LIRBlock> workList; // temporary list (used in markLoops and computeOrder)
-    final LIRBlock[] loopHeaders;
+    final List<Block> workList; // temporary list (used in markLoops and computeOrder)
+    final Block[] loopHeaders;
 
     // accessors for visitedBlocks and activeBlocks
     void initVisited() {
@@ -50,45 +50,45 @@
         visitedBlocks.clearAll();
     }
 
-    boolean isVisited(LIRBlock b) {
-        return visitedBlocks.get(b.blockID());
+    boolean isVisited(Block b) {
+        return visitedBlocks.get(b.getId());
     }
 
-    boolean isActive(LIRBlock b) {
-        return activeBlocks.get(b.blockID());
+    boolean isActive(Block b) {
+        return activeBlocks.get(b.getId());
     }
 
-    void setVisited(LIRBlock b) {
+    void setVisited(Block b) {
         assert !isVisited(b) : "already set";
-        visitedBlocks.set(b.blockID());
+        visitedBlocks.set(b.getId());
     }
 
-    void setActive(LIRBlock b) {
+    void setActive(Block b) {
         assert !isActive(b) : "already set";
-        activeBlocks.set(b.blockID());
+        activeBlocks.set(b.getId());
     }
 
-    void clearActive(LIRBlock b) {
+    void clearActive(Block b) {
         assert isActive(b) : "not already";
-        activeBlocks.clear(b.blockID());
+        activeBlocks.clear(b.getId());
     }
 
     // accessors for forwardBranches
-    void incForwardBranches(LIRBlock b) {
-        forwardBranches[b.blockID()]++;
+    void incForwardBranches(Block b) {
+        forwardBranches[b.getId()]++;
     }
 
-    int decForwardBranches(LIRBlock b) {
-        return --forwardBranches[b.blockID()];
+    int decForwardBranches(Block b) {
+        return --forwardBranches[b.getId()];
     }
 
     // accessors for final result
-    public List<LIRBlock> linearScanOrder() {
+    public List<Block> linearScanOrder() {
         return linearScanOrder;
     }
 
-    public ComputeLinearScanOrder(int maxBlockId, int loopCount, LIRBlock startBlock) {
-        loopHeaders = new LIRBlock[loopCount];
+    public ComputeLinearScanOrder(int maxBlockId, int loopCount, Block startBlock) {
+        loopHeaders = new Block[loopCount];
 
         visitedBlocks = new BitMap(maxBlockId);
         activeBlocks = new BitMap(maxBlockId);
@@ -98,7 +98,6 @@
 
         countEdges(startBlock, null);
         computeOrder(startBlock);
-        printBlocks();
     }
 
     /**
@@ -109,9 +108,9 @@
      * 3. Number loop header blocks.
      * 4. Create a list with all loop end blocks.
      */
-    void countEdges(LIRBlock cur, LIRBlock parent) {
+    void countEdges(Block cur, Block parent) {
         if (GraalOptions.TraceLinearScanLevel >= 3) {
-            TTY.println("Counting edges for block B%d%s", cur.blockID(), parent == null ? "" : " coming from B" + parent.blockID());
+            TTY.println("Counting edges for block B%d%s", cur.getId(), parent == null ? "" : " coming from B" + parent.getId());
         }
 
         if (isActive(cur)) {
@@ -141,14 +140,14 @@
         clearActive(cur);
 
         if (GraalOptions.TraceLinearScanLevel >= 3) {
-            TTY.println("Finished counting edges for block B%d", cur.blockID());
+            TTY.println("Finished counting edges for block B%d", cur.getId());
         }
     }
 
-    static int computeWeight(LIRBlock cur) {
+    static int computeWeight(Block cur) {
 
         // limit loop-depth to 15 bit (only for security reason, it will never be so big)
-        int weight = (cur.loopDepth() & 0x7FFF) << 16;
+        int weight = (cur.getLoopDepth() & 0x7FFF) << 16;
 
         int curBit = 15;
 
@@ -200,7 +199,7 @@
         return weight;
     }
 
-    private boolean readyForProcessing(LIRBlock cur) {
+    private boolean readyForProcessing(Block cur) {
         // Discount the edge just traveled.
         // When the number drops to zero, all forward branches were processed
         if (decForwardBranches(cur) != 0) {
@@ -212,13 +211,13 @@
         return true;
     }
 
-    private void sortIntoWorkList(LIRBlock cur) {
+    private void sortIntoWorkList(Block cur) {
         assert !workList.contains(cur) : "block already in work list";
 
         int curWeight = computeWeight(cur);
 
         // the linearScanNumber is used to cache the weight of a block
-        cur.setLinearScanNumber(curWeight);
+        cur.linearScanNumber = curWeight;
 
         if (GraalOptions.StressLinearScan) {
             workList.add(0, cur);
@@ -228,35 +227,35 @@
         workList.add(null); // provide space for new element
 
         int insertIdx = workList.size() - 1;
-        while (insertIdx > 0 && workList.get(insertIdx - 1).linearScanNumber() > curWeight) {
+        while (insertIdx > 0 && workList.get(insertIdx - 1).linearScanNumber > curWeight) {
             workList.set(insertIdx, workList.get(insertIdx - 1));
             insertIdx--;
         }
         workList.set(insertIdx, cur);
 
         if (GraalOptions.TraceLinearScanLevel >= 3) {
-            TTY.println("Sorted B%d into worklist. new worklist:", cur.blockID());
+            TTY.println("Sorted B%d into worklist. new worklist:", cur.getId());
             for (int i = 0; i < workList.size(); i++) {
-                TTY.println(String.format("%8d B%02d  weight:%6x", i, workList.get(i).blockID(), workList.get(i).linearScanNumber()));
+                TTY.println(String.format("%8d B%02d  weight:%6x", i, workList.get(i).getId(), workList.get(i).linearScanNumber));
             }
         }
 
         for (int i = 0; i < workList.size(); i++) {
-            assert workList.get(i).linearScanNumber() > 0 : "weight not set";
-            assert i == 0 || workList.get(i - 1).linearScanNumber() <= workList.get(i).linearScanNumber() : "incorrect order in worklist";
+            assert workList.get(i).linearScanNumber > 0 : "weight not set";
+            assert i == 0 || workList.get(i - 1).linearScanNumber <= workList.get(i).linearScanNumber : "incorrect order in worklist";
         }
     }
 
-    private void appendBlock(LIRBlock cur) {
+    private void appendBlock(Block cur) {
         if (GraalOptions.TraceLinearScanLevel >= 3) {
-            TTY.println("appending block B%d (weight 0x%06x) to linear-scan order", cur.blockID(), cur.linearScanNumber());
+            TTY.println("appending block B%d (weight 0x%06x) to linear-scan order", cur.getId(), cur.linearScanNumber);
         }
         assert !linearScanOrder.contains(cur) : "cannot add the same block twice";
 
         // currently, the linear scan order and code emit order are equal.
         // therefore the linearScanNumber and the weight of a block must also
         // be equal.
-        cur.setLinearScanNumber(linearScanOrder.size());
+        cur.linearScanNumber = linearScanOrder.size();
         linearScanOrder.add(cur);
 
         if (cur.isLoopEnd() && cur.isLoopHeader()) {
@@ -266,24 +265,24 @@
                 codeEmittingOrder.add(cur);
 
                 if (cur.isLoopEnd() && GraalOptions.OptReorderLoops) {
-                    LIRBlock loopHeader = loopHeaders[cur.loopIndex()];
+                    Block loopHeader = loopHeaders[cur.getLoop().index];
                     assert loopHeader != null;
                     codeEmittingOrder.add(loopHeader);
 
                     for (int i = 0; i < loopHeader.numberOfSux(); i++) {
-                        LIRBlock succ = loopHeader.suxAt(i);
-                        if (succ.loopDepth() == loopHeader.loopDepth()) {
-                            succ.setAlign(true);
+                        Block succ = loopHeader.suxAt(i);
+                        if (succ.getLoopDepth() == loopHeader.getLoopDepth()) {
+                            succ.align = true;
                         }
                     }
                 }
             } else {
-                loopHeaders[cur.loopIndex()] = cur;
+                loopHeaders[cur.getLoop().index] = cur;
             }
         }
     }
 
-    private void computeOrder(LIRBlock startBlock) {
+    private void computeOrder(Block startBlock) {
         if (GraalOptions.TraceLinearScanLevel >= 3) {
             TTY.println("----- computing final block order");
         }
@@ -300,14 +299,14 @@
         sortIntoWorkList(startBlock);
 
         do {
-            LIRBlock cur = workList.remove(workList.size() - 1);
+            Block cur = workList.remove(workList.size() - 1);
             appendBlock(cur);
 
             int i;
             int numSux = cur.numberOfSux();
             // changed loop order to get "intuitive" order of if- and else-blocks
             for (i = 0; i < numSux; i++) {
-                LIRBlock sux = cur.suxAt(i);
+                Block sux = cur.suxAt(i);
                 if (readyForProcessing(sux)) {
                     sortIntoWorkList(sux);
                 }
@@ -315,46 +314,7 @@
         } while (workList.size() > 0);
     }
 
-    public void printBlocks() {
-        if (GraalOptions.TraceLinearScanLevel >= 2) {
-            TTY.println("----- loop information:");
-            for (LIRBlock cur : linearScanOrder) {
-                TTY.print(String.format("%4d: B%02d: ", cur.linearScanNumber(), cur.blockID()));
-                TTY.println(String.format(" . loopIndex: %2d, loopDepth: %2d", cur.loopIndex(), cur.loopDepth()));
-            }
-        }
-
-        if (GraalOptions.TraceLinearScanLevel >= 1) {
-            TTY.println("----- linear-scan block order:");
-            for (LIRBlock cur : linearScanOrder) {
-                TTY.print(String.format("%4d: B%02d    loop: %2d  depth: %2d", cur.linearScanNumber(), cur.blockID(), cur.loopIndex(), cur.loopDepth()));
-
-                TTY.print(cur.isLoopHeader() ? " lh" : "   ");
-                TTY.print(cur.isLoopEnd() ? " le" : "   ");
-
-                TTY.print("    dom: null ");
-
-
-                if (cur.numberOfPreds() > 0) {
-                    TTY.print("    preds: ");
-                    for (int j = 0; j < cur.numberOfPreds(); j++) {
-                        LIRBlock pred = cur.predAt(j);
-                        TTY.print("B%d ", pred.blockID());
-                    }
-                }
-                if (cur.numberOfSux() > 0) {
-                    TTY.print("    sux: ");
-                    for (int j = 0; j < cur.numberOfSux(); j++) {
-                        LIRBlock sux = cur.suxAt(j);
-                        TTY.print("B%d ", sux.blockID());
-                    }
-                }
-                TTY.println();
-            }
-        }
-    }
-
-    public List<LIRBlock> codeEmittingOrder() {
+    public List<Block> codeEmittingOrder() {
         return codeEmittingOrder;
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java	Sun Feb 05 05:40:36 2012 +0100
@@ -24,8 +24,8 @@
 
 import java.util.*;
 
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.debug.*;
 
@@ -40,7 +40,7 @@
      */
     public static void optimize(LIR ir) {
         ControlFlowOptimizer optimizer = new ControlFlowOptimizer(ir);
-        List<LIRBlock> code = ir.codeEmittingOrder();
+        List<Block> code = ir.codeEmittingOrder();
         //optimizer.reorderShortLoops(code);
         optimizer.deleteEmptyBlocks(code);
         ControlFlowOptimizer.deleteUnnecessaryJumps(code);
@@ -90,37 +90,48 @@
 
     // only blocks with exactly one successor can be deleted. Such blocks
     // must always end with an unconditional branch to its successor
-    private boolean canDeleteBlock(LIRBlock block) {
+    private boolean canDeleteBlock(Block block) {
         if (block.numberOfSux() != 1 ||
-            block == ir.startBlock() ||
+            block == ir.cfg.getStartBlock() ||
             block.suxAt(0) == block) {
             return false;
         }
 
-        List<LIRInstruction> instructions = block.lir();
+        List<LIRInstruction> instructions = block.lir;
 
         assert instructions.size() >= 2 : "block must have label and branch";
         assert instructions.get(0) instanceof StandardOp.LabelOp : "first instruction must always be a label";
         assert instructions.get(instructions.size() - 1) instanceof StandardOp.JumpOp : "last instruction must always be a branch";
-        assert ((StandardOp.JumpOp) instructions.get(instructions.size() - 1)).destination().label() == block.suxAt(0).label() : "branch target must be the successor";
+        assert ((StandardOp.JumpOp) instructions.get(instructions.size() - 1)).destination().label() == ((StandardOp.LabelOp) block.suxAt(0).lir.get(0)).getLabel() : "branch target must be the successor";
 
         // block must have exactly one successor
 
         return instructions.size() == 2 && instructions.get(instructions.size() - 1).info == null;
     }
 
-    private void deleteEmptyBlocks(List<LIRBlock> code) {
+    private void deleteEmptyBlocks(List<Block> code) {
         int oldPos = 0;
         int newPos = 0;
         int numBlocks = code.size();
 
         assert verify(code);
         while (oldPos < numBlocks) {
-            LIRBlock block = code.get(oldPos);
+            Block block = code.get(oldPos);
 
             if (canDeleteBlock(block)) {
                 // adjust successor and predecessor lists
-                block.replaceWith(block.suxAt(0));
+                Block other = block.suxAt(0);
+                for (Block pred : block.getPredecessors()) {
+                    Util.replaceAllInList(block, other, pred.getSuccessors());
+                }
+                for (int i = 0; i < other.getPredecessors().size(); i++) {
+                    if (other.getPredecessors().get(i) == block) {
+                        other.getPredecessors().remove(i);
+                        other.getPredecessors().addAll(i, block.getPredecessors());
+                    }
+                }
+                block.getSuccessors().clear();
+                block.getPredecessors().clear();
                 Debug.metric("BlocksDeleted").increment();
             } else {
                 // adjust position of this block in the block list if blocks before
@@ -138,18 +149,18 @@
         assert verify(code);
     }
 
-    private static void deleteUnnecessaryJumps(List<LIRBlock> code) {
+    private static void deleteUnnecessaryJumps(List<Block> code) {
         // skip the last block because there a branch is always necessary
         for (int i = code.size() - 2; i >= 0; i--) {
-            LIRBlock block = code.get(i);
-            List<LIRInstruction> instructions = block.lir();
+            Block block = code.get(i);
+            List<LIRInstruction> instructions = block.lir;
 
             LIRInstruction lastOp = instructions.get(instructions.size() - 1);
             if (lastOp instanceof StandardOp.JumpOp) {
                 StandardOp.JumpOp lastJump = (StandardOp.JumpOp) lastOp;
 
                 if (lastOp.info == null) {
-                    if (lastJump.destination().label() == code.get(i + 1).label()) {
+                    if (lastJump.destination().label() == ((StandardOp.LabelOp) code.get(i + 1).lir.get(0)).getLabel()) {
                         // delete last branch instruction
                         Util.truncate(instructions, instructions.size() - 1);
 
@@ -158,7 +169,7 @@
                         if (prevOp instanceof StandardOp.BranchOp) {
                             StandardOp.BranchOp prevBranch = (StandardOp.BranchOp) prevOp;
 
-                            if (prevBranch.destination().label() == code.get(i + 1).label && prevOp.info == null) {
+                            if (prevBranch.destination().label() == ((StandardOp.LabelOp) code.get(i + 1).lir.get(0)).getLabel() && prevOp.info == null) {
                                 // eliminate a conditional branch to the immediate successor
                                 prevBranch.negate(lastJump.destination());
                                 Util.truncate(instructions, instructions.size() - 1);
@@ -212,8 +223,8 @@
     }
 */
 
-    private static boolean verify(List<LIRBlock> code) {
-        for (LIRBlock block : code) {
+    private static boolean verify(List<Block> code) {
+        for (Block block : code) {
             for (Block sux : block.getSuccessors()) {
                 assert code.contains(sux) : "missing successor from: " + block + "to: " + sux;
             }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/EdgeMoveOptimizer.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/EdgeMoveOptimizer.java	Sun Feb 05 05:40:36 2012 +0100
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.lir.StandardOp.*;
 
@@ -54,12 +55,12 @@
      *
      * @param blockList a list of blocks whose moves should be optimized
      */
-    public static void optimize(List<LIRBlock> blockList) {
+    public static void optimize(List<Block> blockList) {
         EdgeMoveOptimizer optimizer = new EdgeMoveOptimizer();
 
         // ignore the first block in the list (index 0 is not processed)
         for (int i = blockList.size() - 1; i >= 1; i--) {
-            LIRBlock block = blockList.get(i);
+            Block block = blockList.get(i);
 
             if (block.numberOfPreds() > 1) {
                 optimizer.optimizeMovesAtBlockEnd(block);
@@ -104,10 +105,12 @@
      * Moves the longest {@linkplain #same common} subsequence at the end all
      * predecessors of {@code block} to the start of {@code block}.
      */
-    private void optimizeMovesAtBlockEnd(LIRBlock block) {
-        if (block.isPredecessor(block)) {
-            // currently we can't handle this correctly.
-            return;
+    private void optimizeMovesAtBlockEnd(Block block) {
+        for (Block pred : block.getPredecessors()) {
+            if (pred == block) {
+                // currently we can't handle this correctly.
+                return;
+            }
         }
 
         // clear all internal data structures
@@ -117,11 +120,10 @@
         assert numPreds > 1 : "do not call otherwise";
 
         // setup a list with the LIR instructions of all predecessors
-        for (int i = 0; i < numPreds; i++) {
-            LIRBlock pred = block.predAt(i);
+        for (Block pred : block.getPredecessors()) {
             assert pred != null;
-            assert pred.lir() != null;
-            List<LIRInstruction> predInstructions = pred.lir();
+            assert pred.lir != null;
+            List<LIRInstruction> predInstructions = pred.lir;
 
             if (pred.numberOfSux() != 1) {
                 // this can happen with switch-statements where multiple edges are between
@@ -162,7 +164,7 @@
             }
 
             // insert the instruction at the beginning of the current block
-            block.lir().add(1, op);
+            block.lir.add(1, op);
 
             // delete the instruction at the end of all predecessors
             for (int i = 0; i < numPreds; i++) {
@@ -177,12 +179,12 @@
      * successors of {@code block} to the end of {@code block} just prior to the
      * branch instruction ending {@code block}.
      */
-    private void optimizeMovesAtBlockBegin(LIRBlock block) {
+    private void optimizeMovesAtBlockBegin(Block block) {
 
         edgeInstructionSeqences.clear();
         int numSux = block.numberOfSux();
 
-        List<LIRInstruction> instructions = block.lir();
+        List<LIRInstruction> instructions = block.lir;
 
         assert numSux == 2 : "method should not be called otherwise";
 
@@ -212,8 +214,8 @@
 
         // setup a list with the lir-instructions of all successors
         for (int i = 0; i < numSux; i++) {
-            LIRBlock sux = block.suxAt(i);
-            List<LIRInstruction> suxInstructions = sux.lir();
+            Block sux = block.suxAt(i);
+            List<LIRInstruction> suxInstructions = sux.lir;
 
             assert suxInstructions.get(0) instanceof StandardOp.LabelOp : "block must start with label";
 
@@ -247,7 +249,7 @@
             }
 
             // insert instruction at end of current block
-            block.lir().add(insertIdx, op);
+            block.lir.add(insertIdx, op);
             insertIdx++;
 
             // delete the instructions at the beginning of all successors
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Sun Feb 05 05:40:36 2012 +0100
@@ -35,15 +35,16 @@
 import com.oracle.max.graal.compiler.alloc.Interval.RegisterBinding;
 import com.oracle.max.graal.compiler.alloc.Interval.RegisterPriority;
 import com.oracle.max.graal.compiler.alloc.Interval.SpillState;
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.gen.*;
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
+import com.oracle.max.graal.compiler.lir.StandardOp.MoveOp;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.debug.*;
 import com.oracle.max.graal.graph.*;
-import com.oracle.max.graal.compiler.lir.StandardOp.*;
 
 /**
  * An implementation of the linear scan register allocator algorithm described
@@ -62,10 +63,43 @@
 
     private static final int INITIAL_SPLIT_INTERVALS_CAPACITY = 32;
 
+    public static class BlockData {
+        /**
+         * Bit map specifying which {@linkplain OperandPool operands} are live upon entry to this block.
+         * These are values used in this block or any of its successors where such value are not defined
+         * in this block.
+         * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.sun.cri.ci.CiValue) operand number}.
+         */
+        public BitMap liveIn;
+
+        /**
+         * Bit map specifying which {@linkplain OperandPool operands} are live upon exit from this block.
+         * These are values used in a successor block that are either defined in this block or were live
+         * upon entry to this block.
+         * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.sun.cri.ci.CiValue) operand number}.
+         */
+        public BitMap liveOut;
+
+        /**
+         * Bit map specifying which {@linkplain OperandPool operands} are used (before being defined) in this block.
+         * That is, these are the values that are live upon entry to the block.
+         * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.sun.cri.ci.CiValue) operand number}.
+         */
+        public BitMap liveGen;
+
+        /**
+         * Bit map specifying which {@linkplain OperandPool operands} are defined/overwritten in this block.
+         * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.sun.cri.ci.CiValue) operand number}.
+         */
+        public BitMap liveKill;
+    }
+
+    public final BlockMap<BlockData> blockData;
+
     /**
      * List of blocks in linear-scan order. This is only correct as long as the CFG does not change.
      */
-    final LIRBlock[] sortedBlocks;
+    final Block[] sortedBlocks;
 
     /**
      * Map from {@linkplain #operandNumber(CiValue) operand numbers} to intervals.
@@ -96,10 +130,10 @@
 
     /**
      * Map from an instruction {@linkplain LIRInstruction#id id} to the {@linkplain
-     * LIRBlock block} containing the instruction. Entries should be retrieved with
+     * Block block} containing the instruction. Entries should be retrieved with
      * {@link #blockForId(int)} as the id is not simply an index into this array.
      */
-    LIRBlock[] opIdToBlockMap;
+    Block[] opIdToBlockMap;
 
     /**
      * Bit set for each variable that is contained in each loop.
@@ -126,12 +160,13 @@
         this.ir = ir;
         this.gen = gen;
         this.frameMap = frameMap;
-        this.sortedBlocks = ir.linearScanOrder().toArray(new LIRBlock[ir.linearScanOrder().size()]);
+        this.sortedBlocks = ir.linearScanOrder().toArray(new Block[ir.linearScanOrder().size()]);
         this.registerAttributes = frameMap.registerConfig.getAttributesMap();
 
         this.registers = target.arch.registers;
         this.firstVariableNumber = registers.length;
         this.variables = new ArrayList<>(ir.numVariables() * 3 / 2);
+        this.blockData = new BlockMap<>(ir.cfg);
     }
 
     public static boolean isVariableOrRegister(CiValue value) {
@@ -269,13 +304,13 @@
         return sortedBlocks.length;
     }
 
-    LIRBlock blockAt(int index) {
+    Block blockAt(int index) {
         assert sortedBlocks[index] == ir.linearScanOrder().get(index) : "invalid cached block list";
         return sortedBlocks[index];
     }
 
     /**
-     * Gets the size of the {@link LIRBlock#liveIn} and {@link LIRBlock#liveOut} sets for a basic block. These sets do
+     * Gets the size of the {@link Block#liveIn} and {@link Block#liveOut} sets for a basic block. These sets do
      * not include any operands allocated as a result of creating {@linkplain #createDerivedInterval(Interval) derived
      * intervals}.
      */
@@ -284,7 +319,7 @@
     }
 
     int numLoops() {
-        return ir.numLoops();
+        return ir.cfg.getLoops().length;
     }
 
     boolean isIntervalInLoop(int interval, int loop) {
@@ -333,7 +368,7 @@
      * @param opId an instruction {@linkplain LIRInstruction#id id}
      * @return the block containing the instruction denoted by {@code opId}
      */
-    LIRBlock blockForId(int opId) {
+    Block blockForId(int opId) {
         assert opIdToBlockMap.length > 0 && opId >= 0 && opId <= maxOpId() + 1 : "opId out of range";
         return opIdToBlockMap[opIdToIndex(opId)];
     }
@@ -394,8 +429,8 @@
     void changeSpillState(Interval interval, int spillPos) {
         switch (interval.spillState()) {
             case NoSpillStore: {
-                int defLoopDepth = blockForId(interval.spillDefinitionPos()).loopDepth();
-                int spillLoopDepth = blockForId(spillPos).loopDepth();
+                int defLoopDepth = blockForId(interval.spillDefinitionPos()).getLoopDepth();
+                int spillLoopDepth = blockForId(spillPos).getLoopDepth();
 
                 if (defLoopDepth < spillLoopDepth) {
                     // the loop depth of the spilling position is higher then the loop depth
@@ -457,8 +492,8 @@
         LIRInsertionBuffer insertionBuffer = new LIRInsertionBuffer();
         int numBlocks = blockCount();
         for (int i = 0; i < numBlocks; i++) {
-            LIRBlock block = blockAt(i);
-            List<LIRInstruction> instructions = block.lir();
+            Block block = blockAt(i);
+            List<LIRInstruction> instructions = block.lir;
             int numInst = instructions.size();
 
             // iterate all instructions of the block. skip the first because it is always a label
@@ -490,7 +525,7 @@
                     while (interval != Interval.EndMarker && interval.spillDefinitionPos() == opId) {
                         if (!insertionBuffer.initialized()) {
                             // prepare insertion buffer (appended when all instructions of the block are processed)
-                            insertionBuffer.init(block.lir());
+                            insertionBuffer.init(block.lir);
                         }
 
                         CiValue fromLocation = interval.location();
@@ -565,20 +600,21 @@
         int numBlocks = blockCount();
         int numInstructions = 0;
         for (int i = 0; i < numBlocks; i++) {
-            numInstructions += blockAt(i).lir().size();
+            numInstructions += blockAt(i).lir.size();
         }
 
         // initialize with correct length
         opIdToInstructionMap = new LIRInstruction[numInstructions];
-        opIdToBlockMap = new LIRBlock[numInstructions];
+        opIdToBlockMap = new Block[numInstructions];
 
         int opId = 0;
         int index = 0;
 
         for (int i = 0; i < numBlocks; i++) {
-            LIRBlock block = blockAt(i);
-            block.setFirstLirInstructionId(opId);
-            List<LIRInstruction> instructions = block.lir();
+            Block block = blockAt(i);
+            blockData.put(block, new BlockData());
+
+            List<LIRInstruction> instructions = block.lir;
 
             int numInst = instructions.size();
             for (int j = 0; j < numInst; j++) {
@@ -595,7 +631,6 @@
                 index++;
                 opId += 2; // numbering of lirOps by two
             }
-            block.setLastLirInstructionId((opId - 2));
         }
         assert index == numInstructions : "must match";
         assert (index << 1) == opId : "must match: " + (index << 1);
@@ -609,7 +644,7 @@
     }
 
     /**
-     * Computes local live sets (i.e. {@link LIRBlock#liveGen} and {@link LIRBlock#liveKill}) separately for each block.
+     * Computes local live sets (i.e. {@link Block#liveGen} and {@link Block#liveKill}) separately for each block.
      */
     void computeLocalLiveSets() {
         int numBlocks = blockCount();
@@ -619,11 +654,11 @@
 
         // iterate all blocks
         for (int i = 0; i < numBlocks; i++) {
-            final LIRBlock block = blockAt(i);
+            final Block block = blockAt(i);
             final BitMap liveGen = new BitMap(liveSize);
             final BitMap liveKill = new BitMap(liveSize);
 
-            List<LIRInstruction> instructions = block.lir();
+            List<LIRInstruction> instructions = block.lir;
             int numInst = instructions.size();
 
             // iterate all instructions of the block. skip the first because it is always a label
@@ -642,8 +677,8 @@
                                     TTY.println("  Setting liveGen for operand %d at instruction %d", operandNum, op.id());
                                 }
                             }
-                            if (block.loopIndex() >= 0) {
-                                intervalInLoop.setBit(operandNum, block.loopIndex());
+                            if (block.getLoop() != null) {
+                                intervalInLoop.setBit(operandNum, block.getLoop().index);
                             }
                         }
 
@@ -672,8 +707,8 @@
                         if (isVariable(operand)) {
                             int varNum = operandNumber(operand);
                             liveKill.set(varNum);
-                            if (block.loopIndex() >= 0) {
-                                intervalInLoop.setBit(varNum, block.loopIndex());
+                            if (block.getLoop() != null) {
+                                intervalInLoop.setBit(varNum, block.getLoop().index);
                             }
                         }
 
@@ -695,14 +730,14 @@
                 op.forEachOutput(defProc);
             } // end of instruction iteration
 
-            block.liveGen = liveGen;
-            block.liveKill = liveKill;
-            block.liveIn = new BitMap(liveSize);
-            block.liveOut = new BitMap(liveSize);
+            blockData.get(block).liveGen = liveGen;
+            blockData.get(block).liveKill = liveKill;
+            blockData.get(block).liveIn = new BitMap(liveSize);
+            blockData.get(block).liveOut = new BitMap(liveSize);
 
             if (GraalOptions.TraceLinearScanLevel >= 4) {
-                TTY.println("liveGen  B%d %s", block.blockID(), block.liveGen);
-                TTY.println("liveKill B%d %s", block.blockID(), block.liveKill);
+                TTY.println("liveGen  B%d %s", block.getId(), blockData.get(block).liveGen);
+                TTY.println("liveKill B%d %s", block.getId(), blockData.get(block).liveKill);
             }
         } // end of block iteration
     }
@@ -718,13 +753,13 @@
         }
     }
 
-    private void verifyInput(LIRBlock block, BitMap liveKill, CiValue operand) {
+    private void verifyInput(Block block, BitMap liveKill, CiValue operand) {
         // fixed intervals are never live at block boundaries, so
         // they need not be processed in live sets.
         // this is checked by these assertions to be sure about it.
         // the entry block may have incoming
         // values in registers, which is ok.
-        if (isRegister(operand) && block != ir.startBlock()) {
+        if (isRegister(operand) && block != ir.cfg.getStartBlock()) {
             if (isProcessed(operand)) {
                 assert liveKill.get(operandNumber(operand)) : "using fixed register that is not defined in this block";
             }
@@ -732,8 +767,8 @@
     }
 
     /**
-     * Performs a backward dataflow analysis to compute global live sets (i.e. {@link LIRBlock#liveIn} and
-     * {@link LIRBlock#liveOut}) for each block.
+     * Performs a backward dataflow analysis to compute global live sets (i.e. {@link Block#liveIn} and
+     * {@link Block#liveOut}) for each block.
      */
     void computeGlobalLiveSets() {
         int numBlocks = blockCount();
@@ -749,7 +784,7 @@
 
             // iterate all blocks in reverse order
             for (int i = numBlocks - 1; i >= 0; i--) {
-                LIRBlock block = blockAt(i);
+                Block block = blockAt(i);
 
                 changeOccurredInBlock = false;
 
@@ -758,18 +793,18 @@
                 if (n > 0) {
                     // block has successors
                     if (n > 0) {
-                        liveOut.setFrom(block.suxAt(0).liveIn);
+                        liveOut.setFrom(blockData.get(block.suxAt(0)).liveIn);
                         for (int j = 1; j < n; j++) {
-                            liveOut.setUnion(block.suxAt(j).liveIn);
+                            liveOut.setUnion(blockData.get(block.suxAt(j)).liveIn);
                         }
                     } else {
                         liveOut.clearAll();
                     }
 
-                    if (!block.liveOut.isSame(liveOut)) {
+                    if (!blockData.get(block).liveOut.isSame(liveOut)) {
                         // A change occurred. Swap the old and new live out sets to avoid copying.
-                        BitMap temp = block.liveOut;
-                        block.liveOut = liveOut;
+                        BitMap temp = blockData.get(block).liveOut;
+                        blockData.get(block).liveOut = liveOut;
                         liveOut = temp;
 
                         changeOccurred = true;
@@ -780,10 +815,10 @@
                 if (iterationCount == 0 || changeOccurredInBlock) {
                     // liveIn(block) is the union of liveGen(block) with (liveOut(block) & !liveKill(block))
                     // note: liveIn has to be computed only in first iteration or if liveOut has changed!
-                    BitMap liveIn = block.liveIn;
-                    liveIn.setFrom(block.liveOut);
-                    liveIn.setDifference(block.liveKill);
-                    liveIn.setUnion(block.liveGen);
+                    BitMap liveIn = blockData.get(block).liveIn;
+                    liveIn.setFrom(blockData.get(block).liveOut);
+                    liveIn.setDifference(blockData.get(block).liveKill);
+                    liveIn.setUnion(blockData.get(block).liveGen);
                 }
 
                 if (GraalOptions.TraceLinearScanLevel >= 4) {
@@ -802,15 +837,15 @@
         }
 
         // check that the liveIn set of the first block is empty
-        LIRBlock startBlock = ir.startBlock();
-        BitMap liveInArgs = new BitMap(startBlock.liveIn.size());
-        if (!startBlock.liveIn.isSame(liveInArgs)) {
+        Block startBlock = ir.cfg.getStartBlock();
+        BitMap liveInArgs = new BitMap(blockData.get(startBlock).liveIn.size());
+        if (!blockData.get(startBlock).liveIn.isSame(liveInArgs)) {
             if (GraalOptions.DetailedAsserts) {
                 reportFailure(numBlocks);
             }
 
             TTY.println("preds=" + startBlock.getPredecessors().size() + ", succs=" + startBlock.getSuccessors().size());
-            TTY.println("startBlock-ID: " + startBlock.blockID());
+            TTY.println("startBlock-ID: " + startBlock.getId());
 
             // bailout of if this occurs in product mode.
             throw new CiBailout("liveIn set of first block must be empty");
@@ -821,19 +856,19 @@
         TTY.println(method.toString());
         TTY.println("Error: liveIn set of first block must be empty (when this fails, variables are used before they are defined)");
         TTY.print("affected registers:");
-        TTY.println(ir.startBlock().liveIn.toString());
+        TTY.println(blockData.get(ir.cfg.getStartBlock()).liveIn.toString());
 
         // print some additional information to simplify debugging
-        for (int operandNum = 0; operandNum < ir.startBlock().liveIn.size(); operandNum++) {
-            if (ir.startBlock().liveIn.get(operandNum)) {
+        for (int operandNum = 0; operandNum < blockData.get(ir.cfg.getStartBlock()).liveIn.size(); operandNum++) {
+            if (blockData.get(ir.cfg.getStartBlock()).liveIn.get(operandNum)) {
                 CiValue operand = operandFor(operandNum);
                 TTY.println(" var %d; operand=%s", operandNum, operand.toString());
 
                 for (int j = 0; j < numBlocks; j++) {
-                    LIRBlock block = blockAt(j);
-                    if (block.liveGen.get(operandNum)) {
-                        TTY.println("  used in block B%d", block.blockID());
-                        for (LIRInstruction ins : block.lir()) {
+                    Block block = blockAt(j);
+                    if (blockData.get(block).liveGen.get(operandNum)) {
+                        TTY.println("  used in block B%d", block.getId());
+                        for (LIRInstruction ins : block.lir) {
                             TTY.println(ins.id() + ": " + ins.toString());
                             LIRDebugInfo info = ins.info;
                             if (info != null) {
@@ -847,9 +882,9 @@
                             }
                         }
                     }
-                    if (block.liveKill.get(operandNum)) {
-                        TTY.println("  defined in block B%d", block.blockID());
-                        for (LIRInstruction ins : block.lir()) {
+                    if (blockData.get(block).liveKill.get(operandNum)) {
+                        TTY.println("  defined in block B%d", block.getId());
+                        for (LIRInstruction ins : block.lir) {
                             TTY.println(ins.id() + ": " + ins.toString());
                         }
                     }
@@ -862,21 +897,21 @@
         // check that fixed intervals are not live at block boundaries
         // (live set must be empty at fixed intervals)
         for (int i = 0; i < numBlocks; i++) {
-            LIRBlock block = blockAt(i);
+            Block block = blockAt(i);
             for (int j = 0; j <= maxRegisterNumber(); j++) {
-                assert !block.liveIn.get(j) : "liveIn  set of fixed register must be empty";
-                assert !block.liveOut.get(j) : "liveOut set of fixed register must be empty";
-                assert !block.liveGen.get(j) : "liveGen set of fixed register must be empty";
+                assert !blockData.get(block).liveIn.get(j) : "liveIn  set of fixed register must be empty";
+                assert !blockData.get(block).liveOut.get(j) : "liveOut set of fixed register must be empty";
+                assert !blockData.get(block).liveGen.get(j) : "liveGen set of fixed register must be empty";
             }
         }
     }
 
-    private static void traceLiveness(boolean changeOccurredInBlock, int iterationCount, LIRBlock block) {
+    private void traceLiveness(boolean changeOccurredInBlock, int iterationCount, Block block) {
         char c = iterationCount == 0 || changeOccurredInBlock ? '*' : ' ';
-        TTY.print("(%d) liveIn%c  B%d ", iterationCount, c, block.blockID());
-        TTY.println(block.liveIn.toString());
-        TTY.print("(%d) liveOut%c B%d ", iterationCount, c, block.blockID());
-        TTY.println(block.liveOut.toString());
+        TTY.print("(%d) liveIn%c  B%d ", iterationCount, c, block.getId());
+        TTY.println(blockData.get(block).liveIn.toString());
+        TTY.print("(%d) liveOut%c B%d ", iterationCount, c, block.getId());
+        TTY.println(blockData.get(block).liveOut.toString());
     }
 
     void addUse(CiValue operand, int from, int to, RegisterPriority registerPriority, CiKind kind) {
@@ -1067,16 +1102,16 @@
 
         // iterate all blocks in reverse order
         for (int i = blockCount() - 1; i >= 0; i--) {
-            LIRBlock block = blockAt(i);
-            List<LIRInstruction> instructions = block.lir();
-            final int blockFrom = block.firstLirInstructionId();
-            int blockTo = block.lastLirInstructionId();
+            Block block = blockAt(i);
+            List<LIRInstruction> instructions = block.lir;
+            final int blockFrom = block.getFirstLirInstructionId();
+            int blockTo = block.getLastLirInstructionId();
 
             assert blockFrom == instructions.get(0).id();
             assert blockTo == instructions.get(instructions.size() - 1).id();
 
             // Update intervals for operands live at the end of this block;
-            BitMap live = block.liveOut;
+            BitMap live = blockData.get(block).liveOut;
             for (int operandNum = live.nextSetBit(0); operandNum >= 0; operandNum = live.nextSetBit(operandNum + 1)) {
                 assert live.get(operandNum) : "should not stop here otherwise";
                 CiValue operand = operandFor(operandNum);
@@ -1090,7 +1125,7 @@
                 // interval is used anywhere inside this loop. It's possible
                 // that the block was part of a non-natural loop, so it might
                 // have an invalid loop index.
-                if (block.isLoopEnd() && block.loopIndex() != -1 && isIntervalInLoop(operandNum, block.loopIndex())) {
+                if (block.isLoopEnd() && block.getLoop() != null && isIntervalInLoop(operandNum, block.getLoop().index)) {
                     intervalFor(operand).addUsePos(blockTo + 1, RegisterPriority.LiveAtLoopEnd);
                 }
             }
@@ -1365,18 +1400,18 @@
         throw new CiBailout("LinearScan: interval is null");
     }
 
-    Interval intervalAtBlockBegin(LIRBlock block, CiValue operand) {
+    Interval intervalAtBlockBegin(Block block, CiValue operand) {
         assert isVariable(operand) : "register number out of bounds";
         assert intervalFor(operand) != null : "no interval found";
 
-        return splitChildAtOpId(intervalFor(operand), block.firstLirInstructionId(), LIRInstruction.OperandMode.Output);
+        return splitChildAtOpId(intervalFor(operand), block.getFirstLirInstructionId(), LIRInstruction.OperandMode.Output);
     }
 
-    Interval intervalAtBlockEnd(LIRBlock block, CiValue operand) {
+    Interval intervalAtBlockEnd(Block block, CiValue operand) {
         assert isVariable(operand) : "register number out of bounds";
         assert intervalFor(operand) != null : "no interval found";
 
-        return splitChildAtOpId(intervalFor(operand), block.lastLirInstructionId() + 1, LIRInstruction.OperandMode.Output);
+        return splitChildAtOpId(intervalFor(operand), block.getLastLirInstructionId() + 1, LIRInstruction.OperandMode.Output);
     }
 
     Interval intervalAtOpId(CiValue operand, int opId) {
@@ -1386,16 +1421,16 @@
         return splitChildAtOpId(intervalFor(operand), opId, LIRInstruction.OperandMode.Input);
     }
 
-    void resolveCollectMappings(LIRBlock fromBlock, LIRBlock toBlock, MoveResolver moveResolver) {
+    void resolveCollectMappings(Block fromBlock, Block toBlock, MoveResolver moveResolver) {
         assert moveResolver.checkEmpty();
 
         int numOperands = operandSize();
-        BitMap liveAtEdge = toBlock.liveIn;
+        BitMap liveAtEdge = blockData.get(toBlock).liveIn;
 
         // visit all variables for which the liveAtEdge bit is set
         for (int operandNum = liveAtEdge.nextSetBit(0); operandNum >= 0; operandNum = liveAtEdge.nextSetBit(operandNum + 1)) {
             assert operandNum < numOperands : "live information set for not exisiting interval";
-            assert fromBlock.liveOut.get(operandNum) && toBlock.liveIn.get(operandNum) : "interval not live at this edge";
+            assert blockData.get(fromBlock).liveOut.get(operandNum) && blockData.get(toBlock).liveIn.get(operandNum) : "interval not live at this edge";
 
             CiValue liveOperand = operandFor(operandNum);
             Interval fromInterval = intervalAtBlockEnd(fromBlock, liveOperand);
@@ -1408,28 +1443,28 @@
         }
     }
 
-    static void resolveFindInsertPos(LIRBlock fromBlock, LIRBlock toBlock, MoveResolver moveResolver) {
+    static void resolveFindInsertPos(Block fromBlock, Block toBlock, MoveResolver moveResolver) {
         if (fromBlock.numberOfSux() <= 1) {
             if (GraalOptions.TraceLinearScanLevel >= 4) {
-                TTY.println("inserting moves at end of fromBlock B%d", fromBlock.blockID());
+                TTY.println("inserting moves at end of fromBlock B%d", fromBlock.getId());
             }
 
-            List<LIRInstruction> instructions = fromBlock.lir();
+            List<LIRInstruction> instructions = fromBlock.lir;
             LIRInstruction instr = instructions.get(instructions.size() - 1);
             if (instr instanceof StandardOp.JumpOp) {
                 // insert moves before branch
-                moveResolver.setInsertPosition(fromBlock.lir(), instructions.size() - 1);
+                moveResolver.setInsertPosition(fromBlock.lir, instructions.size() - 1);
             } else {
-                moveResolver.setInsertPosition(fromBlock.lir(), instructions.size());
+                moveResolver.setInsertPosition(fromBlock.lir, instructions.size());
             }
 
         } else {
             if (GraalOptions.TraceLinearScanLevel >= 4) {
-                TTY.println("inserting moves at beginning of toBlock B%d", toBlock.blockID());
+                TTY.println("inserting moves at beginning of toBlock B%d", toBlock.getId());
             }
 
             if (GraalOptions.DetailedAsserts) {
-                assert fromBlock.lir().get(0) instanceof StandardOp.LabelOp : "block does not start with a label";
+                assert fromBlock.lir.get(0) instanceof StandardOp.LabelOp : "block does not start with a label";
 
                 // because the number of predecessor edges matches the number of
                 // successor edges, blocks which are reached by switch statements
@@ -1440,7 +1475,7 @@
                 }
             }
 
-            moveResolver.setInsertPosition(toBlock.lir(), 1);
+            moveResolver.setInsertPosition(toBlock.lir, 1);
         }
     }
 
@@ -1456,30 +1491,30 @@
 
         int i;
         for (i = 0; i < numBlocks; i++) {
-            LIRBlock block = blockAt(i);
+            Block block = blockAt(i);
 
             // check if block has only one predecessor and only one successor
             if (block.numberOfPreds() == 1 && block.numberOfSux() == 1) {
-                List<LIRInstruction> instructions = block.lir();
+                List<LIRInstruction> instructions = block.lir;
                 assert instructions.get(0) instanceof StandardOp.LabelOp : "block must start with label";
                 assert instructions.get(instructions.size() - 1) instanceof StandardOp.JumpOp : "block with successor must end with unconditional jump";
 
                 // check if block is empty (only label and branch)
                 if (instructions.size() == 2) {
-                    LIRBlock pred = block.predAt(0);
-                    LIRBlock sux = block.suxAt(0);
+                    Block pred = block.predAt(0);
+                    Block sux = block.suxAt(0);
 
                     // prevent optimization of two consecutive blocks
-                    if (!blockCompleted.get(pred.linearScanNumber()) && !blockCompleted.get(sux.linearScanNumber())) {
+                    if (!blockCompleted.get(pred.linearScanNumber) && !blockCompleted.get(sux.linearScanNumber)) {
                         if (GraalOptions.TraceLinearScanLevel >= 3) {
-                            TTY.println(" optimizing empty block B%d (pred: B%d, sux: B%d)", block.blockID(), pred.blockID(), sux.blockID());
+                            TTY.println(" optimizing empty block B%d (pred: B%d, sux: B%d)", block.getId(), pred.getId(), sux.getId());
                         }
-                        blockCompleted.set(block.linearScanNumber());
+                        blockCompleted.set(block.linearScanNumber);
 
                         // directly resolve between pred and sux (without looking at the empty block between)
                         resolveCollectMappings(pred, sux, moveResolver);
                         if (moveResolver.hasMappings()) {
-                            moveResolver.setInsertPosition(block.lir(), 1);
+                            moveResolver.setInsertPosition(block.lir, 1);
                             moveResolver.resolveAndAppendMoves();
                         }
                     }
@@ -1489,19 +1524,19 @@
 
         for (i = 0; i < numBlocks; i++) {
             if (!blockCompleted.get(i)) {
-                LIRBlock fromBlock = blockAt(i);
+                Block fromBlock = blockAt(i);
                 alreadyResolved.setFrom(blockCompleted);
 
                 int numSux = fromBlock.numberOfSux();
                 for (int s = 0; s < numSux; s++) {
-                    LIRBlock toBlock = fromBlock.suxAt(s);
+                    Block toBlock = fromBlock.suxAt(s);
 
                     // check for duplicate edges between the same blocks (can happen with switch blocks)
-                    if (!alreadyResolved.get(toBlock.linearScanNumber())) {
+                    if (!alreadyResolved.get(toBlock.linearScanNumber)) {
                         if (GraalOptions.TraceLinearScanLevel >= 3) {
-                            TTY.println(" processing edge between B%d and B%d", fromBlock.blockID(), toBlock.blockID());
+                            TTY.println(" processing edge between B%d and B%d", fromBlock.getId(), toBlock.getId());
                         }
-                        alreadyResolved.set(toBlock.linearScanNumber());
+                        alreadyResolved.set(toBlock.linearScanNumber);
 
                         // collect all intervals that have been split between fromBlock and toBlock
                         resolveCollectMappings(fromBlock, toBlock, moveResolver);
@@ -1580,14 +1615,14 @@
 
         if (opId != -1) {
             if (GraalOptions.DetailedAsserts) {
-                LIRBlock block = blockForId(opId);
-                if (block.numberOfSux() <= 1 && opId == block.lastLirInstructionId()) {
+                Block block = blockForId(opId);
+                if (block.numberOfSux() <= 1 && opId == block.getLastLirInstructionId()) {
                     // check if spill moves could have been appended at the end of this block, but
                     // before the branch instruction. So the split child information for this branch would
                     // be incorrect.
-                    LIRInstruction instr = block.lir().get(block.lir().size() - 1);
+                    LIRInstruction instr = block.lir.get(block.lir.size() - 1);
                     if (instr instanceof StandardOp.JumpOp) {
-                        if (block.liveOut.get(operandNumber(operand))) {
+                        if (blockData.get(block).liveOut.get(operandNumber(operand))) {
                             assert false : "can't get split child for the last branch of a block because the information would be incorrect (moves are inserted before the branch in resolveDataFlow)";
                         }
                     }
@@ -1687,17 +1722,17 @@
             public CiValue doValue(CiValue operand) {
                 int tempOpId = op.id();
                 OperandMode mode = OperandMode.Input;
-                LIRBlock block = blockForId(tempOpId);
-                if (block.numberOfSux() == 1 && tempOpId == block.lastLirInstructionId()) {
+                Block block = blockForId(tempOpId);
+                if (block.numberOfSux() == 1 && tempOpId == block.getLastLirInstructionId()) {
                     // generating debug information for the last instruction of a block.
                     // if this instruction is a branch, spill moves are inserted before this branch
                     // and so the wrong operand would be returned (spill moves at block boundaries are not
                     // considered in the live ranges of intervals)
                     // Solution: use the first opId of the branch target block instead.
-                    final LIRInstruction instr = block.lir().get(block.lir().size() - 1);
+                    final LIRInstruction instr = block.lir.get(block.lir.size() - 1);
                     if (instr instanceof StandardOp.JumpOp) {
-                        if (block.liveOut.get(operandNumber(operand))) {
-                            tempOpId = block.suxAt(0).firstLirInstructionId();
+                        if (blockData.get(block).liveOut.get(operandNumber(operand))) {
+                            tempOpId = block.suxAt(0).getFirstLirInstructionId();
                             mode = OperandMode.Output;
                         }
                     }
@@ -1774,8 +1809,8 @@
 
     private void assignLocations() {
         IntervalWalker iw = initComputeOopMaps();
-        for (LIRBlock block : sortedBlocks) {
-            assignLocations(block.lir(), iw);
+        for (Block block : sortedBlocks) {
+            assignLocations(block.lir, iw);
         }
     }
 
@@ -1856,8 +1891,8 @@
             TTY.println();
             TTY.println("--- Basic Blocks ---");
             for (i = 0; i < blockCount(); i++) {
-                LIRBlock block = blockAt(i);
-                TTY.print("B%d [%d, %d, %d, %d] ", block.blockID(), block.firstLirInstructionId(), block.lastLirInstructionId(), block.loopIndex(), block.loopDepth());
+                Block block = blockAt(i);
+                TTY.print("B%d [%d, %d, %s] ", block.getId(), block.getFirstLirInstructionId(), block.getLastLirInstructionId(), block.getLoop());
             }
             TTY.println();
             TTY.println();
@@ -2017,9 +2052,9 @@
         IntervalWalker iw = new IntervalWalker(this, fixedIntervals, otherIntervals);
 
         for (int i = 0; i < blockCount(); i++) {
-            LIRBlock block = blockAt(i);
+            Block block = blockAt(i);
 
-            List<LIRInstruction> instructions = block.lir();
+            List<LIRInstruction> instructions = block.lir;
 
             for (int j = 0; j < instructions.size(); j++) {
                 LIRInstruction op = instructions.get(j);
@@ -2057,13 +2092,13 @@
         int numBlocks = blockCount();
 
         for (int i = 0; i < numBlocks; i++) {
-            LIRBlock block = blockAt(i);
-            BitMap liveAtEdge = block.liveIn;
+            Block block = blockAt(i);
+            BitMap liveAtEdge = blockData.get(block).liveIn;
 
             // visit all operands where the liveAtEdge bit is set
             for (int operandNum = liveAtEdge.nextSetBit(0); operandNum >= 0; operandNum = liveAtEdge.nextSetBit(operandNum + 1)) {
                 if (GraalOptions.TraceLinearScanLevel >= 4) {
-                    TTY.println("checking interval %d of block B%d", operandNum, block.blockID());
+                    TTY.println("checking interval %d of block B%d", operandNum, block.getId());
                 }
                 CiValue operand = operandFor(operandNum);
                 assert isVariable(operand) : "value must have variable operand";
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScanWalker.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScanWalker.java	Sun Feb 05 05:40:36 2012 +0100
@@ -35,6 +35,7 @@
 import com.oracle.max.graal.compiler.alloc.Interval.RegisterPriority;
 import com.oracle.max.graal.compiler.alloc.Interval.SpillState;
 import com.oracle.max.graal.compiler.alloc.Interval.State;
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.compiler.lir.StandardOp.*;
@@ -60,11 +61,11 @@
         return allocator.blockCount();
     }
 
-    LIRBlock blockAt(int idx) {
+    Block blockAt(int idx) {
         return allocator.blockAt(idx);
     }
 
-    LIRBlock blockOfOpWithId(int opId) {
+    Block blockOfOpWithId(int opId) {
         return allocator.blockForId(opId);
     }
 
@@ -231,7 +232,7 @@
         // optimized away later in assignRegNums
 
         int opId = (operandId + 1) & ~1;
-        LIRBlock opBlock = allocator.blockForId(opId);
+        Block opBlock = allocator.blockForId(opId);
         assert opId > 0 && allocator.blockForId(opId - 2) == opBlock : "cannot insert move at block boundary";
 
         // calculate index of instruction inside instruction list of current block
@@ -239,7 +240,7 @@
         // numbering of instructions is known.
         // When the block already contains spill moves, the index must be increased until the
         // correct index is reached.
-        List<LIRInstruction> list = opBlock.lir();
+        List<LIRInstruction> list = opBlock.lir;
         int index = (opId - list.get(0).id()) >> 1;
         assert list.get(index).id() <= opId : "error in calculation";
 
@@ -251,13 +252,13 @@
         assert list.get(index).id() == opId : "error in calculation";
 
         // insert new instruction before instruction at position index
-        moveResolver.moveInsertPosition(opBlock.lir(), index);
+        moveResolver.moveInsertPosition(opBlock.lir, index);
         moveResolver.addMapping(srcIt, dstIt);
     }
 
-    int findOptimalSplitPos(LIRBlock minBlock, LIRBlock maxBlock, int maxSplitPos) {
-        int fromBlockNr = minBlock.linearScanNumber();
-        int toBlockNr = maxBlock.linearScanNumber();
+    int findOptimalSplitPos(Block minBlock, Block maxBlock, int maxSplitPos) {
+        int fromBlockNr = minBlock.linearScanNumber;
+        int toBlockNr = maxBlock.linearScanNumber;
 
         assert 0 <= fromBlockNr && fromBlockNr < blockCount() : "out of range";
         assert 0 <= toBlockNr && toBlockNr < blockCount() : "out of range";
@@ -265,19 +266,19 @@
 
         // Try to split at end of maxBlock. If this would be after
         // maxSplitPos, then use the begin of maxBlock
-        int optimalSplitPos = maxBlock.lastLirInstructionId() + 2;
+        int optimalSplitPos = maxBlock.getLastLirInstructionId() + 2;
         if (optimalSplitPos > maxSplitPos) {
-            optimalSplitPos = maxBlock.firstLirInstructionId();
+            optimalSplitPos = maxBlock.getFirstLirInstructionId();
         }
 
-        int minLoopDepth = maxBlock.loopDepth();
+        int minLoopDepth = maxBlock.getLoopDepth();
         for (int i = toBlockNr - 1; i >= fromBlockNr; i--) {
-            LIRBlock cur = blockAt(i);
+            Block cur = blockAt(i);
 
-            if (cur.loopDepth() < minLoopDepth) {
+            if (cur.getLoopDepth() < minLoopDepth) {
                 // block with lower loop-depth found . split at the end of this block
-                minLoopDepth = cur.loopDepth();
-                optimalSplitPos = cur.lastLirInstructionId() + 2;
+                minLoopDepth = cur.getLoopDepth();
+                optimalSplitPos = cur.getLastLirInstructionId() + 2;
             }
         }
         assert optimalSplitPos > allocator.maxOpId() || allocator.isBlockBegin(optimalSplitPos) : "algorithm must move split pos to block boundary";
@@ -301,15 +302,15 @@
             // reason for using minSplitPos - 1: when the minimal split pos is exactly at the
             // beginning of a block, then minSplitPos is also a possible split position.
             // Use the block before as minBlock, because then minBlock.lastLirInstructionId() + 2 == minSplitPos
-            LIRBlock minBlock = allocator.blockForId(minSplitPos - 1);
+            Block minBlock = allocator.blockForId(minSplitPos - 1);
 
             // reason for using maxSplitPos - 1: otherwise there would be an assert on failure
             // when an interval ends at the end of the last block of the method
             // (in this case, maxSplitPos == allocator().maxLirOpId() + 2, and there is no
             // block at this opId)
-            LIRBlock maxBlock = allocator.blockForId(maxSplitPos - 1);
+            Block maxBlock = allocator.blockForId(maxSplitPos - 1);
 
-            assert minBlock.linearScanNumber() <= maxBlock.linearScanNumber() : "invalid order";
+            assert minBlock.linearScanNumber <= maxBlock.linearScanNumber : "invalid order";
             if (minBlock == maxBlock) {
                 // split position cannot be moved to block boundary : so split as late as possible
                 if (GraalOptions.TraceLinearScanLevel >= 4) {
@@ -331,13 +332,13 @@
                 } else {
                     // seach optimal block boundary between minSplitPos and maxSplitPos
                     if (GraalOptions.TraceLinearScanLevel >= 4) {
-                        TTY.println("      moving split pos to optimal block boundary between block B%d and B%d", minBlock.blockID(), maxBlock.blockID());
+                        TTY.println("      moving split pos to optimal block boundary between block B%d and B%d", minBlock.getId(), maxBlock.getId());
                     }
 
                     if (doLoopOptimization) {
                         // Loop optimization: if a loop-end marker is found between min- and max-position :
                         // then split before this loop
-                        int loopEndPos = interval.nextUsageExact(RegisterPriority.LiveAtLoopEnd, minBlock.lastLirInstructionId() + 2);
+                        int loopEndPos = interval.nextUsageExact(RegisterPriority.LiveAtLoopEnd, minBlock.getLastLirInstructionId() + 2);
                         if (GraalOptions.TraceLinearScanLevel >= 4) {
                             TTY.println("      loop optimization: loop end found at pos %d", loopEndPos);
                         }
@@ -349,15 +350,15 @@
                             // the max-position to this loop block.
                             // Desired result: uses tagged as shouldHaveRegister inside a loop cause a reloading
                             // of the interval (normally, only mustHaveRegister causes a reloading)
-                            LIRBlock loopBlock = allocator.blockForId(loopEndPos);
+                            Block loopBlock = allocator.blockForId(loopEndPos);
 
                             if (GraalOptions.TraceLinearScanLevel >= 4) {
-                                TTY.println("      interval is used in loop that ends in block B%d, so trying to move maxBlock back from B%d to B%d", loopBlock.blockID(), maxBlock.blockID(), loopBlock.blockID());
+                                TTY.println("      interval is used in loop that ends in block B%d, so trying to move maxBlock back from B%d to B%d", loopBlock.getId(), maxBlock.getId(), loopBlock.getId());
                             }
                             assert loopBlock != minBlock : "loopBlock and minBlock must be different because block boundary is needed between";
 
-                            optimalSplitPos = findOptimalSplitPos(minBlock, loopBlock, loopBlock.lastLirInstructionId() + 2);
-                            if (optimalSplitPos == loopBlock.lastLirInstructionId() + 2) {
+                            optimalSplitPos = findOptimalSplitPos(minBlock, loopBlock, loopBlock.getLastLirInstructionId() + 2);
+                            if (optimalSplitPos == loopBlock.getLastLirInstructionId() + 2) {
                                 optimalSplitPos = -1;
                                 if (GraalOptions.TraceLinearScanLevel >= 4) {
                                     TTY.println("      loop optimization not necessary");
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/RegisterVerifier.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/RegisterVerifier.java	Sun Feb 05 05:40:36 2012 +0100
@@ -29,6 +29,7 @@
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.criutils.*;
 import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.*;
 import com.oracle.max.graal.compiler.util.*;
@@ -38,7 +39,7 @@
 final class RegisterVerifier {
 
     LinearScan allocator;
-    List<LIRBlock> workList; // all blocks that must be processed
+    List<Block> workList; // all blocks that must be processed
     ArrayMap<Interval[]> savedStates; // saved information of previous check
 
     // simplified access to methods of LinearScan
@@ -52,15 +53,15 @@
     }
 
     // accessors
-    Interval[] stateForBlock(LIRBlock block) {
-        return savedStates.get(block.blockID());
+    Interval[] stateForBlock(Block block) {
+        return savedStates.get(block.getId());
     }
 
-    void setStateForBlock(LIRBlock block, Interval[] savedState) {
-        savedStates.put(block.blockID(), savedState);
+    void setStateForBlock(Block block, Interval[] savedState) {
+        savedStates.put(block.getId(), savedState);
     }
 
-    void addToWorkList(LIRBlock block) {
+    void addToWorkList(Block block) {
         if (!workList.contains(block)) {
             workList.add(block);
         }
@@ -73,7 +74,7 @@
 
     }
 
-    void verify(LIRBlock start) {
+    void verify(Block start) {
         // setup input registers (method arguments) for first block
         Interval[] inputState = new Interval[stateSize()];
         setStateForBlock(start, inputState);
@@ -81,17 +82,17 @@
 
         // main loop for verification
         do {
-            LIRBlock block = workList.get(0);
+            Block block = workList.get(0);
             workList.remove(0);
 
             processBlock(block);
         } while (!workList.isEmpty());
     }
 
-    private void processBlock(LIRBlock block) {
+    private void processBlock(Block block) {
         if (GraalOptions.TraceLinearScanLevel >= 2) {
             TTY.println();
-            TTY.println("processBlock B%d", block.blockID());
+            TTY.println("processBlock B%d", block.getId());
         }
 
         // must copy state because it is modified
@@ -112,16 +113,16 @@
         }
 
         // process all operations of the block
-        processOperations(block.lir(), inputState);
+        processOperations(block.lir, inputState);
 
         // iterate all successors
         for (int i = 0; i < block.numberOfSux(); i++) {
-            LIRBlock succ = block.suxAt(i);
+            Block succ = block.suxAt(i);
             processSuccessor(succ, inputState);
         }
     }
 
-    private void processSuccessor(LIRBlock block, Interval[] inputState) {
+    private void processSuccessor(Block block, Interval[] inputState) {
         Interval[] savedState = stateForBlock(block);
 
         if (savedState != null) {
@@ -141,7 +142,7 @@
                         savedState[i] = null;
 
                         if (GraalOptions.TraceLinearScanLevel >= 4) {
-                            TTY.println("processSuccessor B%d: invalidating slot %d", block.blockID(), i);
+                            TTY.println("processSuccessor B%d: invalidating slot %d", block.getId(), i);
                         }
                     }
                 }
@@ -150,12 +151,12 @@
             if (savedStateCorrect) {
                 // already processed block with correct inputState
                 if (GraalOptions.TraceLinearScanLevel >= 2) {
-                    TTY.println("processSuccessor B%d: previous visit already correct", block.blockID());
+                    TTY.println("processSuccessor B%d: previous visit already correct", block.getId());
                 }
             } else {
                 // must re-visit this block
                 if (GraalOptions.TraceLinearScanLevel >= 2) {
-                    TTY.println("processSuccessor B%d: must re-visit because input state changed", block.blockID());
+                    TTY.println("processSuccessor B%d: must re-visit because input state changed", block.getId());
                 }
                 addToWorkList(block);
             }
@@ -163,7 +164,7 @@
         } else {
             // block was not processed before, so set initial inputState
             if (GraalOptions.TraceLinearScanLevel >= 2) {
-                TTY.println("processSuccessor B%d: initial visit", block.blockID());
+                TTY.println("processSuccessor B%d: initial visit", block.getId());
             }
 
             setStateForBlock(block, copy(inputState));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/Block.java	Sun Feb 05 05:40:36 2012 +0100
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.cfg;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.nodes.*;
+import com.oracle.max.graal.nodes.java.*;
+
+public class Block {
+    protected int id;
+
+    protected BeginNode beginNode;
+    protected Node endNode;
+    protected Loop loop;
+    protected double probability;
+
+    protected List<Block> predecessors;
+    protected List<Block> successors;
+
+    protected Block dominator;
+    protected List<Block> dominated;
+    protected Block postdominator;
+
+    // Fields that still need to be worked on, try to remove them later.
+    public FrameState lastState;
+    public List<LIRInstruction> lir;
+    public boolean align;
+    public int linearScanNumber;
+    public LIRPhiMapping phis;
+
+    public Block() {
+        id = -1;
+    }
+
+    public int getId() {
+        assert id >= 0;
+        return id;
+    }
+
+    public BeginNode getBeginNode() {
+        return beginNode;
+    }
+
+    public Node getEndNode() {
+        return endNode;
+    }
+
+    public Loop getLoop() {
+        return loop;
+    }
+
+    public int getLoopDepth() {
+        return loop == null ? 0 : loop.depth;
+    }
+
+    public boolean isLoopHeader() {
+        return getBeginNode() instanceof LoopBeginNode;
+    }
+
+    public boolean isLoopEnd() {
+        return getEndNode() instanceof LoopEndNode;
+    }
+
+    public boolean isExceptionEntry() {
+        return getBeginNode().next() instanceof ExceptionObjectNode;
+    }
+
+    public List<Block> getPredecessors() {
+        return predecessors;
+    }
+
+    public List<Block> getSuccessors() {
+        return successors;
+    }
+
+    public Block getDominator() {
+        return dominator;
+    }
+
+    public List<Block> getDominated() {
+        if (dominated == null) {
+            return Collections.emptyList();
+        }
+        return dominated;
+    }
+
+    public Block getPostdominator() {
+        return postdominator;
+    }
+
+    private class NodeIterator implements Iterator<Node> {
+        private Node cur;
+
+        public NodeIterator() {
+            cur = getBeginNode();
+        }
+
+        @Override
+        public boolean hasNext() {
+            return cur != null;
+        }
+
+        @Override
+        public Node next() {
+            Node result = cur;
+            if (cur == getEndNode()) {
+                cur = null;
+            } else {
+                cur = ((FixedWithNextNode) cur).next();
+            }
+            assert !(cur instanceof BeginNode);
+            return result;
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    public Iterable<Node> getNodes() {
+        return new Iterable<Node>() {
+            @Override
+            public Iterator<Node> iterator() {
+                return new NodeIterator();
+            }
+        };
+    }
+
+    public int getFirstLirInstructionId() {
+        int result = lir.get(0).id();
+        assert result >= 0;
+        return result;
+    }
+
+    public int getLastLirInstructionId() {
+        int result = lir.get(lir.size() - 1).id();
+        assert result >= 0;
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "B" + id;
+    }
+
+
+// to be inlined later on
+    public int numberOfPreds() {
+        return getPredecessors().size();
+    }
+
+    public int numberOfSux() {
+        return getSuccessors().size();
+    }
+
+    public Block predAt(int i) {
+        return getPredecessors().get(i);
+    }
+
+    public Block suxAt(int i) {
+        return getSuccessors().get(i);
+    }
+// end to be inlined later on
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/BlockMap.java	Sun Feb 05 05:40:36 2012 +0100
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.cfg;
+
+public class BlockMap<T> {
+    private final T[] data;
+
+    @SuppressWarnings("unchecked")
+    public BlockMap(ControlFlowGraph cfg) {
+        data = (T[]) new Object[cfg.getBlocks().length];
+    }
+
+    public T get(Block block) {
+        return data[block.getId()];
+    }
+
+    public void put(Block block, T value) {
+        data[block.getId()] = value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/CFGVerifier.java	Sun Feb 05 05:40:36 2012 +0100
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.cfg;
+
+public class CFGVerifier {
+    public static boolean verify(ControlFlowGraph cfg) {
+        for (Block block : cfg.getBlocks()) {
+            assert cfg.getBlocks()[block.getId()] == block;
+
+            for (Block pred : block.getPredecessors()) {
+                assert pred.getSuccessors().contains(block);
+                assert pred.getId() < block.getId() || pred.isLoopEnd();
+            }
+
+            for (Block sux : block.getSuccessors()) {
+                assert sux.getPredecessors().contains(block);
+                assert sux.getId() > block.getId() || sux.isLoopHeader();
+            }
+
+            if (block.getDominator() != null) {
+                assert block.getDominator().getId() < block.getId();
+                assert block.getDominator().getDominated().contains(block);
+            }
+            for (Block dominated : block.getDominated()) {
+                assert dominated.getId() > block.getId();
+                assert dominated.getDominator() == block;
+            }
+
+            assert cfg.getLoops() == null || !block.isLoopHeader() || block.getLoop().header == block;
+        }
+
+        if (cfg.getLoops() != null) {
+            for (Loop loop : cfg.getLoops()) {
+                assert loop.header.isLoopHeader();
+
+                for (Block block : loop.blocks) {
+                    assert block.getId() >= loop.header.getId();
+
+                    Loop blockLoop = block.getLoop();
+                    while (blockLoop != loop) {
+                        blockLoop = blockLoop.parent;
+                        assert blockLoop != null;
+                    }
+                }
+
+                for (Block block : loop.exits) {
+                    assert block.getId() >= loop.header.getId();
+
+                    Loop blockLoop = block.getLoop();
+                    while (blockLoop != null) {
+                        blockLoop = blockLoop.parent;
+                        assert blockLoop != loop;
+                    }
+                }
+            }
+        }
+
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/ControlFlowGraph.java	Sun Feb 05 05:40:36 2012 +0100
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.cfg;
+
+import java.util.*;
+
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.nodes.*;
+
+public class ControlFlowGraph {
+
+    public final StructuredGraph graph;
+
+    private final NodeMap<Block> nodeToBlock;
+    private Block[] reversePostOrder;
+    private Loop[] loops;
+
+    public static ControlFlowGraph compute(StructuredGraph graph, boolean connectBlocks, boolean computeLoops, boolean computeDominators, boolean computePostdominators) {
+        ControlFlowGraph cfg = new ControlFlowGraph(graph);
+        cfg.identifyBlocks();
+        if (connectBlocks || computeLoops || computeDominators || computePostdominators) {
+            cfg.connectBlocks();
+        }
+        if (computeLoops) {
+            cfg.computeLoopInformation();
+        }
+        if (computeDominators) {
+            cfg.computeDominators();
+        }
+        if (computePostdominators) {
+            cfg.computePostdominators();
+        }
+        assert CFGVerifier.verify(cfg);
+        return cfg;
+    }
+
+    protected ControlFlowGraph(StructuredGraph graph) {
+        this.graph = graph;
+        this.nodeToBlock = graph.createNodeMap();
+    }
+
+    public Block[] getBlocks() {
+        return reversePostOrder;
+    }
+
+    public Block getStartBlock() {
+        return reversePostOrder[0];
+    }
+
+    public NodeMap<Block> getNodeToBlock() {
+        return nodeToBlock;
+    }
+
+    public Block blockFor(Node node) {
+        return nodeToBlock.get(node);
+    }
+
+    public Loop[] getLoops() {
+        return loops;
+    }
+
+    private void identifyBlocks() {
+        // Find all block headers
+        int numBlocks = 0;
+        for (Node node : graph.getNodes()) {
+            if (node instanceof BeginNode) {
+                Block block = new Block();
+                numBlocks++;
+
+                block.beginNode = (BeginNode) node;
+                Node cur = node;
+                do {
+                    assert !cur.isDeleted();
+                    block.endNode = cur;
+
+                    assert nodeToBlock.get(cur) == null;
+                    nodeToBlock.set(cur, block);
+                    if (cur instanceof MergeNode) {
+                        for (PhiNode phi : ((MergeNode) cur).phis()) {
+                            nodeToBlock.set(phi, block);
+                        }
+                    }
+
+                    if (cur instanceof FixedNode) {
+                        double probability = ((FixedNode) cur).probability();
+                        if (probability > block.probability) {
+                            block.probability = probability;
+                        }
+                    }
+
+                    Node next = null;
+                    for (Node sux : cur.successors()) {
+                        if (sux != null && !(sux instanceof BeginNode)) {
+                            assert next == null;
+                            next = sux;
+                        }
+                    }
+                    cur = next;
+                } while (cur != null);
+            }
+        }
+
+        // Compute reverse postorder.
+        reversePostOrder = new Block[numBlocks];
+        int reversePostOrderId = numBlocks - 1;
+
+        ArrayList<Block> stack = new ArrayList<>();
+        stack.add(blockFor(graph.start()));
+
+        do {
+            Block block = stack.get(stack.size() - 1);
+            if (block.id == -1) {
+                // First time we see this block: push all successors.
+                for (Node suxNode : block.getEndNode().cfgSuccessors()) {
+                    Block suxBlock = blockFor(suxNode);
+                    if (suxBlock.id < 0) {
+                        stack.add(suxBlock);
+                    }
+                }
+                block.id = -2;
+            } else {
+                // Second time we see this block: All successors haved been processed, so insert block into reverse postorder list.
+                assert block.id == -2;
+                stack.remove(stack.size() - 1);
+                block.id = reversePostOrderId;
+                reversePostOrder[reversePostOrderId] = block;
+                reversePostOrderId--;
+            }
+        } while (!stack.isEmpty());
+        assert reversePostOrderId == -1;
+    }
+
+    // Connect blocks (including loop backward edges).
+    private void connectBlocks() {
+        for (Block block : reversePostOrder) {
+            List<Block> predecessors = new ArrayList<>();
+            for (Node predNode : block.getBeginNode().cfgPredecessors()) {
+                predecessors.add(nodeToBlock.get(predNode));
+            }
+            if (block.getBeginNode() instanceof LoopBeginNode) {
+                predecessors.add(nodeToBlock.get(((LoopBeginNode) block.getBeginNode()).loopEnd()));
+            }
+            block.predecessors = predecessors;
+
+            List<Block> successors = new ArrayList<>();
+            for (Node suxNode : block.getEndNode().cfgSuccessors()) {
+                successors.add(nodeToBlock.get(suxNode));
+            }
+            if (block.getEndNode() instanceof LoopEndNode) {
+                successors.add(nodeToBlock.get(((LoopEndNode) block.getEndNode()).loopBegin()));
+            }
+            block.successors = successors;
+        }
+    }
+
+    private void computeLoopInformation() {
+        List<Loop> loopsList = new ArrayList<>();
+        for (Block block : reversePostOrder) {
+            Node beginNode = block.getBeginNode();
+            if (beginNode instanceof LoopBeginNode) {
+                Loop loop = new Loop(block.getLoop(), loopsList.size(), block);
+                loopsList.add(loop);
+
+                LoopEndNode end = ((LoopBeginNode) beginNode).loopEnd();
+                Block endBlock = nodeToBlock.get(end);
+                computeLoopBlocks(endBlock, loop);
+            }
+        }
+        loops = loopsList.toArray(new Loop[loopsList.size()]);
+
+        for (Loop loop : loops) {
+            for (Block block : loop.blocks) {
+                for (Block sux : block.getSuccessors()) {
+                    if (sux.getLoopDepth() < loop.depth) {
+                        loop.exits.add(sux);
+                    }
+                }
+            }
+        }
+    }
+
+    private void computeLoopBlocks(Block block, Loop loop) {
+        if (block.getLoop() == loop) {
+            return;
+        }
+        assert block.loop == loop.parent;
+        block.loop = loop;
+
+        assert !loop.blocks.contains(block);
+        loop.blocks.add(block);
+
+        if (block != loop.header) {
+            for (Block pred : block.getPredecessors()) {
+                computeLoopBlocks(pred, loop);
+            }
+        }
+    }
+
+    private void computeDominators() {
+        assert reversePostOrder[0].getPredecessors().size() == 0 : "start block has no predecessor and therefore no dominator";
+        for (int i = 1; i < reversePostOrder.length; i++) {
+            Block block = reversePostOrder[i];
+            List<Block> predecessors = block.getPredecessors();
+            assert predecessors.size() > 0;
+
+            if (block.isLoopHeader()) {
+                // Loop headers have exactly one non-loop predecessor, and that is the dominator.
+                setDominator(block, predecessors.get(0));
+                continue;
+            }
+
+            Block dominator = predecessors.get(0);
+            for (int j = 1; j < predecessors.size(); j++) {
+                Block pred = predecessors.get(j);
+                dominator = commonDominator(dominator, pred);
+            }
+            setDominator(block, dominator);
+        }
+    }
+
+    private static void setDominator(Block block, Block dominator) {
+        block.dominator = dominator;
+        if (dominator.dominated == null) {
+            dominator.dominated = new ArrayList<>();
+        }
+        dominator.dominated.add(block);
+    }
+
+    public static Block commonDominator(Block a, Block b) {
+        Block iterA = a;
+        Block iterB = b;
+        while (iterA != iterB) {
+            if (iterA.getId() > iterB.getId()) {
+                iterA = iterA.getDominator();
+            } else {
+                assert iterB.getId() > iterA.getId();
+                iterB = iterB.getDominator();
+            }
+        }
+        return iterA;
+    }
+
+    private void computePostdominators() {
+        for (Block block : reversePostOrder) {
+            if (block.isLoopEnd()) {
+                // We do not want the loop header registered as the postdominator of the loop end.
+                continue;
+            }
+            Block postdominator = null;
+            for (Block sux : block.getSuccessors()) {
+                if (sux.isExceptionEntry()) {
+                    // We ignore exception handlers.
+                } else if (postdominator == null) {
+                    postdominator = sux;
+                } else {
+                    postdominator = commonPostdominator(postdominator, sux);
+                }
+            }
+            block.postdominator = postdominator;
+        }
+    }
+
+    private static Block commonPostdominator(Block a, Block b) {
+        Block iterA = a;
+        Block iterB = b;
+        while (iterA != iterB) {
+            if (iterA.getId() < iterB.getId()) {
+                iterA = iterA.getPostdominator();
+                if (iterA == null) {
+                    return null;
+                }
+            } else {
+                assert iterB.getId() < iterA.getId();
+                iterB = iterB.getPostdominator();
+                if (iterB == null) {
+                    return null;
+                }
+            }
+        }
+        return iterA;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/Loop.java	Sun Feb 05 05:40:36 2012 +0100
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.cfg;
+
+import java.util.*;
+
+public class Loop {
+    public final Loop parent;
+    public final List<Loop> children;
+
+    public final int depth;
+    public final int index;
+    public final Block header;
+    public final List<Block> blocks;
+    public final List<Block> exits;
+
+    protected Loop(Loop parent, int index, Block header) {
+        this.parent = parent;
+        if (parent != null) {
+            this.depth = parent.depth + 1;
+            parent.children.add(this);
+        } else {
+            this.depth = 1;
+        }
+        this.index = index;
+        this.header = header;
+        this.blocks = new ArrayList<>();
+        this.children = new ArrayList<>();
+        this.exits = new ArrayList<>();
+    }
+
+    @Override
+    public String toString() {
+        return "loop " + index + " depth " + depth + (parent != null ? " outer " + parent.index : "");
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Sun Feb 05 05:40:36 2012 +0100
@@ -46,9 +46,9 @@
 import com.oracle.max.cri.xir.*;
 import com.oracle.max.criutils.*;
 import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.lir.StandardOp.ParametersOp;
-import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.debug.*;
 import com.oracle.max.graal.graph.*;
@@ -77,7 +77,7 @@
     protected final RiXirGenerator xir;
     private final DebugInfoBuilder debugInfoBuilder;
 
-    private LIRBlock currentBlock;
+    private Block currentBlock;
     private ValueNode currentInstruction;
     private ValueNode lastInstructionPrinted; // Debugging only
     private FrameState lastState;
@@ -157,12 +157,12 @@
         return target;
     }
 
-    private LockScope locksFor(LIRBlock block) {
-        return blockLocks[block.blockID()];
+    private LockScope locksFor(Block block) {
+        return blockLocks[block.getId()];
     }
 
-    private void setLocksFor(LIRBlock block, LockScope locks) {
-        blockLocks[block.blockID()] = locks;
+    private void setLocksFor(Block block, LockScope locks) {
+        blockLocks[block.getId()] = locks;
     }
 
     /**
@@ -242,7 +242,7 @@
     }
 
     protected LabelRef getLIRBlock(FixedNode b) {
-        LIRBlock result = lir.valueToBlock().get(b);
+        Block result = lir.cfg.blockFor(b);
         int suxIndex = currentBlock.getSuccessors().indexOf(result);
         assert suxIndex != -1 : "Block not in successor list of current block";
 
@@ -287,46 +287,50 @@
             TTY.println(op.toStringWithIdPrefix());
             TTY.println();
         }
-        currentBlock.lir().add(op);
+        currentBlock.lir.add(op);
     }
 
-    public void doBlock(LIRBlock block) {
+    public void doBlock(Block block) {
         if (GraalOptions.PrintIRWithLIR) {
             TTY.print(block.toString());
         }
 
         currentBlock = block;
         // set up the list of LIR instructions
-        assert block.lir() == null : "LIR list already computed for this block";
-        block.setLir(new ArrayList<LIRInstruction>());
+        assert block.lir == null : "LIR list already computed for this block";
+        block.lir = new ArrayList<>();
 
-        emitLabel(block.label(), block.align());
+        emitLabel(new Label(), block.align);
 
         if (GraalOptions.TraceLIRGeneratorLevel >= 1) {
-            TTY.println("BEGIN Generating LIR for block B" + block.blockID());
+            TTY.println("BEGIN Generating LIR for block B" + block.getId());
         }
 
-        if (block == lir.startBlock()) {
+        curLocks = null;
+        for (Block pred : block.getPredecessors()) {
+            LockScope predLocks = locksFor(pred);
+            if (curLocks == null) {
+                curLocks = predLocks;
+            } else if (curLocks != predLocks && (!pred.isLoopEnd() || predLocks != null)) {
+                throw new CiBailout("unbalanced monitors: predecessor blocks have different monitor states");
+            }
+        }
+
+        if (block == lir.cfg.getStartBlock()) {
             assert block.getPredecessors().size() == 0;
             emitPrologue();
-            curLocks = null;
 
         } else {
             assert block.getPredecessors().size() > 0;
             FrameState fs = null;
-            curLocks = locksFor(block.predAt(0));
 
-            for (Block p : block.getPredecessors()) {
-                LIRBlock pred = (LIRBlock) p;
+            for (Block pred : block.getPredecessors()) {
                 if (fs == null) {
-                    fs = pred.lastState();
-                } else if (fs != pred.lastState()) {
+                    fs = pred.lastState;
+                } else if (fs != pred.lastState) {
                     fs = null;
                     break;
                 }
-                if (curLocks != locksFor(pred)) {
-                    throw new CiBailout("unbalanced monitors: predecessor blocks have different monitor states");
-                }
             }
             if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
                 if (fs == null) {
@@ -341,17 +345,18 @@
             lastState = fs;
         }
 
-        if (GraalOptions.AllocSSA && block.firstNode() instanceof MergeNode) {
+        if (GraalOptions.AllocSSA && block.getBeginNode() instanceof MergeNode) {
             block.phis = new LIRPhiMapping(block, this);
         }
 
-        for (int i = 0; i < block.getInstructions().size(); ++i) {
-            Node instr = block.getInstructions().get(i);
+        List<Node> nodes = lir.nodesFor(block);
+        for (int i = 0; i < nodes.size(); i++) {
+            Node instr = nodes.get(i);
 
             if (GraalOptions.OptImplicitNullChecks) {
                 Node nextInstr = null;
-                if (i < block.getInstructions().size() - 1) {
-                    nextInstr = block.getInstructions().get(i + 1);
+                if (i < nodes.size() - 1) {
+                    nextInstr = nodes.get(i + 1);
                 }
 
                 if (instr instanceof GuardNode) {
@@ -390,19 +395,19 @@
                 }
             }
         }
-        if (block.numberOfSux() >= 1 && !block.endsWithJump()) {
-            NodeSuccessorsIterable successors = block.lastNode().successors();
-            assert successors.explicitCount() >= 1 : "should have at least one successor : " + block.lastNode();
+        if (block.numberOfSux() >= 1 && !endsWithJump(block)) {
+            NodeSuccessorsIterable successors = block.getEndNode().successors();
+            assert successors.count() >= 1 : "should have at least one successor : " + block.getEndNode();
 
             emitJump(getLIRBlock((FixedNode) successors.first()), null);
         }
 
         if (GraalOptions.TraceLIRGeneratorLevel >= 1) {
-            TTY.println("END Generating LIR for block B" + block.blockID());
+            TTY.println("END Generating LIR for block B" + block.getId());
         }
 
         setLocksFor(currentBlock, curLocks);
-        block.setLastState(lastState);
+        block.lastState = lastState;
         currentBlock = null;
 
         if (GraalOptions.PrintIRWithLIR) {
@@ -410,6 +415,18 @@
         }
     }
 
+    private static boolean endsWithJump(Block block) {
+        if (block.lir.size() == 0) {
+            return false;
+        }
+        LIRInstruction lirInstruction = block.lir.get(block.lir.size() - 1);
+        if (lirInstruction instanceof LIRXirInstruction) {
+            LIRXirInstruction lirXirInstruction = (LIRXirInstruction) lirInstruction;
+            return (lirXirInstruction.falseSuccessor != null) && (lirXirInstruction.trueSuccessor != null);
+        }
+        return lirInstruction instanceof StandardOp.JumpOp;
+    }
+
     private void doRoot(ValueNode instr) {
         if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
             TTY.println("Emitting LIR for instruction " + instr);
@@ -480,7 +497,7 @@
 
     @Override
     public void visitCheckCast(CheckCastNode x) {
-        XirSnippet snippet = xir.genCheckCast(site(x), toXirArgument(x.object()), toXirArgument(x.targetClassInstruction()), x.targetClass());
+        XirSnippet snippet = xir.genCheckCast(site(x), toXirArgument(x.object()), toXirArgument(x.targetClassInstruction()), x.targetClass(), x.hints(), x.hintsExact());
         emitXir(snippet, x, state(), true);
         // The result of a checkcast is the unmodified object, so no need to allocate a new variable for it.
         setResult(x, operand(x.object()));
@@ -740,7 +757,7 @@
 
     private void emitInstanceOfBranch(InstanceOfNode x, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRDebugInfo info) {
         XirArgument obj = toXirArgument(x.object());
-        XirSnippet snippet = xir.genInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), x.targetClass());
+        XirSnippet snippet = xir.genInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), x.targetClass(), x.hints(), x.hintsExact());
         emitXir(snippet, x, info, null, false, x.negated() ? falseSuccessor : trueSuccessor, x.negated() ? trueSuccessor : falseSuccessor);
     }
 
@@ -760,8 +777,8 @@
     }
 
     public Variable emitConditional(BooleanNode node, CiValue trueValue, CiValue falseValue) {
-        assert trueValue instanceof CiConstant && trueValue.kind.stackKind() == CiKind.Int;
-        assert falseValue instanceof CiConstant && falseValue.kind.stackKind() == CiKind.Int;
+        assert trueValue instanceof CiConstant && (trueValue.kind.stackKind() == CiKind.Int || trueValue.kind == CiKind.Long);
+        assert falseValue instanceof CiConstant && (falseValue.kind.stackKind() == CiKind.Int || trueValue.kind == CiKind.Long);
 
         if (node instanceof NullCheckNode) {
             return emitNullCheckConditional((NullCheckNode) node, trueValue, falseValue);
@@ -785,7 +802,7 @@
         XirArgument obj = toXirArgument(x.object());
         XirArgument trueArg = toXirArgument(x.negated() ? falseValue : trueValue);
         XirArgument falseArg = toXirArgument(x.negated() ? trueValue : falseValue);
-        XirSnippet snippet = xir.genMaterializeInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), trueArg, falseArg, x.targetClass());
+        XirSnippet snippet = xir.genMaterializeInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), trueArg, falseArg, x.targetClass(), x.hints(), x.hintsExact());
         return (Variable) emitXir(snippet, null, null, false);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIR.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIR.java	Sun Feb 05 05:40:36 2012 +0100
@@ -28,6 +28,7 @@
 import com.oracle.max.criutils.*;
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.asm.*;
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.graph.*;
 
@@ -37,22 +38,23 @@
  */
 public class LIR {
 
+    public final ControlFlowGraph cfg;
+
     /**
-     * The start block of this LIR.
+     * The nodes for the blocks.
+     * TODO: This should go away, we want all nodes connected with a next-pointer.
      */
-    private final LIRBlock startBlock;
+    private final BlockMap<List<Node>> nodesFor;
 
     /**
      * The linear-scan ordered list of blocks.
      */
-    private final List<LIRBlock> linearScanOrder;
+    private final List<Block> linearScanOrder;
 
     /**
      * The order in which the code is emitted.
      */
-    private final List<LIRBlock> codeEmittingOrder;
-
-    private final NodeMap<LIRBlock> valueToBlock;
+    private final List<Block> codeEmittingOrder;
 
 
     public final List<SlowPath> slowPaths;
@@ -65,7 +67,6 @@
     public SlowPath methodEndMarker;
 
     private int numVariables;
-    private final int numLoops;
 
     public SpillMoveFactory spillMoveFactory;
 
@@ -83,37 +84,32 @@
      * @param numLoops number of loops
      * @param compilation the compilation
      */
-    public LIR(LIRBlock startBlock, List<LIRBlock> linearScanOrder, List<LIRBlock> codeEmittingOrder, NodeMap<LIRBlock> valueToBlock, int numLoops) {
+    public LIR(ControlFlowGraph cfg, BlockMap<List<Node>> nodesFor, List<Block> linearScanOrder, List<Block> codeEmittingOrder) {
+        this.cfg = cfg;
+        this.nodesFor = nodesFor;
         this.codeEmittingOrder = codeEmittingOrder;
         this.linearScanOrder = linearScanOrder;
-        this.startBlock = startBlock;
-        this.valueToBlock = valueToBlock;
-        this.numLoops = numLoops;
 
         slowPaths = new ArrayList<>();
         deoptimizationStubs = new ArrayList<>();
     }
 
+    public List<Node> nodesFor(Block block) {
+        return nodesFor.get(block);
+    }
+
     /**
      * Gets the linear scan ordering of blocks as a list.
      * @return the blocks in linear scan order
      */
-    public List<LIRBlock> linearScanOrder() {
+    public List<Block> linearScanOrder() {
         return linearScanOrder;
     }
 
-    public List<LIRBlock> codeEmittingOrder() {
+    public List<Block> codeEmittingOrder() {
         return codeEmittingOrder;
     }
 
-    public LIRBlock startBlock() {
-        return startBlock;
-    }
-
-    public NodeMap<LIRBlock> valueToBlock() {
-        return valueToBlock;
-    }
-
     public int numVariables() {
         return numVariables;
     }
@@ -127,7 +123,7 @@
             printLIR(codeEmittingOrder());
         }
 
-        for (LIRBlock b : codeEmittingOrder()) {
+        for (Block b : codeEmittingOrder()) {
             emitBlock(tasm, b);
         }
 
@@ -143,16 +139,16 @@
         emitSlowPath(tasm, methodEndMarker);
     }
 
-    private void emitBlock(TargetMethodAssembler tasm, LIRBlock block) {
+    private void emitBlock(TargetMethodAssembler tasm, Block block) {
         if (GraalOptions.PrintLIRWithAssembly) {
-            block.printWithoutPhis(TTY.out());
+            TTY.println(block.toString());
         }
 
         if (GraalOptions.CommentedAssembly) {
-            tasm.blockComment(String.format("block B%d loop %d depth %d", block.blockID(), block.loopIndex(), block.loopDepth()));
+            tasm.blockComment(String.format("block B%d %s", block.getId(), block.getLoop()));
         }
 
-        for (LIRInstruction op : block.lir()) {
+        for (LIRInstruction op : block.lir) {
             if (GraalOptions.CommentedAssembly) {
                 tasm.blockComment(String.format("%d %s", op.id(), op));
             }
@@ -208,9 +204,9 @@
     }
 
 
-    public static void printBlock(LIRBlock x) {
+    public static void printBlock(Block x) {
         // print block id
-        TTY.print("B%d ", x.blockID());
+        TTY.print("B%d ", x.getId());
 
         // print flags
         if (x.isLoopHeader()) {
@@ -227,39 +223,35 @@
         if (x.numberOfPreds() > 0) {
             TTY.print("preds: ");
             for (int i = 0; i < x.numberOfPreds(); i++) {
-                TTY.print("B%d ", x.predAt(i).blockID());
+                TTY.print("B%d ", x.predAt(i).getId());
             }
         }
 
         if (x.numberOfSux() > 0) {
             TTY.print("sux: ");
             for (int i = 0; i < x.numberOfSux(); i++) {
-                TTY.print("B%d ", x.suxAt(i).blockID());
+                TTY.print("B%d ", x.suxAt(i).getId());
             }
         }
 
         TTY.println();
     }
 
-    public static void printLIR(List<LIRBlock> blocks) {
+    public static void printLIR(List<Block> blocks) {
         if (TTY.isSuppressed()) {
             return;
         }
         TTY.println("LIR:");
         int i;
         for (i = 0; i < blocks.size(); i++) {
-            LIRBlock bb = blocks.get(i);
+            Block bb = blocks.get(i);
             printBlock(bb);
             TTY.println("__id_Instruction___________________________________________");
-            for (LIRInstruction op : bb.lir()) {
+            for (LIRInstruction op : bb.lir) {
                 TTY.println(op.toStringWithIdPrefix());
                 TTY.println();
             }
             TTY.println();
         }
     }
-
-    public int numLoops() {
-        return numLoops;
-    }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java	Sun Feb 05 05:37:52 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,216 +0,0 @@
-/*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.lir;
-
-import java.util.*;
-
-import com.oracle.max.asm.*;
-import com.oracle.max.criutils.*;
-import com.oracle.max.graal.compiler.schedule.*;
-import com.oracle.max.graal.compiler.util.*;
-import com.oracle.max.graal.graph.*;
-import com.oracle.max.graal.nodes.*;
-import com.oracle.max.graal.nodes.java.*;
-
-/**
- * The {@code LIRBlock} class definition.
- */
-public final class LIRBlock extends Block {
-
-    public static final IdentifyBlocksPhase.BlockFactory FACTORY = new IdentifyBlocksPhase.BlockFactory() {
-        @Override
-        public Block createBlock(int blockID) {
-            return new LIRBlock(blockID);
-        }
-    };
-
-    public final Label label;
-    private List<LIRInstruction> lir;
-    private FrameState lastState;
-
-    private boolean align;
-
-    private int linearScanNumber;
-
-    public LIRPhiMapping phis;
-
-    /**
-     * Bit map specifying which {@linkplain OperandPool operands} are live upon entry to this block.
-     * These are values used in this block or any of its successors where such value are not defined
-     * in this block.
-     * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.sun.cri.ci.CiValue) operand number}.
-     */
-    public BitMap liveIn;
-
-    /**
-     * Bit map specifying which {@linkplain OperandPool operands} are live upon exit from this block.
-     * These are values used in a successor block that are either defined in this block or were live
-     * upon entry to this block.
-     * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.sun.cri.ci.CiValue) operand number}.
-     */
-    public BitMap liveOut;
-
-    /**
-     * Bit map specifying which {@linkplain OperandPool operands} are used (before being defined) in this block.
-     * That is, these are the values that are live upon entry to the block.
-     * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.sun.cri.ci.CiValue) operand number}.
-     */
-    public BitMap liveGen;
-
-    /**
-     * Bit map specifying which {@linkplain OperandPool operands} are defined/overwritten in this block.
-     * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.sun.cri.ci.CiValue) operand number}.
-     */
-    public BitMap liveKill;
-
-    private int firstLirInstructionID;
-    private int lastLirInstructionID;
-
-
-    public LIRBlock(int blockID) {
-        super(blockID);
-        label = new Label();
-    }
-
-    public int firstLirInstructionId() {
-        return firstLirInstructionID;
-    }
-
-    public boolean align() {
-        return align;
-    }
-
-    public void setAlign(boolean b) {
-        align = b;
-    }
-
-    public void setFirstLirInstructionId(int firstLirInstructionId) {
-        this.firstLirInstructionID = firstLirInstructionId;
-    }
-
-    public int lastLirInstructionId() {
-        return lastLirInstructionID;
-    }
-
-    public void setLastLirInstructionId(int lastLirInstructionId) {
-        this.lastLirInstructionID = lastLirInstructionId;
-    }
-
-    public List<LIRInstruction> lir() {
-        return lir;
-    }
-
-    public void setLir(List<LIRInstruction> lir) {
-        this.lir = lir;
-    }
-
-    public void printWithoutPhis(LogStream out) {
-        out.println("LIR Block " + blockID());
-    }
-
-    public int numberOfPreds() {
-        return predecessors.size();
-    }
-
-    public int numberOfSux() {
-        return successors.size();
-    }
-
-    public boolean isPredecessor(LIRBlock block) {
-        return predecessors.contains(block);
-    }
-
-    public LIRBlock predAt(int i) {
-        return (LIRBlock) predecessors.get(i);
-    }
-
-    public LIRBlock suxAt(int i) {
-        return (LIRBlock) successors.get(i);
-    }
-
-    @SuppressWarnings({"unchecked", "cast"})
-    public List<LIRBlock> getLIRSuccessors() {
-        return (List<LIRBlock>) (List) super.getSuccessors();
-    }
-
-    @SuppressWarnings({"unchecked", "cast"})
-    public List<LIRBlock> getLIRPredecessors() {
-        return (List<LIRBlock>) (List) super.getPredecessors();
-    }
-
-
-    @Override
-    public String toString() {
-        return "B" + blockID();
-    }
-
-    public Label label() {
-        return label;
-    }
-
-    public void setLinearScanNumber(int v) {
-        linearScanNumber = v;
-    }
-
-    public int linearScanNumber() {
-        return linearScanNumber;
-    }
-
-    public void replaceWith(LIRBlock other) {
-        for (Block pred : predecessors) {
-            Util.replaceAllInList(this, other, ((LIRBlock) pred).successors);
-        }
-        for (int i = 0; i < other.predecessors.size(); ++i) {
-            if (other.predecessors.get(i) == this) {
-                other.predecessors.remove(i);
-                other.predecessors.addAll(i, this.predecessors);
-            }
-        }
-        successors.clear();
-        predecessors.clear();
-    }
-
-    public void setLastState(FrameState fs) {
-        lastState = fs;
-    }
-
-    public FrameState lastState() {
-        return lastState;
-    }
-
-    public boolean endsWithJump() {
-        if (lir.size() == 0) {
-            return false;
-        }
-        LIRInstruction lirInstruction = lir.get(lir.size() - 1);
-        if (lirInstruction instanceof LIRXirInstruction) {
-            LIRXirInstruction lirXirInstruction = (LIRXirInstruction) lirInstruction;
-            return (lirXirInstruction.falseSuccessor != null) && (lirXirInstruction.trueSuccessor != null);
-        }
-        return lirInstruction instanceof StandardOp.JumpOp;
-    }
-
-    public boolean isExceptionEntry() {
-        return firstNode() instanceof ExceptionObjectNode;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRPhiMapping.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRPhiMapping.java	Sun Feb 05 05:40:36 2012 +0100
@@ -25,6 +25,7 @@
 import java.util.*;
 
 import com.oracle.max.cri.ci.*;
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.gen.*;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode;
@@ -33,16 +34,16 @@
 import com.oracle.max.graal.nodes.PhiNode.*;
 
 public class LIRPhiMapping {
-    private final LIRBlock block;
+    private final Block block;
 
     private CiValue[][] inputs;
     private CiValue[] results;
 
-    public LIRPhiMapping(LIRBlock block, LIRGenerator gen) {
+    public LIRPhiMapping(Block block, LIRGenerator gen) {
         this.block = block;
 
-        assert block.firstNode() instanceof MergeNode : "phi functions are only present at control flow merges";
-        MergeNode mergeNode = (MergeNode) block.firstNode();
+        assert block.getBeginNode() instanceof MergeNode : "phi functions are only present at control flow merges";
+        MergeNode mergeNode = (MergeNode) block.getBeginNode();
         List<PhiNode> phis = mergeNode.phis().snapshot();
 
         for (int i = 0; i < phis.size(); i++) {
@@ -54,8 +55,8 @@
     }
 
     public void fillInputs(LIRGenerator gen) {
-        assert block.firstNode() instanceof MergeNode : "phi functions are only present at control flow merges";
-        MergeNode mergeNode = (MergeNode) block.firstNode();
+        assert block.getBeginNode() instanceof MergeNode : "phi functions are only present at control flow merges";
+        MergeNode mergeNode = (MergeNode) block.getBeginNode();
         List<PhiNode> phis = mergeNode.phis().snapshot();
 
         int numPhis = 0;
@@ -75,7 +76,7 @@
             if (phi.type() == PhiType.Value) {
                 results[phiIdx] = gen.operand(phi);
                 for (int j = 0; j < numPreds; j++) {
-                    assert j == mergeNode.phiPredecessorIndex((FixedNode) block.predAt(j).lastNode()) : "block predecessors and node predecessors must have same order";
+                    assert j == mergeNode.phiPredecessorIndex((FixedNode) block.predAt(j).getEndNode()) : "block predecessors and node predecessors must have same order";
                     inputs[j][phiIdx] = gen.operand(phi.valueAt(j));
                 }
                 phiIdx++;
@@ -88,7 +89,7 @@
         return results;
     }
 
-    public CiValue[] inputs(LIRBlock pred) {
+    public CiValue[] inputs(Block pred) {
         assert pred.numberOfSux() == 1 && pred.suxAt(0) == block;
         return inputs[block.getPredecessors().indexOf(pred)];
     }
@@ -96,7 +97,7 @@
     private static final EnumSet<OperandFlag> INPUT_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
     private static final EnumSet<OperandFlag> OUTPUT_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
 
-    public void forEachInput(LIRBlock pred, PhiValueProcedure proc) {
+    public void forEachInput(Block pred, PhiValueProcedure proc) {
         CiValue[] predInputs = inputs(pred);
         for (int i = 0; i < predInputs.length; i++) {
             predInputs[i] = proc.doValue(predInputs[i], results[i]);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRVerifier.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRVerifier.java	Sun Feb 05 05:40:36 2012 +0100
@@ -29,11 +29,11 @@
 
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.criutils.*;
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
 import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure;
-import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.compiler.util.*;
 
 public final class LIRVerifier {
@@ -46,10 +46,10 @@
     private final Object[] variableDefinitions;
 
     private BitSet liveOutFor(Block block) {
-        return blockLiveOut[block.blockID()];
+        return blockLiveOut[block.getId()];
     }
     private void setLiveOutFor(Block block, BitSet liveOut) {
-        blockLiveOut[block.blockID()] = liveOut;
+        blockLiveOut[block.getId()] = liveOut;
     }
 
     private int maxRegisterNum() {
@@ -91,7 +91,7 @@
     private BitSet curVariablesLive;
     private CiValue[] curRegistersLive;
 
-    private LIRBlock curBlock;
+    private Block curBlock;
     private Object curInstruction;
     private BitSet curRegistersDefined;
 
@@ -100,13 +100,13 @@
         ValueProcedure defProc =    new ValueProcedure() {    @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return def(value, mode, flags); } };
 
         curRegistersDefined = new BitSet();
-        for (LIRBlock block : lir.linearScanOrder()) {
+        for (Block block : lir.linearScanOrder()) {
             curBlock = block;
             curVariablesLive = new BitSet();
             curRegistersLive = new CiValue[maxRegisterNum()];
 
-            if (block.dominator() != null) {
-                curVariablesLive.or(liveOutFor(block.dominator()));
+            if (block.getDominator() != null) {
+                curVariablesLive.or(liveOutFor(block.getDominator()));
             }
 
             if (block.phis != null) {
@@ -115,13 +115,13 @@
                 block.phis.forEachOutput(defProc);
             }
 
-            assert block.lir().get(0) instanceof StandardOp.LabelOp : "block must start with label";
+            assert block.lir.get(0) instanceof StandardOp.LabelOp : "block must start with label";
             if (block.numberOfSux() > 0) {
-                LIRInstruction last = block.lir().get(block.lir().size() - 1);
+                LIRInstruction last = block.lir.get(block.lir.size() - 1);
                 assert last instanceof StandardOp.JumpOp || last instanceof LIRXirInstruction : "block with successor must end with unconditional jump";
             }
 
-            for (LIRInstruction op : block.lir()) {
+            for (LIRInstruction op : block.lir) {
                 curInstruction = op;
 
                 op.forEachInput(useProc);
@@ -139,7 +139,7 @@
                 curInstruction = null;
             }
 
-            for (LIRBlock sux : block.getLIRSuccessors()) {
+            for (Block sux : block.getSuccessors()) {
                 if (sux.phis != null) {
                     assert beforeRegisterAllocation;
                     curInstruction = sux.phis;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LabelRef.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LabelRef.java	Sun Feb 05 05:40:36 2012 +0100
@@ -23,9 +23,10 @@
 package com.oracle.max.graal.compiler.lir;
 
 import com.oracle.max.asm.*;
+import com.oracle.max.graal.compiler.cfg.*;
 
 /**
- * LIR instructions such as JUMP and BRANCH need to reference their target {@link LIRBlock}. However,
+ * LIR instructions such as JUMP and BRANCH need to reference their target {@link Block}. However,
  * direct references are not possible since the control flow graph (and therefore successors lists) can
  * be changed by optimizations - and fixing the instructions is error prone.
  * Therefore, we only reference of block B from block A only via the tuple (A, successor-index-of-B), i.e.,
@@ -66,11 +67,11 @@
      * @param suxIndex The index of the successor.
      * @return The newly created label reference.
      */
-    public static LabelRef forSuccessor(final LIRBlock block, final int suxIndex) {
+    public static LabelRef forSuccessor(final Block block, final int suxIndex) {
         return new LabelRef() {
             @Override
             public Label label() {
-                return block.suxAt(suxIndex).label();
+                return ((StandardOp.LabelOp) block.suxAt(suxIndex).lir.get(0)).getLabel();
             }
 
             @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/StandardOp.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/StandardOp.java	Sun Feb 05 05:40:36 2012 +0100
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.max.asm.*;
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.graal.compiler.asm.*;
 import com.oracle.max.graal.compiler.util.*;
@@ -39,6 +40,7 @@
      * The first operation of every block must implement this interface.
      */
     public interface LabelOp {
+        Label getLabel();
     }
 
     /**
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/loop/Loop.java	Sun Feb 05 05:37:52 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.loop;
-
-import java.util.*;
-
-import com.oracle.max.graal.graph.*;
-import com.oracle.max.graal.nodes.*;
-
-public class Loop {
-    private final LoopBeginNode loopBegin;
-    private Loop parent;
-    private final List<Loop> children;
-    private final NodeBitMap exits;
-    private final NodeBitMap directCFGNodes;
-    private NodeBitMap loopVariant;
-    private boolean finished;
-
-    public Loop(LoopBeginNode loopBegin) {
-        this.loopBegin = loopBegin;
-        this.children = new ArrayList<>(1);
-        this.exits = loopBegin.graph().createNodeBitMap();
-        this.directCFGNodes = loopBegin.graph().createNodeBitMap();
-    }
-
-    public LoopBeginNode loopBegin() {
-        return loopBegin;
-    }
-
-    public Loop parent() {
-        return parent;
-    }
-
-    public boolean isFinished() {
-        return finished;
-    }
-
-    public void setFinished() {
-        finished = true;
-    }
-
-    public List<Loop> children() {
-        return children;
-    }
-
-    public NodeBitMap exits() {
-        return exits;
-    }
-
-    public boolean isLoopExit(FixedNode node) {
-        return exits.isMarked(node);
-    }
-
-    public boolean isChildOf(Loop l) {
-        return parent == l || (parent != null && parent.isChildOf(l));
-    }
-
-    public boolean containsDirectFixed(FixedNode n) {
-        return directCFGNodes.isMarked(n);
-    }
-
-    public boolean containsFixed(FixedNode n) {
-        if (containsDirectFixed(n)) {
-            return true;
-        }
-        for (Loop child : children()) {
-            if (child.containsFixed(n)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public boolean isLoopInvariant(ValueNode value) {
-        if (loopVariant().isMarked(value)) {
-            return false;
-        }
-        for (Loop child : children()) {
-            if (!child.isLoopInvariant(value)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    @SuppressWarnings("unchecked")
-    public Iterable<FixedNode> directFixedNodes() {
-        return (Iterable) directCFGNodes;
-    }
-
-    public void addChildren(Loop loop) {
-        this.children.add(loop);
-        loop.parent = this;
-    }
-
-    NodeBitMap directCFGNodes() {
-        return directCFGNodes;
-    }
-
-    @Override
-    public String toString() {
-        return "Loop " + loopBegin();
-    }
-
-    NodeBitMap loopVariant() {
-        if (loopVariant == null) {
-            loopVariant = loopBegin().graph().createNodeBitMap();
-            NodeFlood work = loopBegin().graph().createNodeFlood();
-            work.addAll(directCFGNodes);
-            for (Node n : work) {
-                loopVariant.mark(n);
-                work.addAll(n.usages());
-            }
-        }
-        return loopVariant;
-    }
-
-    public int depth() {
-        if (parent() == null) {
-            return 0;
-        }
-        return parent().depth() + 1;
-    }
-
-    public int directFixedNodesCount() {
-        return directCFGNodes.cardinality();
-    }
-
-    public int fixedNodesCount() {
-        int count = directFixedNodesCount();
-        for (Loop child : children()) {
-            count += child.directFixedNodesCount();
-        }
-        return count;
-    }
-
-    public int exitsCount() {
-        return exits().cardinality();
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/loop/LoopInfo.java	Sun Feb 05 05:37:52 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.loop;
-
-import java.util.*;
-
-import com.oracle.max.criutils.*;
-import com.oracle.max.graal.graph.*;
-import com.oracle.max.graal.util.*;
-
-public class LoopInfo {
-    private final NodeMap<Loop> nodeToLoop;
-    private final List<Loop> rootLoops;
-
-    public LoopInfo(NodeMap<Loop> nodeToLoop, List<Loop> rootLoops) {
-        this.nodeToLoop = nodeToLoop;
-        this.rootLoops = rootLoops;
-    }
-
-    public Loop loop(Node n) {
-        return nodeToLoop.get(n);
-    }
-
-    public List<Loop> rootLoops() {
-        return rootLoops;
-    }
-
-    public Iterable<Loop> loops() {
-        return new Iterable<Loop>() {
-            @Override
-            public Iterator<Loop> iterator() {
-                return new TreeIterators.PrefixTreeIterator<Loop>(rootLoops()) {
-                    @Override
-                    protected Iterable<Loop> children(Loop node) {
-                        return node.children();
-                    }
-                };
-            }
-        };
-    }
-
-    public void print() {
-        for (Loop loop : rootLoops) {
-            print(loop);
-        }
-    }
-
-    private void print(final Loop loop) {
-        TTY.out().printf("%s\n", loop.loopBegin());
-        TTY.out().println("-- exits");
-        TTY.out().adjustIndentation(+2);
-        for (Node n : loop.exits()) {
-            TTY.out().printf("%s from %s\n", n, n.predecessor());
-        }
-        TTY.out().adjustIndentation(-2);
-        TTY.out().println("-- directNodes");
-        TTY.out().adjustIndentation(+2);
-        for (final Node node : loop.directFixedNodes()) {
-            TTY.out().printf("%s\n", node);
-        }
-        TTY.out().adjustIndentation(-2);
-        TTY.out().println("-- subloops");
-        TTY.out().adjustIndentation(+2);
-        for (Loop sub : loop.children()) {
-            print(sub);
-        }
-        TTY.out().adjustIndentation(-2);
-        TTY.out().println("-- sub");
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/loop/LoopUtil.java	Sun Feb 05 05:37:52 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.loop;
-
-import java.util.*;
-
-import com.oracle.max.graal.graph.*;
-import com.oracle.max.graal.nodes.*;
-
-
-public class LoopUtil {
-
-    public static LoopInfo computeLoopInfo(Graph graph) {
-        // Create node-to-loop relation.
-        NodeMap<Loop> nodeToLoop = graph.createNodeMap();
-        for (LoopBeginNode begin : graph.getNodes(LoopBeginNode.class)) {
-            mark(begin, nodeToLoop);
-        }
-
-        List<Loop> rootLoops = new ArrayList<>(1);
-        LoopInfo info = new LoopInfo(nodeToLoop, rootLoops);
-
-        // Get parent-child relationships between loops.
-        for (LoopBeginNode begin : graph.getNodes(LoopBeginNode.class)) {
-            Loop loop = nodeToLoop.get(begin);
-            Loop parentLoop = nodeToLoop.get(begin.forwardEdge());
-            if (parentLoop != null) {
-                parentLoop.addChildren(loop);
-            } else {
-                rootLoops.add(loop);
-            }
-        }
-
-        //Find exits
-        for (Loop loop : info.loops()) {
-            for (FixedNode n : loop.directFixedNodes()) {
-                if (n instanceof ControlSplitNode) {
-                    for (BeginNode sux : ((ControlSplitNode) n).blockSuccessors()) {
-                        Loop l = loop;
-                        while (l != null && !l.containsFixed(sux)) {
-                            l.exits().mark(sux);
-                            l = l.parent();
-                        }
-                    }
-                }
-            }
-        }
-
-        return info;
-    }
-
-    private static void mark(LoopBeginNode begin, NodeMap<Loop> nodeToLoop) {
-
-        if (nodeToLoop.get(begin) != null) {
-            // Loop already processed.
-            return;
-        }
-        Loop loop = new Loop(begin);
-        nodeToLoop.set(begin, loop);
-
-        NodeFlood workCFG = begin.graph().createNodeFlood();
-        workCFG.add(begin.loopEnd());
-        for (Node n : workCFG) {
-            if (n == begin) {
-                // Stop at loop begin.
-                continue;
-            }
-            markNode(n, loop, nodeToLoop);
-
-            for (Node pred : n.cfgPredecessors()) {
-                workCFG.add(pred);
-            }
-        }
-
-        // We finished marking the loop.
-        loop.setFinished();
-    }
-
-    private static void markNode(Node n, Loop loop, NodeMap<Loop> nodeToLoop) {
-        Loop oldMark = nodeToLoop.get(n);
-        if (oldMark == null || !oldMark.isFinished()) {
-
-            // We have an inner loop, start marking it.
-            if (n instanceof LoopBeginNode) {
-                mark((LoopBeginNode) n, nodeToLoop);
-            } else {
-                if (oldMark != null) {
-                    oldMark.directCFGNodes().clear(n);
-                }
-                nodeToLoop.set(n, loop);
-                loop.directCFGNodes().mark(n);
-            }
-        }
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/BoxingEliminationPhase.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/BoxingEliminationPhase.java	Sun Feb 05 05:40:36 2012 +0100
@@ -22,11 +22,14 @@
  */
 package com.oracle.max.graal.compiler.phases;
 
+import static com.oracle.max.graal.graph.iterators.NodePredicates.*;
+
 import java.util.*;
 
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.iterators.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.PhiNode.*;
 import com.oracle.max.graal.nodes.extended.*;
@@ -106,11 +109,9 @@
 
         virtualizeUsages(boxNode, boxNode.source(), boxNode.exactType());
 
-        for (Node n : boxNode.usages()) {
-            if (!(n instanceof FrameState) && !(n instanceof VirtualObjectFieldNode)) {
-                // Elimination failed, because boxing object escapes.
-                return;
-            }
+        if (boxNode.usages().filter(isNotA(FrameState.class).nor(VirtualObjectFieldNode.class)).isNotEmpty()) {
+            // Elimination failed, because boxing object escapes.
+            return;
         }
 
         // TODO(ls) this seems weird: there might still be references to boxNode, yet it is deleted...
@@ -125,7 +126,7 @@
     private static void virtualizeUsages(ValueNode boxNode, ValueNode replacement, RiResolvedType exactType) {
         ValueNode virtualValueNode = null;
         VirtualObjectNode virtualObjectNode = null;
-        for (Node n : boxNode.usages().filter(FrameState.class).or(VirtualObjectFieldNode.class).snapshot()) {
+        for (Node n : boxNode.usages().filter(NodePredicates.isA(FrameState.class).or(VirtualObjectFieldNode.class)).snapshot()) {
             if (virtualValueNode == null) {
                 virtualObjectNode = n.graph().unique(new BoxedVirtualObjectNode(exactType, replacement));
             }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java	Sun Feb 05 05:40:36 2012 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.max.graal.compiler.phases;
 
+import static com.oracle.max.graal.graph.iterators.NodePredicates.*;
+
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.graal.debug.*;
@@ -63,7 +65,7 @@
         Tool tool = new Tool(nodeWorkList, runtime, target, assumptions);
         for (Node node : nodeWorkList) {
             if (node instanceof Canonicalizable) {
-                Debug.log("Canonicalizer: work on %1s");
+                Debug.log("Canonicalizer: work on %s", node);
                 graph.mark();
                 ValueNode canonical = ((Canonicalizable) node).canonical(tool);
 //     cases:                                           original node:
@@ -232,8 +234,8 @@
             if (node instanceof PhiNode) {
                 node.replaceFirstInput(input, null);
             } else {
-                for (Node usage : node.usages().snapshot()) {
-                    if ((usage instanceof FloatingNode || usage instanceof CallTargetNode) && !usage.isDeleted()) {
+                for (Node usage : node.usages().filter(isA(FloatingNode.class).or(CallTargetNode.class)).snapshot()) {
+                    if (!usage.isDeleted()) {
                         killNonCFG(usage, node);
                     }
                 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java	Sun Feb 05 05:40:36 2012 +0100
@@ -306,7 +306,7 @@
     private static Node escape(EscapeRecord record, Node usage) {
         final Node node = record.node;
         if (usage instanceof FrameState) {
-            assert ((FrameState) usage).inputs().contains(node);
+            assert usage.inputs().contains(node);
             return null;
         } else {
             if (usage instanceof FixedNode) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/FloatingReadPhase.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/FloatingReadPhase.java	Sun Feb 05 05:40:36 2012 +0100
@@ -25,8 +25,7 @@
 import java.util.*;
 
 import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.compiler.loop.*;
-import com.oracle.max.graal.compiler.schedule.*;
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.debug.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
@@ -90,7 +89,7 @@
                     Node current = anyLocationNode;
                     if (anyLocationNode instanceof PhiNode) {
                         PhiNode phiNode = (PhiNode) anyLocationNode;
-                        if (phiNode.merge() == block.firstNode()) {
+                        if (phiNode.merge() == block.getBeginNode()) {
                             PhiNode phiCopy = (PhiNode) phiNode.copyWithInputs();
                             phiCopy.removeInput(phiCopy.valueCount() - 1);
                             current = phiCopy;
@@ -109,7 +108,7 @@
                 Debug.log("Nothing to merge both nodes are %s.", original);
                 return;
             }
-            MergeNode m = (MergeNode) mergeBlock.firstNode();
+            MergeNode m = (MergeNode) mergeBlock.getBeginNode();
             if (m.isPhiAtMerge(original)) {
                 PhiNode phi = (PhiNode) original;
                 phi.addInput((ValueNode) newValue);
@@ -188,7 +187,7 @@
         }
 
         private void createLoopEntryPhi(Object modifiedLocation, Node other, Loop loop) {
-            PhiNode phi = other.graph().unique(new PhiNode(CiKind.Illegal, loop.loopBegin(), PhiType.Memory));
+            PhiNode phi = other.graph().unique(new PhiNode(CiKind.Illegal, (MergeNode) loop.header.getBeginNode(), PhiType.Memory));
             phi.addInput((ValueNode) other);
             map.put(modifiedLocation, phi);
             loopEntryMap.put(modifiedLocation, phi);
@@ -206,43 +205,43 @@
         // Add start node write checkpoint.
         addStartCheckpoint(graph);
 
-        LoopInfo loopInfo = LoopUtil.computeLoopInfo(graph);
+        // Identify blocks.
+        ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, false, false);
+        Block[] blocks = cfg.getBlocks();
 
         HashMap<Loop, Set<Object>> modifiedValues = new HashMap<>();
         // Initialize modified values to empty hash set.
-        for (Loop loop : loopInfo.loops()) {
+        for (Loop loop : cfg.getLoops()) {
             modifiedValues.put(loop, new HashSet<>());
         }
 
         // Get modified values in loops.
         for (Node n : graph.getNodes()) {
-            Loop loop = loopInfo.loop(n);
-            if (loop != null) {
+            Block block = cfg.blockFor(n);
+            if (block != null && block.getLoop() != null) {
                 if (n instanceof WriteNode) {
                     WriteNode writeNode = (WriteNode) n;
-                    traceWrite(loop, writeNode.location().locationIdentity(), modifiedValues);
+                    traceWrite(block.getLoop(), writeNode.location().locationIdentity(), modifiedValues);
                 } else if (n instanceof MemoryCheckpoint) {
-                    traceMemoryCheckpoint(loop, modifiedValues);
+                    traceMemoryCheckpoint(block.getLoop(), modifiedValues);
                 }
             }
         }
 
         // Propagate values to parent loops.
-        for (Loop loop : loopInfo.rootLoops()) {
-            propagateFromChildren(loop, modifiedValues);
+        for (Loop loop : cfg.getLoops()) {
+            if (loop.depth == 1) {
+                propagateFromChildren(loop, modifiedValues);
+            }
         }
 
         Debug.log("Modified values: %s.", modifiedValues);
 
-        // Identify blocks.
-        final IdentifyBlocksPhase s = new IdentifyBlocksPhase(false);
-        s.apply(graph);
-        List<Block> blocks = s.getBlocks();
 
         // Process blocks (predecessors first).
-        MemoryMap[] memoryMaps = new MemoryMap[blocks.size()];
+        MemoryMap[] memoryMaps = new MemoryMap[blocks.length];
         for (final Block b : blocks) {
-            processBlock(b, memoryMaps, s.getNodeToBlock(), modifiedValues, loopInfo);
+            processBlock(b, memoryMaps, cfg.getNodeToBlock(), modifiedValues);
         }
     }
 
@@ -254,41 +253,28 @@
         }
     }
 
-    private void processBlock(Block b, MemoryMap[] memoryMaps, NodeMap<Block> nodeToBlock, HashMap<Loop, Set<Object>> modifiedValues, LoopInfo loopInfo) {
-
-        // Visit every block at most once.
-        if (memoryMaps[b.blockID()] != null) {
-            return;
-        }
-
-        // Process predecessors before this block.
-        for (Block pred : b.getPredecessors()) {
-            processBlock(pred, memoryMaps, nodeToBlock, modifiedValues, loopInfo);
-        }
-
-
+    private static void processBlock(Block b, MemoryMap[] memoryMaps, NodeMap<Block> nodeToBlock, HashMap<Loop, Set<Object>> modifiedValues) {
         // Create initial memory map for the block.
         MemoryMap map = null;
         if (b.getPredecessors().size() == 0) {
             map = new MemoryMap(b);
         } else {
-            map = new MemoryMap(b, memoryMaps[b.getPredecessors().get(0).blockID()]);
+            map = new MemoryMap(b, memoryMaps[b.getPredecessors().get(0).getId()]);
             if (b.isLoopHeader()) {
-                assert b.getPredecessors().size() == 1;
-                Loop loop = loopInfo.loop(b.firstNode());
+                Loop loop = b.getLoop();
                 map.createLoopEntryMemoryMap(modifiedValues.get(loop), loop);
             } else {
                 for (int i = 1; i < b.getPredecessors().size(); ++i) {
-                    assert b.firstNode() instanceof MergeNode : b.firstNode();
+                    assert b.getBeginNode() instanceof MergeNode : b.getBeginNode();
                     Block block = b.getPredecessors().get(i);
-                    map.mergeWith(memoryMaps[block.blockID()], b);
+                    map.mergeWith(memoryMaps[block.getId()], b);
                 }
             }
         }
-        memoryMaps[b.blockID()] = map;
+        memoryMaps[b.getId()] = map;
 
         // Process instructions of this block.
-        for (Node n : b.getInstructions()) {
+        for (Node n : b.getNodes()) {
             if (n instanceof ReadNode) {
                 ReadNode readNode = (ReadNode) n;
                 map.processRead(readNode);
@@ -302,12 +288,12 @@
         }
 
 
-        if (b.lastNode() instanceof LoopEndNode) {
-            LoopEndNode end = (LoopEndNode) b.lastNode();
+        if (b.getEndNode() instanceof LoopEndNode) {
+            LoopEndNode end = (LoopEndNode) b.getEndNode();
             LoopBeginNode begin = end.loopBegin();
             Block beginBlock = nodeToBlock.get(begin);
-            MemoryMap memoryMap = memoryMaps[beginBlock.blockID()];
-            assert memoryMap != null : beginBlock.name();
+            MemoryMap memoryMap = memoryMaps[beginBlock.getId()];
+            assert memoryMap != null;
             assert memoryMap.getLoopEntryMap() != null;
             memoryMap.mergeLoopEntryWith(map, begin);
         }
@@ -318,7 +304,7 @@
     }
 
     private void propagateFromChildren(Loop loop, HashMap<Loop, Set<Object>> modifiedValues) {
-        for (Loop child : loop.children()) {
+        for (Loop child : loop.children) {
             propagateFromChildren(child, modifiedValues);
             modifiedValues.get(loop).addAll(modifiedValues.get(child));
         }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Sun Feb 05 05:40:36 2012 +0100
@@ -47,7 +47,7 @@
     private final CiTarget target;
     private final GraalRuntime runtime;
 
-    private final Collection<Invoke> hints;
+    private final Collection<? extends Invoke> hints;
 
     private final PriorityQueue<InlineInfo> inlineCandidates = new PriorityQueue<>();
     private CiAssumptions assumptions;
@@ -58,7 +58,7 @@
     private static final DebugMetric metricInliningPerformed = Debug.metric("InliningPerformed");
     private static final DebugMetric metricInliningConsidered = Debug.metric("InliningConsidered");
 
-    public InliningPhase(CiTarget target, GraalRuntime runtime, Collection<Invoke> hints, CiAssumptions assumptions, PhasePlan plan) {
+    public InliningPhase(CiTarget target, GraalRuntime runtime, Collection<? extends Invoke> hints, CiAssumptions assumptions, PhasePlan plan) {
         this.target = target;
         this.runtime = runtime;
         this.hints = hints;
@@ -125,11 +125,8 @@
                     Invoke invoke = (Invoke) node;
                     scanInvoke(invoke, level);
                 }
-                for (Node usage : node.usages().snapshot()) {
-                    if (usage instanceof Invoke) {
-                        Invoke invoke = (Invoke) usage;
-                        scanInvoke(invoke, level);
-                    }
+                for (Node usage : node.usages().filterInterface(Invoke.class).snapshot()) {
+                    scanInvoke((Invoke) usage, level);
                 }
             }
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java	Sun Feb 05 05:40:36 2012 +0100
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.phases;
+
+import com.oracle.max.graal.nodes.*;
+
+public class InsertStateAfterPlaceholderPhase extends Phase {
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (ReturnNode ret : graph.getNodes(ReturnNode.class)) {
+            PlaceholderNode p = graph.add(new PlaceholderNode());
+            p.setStateAfter(graph.add(new FrameState(null, FrameState.AFTER_BCI, 0, 0, false)));
+            graph.addBeforeFixed(ret, p);
+        }
+    }
+
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/IntrinsificationPhase.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/IntrinsificationPhase.java	Sun Feb 05 05:40:36 2012 +0100
@@ -25,6 +25,7 @@
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.cri.*;
+import com.oracle.max.graal.debug.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 
@@ -58,6 +59,7 @@
             intrinsicGraph = runtime.intrinsicGraph(invoke.stateAfter().method(), invoke.bci(), target, invoke.callTarget().arguments());
         }
         if (intrinsicGraph != null) {
+            Debug.log(" > Intrinsify %s", target);
             InliningUtil.inline(invoke, intrinsicGraph, true);
         }
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java	Sun Feb 05 05:40:36 2012 +0100
@@ -23,7 +23,7 @@
 package com.oracle.max.graal.compiler.phases;
 
 import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.schedule.*;
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.cri.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
@@ -39,13 +39,11 @@
 
     @Override
     protected void run(final StructuredGraph graph) {
-        final IdentifyBlocksPhase s = new IdentifyBlocksPhase(false);
-        s.apply(graph);
-        s.calculateAlwaysReachedBlock();
+        ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, false, true, true);
 
         NodeBitMap processed = graph.createNodeBitMap();
         NodeBitMap activeGuards = graph.createNodeBitMap();
-        processBlock(s.getStartBlock(), activeGuards, processed, null);
+        processBlock(cfg.getStartBlock(), activeGuards, processed, null);
 
         processed.negate();
         final CiLoweringTool loweringTool = new CiLoweringTool() {
@@ -62,6 +60,7 @@
 
             @Override
             public Node createGuard(Node condition) {
+                // TODO(tw): Explain why this must not be called on floating nodes.
                 throw new UnsupportedOperationException();
             }
         };
@@ -77,21 +76,21 @@
 
         FixedNode anchor = parentAnchor;
         if (anchor == null) {
-            anchor = block.createAnchor();
+            anchor = block.getBeginNode();
         }
         process(block, activeGuards, processed, anchor);
 
         // Process always reached block first.
-        Block alwaysReachedBlock = block.alwaysReachedBlock();
-        if (alwaysReachedBlock != null && alwaysReachedBlock.dominator() == block) {
-            assert alwaysReachedBlock.dominator() == block;
+        Block alwaysReachedBlock = block.getPostdominator();
+        if (alwaysReachedBlock != null && alwaysReachedBlock.getDominator() == block) {
+            assert alwaysReachedBlock.getDominator() == block;
             processBlock(alwaysReachedBlock, activeGuards, processed, anchor);
         }
 
         // Now go for the other dominators.
         for (Block dominated : block.getDominated()) {
             if (dominated != alwaysReachedBlock) {
-                assert dominated.dominator() == block;
+                assert dominated.getDominator() == block;
                 processBlock(dominated, activeGuards, processed, null);
             }
         }
@@ -135,7 +134,7 @@
         };
 
         // Lower the instructions of this block.
-        for (final Node node : b.getInstructions()) {
+        for (Node node : b.getNodes()) {
             processed.mark(node);
             if (node instanceof Lowerable) {
                 ((Lowerable) node).lower(loweringTool);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/PhiStampPhase.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/PhiStampPhase.java	Sun Feb 05 05:40:36 2012 +0100
@@ -22,7 +22,6 @@
  */
 package com.oracle.max.graal.compiler.phases;
 
-import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 
 public class PhiStampPhase extends Phase {
@@ -45,22 +44,16 @@
 
     private void iterativeInferPhi(PhiNode phi) {
         if (phi.inferStamp()) {
-            for (Node n : phi.usages()) {
-                if (n instanceof PhiNode) {
-                    PhiNode phiUsage = (PhiNode) n;
-                    iterativeInferPhi(phiUsage);
-                }
+            for (PhiNode phiUsage : phi.usages().filter(PhiNode.class)) {
+                iterativeInferPhi(phiUsage);
             }
         }
     }
 
     private void inferPhi(PhiNode phi) {
-        for (ValueNode v : phi.values()) {
-            if (v instanceof PhiNode) {
-                PhiNode phiInput = (PhiNode) v;
-                if (!phiInput.isLoopPhi()) {
-                    inferPhi(phiInput);
-                }
+        for (PhiNode phiInput : phi.values().filter(PhiNode.class)) {
+            if (!phiInput.isLoopPhi()) {
+                inferPhi(phiInput);
             }
         }
         phi.inferStamp();
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/RemovePlaceholderPhase.java	Sun Feb 05 05:37:52 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.phases;
-
-import com.oracle.max.graal.nodes.*;
-
-public class RemovePlaceholderPhase extends Phase {
-    @Override
-    protected void run(StructuredGraph graph) {
-        for (PlaceholderNode n : graph.getNodes(PlaceholderNode.class)) {
-            graph.removeFixed(n);
-        }
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/SafepointPollingEliminationPhase.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/SafepointPollingEliminationPhase.java	Sun Feb 05 05:40:36 2012 +0100
@@ -22,9 +22,9 @@
  */
 package com.oracle.max.graal.compiler.phases;
 
-import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.graph.iterators.*;
 import com.oracle.max.graal.nodes.*;
+import com.oracle.max.graal.util.*;
 
 public class SafepointPollingEliminationPhase extends Phase {
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/SnippetIntrinsificationPhase.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/SnippetIntrinsificationPhase.java	Sun Feb 05 05:40:36 2012 +0100
@@ -156,6 +156,7 @@
         Constructor< ? > constructor;
         try {
             constructor = nodeClass.getDeclaredConstructor(parameterTypes);
+            constructor.setAccessible(true);
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
@@ -169,36 +170,33 @@
     public void cleanUpReturnCheckCast(Node newInstance) {
         if (newInstance instanceof ValueNode && ((ValueNode) newInstance).kind() != CiKind.Object) {
             StructuredGraph graph = (StructuredGraph) newInstance.graph();
-            for (Node usage : newInstance.usages().snapshot()) {
-                if (usage instanceof CheckCastNode) {
-                    CheckCastNode checkCastNode = (CheckCastNode) usage;
-                    for (Node checkCastUsage : checkCastNode.usages().snapshot()) {
-                        if (checkCastUsage instanceof ValueAnchorNode) {
-                            ValueAnchorNode valueAnchorNode = (ValueAnchorNode) checkCastUsage;
-                            graph.removeFixed(valueAnchorNode);
-                        } else if (checkCastUsage instanceof MethodCallTargetNode) {
-                            MethodCallTargetNode checkCastCallTarget = (MethodCallTargetNode) checkCastUsage;
-                            assert pool.isUnboxingMethod(checkCastCallTarget.targetMethod());
-                            Invoke invokeNode = checkCastCallTarget.invoke();
-                            invokeNode.node().replaceAtUsages(newInstance);
-                            if (invokeNode instanceof InvokeWithExceptionNode) {
-                                // Destroy exception edge & clear stateAfter.
-                                InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invokeNode;
+            for (CheckCastNode checkCastNode : newInstance.usages().filter(CheckCastNode.class).snapshot()) {
+                for (Node checkCastUsage : checkCastNode.usages().snapshot()) {
+                    if (checkCastUsage instanceof ValueAnchorNode) {
+                        ValueAnchorNode valueAnchorNode = (ValueAnchorNode) checkCastUsage;
+                        graph.removeFixed(valueAnchorNode);
+                    } else if (checkCastUsage instanceof MethodCallTargetNode) {
+                        MethodCallTargetNode checkCastCallTarget = (MethodCallTargetNode) checkCastUsage;
+                        assert pool.isUnboxingMethod(checkCastCallTarget.targetMethod());
+                        Invoke invokeNode = checkCastCallTarget.invoke();
+                        invokeNode.node().replaceAtUsages(newInstance);
+                        if (invokeNode instanceof InvokeWithExceptionNode) {
+                            // Destroy exception edge & clear stateAfter.
+                            InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invokeNode;
 
-                                invokeWithExceptionNode.killExceptionEdge();
-                                graph.removeSplit(invokeWithExceptionNode, InvokeWithExceptionNode.NORMAL_EDGE);
-                            } else {
-                                graph.removeFixed((InvokeNode) invokeNode);
-                            }
-                            checkCastCallTarget.safeDelete();
-                        } else if (checkCastUsage instanceof FrameState) {
-                            checkCastUsage.replaceFirstInput(checkCastNode, null);
+                            invokeWithExceptionNode.killExceptionEdge();
+                            graph.removeSplit(invokeWithExceptionNode, InvokeWithExceptionNode.NORMAL_EDGE);
                         } else {
-                            assert false : "unexpected checkcast usage: " + checkCastUsage;
+                            graph.removeFixed((InvokeNode) invokeNode);
                         }
+                        checkCastCallTarget.safeDelete();
+                    } else if (checkCastUsage instanceof FrameState) {
+                        checkCastUsage.replaceFirstInput(checkCastNode, null);
+                    } else {
+                        assert false : "unexpected checkcast usage: " + checkCastUsage;
                     }
-                    checkCastNode.safeDelete();
                 }
+                checkCastNode.safeDelete();
             }
         }
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java	Sun Feb 05 05:37:52 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,249 +0,0 @@
-/*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.schedule;
-
-import java.util.*;
-
-import com.oracle.max.graal.graph.*;
-import com.oracle.max.graal.nodes.*;
-import com.oracle.max.graal.nodes.java.*;
-
-
-public class Block {
-
-    private int blockID;
-    protected final List<Block> successors = new ArrayList<>();
-    protected final List<Block> predecessors = new ArrayList<>();
-    private final List<Block> dominated = new ArrayList<>();
-    private List<Node> instructions = new ArrayList<>();
-    private Block alwaysReachedBlock;
-    private Block dominator;
-    private EndNode end;
-    private int loopDepth = 0;
-    private int loopIndex = -1;
-    private double probability;
-
-    /**
-     * For loop headers only: The list of all blocks in this loop.
-     */
-    public List<Block> loopBlocks;
-
-    private Node firstNode;
-    private Node lastNode;
-
-    public Node firstNode() {
-        return firstNode;
-    }
-
-    public void setFirstNode(Node node) {
-        this.firstNode = node;
-    }
-
-    public Block alwaysReachedBlock() {
-        return alwaysReachedBlock;
-    }
-
-    public boolean isExceptionBlock() {
-        return firstNode() instanceof ExceptionObjectNode;
-    }
-
-    public void setAlwaysReachedBlock(Block alwaysReachedBlock) {
-        assert alwaysReachedBlock != this;
-        this.alwaysReachedBlock = alwaysReachedBlock;
-    }
-
-    public EndNode end() {
-        return end;
-    }
-
-    public void setEnd(EndNode end) {
-        this.end = end;
-    }
-
-    public Node lastNode() {
-        return lastNode;
-    }
-
-    public int loopDepth() {
-        return loopDepth;
-    }
-
-    public void setLoopDepth(int i) {
-        loopDepth = i;
-    }
-
-    public int loopIndex() {
-        return loopIndex;
-    }
-
-    public void setLoopIndex(int i) {
-        loopIndex = i;
-    }
-
-    public double probability() {
-        return probability;
-    }
-
-
-    public void setProbability(double probability) {
-        if (probability > this.probability) {
-            this.probability = probability;
-        }
-    }
-
-    public BeginNode createAnchor() {
-        return (BeginNode) firstNode;
-    }
-
-    public void setLastNode(Node node) {
-        this.lastNode = node;
-    }
-
-    public List<Block> getSuccessors() {
-        return Collections.unmodifiableList(successors);
-    }
-
-    public void setDominator(Block dominator) {
-        assert this.dominator == null;
-        assert dominator != null;
-        this.dominator = dominator;
-        dominator.dominated.add(this);
-    }
-
-    public List<Block> getDominated() {
-        return Collections.unmodifiableList(dominated);
-    }
-
-    public List<Node> getInstructions() {
-        return instructions;
-    }
-
-    public List<Block> getPredecessors() {
-        return Collections.unmodifiableList(predecessors);
-    }
-
-    public Block(int blockID) {
-        this.blockID = blockID;
-    }
-
-    public void addSuccessor(Block other) {
-        successors.add(other);
-        other.predecessors.add(this);
-    }
-
-    public int blockID() {
-        return blockID;
-    }
-
-    /**
-     * Iterate over this block, its exception handlers, and its successors, in that order.
-     *
-     * @param closure the closure to apply to each block
-     */
-    public void iteratePreOrder(BlockClosure closure) {
-        // TODO: identity hash map might be too slow, consider a boolean array or a mark field
-        iterate(new IdentityHashMap<Block, Block>(), closure);
-    }
-
-    private void iterate(IdentityHashMap<Block, Block> mark, BlockClosure closure) {
-        if (!mark.containsKey(this)) {
-            mark.put(this, this);
-            closure.apply(this);
-
-            iterateReverse(mark, closure, this.successors);
-        }
-    }
-
-    private static void iterateReverse(IdentityHashMap<Block, Block> mark, BlockClosure closure, List<Block> list) {
-        for (int i = list.size() - 1; i >= 0; i--) {
-            list.get(i).iterate(mark, closure);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return "B" + blockID;
-    }
-
-    public boolean isLoopHeader() {
-        return firstNode instanceof LoopBeginNode;
-    }
-
-    public boolean isLoopEnd() {
-        return lastNode instanceof LoopEndNode;
-    }
-
-    public Block dominator() {
-        return dominator;
-    }
-
-    public void setInstructions(List<Node> instructions) {
-        this.instructions = instructions;
-    }
-
-    public static void iteratePostOrder(List<Block> blocks, BlockClosure closure) {
-        ArrayList<Block> startBlocks = new ArrayList<>();
-        for (Block block : blocks) {
-            if (block.getPredecessors().size() == 0) {
-                startBlocks.add(block);
-            }
-        }
-        iteratePostOrder(blocks, closure, startBlocks.toArray(new Block[startBlocks.size()]));
-    }
-
-    public static void iteratePostOrder(List<Block> blocks, BlockClosure closure, Block... startBlocks) {
-        BitMap visited = new BitMap(blocks.size());
-        LinkedList<Block> workList = new LinkedList<>();
-        for (Block block : startBlocks) {
-            workList.add(block);
-            visited.set(block.blockID());
-        }
-
-        while (!workList.isEmpty()) {
-            Block b = workList.remove();
-
-            closure.apply(b);
-
-            for (Block succ : b.getSuccessors()) {
-                if (!visited.get(succ.blockID())) {
-                    boolean delay = false;
-                    for (Block pred : succ.getPredecessors()) {
-                        if (!visited.get(pred.blockID()) && !(pred.lastNode instanceof LoopEndNode)) {
-                            delay = true;
-                            break;
-                        }
-                    }
-
-                    if (!delay) {
-                        visited.set(succ.blockID());
-                        workList.add(succ);
-                    }
-                }
-            }
-        }
-    }
-
-    public String name() {
-        return "B" + blockID;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/BlockClosure.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/BlockClosure.java	Sun Feb 05 05:40:36 2012 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.max.graal.compiler.schedule;
 
+import com.oracle.max.graal.compiler.cfg.*;
+
 /**
  * The {@code BlockClosure} interface represents a closure for iterating over blocks.
  */
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java	Sun Feb 05 05:37:52 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,641 +0,0 @@
-/*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.schedule;
-
-import java.util.*;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.criutils.*;
-import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.phases.*;
-import com.oracle.max.graal.compiler.util.*;
-import com.oracle.max.graal.graph.*;
-import com.oracle.max.graal.graph.Node.Verbosity;
-import com.oracle.max.graal.nodes.*;
-import com.oracle.max.graal.nodes.extended.*;
-import com.oracle.max.graal.nodes.virtual.*;
-
-
-public class IdentifyBlocksPhase extends Phase {
-
-    public static class BlockFactory {
-        public Block createBlock(int blockID) {
-            return new Block(blockID);
-        }
-    }
-
-    private final BlockFactory blockFactory;
-    private final List<Block> blocks = new ArrayList<>();
-    private NodeMap<Block> nodeToBlock;
-    private NodeMap<Block> earliestCache;
-    private Block startBlock;
-    private boolean scheduleAllNodes;
-    private int loopCount;
-
-    public IdentifyBlocksPhase(boolean scheduleAllNodes) {
-        this(scheduleAllNodes, new BlockFactory());
-    }
-
-    public IdentifyBlocksPhase(boolean scheduleAllNodes, BlockFactory blockFactory) {
-        super(scheduleAllNodes ? "FullSchedule" : "PartSchedule");
-        this.blockFactory = blockFactory;
-        this.scheduleAllNodes = scheduleAllNodes;
-    }
-
-    public void calculateAlwaysReachedBlock() {
-        for (Block b : blocks) {
-            calculateAlwaysReachedBlock(b);
-        }
-    }
-
-
-    private void calculateAlwaysReachedBlock(Block b) {
-        if (b.getSuccessors().size() == 1) {
-            b.setAlwaysReachedBlock(b.getSuccessors().get(0));
-        } else if (b.getSuccessors().size() > 1) {
-            BitMap blockBitMap = new BitMap(blocks.size());
-            List<Block> visitedBlocks = new ArrayList<>();
-
-            // Do a fill starting at the dominated blocks and going upwards over predecessors.
-            for (Block dominated : b.getDominated()) {
-                for (Block pred : dominated.getPredecessors()) {
-                    blockFill(blockBitMap, pred, b, visitedBlocks);
-                }
-            }
-
-            boolean ok = true;
-
-            // Find out if there is exactly 1 dominated block that is left unmarked (this is the potential merge block that is always reached).
-            Block unmarkedDominated = null;
-            for (Block dominated : b.getDominated()) {
-                if (!blockBitMap.get(dominated.blockID())) {
-                    if (unmarkedDominated != null) {
-                        ok = false;
-                        break;
-                    }
-                    unmarkedDominated = dominated;
-                }
-            }
-
-            if (ok) {
-                // Check that there is no exit possible except for exception edges.
-                for (Block visitedBlock : visitedBlocks) {
-                    assert blockBitMap.get(visitedBlock.blockID());
-                    for (Block succ : visitedBlock.getSuccessors()) {
-                        if (succ != unmarkedDominated && !succ.isExceptionBlock() && !blockBitMap.get(succ.blockID())) {
-                            ok = false;
-                            break;
-                        }
-                    }
-
-                    if (!ok) {
-                        break;
-                    }
-                }
-            }
-
-            if (ok) {
-                assert unmarkedDominated != null;
-                b.setAlwaysReachedBlock(unmarkedDominated);
-            }
-        }
-    }
-
-    private void blockFill(BitMap blockBitMap, Block cur, Block stop, List<Block> visitedBlocks) {
-        if (blockBitMap.get(cur.blockID())) {
-            return;
-        }
-
-        blockBitMap.set(cur.blockID());
-        visitedBlocks.add(cur);
-
-        if (cur != stop) {
-            for (Block pred : cur.getPredecessors()) {
-                blockFill(blockBitMap, pred, stop, visitedBlocks);
-            }
-        }
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        nodeToBlock = graph.createNodeMap();
-        earliestCache = graph.createNodeMap();
-        identifyBlocks(graph);
-    }
-
-    public Block getStartBlock() {
-        return startBlock;
-    }
-
-    public List<Block> getBlocks() {
-        return Collections.unmodifiableList(blocks);
-    }
-
-    public NodeMap<Block> getNodeToBlock() {
-        return nodeToBlock;
-    }
-
-    private Block createBlock() {
-        Block b = blockFactory.createBlock(blocks.size());
-        blocks.add(b);
-        return b;
-    }
-
-    public int loopCount() {
-        return loopCount;
-    }
-
-    private Block assignBlockNew(Node n, Block block, StructuredGraph graph) {
-        Block b = block;
-        if (b == null) {
-            b = createBlock();
-        }
-
-        assert nodeToBlock.get(n) == null;
-        nodeToBlock.set(n, b);
-
-        if (n == graph.start()) {
-            startBlock = b;
-        }
-
-        if (n instanceof MergeNode) {
-            for (Node usage : n.usages()) {
-                if (usage instanceof PhiNode) {
-                    nodeToBlock.set(usage, b);
-                }
-            }
-        }
-        if (n instanceof EndNode) {
-            assert b.end() == null || n == b.end();
-            b.setEnd((EndNode) n);
-        }
-        if (b.lastNode() == null) {
-            b.setFirstNode(n);
-            b.setLastNode(n);
-            b.getInstructions().add(n);
-        } else {
-            b.getInstructions().add(0, n);
-            b.setFirstNode(n);
-        }
-
-        return b;
-    }
-
-    public static boolean isBlockEnd(Node n) {
-        return trueSuccessorCount(n) > 1 || n instanceof ReturnNode || n instanceof UnwindNode || n instanceof DeoptimizeNode;
-    }
-
-    private void identifyBlocks(StructuredGraph graph) {
-
-        // Identify blocks.
-        for (Node n : graph.getNodes()) {
-            if (n instanceof EndNode || n instanceof ReturnNode || n instanceof UnwindNode || n instanceof LoopEndNode || n instanceof DeoptimizeNode) {
-                Block block = null;
-                Node currentNode = n;
-                Node prev = null;
-                while (nodeToBlock.get(currentNode) == null) {
-                    block = assignBlockNew(currentNode, block, graph);
-                    if (currentNode instanceof FixedNode) {
-                        block.setProbability(((FixedNode) currentNode).probability());
-                    }
-                    if (currentNode.predecessor() == null) {
-                        // At a merge node => stop iteration.
-                        assert currentNode instanceof MergeNode || currentNode == ((StructuredGraph) currentNode.graph()).start() : currentNode;
-                        break;
-                    }
-                    if (block != null && currentNode instanceof BeginNode) {
-                        // We are at a split node => start a new block.
-                        block = null;
-                    }
-                    prev = currentNode;
-                    currentNode = currentNode.predecessor();
-                    // FIX(ls) what's the meaning of this assert?
-//                    assert !(currentNode instanceof AccessNode && ((AccessNode) currentNode).next() != prev) : currentNode;
-                    assert !currentNode.isDeleted() : prev + " " + currentNode;
-                }
-            }
-        }
-
-        // Connect blocks.
-        for (Block block : blocks) {
-            Node n = block.firstNode();
-            if (n instanceof MergeNode) {
-                MergeNode m = (MergeNode) n;
-                for (Node pred : m.cfgPredecessors()) {
-                    Block predBlock = nodeToBlock.get(pred);
-                    predBlock.addSuccessor(block);
-                }
-            } else {
-                if (n.predecessor() != null) {
-                    if (Util.isFixed(n.predecessor())) {
-                        Block predBlock = nodeToBlock.get(n.predecessor());
-                        predBlock.addSuccessor(block);
-                    }
-                }
-            }
-        }
-
-        computeDominators(graph);
-
-        if (scheduleAllNodes) {
-            computeLoopInformation(); // Will make the graph cyclic.
-            assignBlockToNodes(graph);
-            sortNodesWithinBlocks(graph);
-        }
-    }
-
-    private void computeLoopInformation() {
-        // Add successors of loop end nodes. Makes the graph cyclic.
-        for (Block block : blocks) {
-            Node n = block.lastNode();
-            if (n instanceof LoopEndNode) {
-                LoopEndNode loopEnd = (LoopEndNode) n;
-                assert loopEnd.loopBegin() != null;
-                Block loopBeginBlock = nodeToBlock.get(loopEnd.loopBegin());
-                block.addSuccessor(loopBeginBlock);
-                BitMap map = new BitMap(blocks.size());
-                loopBeginBlock.loopBlocks = new ArrayList<>();
-                markBlocks(block, loopBeginBlock, map, loopCount++, block.loopDepth());
-                assert loopBeginBlock.loopDepth() == block.loopDepth() && loopBeginBlock.loopIndex() == block.loopIndex();
-            }
-        }
-    }
-
-    private void markBlocks(Block block, Block loopBeginBlock, BitMap map, int loopIndex, int initialDepth) {
-        if (map.get(block.blockID())) {
-            return;
-        }
-
-        map.set(block.blockID());
-        loopBeginBlock.loopBlocks.add(block);
-        if (block.loopDepth() <= initialDepth) {
-            assert block.loopDepth() == initialDepth;
-            block.setLoopIndex(loopIndex);
-        }
-        block.setLoopDepth(block.loopDepth() + 1);
-
-        if (block == loopBeginBlock) {
-            return;
-        }
-
-        for (Block pred : block.getPredecessors()) {
-            markBlocks(pred, loopBeginBlock, map, loopIndex, initialDepth);
-        }
-
-        if (block.isLoopHeader()) {
-            markBlocks(nodeToBlock.get(((LoopBeginNode) block.firstNode()).loopEnd()), loopBeginBlock, map, loopIndex, initialDepth);
-        }
-    }
-
-    private void assignBlockToNodes(StructuredGraph graph) {
-        for (Node n : graph.getNodes()) {
-            assignBlockToNode(n);
-        }
-    }
-
-    public void assignBlockToNode(Node n) {
-        if (n == null) {
-            return;
-        }
-
-        assert !n.isDeleted();
-
-        Block prevBlock = nodeToBlock.get(n);
-        if (prevBlock != null) {
-            return;
-        }
-        assert !(n instanceof PhiNode) : n;
-        // if in CFG, schedule at the latest position possible in the outermost loop possible
-        Block latestBlock = latestBlock(n);
-        Block block;
-        if (latestBlock == null) {
-            block = earliestBlock(n);
-        } else if (GraalOptions.ScheduleOutOfLoops && !(n instanceof VirtualObjectFieldNode) && !(n instanceof VirtualObjectNode)) {
-            Block earliestBlock = earliestBlock(n);
-            block = scheduleOutOfLoops(n, latestBlock, earliestBlock);
-        } else {
-            block = latestBlock;
-        }
-        assert !(n instanceof MergeNode);
-        nodeToBlock.set(n, block);
-        block.getInstructions().add(n);
-    }
-
-    private Block latestBlock(Node n) {
-        Block block = null;
-        for (Node succ : n.successors()) {
-            if (succ == null) {
-                continue;
-            }
-            assignBlockToNode(succ);
-            block = getCommonDominator(block, nodeToBlock.get(succ));
-        }
-        ensureScheduledUsages(n);
-        CommonDominatorBlockClosure cdbc = new CommonDominatorBlockClosure(block);
-        for (Node usage : n.usages()) {
-            blocksForUsage(n, usage, cdbc);
-        }
-        return cdbc.block;
-    }
-
-    private class CommonDominatorBlockClosure implements BlockClosure {
-        public Block block;
-        public CommonDominatorBlockClosure(Block block) {
-            this.block = block;
-        }
-        @Override
-        public void apply(Block newBlock) {
-            this.block = getCommonDominator(this.block, newBlock);
-        }
-    }
-
-    private Block earliestBlock(Node n) {
-        Block earliest = nodeToBlock.get(n);
-        if (earliest != null) {
-            return earliest;
-        }
-        earliest = earliestCache.get(n);
-        if (earliest != null) {
-            return earliest;
-        }
-        BitMap bits = new BitMap(blocks.size());
-        ArrayList<Node> before = new ArrayList<>();
-        if (n.predecessor() != null) {
-            before.add(n.predecessor());
-        }
-        for (Node input : n.inputs()) {
-            before.add(input);
-        }
-        for (Node pred : before) {
-            if (pred == null) {
-                continue;
-            }
-            Block b = earliestBlock(pred);
-            if (!bits.get(b.blockID())) {
-                earliest = b;
-                do {
-                    bits.set(b.blockID());
-                    b = b.dominator();
-                } while(b != null && !bits.get(b.blockID()));
-            }
-        }
-        if (earliest == null) {
-            Block start = nodeToBlock.get(((StructuredGraph) n.graph()).start());
-            assert start != null;
-            return start;
-        }
-        earliestCache.set(n, earliest);
-        return earliest;
-    }
-
-
-    private static Block scheduleOutOfLoops(Node n, Block latestBlock, Block earliest) {
-        assert latestBlock != null : "no latest : " + n;
-        Block cur = latestBlock;
-        Block result = latestBlock;
-        while (cur.loopDepth() != 0 && cur != earliest && cur.dominator() != null) {
-            Block dom = cur.dominator();
-            if (dom.loopDepth() < result.loopDepth()) {
-                result = dom;
-            }
-            cur = dom;
-        }
-        return result;
-    }
-
-    private void blocksForUsage(Node node, Node usage, BlockClosure closure) {
-        if (usage instanceof PhiNode) {
-            PhiNode phi = (PhiNode) usage;
-            MergeNode merge = phi.merge();
-            Block mergeBlock = nodeToBlock.get(merge);
-            assert mergeBlock != null : "no block for merge " + merge.toString(Verbosity.Id);
-            for (int i = 0; i < phi.valueCount(); ++i) {
-                if (phi.valueAt(i) == node) {
-                    if (mergeBlock.getPredecessors().size() <= i) {
-                        TTY.println(merge.toString());
-                        TTY.println(phi.toString());
-                        TTY.println(merge.cfgPredecessors().toString());
-                        TTY.println(phi.inputs().toString());
-                        TTY.println("value count: " + phi.valueCount());
-                    }
-                closure.apply(mergeBlock.getPredecessors().get(i));
-                }
-            }
-        } else if (usage instanceof FrameState && ((FrameState) usage).block() != null) {
-            MergeNode merge = ((FrameState) usage).block();
-            Block block = null;
-            for (Node pred : merge.cfgPredecessors()) {
-                block = getCommonDominator(block, nodeToBlock.get(pred));
-            }
-            closure.apply(block);
-        } else {
-            assignBlockToNode(usage);
-            closure.apply(nodeToBlock.get(usage));
-        }
-    }
-
-    private void ensureScheduledUsages(Node node) {
-        for (Node usage : node.usages().snapshot()) {
-            assignBlockToNode(usage);
-        }
-        // now true usages are ready
-    }
-
-    private Block getCommonDominator(Block a, Block b) {
-        if (a == null) {
-            return b;
-        }
-        if (b == null) {
-            return a;
-        }
-        return commonDominator(a, b);
-    }
-
-    private void sortNodesWithinBlocks(StructuredGraph graph) {
-        NodeBitMap map = graph.createNodeBitMap();
-        for (Block b : blocks) {
-            sortNodesWithinBlocks(b, map);
-        }
-    }
-
-    private void sortNodesWithinBlocks(Block b, NodeBitMap map) {
-        List<Node> instructions = b.getInstructions();
-        List<Node> sortedInstructions = new ArrayList<>(instructions.size() + 2);
-
-        assert !map.isMarked(b.firstNode()) && nodeToBlock.get(b.firstNode()) == b;
-        assert !map.isMarked(b.lastNode()) && nodeToBlock.get(b.lastNode()) == b;
-
-        for (Node i : instructions) {
-            addToSorting(b, i, sortedInstructions, map);
-        }
-
-        // Make sure that last node gets really last (i.e. when a frame state successor hangs off it).
-        Node lastSorted = sortedInstructions.get(sortedInstructions.size() - 1);
-        if (lastSorted != b.lastNode()) {
-            int idx = sortedInstructions.indexOf(b.lastNode());
-            boolean canNotMove = false;
-            for (int i = idx + 1; i < sortedInstructions.size(); i++) {
-                if (sortedInstructions.get(i).inputs().contains(b.lastNode())) {
-                    canNotMove = true;
-                    break;
-                }
-            }
-            if (canNotMove) {
-                // (cwi) this was the assertion commented out below.  However, it is failing frequently when the
-                // scheduler is used for debug printing in early compiler phases. This was annoying during debugging
-                // when an excpetion breakpoint is set for assertion errors, so I changed it to a bailout.
-                if (b.lastNode() instanceof ControlSplitNode) {
-                    throw new CiBailout("");
-                }
-                //assert !(b.lastNode() instanceof ControlSplitNode);
-
-                //b.setLastNode(lastSorted);
-            } else {
-                sortedInstructions.remove(b.lastNode());
-                sortedInstructions.add(b.lastNode());
-            }
-        }
-        b.setInstructions(sortedInstructions);
-    }
-
-    private void addToSorting(Block b, Node i, List<Node> sortedInstructions, NodeBitMap map) {
-        if (i == null || map.isMarked(i) || nodeToBlock.get(i) != b || i instanceof PhiNode || i instanceof LocalNode) {
-            return;
-        }
-
-        if (i instanceof WriteNode) {
-            // TODO(tw): Make sure every ReadNode that is connected to the same memory state is executed before every write node.
-            // WriteNode wn = (WriteNode) i;
-        }
-
-        FrameState state = null;
-        WriteNode writeNode = null;
-        for (Node input : i.inputs()) {
-            if (input instanceof WriteNode && !map.isMarked(input) && nodeToBlock.get(input) == b) {
-                writeNode = (WriteNode) input;
-            } else if (input instanceof FrameState) {
-                state = (FrameState) input;
-            } else {
-                addToSorting(b, input, sortedInstructions, map);
-            }
-        }
-
-        if (i.predecessor() != null) {
-            addToSorting(b, i.predecessor(), sortedInstructions, map);
-        }
-
-        map.mark(i);
-
-        addToSorting(b, state, sortedInstructions, map);
-        assert writeNode == null || !map.isMarked(writeNode);
-        addToSorting(b, writeNode, sortedInstructions, map);
-
-        // Now predecessors and inputs are scheduled => we can add this node.
-        sortedInstructions.add(i);
-    }
-
-    private void computeDominators(StructuredGraph graph) {
-        Block dominatorRoot = nodeToBlock.get(graph.start());
-        assert dominatorRoot != null;
-        assert dominatorRoot.getPredecessors().size() == 0;
-        BitMap visited = new BitMap(blocks.size());
-        visited.set(dominatorRoot.blockID());
-        LinkedList<Block> workList = new LinkedList<>();
-        workList.add(dominatorRoot);
-
-        int cnt = 0;
-        while (!workList.isEmpty()) {
-            if (cnt++ > blocks.size() * 20) {
-                throw new RuntimeException("(ls) endless loop in computeDominators?");
-            }
-            Block b = workList.remove();
-
-            List<Block> predecessors = b.getPredecessors();
-            if (predecessors.size() == 1) {
-                b.setDominator(predecessors.get(0));
-            } else if (predecessors.size() > 1) {
-                boolean delay = false;
-                for (Block pred : predecessors) {
-                    if (pred != dominatorRoot && pred.dominator() == null) {
-                        delay = true;
-                        break;
-                    }
-                }
-
-                if (delay) {
-                    workList.add(b);
-                    continue;
-                }
-
-                Block dominator = null;
-                for (Block pred : predecessors) {
-                    if (dominator == null) {
-                        dominator = pred;
-                    } else {
-                        dominator = commonDominator(dominator, pred);
-                    }
-                }
-                b.setDominator(dominator);
-            }
-
-            for (Block succ : b.getSuccessors()) {
-                if (!visited.get(succ.blockID())) {
-                    visited.set(succ.blockID());
-                    workList.add(succ);
-                }
-            }
-        }
-    }
-
-    public Block commonDominator(Block a, Block b) {
-        BitMap bitMap = new BitMap(blocks.size());
-        Block cur = a;
-        while (cur != null) {
-            bitMap.set(cur.blockID());
-            cur = cur.dominator();
-        }
-
-        cur = b;
-        while (cur != null) {
-            if (bitMap.get(cur.blockID())) {
-                return cur;
-            }
-            cur = cur.dominator();
-        }
-
-        throw new IllegalStateException("no common dominator between " + a + " and " + b);
-    }
-
-    public static int trueSuccessorCount(Node n) {
-        if (n == null) {
-            return 0;
-        }
-        int i = 0;
-        for (Node s : n.successors()) {
-            if (Util.isFixed(s)) {
-                i++;
-            }
-        }
-        return i;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/SchedulePhase.java	Sun Feb 05 05:40:36 2012 +0100
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.schedule;
+
+import java.util.*;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.criutils.*;
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.cfg.*;
+import com.oracle.max.graal.compiler.phases.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.Node.Verbosity;
+import com.oracle.max.graal.nodes.*;
+import com.oracle.max.graal.nodes.extended.*;
+import com.oracle.max.graal.nodes.virtual.*;
+
+public class SchedulePhase extends Phase {
+    private ControlFlowGraph cfg;
+    private NodeMap<Block> earliestCache;
+
+    private BlockMap<List<Node>> nodesFor;
+
+    public SchedulePhase() {
+        super("Schedule");
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        cfg = ControlFlowGraph.compute(graph, true, true, true, false);
+        earliestCache = graph.createNodeMap();
+        nodesFor = new BlockMap<>(cfg);
+
+        assignBlockToNodes(graph);
+        sortNodesWithinBlocks(graph);
+    }
+
+    public ControlFlowGraph getCFG() {
+        return cfg;
+    }
+
+    public BlockMap<List<Node>> getNodesFor() {
+        return nodesFor;
+    }
+
+    public List<Node> nodesFor(Block block) {
+        return nodesFor.get(block);
+    }
+
+    private void assignBlockToNodes(StructuredGraph graph) {
+        for (Block block : cfg.getBlocks()) {
+            List<Node> nodes = new ArrayList<>();
+            assert nodesFor.get(block) == null;
+            nodesFor.put(block, nodes);
+            for (Node node : block.getNodes()) {
+                nodes.add(node);
+            }
+        }
+
+        for (Node n : graph.getNodes()) {
+            assignBlockToNode(n);
+        }
+    }
+
+    private void assignBlockToNode(Node n) {
+        if (n == null) {
+            return;
+        }
+
+        assert !n.isDeleted();
+
+        Block prevBlock = cfg.getNodeToBlock().get(n);
+        if (prevBlock != null) {
+            return;
+        }
+        assert !(n instanceof PhiNode) : n;
+        // if in CFG, schedule at the latest position possible in the outermost loop possible
+        Block latestBlock = latestBlock(n);
+        Block block;
+        if (latestBlock == null) {
+            block = earliestBlock(n);
+        } else if (GraalOptions.ScheduleOutOfLoops && !(n instanceof VirtualObjectFieldNode) && !(n instanceof VirtualObjectNode)) {
+            Block earliestBlock = earliestBlock(n);
+            block = scheduleOutOfLoops(n, latestBlock, earliestBlock);
+        } else {
+            block = latestBlock;
+        }
+        assert !(n instanceof MergeNode);
+        cfg.getNodeToBlock().set(n, block);
+        nodesFor.get(block).add(n);
+    }
+
+    private Block latestBlock(Node n) {
+        Block block = null;
+        for (Node succ : n.successors()) {
+            if (succ == null) {
+                continue;
+            }
+            assignBlockToNode(succ);
+            block = getCommonDominator(block, cfg.getNodeToBlock().get(succ));
+        }
+        ensureScheduledUsages(n);
+        CommonDominatorBlockClosure cdbc = new CommonDominatorBlockClosure(block);
+        for (Node usage : n.usages()) {
+            blocksForUsage(n, usage, cdbc);
+        }
+        return cdbc.block;
+    }
+
+    private class CommonDominatorBlockClosure implements BlockClosure {
+        public Block block;
+        public CommonDominatorBlockClosure(Block block) {
+            this.block = block;
+        }
+        @Override
+        public void apply(Block newBlock) {
+            this.block = getCommonDominator(this.block, newBlock);
+        }
+    }
+
+    private Block earliestBlock(Node n) {
+        Block earliest = cfg.getNodeToBlock().get(n);
+        if (earliest != null) {
+            return earliest;
+        }
+        earliest = earliestCache.get(n);
+        if (earliest != null) {
+            return earliest;
+        }
+        BitMap bits = new BitMap(cfg.getBlocks().length);
+        ArrayList<Node> before = new ArrayList<>();
+        if (n.predecessor() != null) {
+            before.add(n.predecessor());
+        }
+        for (Node input : n.inputs()) {
+            before.add(input);
+        }
+        for (Node pred : before) {
+            if (pred == null) {
+                continue;
+            }
+            Block b = earliestBlock(pred);
+            if (!bits.get(b.getId())) {
+                earliest = b;
+                do {
+                    bits.set(b.getId());
+                    b = b.getDominator();
+                } while(b != null && !bits.get(b.getId()));
+            }
+        }
+        if (earliest == null) {
+            Block start = cfg.getNodeToBlock().get(((StructuredGraph) n.graph()).start());
+            assert start != null;
+            return start;
+        }
+        earliestCache.set(n, earliest);
+        return earliest;
+    }
+
+
+    private static Block scheduleOutOfLoops(Node n, Block latestBlock, Block earliest) {
+        assert latestBlock != null : "no latest : " + n;
+        Block cur = latestBlock;
+        Block result = latestBlock;
+        while (cur.getLoop() != null && cur != earliest && cur.getDominator() != null) {
+            Block dom = cur.getDominator();
+            if (dom.getLoopDepth() < result.getLoopDepth()) {
+                result = dom;
+            }
+            cur = dom;
+        }
+        return result;
+    }
+
+    private void blocksForUsage(Node node, Node usage, BlockClosure closure) {
+        if (usage instanceof PhiNode) {
+            PhiNode phi = (PhiNode) usage;
+            MergeNode merge = phi.merge();
+            Block mergeBlock = cfg.getNodeToBlock().get(merge);
+            assert mergeBlock != null : "no block for merge " + merge.toString(Verbosity.Id);
+            for (int i = 0; i < phi.valueCount(); ++i) {
+                if (phi.valueAt(i) == node) {
+                    if (mergeBlock.getPredecessors().size() <= i) {
+                        TTY.println(merge.toString());
+                        TTY.println(phi.toString());
+                        TTY.println(merge.cfgPredecessors().toString());
+                        TTY.println(phi.inputs().toString());
+                        TTY.println("value count: " + phi.valueCount());
+                    }
+                closure.apply(mergeBlock.getPredecessors().get(i));
+                }
+            }
+        } else if (usage instanceof FrameState && ((FrameState) usage).block() != null) {
+            MergeNode merge = ((FrameState) usage).block();
+            Block block = null;
+            for (Node pred : merge.cfgPredecessors()) {
+                block = getCommonDominator(block, cfg.getNodeToBlock().get(pred));
+            }
+            closure.apply(block);
+        } else {
+            assignBlockToNode(usage);
+            closure.apply(cfg.getNodeToBlock().get(usage));
+        }
+    }
+
+    private void ensureScheduledUsages(Node node) {
+        for (Node usage : node.usages().snapshot()) {
+            assignBlockToNode(usage);
+        }
+        // now true usages are ready
+    }
+
+    private static Block getCommonDominator(Block a, Block b) {
+        if (a == null) {
+            return b;
+        }
+        if (b == null) {
+            return a;
+        }
+        return ControlFlowGraph.commonDominator(a, b);
+    }
+
+    private void sortNodesWithinBlocks(StructuredGraph graph) {
+        NodeBitMap map = graph.createNodeBitMap();
+        for (Block b : cfg.getBlocks()) {
+            sortNodesWithinBlocks(b, map);
+        }
+    }
+
+    private void sortNodesWithinBlocks(Block b, NodeBitMap map) {
+        List<Node> instructions = nodesFor.get(b);
+        List<Node> sortedInstructions = new ArrayList<>(instructions.size() + 2);
+
+        assert !map.isMarked(b.getBeginNode()) && cfg.blockFor(b.getBeginNode()) == b;
+        assert !map.isMarked(b.getEndNode()) && cfg.blockFor(b.getEndNode()) == b;
+
+        for (Node i : instructions) {
+            addToSorting(b, i, sortedInstructions, map);
+        }
+
+        // Make sure that last node gets really last (i.e. when a frame state successor hangs off it).
+        Node lastSorted = sortedInstructions.get(sortedInstructions.size() - 1);
+        if (lastSorted != b.getEndNode()) {
+            int idx = sortedInstructions.indexOf(b.getEndNode());
+            boolean canNotMove = false;
+            for (int i = idx + 1; i < sortedInstructions.size(); i++) {
+                if (sortedInstructions.get(i).inputs().contains(b.getEndNode())) {
+                    canNotMove = true;
+                    break;
+                }
+            }
+            if (canNotMove) {
+                // (cwi) this was the assertion commented out below.  However, it is failing frequently when the
+                // scheduler is used for debug printing in early compiler phases. This was annoying during debugging
+                // when an excpetion breakpoint is set for assertion errors, so I changed it to a bailout.
+                if (b.getEndNode() instanceof ControlSplitNode) {
+                    throw new CiBailout("");
+                }
+                //assert !(b.lastNode() instanceof ControlSplitNode);
+
+                //b.setLastNode(lastSorted);
+            } else {
+                sortedInstructions.remove(b.getEndNode());
+                sortedInstructions.add(b.getEndNode());
+            }
+        }
+        nodesFor.put(b, sortedInstructions);
+    }
+
+    private void addToSorting(Block b, Node i, List<Node> sortedInstructions, NodeBitMap map) {
+        if (i == null || map.isMarked(i) || cfg.getNodeToBlock().get(i) != b || i instanceof PhiNode || i instanceof LocalNode) {
+            return;
+        }
+
+        if (i instanceof WriteNode) {
+            // TODO(tw): Make sure every ReadNode that is connected to the same memory state is executed before every write node.
+            // WriteNode wn = (WriteNode) i;
+        }
+
+        FrameState state = null;
+        WriteNode writeNode = null;
+        for (Node input : i.inputs()) {
+            if (input instanceof WriteNode && !map.isMarked(input) && cfg.getNodeToBlock().get(input) == b) {
+                writeNode = (WriteNode) input;
+            } else if (input instanceof FrameState) {
+                state = (FrameState) input;
+            } else {
+                addToSorting(b, input, sortedInstructions, map);
+            }
+        }
+
+        if (i.predecessor() != null) {
+            addToSorting(b, i.predecessor(), sortedInstructions, map);
+        }
+
+        map.mark(i);
+
+        addToSorting(b, state, sortedInstructions, map);
+        assert writeNode == null || !map.isMarked(writeNode);
+        addToSorting(b, writeNode, sortedInstructions, map);
+
+        // Now predecessors and inputs are scheduled => we can add this node.
+        sortedInstructions.add(i);
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ControlFlow.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ControlFlow.java	Sun Feb 05 05:40:36 2012 +0100
@@ -66,6 +66,11 @@
         protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
             throw Util.shouldNotReachHere();
         }
+
+        @Override
+        public Label getLabel() {
+            return label;
+        }
     }
 
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/InliningUtil.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/InliningUtil.java	Sun Feb 05 05:40:36 2012 +0100
@@ -371,7 +371,7 @@
             InvokeWithExceptionNode invokeWithException = ((InvokeWithExceptionNode) invoke);
             if (unwindNode != null) {
                 assert unwindNode.predecessor() != null;
-                assert invokeWithException.exceptionEdge().successors().explicitCount() == 1;
+                assert invokeWithException.exceptionEdge().successors().count() == 1;
                 ExceptionObjectNode obj = (ExceptionObjectNode) invokeWithException.exceptionEdge().next();
                 stateAtExceptionEdge = obj.stateAfter();
                 UnwindNode unwindDuplicate = (UnwindNode) duplicates.get(unwindNode);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/NodeIterators.java	Sun Feb 05 05:37:52 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.util;
-
-import java.util.*;
-
-import com.oracle.max.graal.graph.iterators.*;
-import com.oracle.max.graal.nodes.*;
-import com.oracle.max.graal.util.*;
-
-public class NodeIterators {
-
-    public static NodeIterable<FixedNode> dominators(final FixedNode n) {
-        return new NodeIterable<FixedNode>() {
-            @Override
-            public Iterator<FixedNode> iterator() {
-                return new NodeIterator<FixedNode>(until){
-                    FixedNode p = n;
-                    @Override
-                    protected void forward() {
-                        if (current == null) {
-                            if (p instanceof MergeNode) {
-                                current = new ComputeImmediateDominator((MergeNode) p).compute();
-                            } else {
-                                current = (FixedNode) p.predecessor();
-                            }
-                            p = current;
-                        }
-                    }
-                };
-            }
-        };
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/Util.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/Util.java	Sun Feb 05 05:40:36 2012 +0100
@@ -22,9 +22,11 @@
  */
 package com.oracle.max.graal.compiler.util;
 
+import java.lang.reflect.*;
 import java.util.*;
 
 import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
 import com.oracle.max.criutils.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
@@ -371,4 +373,8 @@
     public static boolean isFloating(Node n) {
         return n instanceof FloatingNode;
     }
+
+    public static boolean isFinalClass(RiResolvedType type) {
+        return Modifier.isFinal(type.accessFlags()) || (type.isArrayClass() && Modifier.isFinal(type.componentType().accessFlags()));
+    }
 }
--- a/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/Debug.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/Debug.java	Sun Feb 05 05:40:36 2012 +0100
@@ -144,7 +144,7 @@
         }
     }
 
-    public static DebugConfig fixedConfig(final boolean isLogEnabled, final boolean isDumpEnabled, final boolean isMeterEnabled, final boolean isTimerEnabled) {
+    public static DebugConfig fixedConfig(final boolean isLogEnabled, final boolean isDumpEnabled, final boolean isMeterEnabled, final boolean isTimerEnabled, final List<DebugDumpHandler> dumpHandlers) {
         return new DebugConfig() {
 
             @Override
@@ -174,7 +174,7 @@
 
             @Override
             public Collection< ? extends DebugDumpHandler> dumpHandlers() {
-                return Collections.emptyList();
+                return dumpHandlers;
             }
         };
     }
--- a/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/internal/DebugScope.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/internal/DebugScope.java	Sun Feb 05 05:40:36 2012 +0100
@@ -136,7 +136,6 @@
 
     private <T> T executeScope(Runnable runnable, Callable<T> callable) {
         try {
-            instanceTL.get().log("Starting scope %s", instanceTL.get().getQualifiedName());
             if (runnable != null) {
                 runnable.run();
             }
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Graph.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Graph.java	Sun Feb 05 05:40:36 2012 +0100
@@ -265,9 +265,9 @@
      * Returns an {@link Iterable} providing all nodes added since the last {@link Graph#mark() mark}.
      * @return an {@link Iterable} providing the new nodes
      */
-    public Iterable<Node> getNewNodes() {
+    public NodeIterable<Node> getNewNodes() {
         final int index = this.mark;
-        return new Iterable<Node>() {
+        return new NodeIterable<Node>() {
             @Override
             public Iterator<Node> iterator() {
                 return new NodeIterator(index);
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Node.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Node.java	Sun Feb 05 05:40:36 2012 +0100
@@ -496,11 +496,11 @@
     @Override
     public void formatTo(Formatter formatter, int flags, int width, int precision) {
         if ((flags & FormattableFlags.ALTERNATE) == FormattableFlags.ALTERNATE) {
-            formatter.format(toString(Verbosity.Id));
+            formatter.format("%s", toString(Verbosity.Id));
         } else if ((flags & FormattableFlags.UPPERCASE) == FormattableFlags.UPPERCASE) {
-            formatter.format(toString(Verbosity.Long));
+            formatter.format("%s", toString(Verbosity.Long));
         } else {
-            formatter.format(toString(Verbosity.Short));
+            formatter.format("%s", toString(Verbosity.Short));
         }
 
         boolean neighborsAlternate = ((flags & FormattableFlags.LEFT_JUSTIFY) == FormattableFlags.LEFT_JUSTIFY);
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeInputList.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeInputList.java	Sun Feb 05 05:40:36 2012 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.max.graal.graph;
 
+import java.util.*;
+
 
 public final class NodeInputList<T extends Node> extends NodeList<T> {
 
@@ -42,6 +44,12 @@
         this.self = self;
     }
 
+    public NodeInputList(Node self, List<? extends T> elements) {
+        super(elements);
+        assert self.usages() == null;
+        this.self = self;
+    }
+
     @Override
     protected void update(T oldNode, T newNode) {
         self.updateUsages(oldNode, newNode);
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeInputsIterable.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeInputsIterable.java	Sun Feb 05 05:40:36 2012 +0100
@@ -26,9 +26,6 @@
 import com.oracle.max.graal.graph.iterators.*;
 
 public abstract class NodeInputsIterable extends NodeIterable<Node> {
-
-    public abstract boolean contains(Node node);
-
     @Override
     public abstract NodeClassIterator iterator();
 }
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeList.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeList.java	Sun Feb 05 05:40:36 2012 +0100
@@ -27,7 +27,9 @@
 import java.util.List;
 import java.util.ListIterator;
 
-public abstract class NodeList<T extends Node> implements Iterable<T>, List<T> {
+import com.oracle.max.graal.graph.iterators.*;
+
+public abstract class NodeList<T extends Node> extends NodeIterable<T> implements List<T> {
 
     protected static final Node[] EMPTY_NODE_ARRAY = new Node[0];
 
@@ -62,6 +64,21 @@
         }
     }
 
+    protected NodeList(List<? extends T> elements) {
+        if (elements == null || elements.isEmpty()) {
+            this.size = 0;
+            this.nodes = EMPTY_NODE_ARRAY;
+            this.initialSize = 0;
+        } else {
+            this.size = elements.size();
+            this.initialSize = elements.size();
+            this.nodes = new Node[elements.size()];
+            for (int i = 0; i < elements.size(); i++) {
+                this.nodes[i] = elements.get(i);
+            }
+        }
+    }
+
     protected abstract void update(T oldNode, T newNode);
 
     @Override
@@ -74,6 +91,16 @@
         return size == 0;
     }
 
+    @Override
+    public boolean isNotEmpty() {
+        return size > 0;
+    }
+
+    @Override
+    public int count() {
+        return size;
+    }
+
     protected final void incModCount() {
         modCount++;
     }
@@ -214,6 +241,7 @@
         };
     }
 
+    @Override
     public boolean contains(T other) {
         for (int i = 0; i < size; i++) {
             if (nodes[i] == other) {
@@ -223,33 +251,10 @@
         return false;
     }
 
-    public Iterable<T> snapshot() {
-        return new Iterable<T>() {
-
-            @Override
-            public Iterator<T> iterator() {
-                return new Iterator<T>() {
-                    private Node[] nodesCopy = Arrays.copyOf(NodeList.this.nodes, NodeList.this.size);
-                    private int index = 0;
-
-                    @Override
-                    public boolean hasNext() {
-                        return index < nodesCopy.length;
-                    }
-
-                    @SuppressWarnings("unchecked")
-                    @Override
-                    public T next() {
-                        return (T) nodesCopy[index++];
-                    }
-
-                    @Override
-                    public void remove() {
-                        throw new UnsupportedOperationException();
-                    }
-                };
-            }
-        };
+    @SuppressWarnings("unchecked")
+    @Override
+    public List<T> snapshot() {
+        return (List<T>) Arrays.asList(Arrays.copyOf(this.nodes, this.size));
     }
 
     @SuppressWarnings("unchecked")
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeSuccessorsIterable.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeSuccessorsIterable.java	Sun Feb 05 05:40:36 2012 +0100
@@ -26,17 +26,6 @@
 import com.oracle.max.graal.graph.iterators.*;
 
 public abstract class NodeSuccessorsIterable extends NodeIterable<Node> {
-
-    public int explicitCount() {
-        int count = 0;
-        for (@SuppressWarnings("unused") Node node : this) {
-            count++;
-        }
-        return count;
-    }
-
-    public abstract boolean contains(Node node);
-
     @Override
     public abstract NodeClassIterator iterator();
 }
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeUsagesList.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeUsagesList.java	Sun Feb 05 05:40:36 2012 +0100
@@ -58,6 +58,11 @@
         return size > 0;
     }
 
+    @Override
+    public int count() {
+        return size;
+    }
+
     protected void incModCount() {
         modCount++;
     }
@@ -140,6 +145,7 @@
         };
     }
 
+    @Override
     public boolean contains(Node other) {
         for (int i = 0; i < size; i++) {
             if (nodes[i] == other) {
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/FilteredNodeIterable.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/FilteredNodeIterable.java	Sun Feb 05 05:40:36 2012 +0100
@@ -28,20 +28,10 @@
 
 public class FilteredNodeIterable<T extends Node> extends NodeIterable<T> {
     private final NodeIterable<T> nodeIterable;
-    private NodePredicate predicate = NodePredicate.TAUTOLOGY;
+    private NodePredicate predicate = NodePredicates.alwaysTrue();
+    private NodePredicate until = NodePredicates.isNull();
     public FilteredNodeIterable(NodeIterable<T> nodeIterable) {
         this.nodeIterable = nodeIterable;
-        this.until = nodeIterable.until;
-    }
-    @SuppressWarnings("unchecked")
-    public <F extends T> FilteredNodeIterable<F> and(Class<F> clazz) {
-        this.predicate = predicate.and(new TypePredicate(clazz));
-        return (FilteredNodeIterable<F>) this;
-    }
-    @SuppressWarnings("unchecked")
-    public FilteredNodeIterable<Node> or(Class<? extends Node> clazz) {
-        this.predicate = predicate.or(new TypePredicate(clazz));
-        return (FilteredNodeIterable<Node>) this;
     }
     public FilteredNodeIterable<T> and(NodePredicate nodePredicate) {
         this.predicate = this.predicate.and(nodePredicate);
@@ -52,8 +42,34 @@
         return this;
     }
     @Override
+    public NodeIterable<T> until(final T u) {
+        until = until.or(NodePredicates.equals(u));
+        return this;
+    }
+    @Override
+    public NodeIterable<T> until(final Class<? extends T> clazz) {
+        until = until.or(NodePredicates.isA(clazz));
+        return this;
+    }
+    @Override
     public Iterator<T> iterator() {
         final Iterator<T> iterator = nodeIterable.iterator();
         return new PredicatedProxyNodeIterator<>(until, iterator, predicate);
     }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <F extends T> FilteredNodeIterable<F> filter(Class<F> clazz) {
+        return (FilteredNodeIterable<F>) this.and(NodePredicates.isA(clazz));
+    }
+
+    @Override
+    public FilteredNodeIterable<T> filter(NodePredicate p) {
+        return this.and(p);
+    }
+
+    @Override
+    public FilteredNodeIterable<T> filterInterface(Class< ? > iface) {
+        return this.and(NodePredicates.isAInterface(iface));
+    }
 }
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/NodeIterable.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/NodeIterable.java	Sun Feb 05 05:40:36 2012 +0100
@@ -27,17 +27,18 @@
 import com.oracle.max.graal.graph.*;
 
 public abstract class NodeIterable<T extends Node> implements Iterable<T> {
-    protected NodePredicate until = NodePredicate.IS_NULL;
     public NodeIterable<T> until(final T u) {
-        until = until.or(NodePredicate.equals(u));
-        return this;
+        return new FilteredNodeIterable<>(this).until(u);
     }
     public NodeIterable<T> until(final Class<? extends T> clazz) {
-        until = until.or(new TypePredicate(clazz));
-        return this;
+        return new FilteredNodeIterable<>(this).until(clazz);
     }
+    @SuppressWarnings("unchecked")
     public <F extends T> FilteredNodeIterable<F> filter(Class<F> clazz) {
-        return new FilteredNodeIterable<>(this).and(clazz);
+        return (FilteredNodeIterable<F>) new FilteredNodeIterable<>(this).and(NodePredicates.isA(clazz));
+    }
+    public FilteredNodeIterable<T> filterInterface(Class<?> iface) {
+        return new FilteredNodeIterable<>(this).and(NodePredicates.isAInterface(iface));
     }
     public FilteredNodeIterable<T> filter(NodePredicate predicate) {
         return new FilteredNodeIterable<>(this).and(predicate);
@@ -71,4 +72,7 @@
     public boolean isNotEmpty() {
         return iterator().hasNext();
     }
+    public boolean contains(T node) {
+        return this.filter(NodePredicates.equals(node)).isNotEmpty();
+    }
 }
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/NodeIterator.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/NodeIterator.java	Sun Feb 05 05:40:36 2012 +0100
@@ -28,21 +28,17 @@
 
 public abstract class NodeIterator<T extends Node> implements Iterator<T>{
     protected T current;
-    protected final NodePredicate until;
-    public NodeIterator(NodePredicate until) {
-        this.until = until;
-    }
     protected abstract void forward();
     @Override
     public boolean hasNext() {
         forward();
-        return current != null && !until.apply(current);
+        return current != null;
     }
     @Override
     public T next() {
         forward();
         T ret = current;
-        if (current == null || until.apply(current)) {
+        if (current == null) {
             throw new NoSuchElementException();
         }
         current = null;
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/NodePredicate.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/NodePredicate.java	Sun Feb 05 05:40:36 2012 +0100
@@ -25,78 +25,18 @@
 import com.oracle.max.graal.graph.*;
 
 public abstract class NodePredicate {
-    public static final TautologyPredicate TAUTOLOGY = new TautologyPredicate();
-
-    public static final IsNullPredicate IS_NULL = new IsNullPredicate();
-
-    public static final class TautologyPredicate extends NodePredicate {
-        @Override
-        public boolean apply(Node n) {
-            return true;
-        }
-    }
-
-    public static final class AndPredicate extends NodePredicate {
-        private final NodePredicate a;
-        private final NodePredicate b;
-        private AndPredicate(NodePredicate np, NodePredicate thiz) {
-            this.a = np;
-            this.b = thiz;
-        }
-        @Override
-        public boolean apply(Node n) {
-            return b.apply(n) && a.apply(n);
-        }
-    }
-
-    public static final class OrPredicate extends NodePredicate {
-        private final NodePredicate a;
-        private final NodePredicate b;
-        private OrPredicate(NodePredicate np, NodePredicate thiz) {
-            this.a = np;
-            this.b = thiz;
-        }
-        @Override
-        public boolean apply(Node n) {
-            return b.apply(n) || a.apply(n);
-        }
-    }
-
-    public static final class IsNullPredicate extends NodePredicate {
-        @Override
-        public boolean apply(Node n) {
-            return n == null;
-        }
-    }
-
-    public static final class EqualsPredicate<T extends Node> extends NodePredicate {
-        private final T u;
-        public EqualsPredicate(T u) {
-            this.u = u;
-        }
-        @Override
-        public boolean apply(Node n) {
-            return u == n;
-        }
-    }
 
     public abstract boolean apply(Node n);
 
-    public NodePredicate and(final NodePredicate np) {
-        if (this instanceof TautologyPredicate) {
-            return np;
-        }
-        return new AndPredicate(this, np);
+    public NodePredicate and(NodePredicate np) {
+        return NodePredicates.and(this, np);
     }
 
-    public NodePredicate or(final NodePredicate np) {
-        if (this instanceof TautologyPredicate) {
-            return this;
-        }
-        return new OrPredicate(this, np);
+    public NodePredicate or(NodePredicate np) {
+        return NodePredicates.or(this, np);
     }
 
-    public static <T extends Node> EqualsPredicate<T> equals(T u) {
-        return new EqualsPredicate<>(u);
+    public NodePredicate negate() {
+        return NodePredicates.not(this);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/NodePredicates.java	Sun Feb 05 05:40:36 2012 +0100
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.graph.iterators;
+
+import com.oracle.max.graal.graph.*;
+
+public abstract class NodePredicates {
+    private static final TautologyPredicate TAUTOLOGY = new TautologyPredicate();
+    private static final FalsePredicate FALSE = new FalsePredicate();
+    private static final IsNullPredicate IS_NULL = new IsNullPredicate();
+    private static final IsNotNullPredicate IS_NOT_NULL = new IsNotNullPredicate();
+
+    public static NodePredicate alwaysTrue() {
+        return TAUTOLOGY;
+    }
+
+    public static NodePredicate alwaysFalse() {
+        return FALSE;
+    }
+
+    public static NodePredicate isNull() {
+        return IS_NULL;
+    }
+
+    public static NodePredicate isNotNull() {
+        return IS_NOT_NULL;
+    }
+
+    public static NodePredicate equals(Node n) {
+        return new EqualsPredicate(n);
+    }
+
+    public static NodePredicate not(NodePredicate a) {
+        if (a == TAUTOLOGY) {
+            return FALSE;
+        }
+        if (a == FALSE) {
+            return TAUTOLOGY;
+        }
+        if (a == IS_NULL) {
+            return IS_NOT_NULL;
+        }
+        if (a == IS_NOT_NULL) {
+            return IS_NULL;
+        }
+        if (a instanceof NotPredicate) {
+            return ((NotPredicate) a).a;
+        }
+        if (a instanceof PositiveTypePredicate) {
+            return new NegativeTypePredicate((PositiveTypePredicate) a);
+        }
+        if (a instanceof NegativeTypePredicate) {
+            return new PositiveTypePredicate((NegativeTypePredicate) a);
+        }
+        if (a instanceof EqualsPredicate) {
+            return new NotEqualsPredicate(((EqualsPredicate) a).u);
+        }
+        if (a instanceof NotEqualsPredicate) {
+            return new EqualsPredicate(((NotEqualsPredicate) a).u);
+        }
+        return new NotPredicate(a);
+    }
+
+    public static NodePredicate and(NodePredicate a, NodePredicate b) {
+        if (a == TAUTOLOGY) {
+            return b;
+        }
+        if (b == TAUTOLOGY) {
+            return a;
+        }
+        if (a == FALSE || b == FALSE) {
+            return FALSE;
+        }
+        return new AndPredicate(a, b);
+    }
+
+    public static NodePredicate or(NodePredicate a, NodePredicate b) {
+        if (a == FALSE) {
+            return b;
+        }
+        if (b == FALSE) {
+            return a;
+        }
+        if (a == TAUTOLOGY || b == TAUTOLOGY) {
+            return TAUTOLOGY;
+        }
+        return new OrPredicate(a, b);
+    }
+
+    public static NegativeTypePredicate isNotA(Class<? extends Node> clazz) {
+        return new NegativeTypePredicate(clazz);
+    }
+
+    public static PositiveTypePredicate isA(Class<? extends Node> clazz) {
+        return new PositiveTypePredicate(clazz);
+    }
+
+    public static NodePredicate isAInterface(Class<?> iface) {
+        assert iface.isInterface();
+        return new PositiveTypePredicate(iface);
+    }
+
+    public static NodePredicate isNotAInterface(Class<?> iface) {
+        assert iface.isInterface();
+        return new NegativeTypePredicate(iface);
+    }
+
+    private static final class TautologyPredicate extends NodePredicate {
+        @Override
+        public boolean apply(Node n) {
+            return true;
+        }
+    }
+
+    private static final class FalsePredicate extends NodePredicate {
+        @Override
+        public boolean apply(Node n) {
+            return false;
+        }
+    }
+
+    private static final class AndPredicate extends NodePredicate {
+        private final NodePredicate a;
+        private final NodePredicate b;
+        private AndPredicate(NodePredicate a, NodePredicate b) {
+            this.a = a;
+            this.b = b;
+        }
+        @Override
+        public boolean apply(Node n) {
+            return a.apply(n) && b.apply(n);
+        }
+    }
+
+    private static final class NotPredicate extends NodePredicate {
+        private final NodePredicate a;
+        private NotPredicate(NodePredicate n) {
+            this.a = n;
+        }
+        @Override
+        public boolean apply(Node n) {
+            return !a.apply(n);
+        }
+    }
+
+    private static final class OrPredicate extends NodePredicate {
+        private final NodePredicate a;
+        private final NodePredicate b;
+        private OrPredicate(NodePredicate a, NodePredicate b) {
+            this.a = a;
+            this.b = b;
+        }
+        @Override
+        public boolean apply(Node n) {
+            return a.apply(n) || b.apply(n);
+        }
+    }
+
+    private static final class IsNullPredicate extends NodePredicate {
+        @Override
+        public boolean apply(Node n) {
+            return n == null;
+        }
+    }
+
+    private static final class IsNotNullPredicate extends NodePredicate {
+        @Override
+        public boolean apply(Node n) {
+            return n != null;
+        }
+    }
+
+    private static final class EqualsPredicate extends NodePredicate {
+        private final Node u;
+        public EqualsPredicate(Node u) {
+            this.u = u;
+        }
+        @Override
+        public boolean apply(Node n) {
+            return u == n;
+        }
+    }
+
+    private static final class NotEqualsPredicate extends NodePredicate {
+        private final Node u;
+        public NotEqualsPredicate(Node u) {
+            this.u = u;
+        }
+        @Override
+        public boolean apply(Node n) {
+            return u != n;
+        }
+    }
+
+    public static final class PositiveTypePredicate extends NodePredicate {
+        private final Class<?> type;
+        private PositiveTypePredicate or;
+        public PositiveTypePredicate(Class<?> type) {
+            this.type = type;
+        }
+        public PositiveTypePredicate(NegativeTypePredicate a) {
+            type = a.type;
+            if (a.nor != null) {
+                or = new PositiveTypePredicate(a.nor);
+            }
+        }
+        @Override
+        public boolean apply(Node n) {
+            return type.isInstance(n) || (or != null && or.apply(n));
+        }
+        public PositiveTypePredicate or(Class<? extends Node> clazz) {
+            if (or == null) {
+                or = new PositiveTypePredicate(clazz);
+            } else {
+                or.or(clazz);
+            }
+            return this;
+        }
+    }
+
+    public static final class NegativeTypePredicate extends NodePredicate {
+        private final Class<?> type;
+        private NegativeTypePredicate nor;
+        public NegativeTypePredicate(Class<?> type) {
+            this.type = type;
+        }
+        public NegativeTypePredicate(PositiveTypePredicate a) {
+            type = a.type;
+            if (a.or != null) {
+                nor = new NegativeTypePredicate(a.or);
+            }
+        }
+        @Override
+        public boolean apply(Node n) {
+            return !type.isInstance(n) && (nor == null || nor.apply(n));
+        }
+        public NegativeTypePredicate nor(Class<? extends Node> clazz) {
+            if (nor == null) {
+                nor = new NegativeTypePredicate(clazz);
+            } else {
+                nor.nor(clazz);
+            }
+            return this;
+        }
+    }
+}
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/PredicatedProxyNodeIterator.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/PredicatedProxyNodeIterator.java	Sun Feb 05 05:40:36 2012 +0100
@@ -29,8 +29,9 @@
 public final class PredicatedProxyNodeIterator<T extends Node> extends NodeIterator<T> {
     private final Iterator<T> iterator;
     private final NodePredicate predicate;
+    private final NodePredicate until;
     public PredicatedProxyNodeIterator(NodePredicate until, Iterator<T> iterator, NodePredicate predicate) {
-        super(until);
+        this.until = until;
         this.iterator = iterator;
         this.predicate = predicate;
     }
@@ -39,7 +40,7 @@
         while ((current == null || !current.isAlive() || !predicate.apply(current)) && iterator.hasNext()) {
             current = iterator.next();
         }
-        if (current != null && (!current.isAlive() || !predicate.apply(current))) {
+        if (current != null && (!current.isAlive() || !predicate.apply(current) || until.apply(current))) {
             current = null;
         }
     }
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/TypePredicate.java	Sun Feb 05 05:37:52 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.graph.iterators;
-
-import com.oracle.max.graal.graph.*;
-
-public final class TypePredicate extends NodePredicate {
-    private final Class<? extends Node> type;
-    public TypePredicate(Class< ? extends Node> type) {
-        this.type = type;
-    }
-    @Override
-    public boolean apply(Node n) {
-        return type.isInstance(n);
-    }
-}
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotDebugConfig.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotDebugConfig.java	Sun Feb 05 05:40:36 2012 +0100
@@ -25,6 +25,7 @@
 import java.util.*;
 import java.util.regex.*;
 
+import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.debug.*;
@@ -76,7 +77,6 @@
             filter = filter.replace("[", "\\[");
             filter = filter.replace("]", "\\]");
             filter = filter.replace(":", "\\:");*/
-            System.out.println("regexp: " + filter + " string=" + currentScope + ", " + Pattern.matches(filter, currentScope));
             return Pattern.matches(filter, currentScope);
         }
         return currentScope.contains(filter);
@@ -89,7 +89,7 @@
             for (Object o : Debug.context()) {
                 if (o instanceof RiMethod) {
                     RiMethod riMethod = (RiMethod) o;
-                    if (riMethod.toString().contains(methodFilter)) {
+                    if (CiUtil.format("%H.%n", riMethod).contains(methodFilter)) {
                         return true;
                     }
                 }
@@ -121,7 +121,11 @@
 
     @Override
     public RuntimeException interceptException(RuntimeException e) {
-        Debug.setConfig(Debug.fixedConfig(true, true, false, false));
+        if (e instanceof CiBailout) {
+            return e;
+        }
+        Debug.setConfig(Debug.fixedConfig(true, true, false, false, dumpHandlers));
+        // sync "Exception occured in scope: " with mx/sanitycheck.py::Test.__init__
         Debug.log(String.format("Exception occured in scope: %s", Debug.currentScope()));
         for (Object o : Debug.context()) {
             Debug.log("Context obj %s", o);
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVM.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVM.java	Sun Feb 05 05:40:36 2012 +0100
@@ -31,7 +31,7 @@
 import com.oracle.max.graal.hotspot.ri.*;
 
 /**
- * Entries into the HotSpot VM from Java code.
+ * Calls from Java into HotSpot.
  */
 public interface CompilerToVM {
 
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompiler.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompiler.java	Sun Feb 05 05:40:36 2012 +0100
@@ -28,7 +28,7 @@
 import com.oracle.max.graal.hotspot.ri.*;
 
 /**
- * Exits from the HotSpot VM into Java code.
+ * Calls from HotSpot into Java.
  */
 public interface VMToCompiler {
 
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java	Sun Feb 05 05:40:36 2012 +0100
@@ -39,6 +39,7 @@
 import com.oracle.max.graal.hotspot.Compiler;
 import com.oracle.max.graal.hotspot.ri.*;
 import com.oracle.max.graal.hotspot.server.*;
+import com.oracle.max.graal.hotspot.snippets.*;
 import com.oracle.max.graal.java.*;
 import com.oracle.max.graal.snippets.*;
 
@@ -49,6 +50,7 @@
 
     private final Compiler compiler;
     private int compiledMethodCount;
+    private IntrinsifyArrayCopyPhase intrinsifyArrayCopy;
 
     public final HotSpotTypePrimitive typeBoolean;
     public final HotSpotTypePrimitive typeChar;
@@ -110,9 +112,11 @@
         // Install intrinsics.
         HotSpotRuntime runtime = (HotSpotRuntime) compiler.getCompiler().runtime;
         if (GraalOptions.Intrinsify) {
+            this.intrinsifyArrayCopy = new IntrinsifyArrayCopyPhase(runtime);
             GraalIntrinsics.installIntrinsics(runtime, runtime.getCompiler().getTarget(), PhasePlan.DEFAULT);
             Snippets.install(runtime, runtime.getCompiler().getTarget(), new SystemSnippets(), PhasePlan.DEFAULT);
             Snippets.install(runtime, runtime.getCompiler().getTarget(), new UnsafeSnippets(), PhasePlan.DEFAULT);
+            Snippets.install(runtime, runtime.getCompiler().getTarget(), new ArrayCopySnippets(), PhasePlan.DEFAULT);
         }
 
         // Create compilation queue.
@@ -227,15 +231,27 @@
     @Override
     public void compileMethod(final HotSpotMethodResolved method, final int entryBCI, boolean blocking) throws Throwable {
         try {
-            if (Thread.currentThread() instanceof CompilerThread && method.holder().name().contains("java/util/concurrent")) {
-                return;
+            if (Thread.currentThread() instanceof CompilerThread) {
+                if (method.holder().name().contains("java/util/concurrent")) {
+                    // This is required to avoid deadlocking a compiler thread. The issue is that a
+                    // java.util.concurrent.BlockingQueue is used to implement the compilation worker
+                    // queues. If a compiler thread triggers a compilation, then it may be blocked trying
+                    // to add something to its own queue.
+                    return;
+                }
+            } else {
+                if (GraalOptions.Debug) {
+                    Debug.enable();
+                    HotSpotDebugConfig hotspotDebugConfig = new HotSpotDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter);
+                    Debug.setConfig(hotspotDebugConfig);
+                }
             }
 
             Runnable runnable = new Runnable() {
 
                 public void run() {
                     try {
-                        PhasePlan plan = new PhasePlan();
+                        PhasePlan plan = getDefaultPhasePlan();
                         GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime());
                         plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
                         long startTime = 0;
@@ -372,4 +388,10 @@
     public CiConstant createCiConstantObject(Object object) {
         return CiConstant.forObject(object);
     }
+
+    private PhasePlan getDefaultPhasePlan() {
+        PhasePlan phasePlan = new PhasePlan();
+        phasePlan.addPhase(PhasePosition.HIGH_LEVEL, intrinsifyArrayCopy);
+        return phasePlan;
+    }
 }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/nodes/TailcallNode.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/nodes/TailcallNode.java	Sun Feb 05 05:40:36 2012 +0100
@@ -30,6 +30,7 @@
 import com.oracle.max.graal.compiler.gen.*;
 import com.oracle.max.graal.hotspot.*;
 import com.oracle.max.graal.hotspot.target.amd64.*;
+import com.oracle.max.graal.java.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.spi.*;
 import com.oracle.max.graal.nodes.type.*;
@@ -62,10 +63,10 @@
 
         CiKind[] signature = CiUtil.signatureToKinds(method.signature(), isStatic ? null : method.holder().kind(true));
         CiCallingConvention cc = gen.frameMap().registerConfig.getCallingConvention(CiCallingConvention.Type.JavaCall, signature, gen.target(), false);
-        gen.frameMap().callsMethod(cc, CiCallingConvention.Type.JavaCall);
+        gen.frameMap().callsMethod(cc, CiCallingConvention.Type.JavaCall); // TODO (aw): I think this is unnecessary for a tail call.
         List<ValueNode> parameters = new ArrayList<>();
-        for (int i = 0; i < cc.locations.length; i++) {
-            parameters.add(frameState.localAt(i));
+        for (int i = 0, slot = 0; i < cc.locations.length; i++, slot += FrameStateBuilder.stackSlots(frameState.localAt(slot).kind())) {
+            parameters.add(frameState.localAt(slot));
         }
         List<CiValue> argList = gen.visitInvokeArguments(cc, parameters, null);
 
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotTypeResolvedImpl.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotTypeResolvedImpl.java	Sun Feb 05 05:40:36 2012 +0100
@@ -81,7 +81,11 @@
 
     @Override
     public RiResolvedType uniqueConcreteSubtype() {
-        return (RiResolvedType) compiler.getVMEntries().RiType_uniqueConcreteSubtype(this);
+        if (isArrayClass()) {
+            return Modifier.isFinal(componentType().accessFlags()) ? this : null;
+        } else {
+            return (RiResolvedType) compiler.getVMEntries().RiType_uniqueConcreteSubtype(this);
+        }
     }
 
     @Override
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java	Sun Feb 05 05:40:36 2012 +0100
@@ -637,14 +637,13 @@
         }
     };
 
-    private SimpleTemplates checkCastTemplates = new SimpleTemplates(NULL_CHECK) {
+    private IndexTemplates checkCastTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) {
 
         @Override
-        protected XirTemplate create(CiXirAssembler asm, long flags) {
+        protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) {
             asm.restart(CiKind.Void);
             XirParameter object = asm.createInputParameter("object", CiKind.Object);
-            final XirOperand hub;
-            hub = asm.createConstantInputParameter("hub", CiKind.Object);
+            final XirOperand hub = is(EXACT_HINTS, flags) ? null : asm.createConstantInputParameter("hub", CiKind.Object);
 
             XirOperand objHub = asm.createTemp("objHub", CiKind.Object);
 
@@ -657,15 +656,37 @@
             }
 
             asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false);
-            // if we get an exact match: succeed immediately
-            asm.jneq(slowPath, objHub, hub);
-            asm.bindInline(end);
+            if (hintCount == 0) {
+                assert !is(EXACT_HINTS, flags);
+                checkSubtype(asm, objHub, objHub, hub);
+                asm.jeq(slowPath, objHub, asm.o(null));
+                asm.bindInline(end);
 
-            // -- out of line -------------------------------------------------------
-            asm.bindOutOfLine(slowPath);
-            checkSubtype(asm, objHub, objHub, hub);
-            asm.jneq(end, objHub, asm.o(null));
+                // -- out of line -------------------------------------------------------
+                asm.bindOutOfLine(slowPath);
+            } else {
+                XirOperand scratchObject = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10);
+                // if we get an exact match: succeed immediately
+                for (int i = 0; i < hintCount; i++) {
+                    XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, CiKind.Object);
+                    asm.mov(scratchObject, hintHub);
+                    if (i < hintCount - 1) {
+                        asm.jeq(end, objHub, scratchObject);
+                    } else {
+                        asm.jneq(slowPath, objHub, scratchObject);
+                    }
+                }
+                asm.bindInline(end);
+
+                // -- out of line -------------------------------------------------------
+                asm.bindOutOfLine(slowPath);
+                if (!is(EXACT_HINTS, flags)) {
+                    checkSubtype(asm, objHub, objHub, hub);
+                    asm.jneq(end, objHub, asm.o(null));
+                }
+            }
             XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10);
+
             asm.mov(scratch, wordConst(asm, 2));
 
             asm.callRuntime(CiRuntimeCall.Deoptimize, null);
@@ -675,18 +696,16 @@
         }
     };
 
-    private SimpleTemplates instanceOfTemplates = new SimpleTemplates(NULL_CHECK) {
+    private IndexTemplates instanceOfTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) {
 
         @Override
-        protected XirTemplate create(CiXirAssembler asm, long flags) {
+        protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) {
             asm.restart(CiKind.Void);
             XirParameter object = asm.createInputParameter("object", CiKind.Object);
-            final XirOperand hub;
-            hub = asm.createConstantInputParameter("hub", CiKind.Object);
+            final XirOperand hub = is(EXACT_HINTS, flags) ? null : asm.createConstantInputParameter("hub", CiKind.Object);
 
             XirOperand objHub = asm.createTemp("objHub", CiKind.Object);
 
-            XirLabel slowPath = asm.createOutOfLineLabel("slow path");
             XirLabel trueSucc = asm.createInlineLabel(XirLabel.TrueSuccessor);
             XirLabel falseSucc = asm.createInlineLabel(XirLabel.FalseSuccessor);
 
@@ -696,37 +715,60 @@
             }
 
             asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false);
-            // if we get an exact match: succeed immediately
-            asm.jeq(trueSucc, objHub, hub);
-            asm.jmp(slowPath);
+            if (hintCount == 0) {
+                assert !is(EXACT_HINTS, flags);
+                checkSubtype(asm, objHub, objHub, hub);
+                asm.jeq(falseSucc, objHub, asm.o(null));
+                asm.jmp(trueSucc);
+            } else {
+                XirLabel slowPath = null;
+                XirOperand scratchObject = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10);
 
-            // -- out of line -------------------------------------------------------
-            asm.bindOutOfLine(slowPath);
-            checkSubtype(asm, objHub, objHub, hub);
-            asm.jeq(falseSucc, objHub, asm.o(null));
-            asm.jmp(trueSucc);
+                // if we get an exact match: succeed immediately
+                for (int i = 0; i < hintCount; i++) {
+                    XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, CiKind.Object);
+                    asm.mov(scratchObject, hintHub);
+                    if (i < hintCount - 1) {
+                        asm.jeq(trueSucc, objHub, scratchObject);
+                    } else {
+                        if (is(EXACT_HINTS, flags)) {
+                            asm.jneq(falseSucc, objHub, scratchObject);
+                            asm.jmp(trueSucc);
+                        } else {
+                            slowPath = asm.createOutOfLineLabel("slow path");
+                            asm.jneq(slowPath, objHub, scratchObject);
+                            asm.jmp(trueSucc);
+                        }
+                    }
+                }
+
+                // -- out of line -------------------------------------------------------
+                if (slowPath != null) {
+                    asm.bindOutOfLine(slowPath);
+                    checkSubtype(asm, objHub, objHub, hub);
+                    asm.jeq(falseSucc, objHub, asm.o(null));
+                    asm.jmp(trueSucc);
+                }
+            }
 
             return asm.finishTemplate("instanceof");
         }
     };
 
-    private SimpleTemplates materializeInstanceOfTemplates = new SimpleTemplates(NULL_CHECK) {
+    private IndexTemplates materializeInstanceOfTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) {
 
         @Override
-        protected XirTemplate create(CiXirAssembler asm, long flags) {
+        protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) {
             XirOperand result = asm.restart(CiKind.Int);
             XirParameter object = asm.createInputParameter("object", CiKind.Object);
-            final XirOperand hub;
-            hub = asm.createConstantInputParameter("hub", CiKind.Object);
+            final XirOperand hub = is(EXACT_HINTS, flags) ? null : asm.createConstantInputParameter("hub", CiKind.Object);
             XirOperand trueValue = asm.createConstantInputParameter("trueValue", CiKind.Int);
             XirOperand falseValue = asm.createConstantInputParameter("falseValue", CiKind.Int);
 
             XirOperand objHub = asm.createTemp("objHub", CiKind.Object);
 
-            XirLabel slowPath = asm.createOutOfLineLabel("slow path");
-            XirLabel trueSucc = asm.createInlineLabel("ok");
+            XirLabel end = asm.createInlineLabel("end");
             XirLabel falseSucc = asm.createInlineLabel("ko");
-            XirLabel end = asm.createInlineLabel("end");
 
             if (is(NULL_CHECK, flags)) {
                 // null isn't "instanceof" anything
@@ -734,22 +776,47 @@
             }
 
             asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false);
-            // if we get an exact match: succeed immediately
-            asm.jeq(trueSucc, objHub, hub);
-            asm.jmp(slowPath);
+            asm.mov(result, trueValue);
+
+            if (hintCount == 0) {
+                assert !is(EXACT_HINTS, flags);
+                checkSubtype(asm, objHub, objHub, hub);
+                asm.jneq(end, objHub, asm.o(null));
+                asm.bindInline(falseSucc);
+                asm.mov(result, falseValue);
+                asm.bindInline(end);
+            } else {
+                XirLabel slowPath = null;
+                XirOperand scratchObject = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10);
 
-            asm.bindInline(trueSucc);
-            asm.mov(result, trueValue);
-            asm.jmp(end);
-            asm.bindInline(falseSucc);
-            asm.mov(result, falseValue);
-            asm.bindInline(end);
+                // if we get an exact match: succeed immediately
+                for (int i = 0; i < hintCount; i++) {
+                    XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, CiKind.Object);
+                    asm.mov(scratchObject, hintHub);
+                    if (i < hintCount - 1) {
+                        asm.jeq(end, objHub, scratchObject);
+                    } else {
+                        if (is(EXACT_HINTS, flags)) {
+                            asm.jeq(end, objHub, scratchObject);
+                        } else {
+                            slowPath = asm.createOutOfLineLabel("slow path");
+                            asm.jeq(end, objHub, scratchObject);
+                            asm.jmp(slowPath);
+                        }
+                    }
+                }
+                asm.bindInline(falseSucc);
+                asm.mov(result, falseValue);
+                asm.bindInline(end);
 
-            // -- out of line -------------------------------------------------------
-            asm.bindOutOfLine(slowPath);
-            checkSubtype(asm, objHub, objHub, hub);
-            asm.jeq(falseSucc, objHub, asm.o(null));
-            asm.jmp(trueSucc);
+                // -- out of line -------------------------------------------------------
+                if (slowPath != null) {
+                    asm.bindOutOfLine(slowPath);
+                    checkSubtype(asm, objHub, objHub, hub);
+                    asm.jeq(falseSucc, objHub, asm.o(null));
+                    asm.jmp(end);
+                }
+            }
 
             return asm.finishTemplate("instanceof");
         }
@@ -1253,18 +1320,62 @@
     }
 
     @Override
-    public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type) {
-        return new XirSnippet(checkCastTemplates.get(site), receiver, hub);
+    public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact) {
+        if (hints == null || hints.length == 0) {
+            return new XirSnippet(checkCastTemplates.get(site, 0), receiver, hub);
+        } else {
+            XirArgument[] params = new XirArgument[hints.length + (hintsExact ? 1 : 2)];
+            int i = 0;
+            params[i++] = receiver;
+            if (!hintsExact) {
+                params[i++] = hub;
+            }
+            for (RiResolvedType hint : hints) {
+                params[i++] = XirArgument.forObject(hint);
+            }
+            XirTemplate template = hintsExact ? checkCastTemplates.get(site, hints.length, EXACT_HINTS) : checkCastTemplates.get(site, hints.length);
+            return new XirSnippet(template, params);
+        }
     }
 
     @Override
-    public XirSnippet genInstanceOf(XirSite site, XirArgument object, XirArgument hub, RiType type) {
-        return new XirSnippet(instanceOfTemplates.get(site), object, hub);
+    public XirSnippet genInstanceOf(XirSite site, XirArgument object, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact) {
+        if (hints == null || hints.length == 0) {
+            return new XirSnippet(instanceOfTemplates.get(site, 0), object, hub);
+        } else {
+            XirArgument[] params = new XirArgument[hints.length + (hintsExact ? 1 : 2)];
+            int i = 0;
+            params[i++] = object;
+            if (!hintsExact) {
+                params[i++] = hub;
+            }
+            for (RiResolvedType hint : hints) {
+                params[i++] = XirArgument.forObject(hint);
+            }
+            XirTemplate template = hintsExact ? instanceOfTemplates.get(site, hints.length, EXACT_HINTS) : instanceOfTemplates.get(site, hints.length);
+            return new XirSnippet(template, params);
+        }
     }
 
     @Override
-    public XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument object, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type) {
-        return new XirSnippet(materializeInstanceOfTemplates.get(site), object, hub, trueValue, falseValue);
+    public XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument object, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type, RiResolvedType[] hints, boolean hintsExact) {
+        if (hints == null || hints.length == 0) {
+            return new XirSnippet(materializeInstanceOfTemplates.get(site, 0), object, hub, trueValue, falseValue);
+        } else {
+            XirArgument[] params = new XirArgument[hints.length + (hintsExact ? 3 : 4)];
+            int i = 0;
+            params[i++] = object;
+            if (!hintsExact) {
+                params[i++] = hub;
+            }
+            params[i++] = trueValue;
+            params[i++] = falseValue;
+            for (RiResolvedType hint : hints) {
+                params[i++] = XirArgument.forObject(hint);
+            }
+            XirTemplate template = hintsExact ? materializeInstanceOfTemplates.get(site, hints.length, EXACT_HINTS) : materializeInstanceOfTemplates.get(site, hints.length);
+            return new XirSnippet(template, params);
+        }
     }
 
     @Override
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/TemplateFlag.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/TemplateFlag.java	Sun Feb 05 05:40:36 2012 +0100
@@ -23,7 +23,7 @@
 package com.oracle.max.graal.hotspot.ri;
 
 enum TemplateFlag {
-    NULL_CHECK, READ_BARRIER, WRITE_BARRIER, STORE_CHECK, BOUNDS_CHECK, GIVEN_LENGTH, INPUTS_DIFFERENT, INPUTS_SAME, STATIC_METHOD, SYNCHRONIZED;
+    NULL_CHECK, READ_BARRIER, WRITE_BARRIER, STORE_CHECK, BOUNDS_CHECK, GIVEN_LENGTH, INPUTS_DIFFERENT, INPUTS_SAME, STATIC_METHOD, SYNCHRONIZED, EXACT_HINTS;
 
     private static final long FIRST_FLAG = 0x0000000100000000L;
     public static final long FLAGS_MASK = 0x0000FFFF00000000L;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/ArrayCopySnippets.java	Sun Feb 05 05:40:36 2012 +0100
@@ -0,0 +1,462 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.hotspot.snippets;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.graal.cri.*;
+import com.oracle.max.graal.hotspot.*;
+import com.oracle.max.graal.nodes.*;
+import com.oracle.max.graal.nodes.extended.*;
+import com.oracle.max.graal.nodes.spi.*;
+import com.oracle.max.graal.nodes.type.*;
+import com.oracle.max.graal.snippets.*;
+import com.oracle.max.graal.snippets.nodes.*;
+
+
+public class ArrayCopySnippets implements SnippetsInterface{
+
+    @Snippet
+    public static void arraycopy(byte[] src, int srcPos, byte[] dest, int destPos, int length) {
+        if (src == null || dest == null) {
+            throw new NullPointerException();
+        }
+        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (src == dest && srcPos < destPos) { // bad aliased case
+            if ((length & 0x01) == 0) {
+                if ((length & 0x02) == 0) {
+                    if ((length & 0x04) == 0) {
+                        copyLongsDown(src, srcPos, dest, destPos, length >> 3);
+                    } else {
+                        copyIntsDown(src, srcPos, dest, destPos, length >> 2);
+                    }
+                } else {
+                    copyShortsDown(src, srcPos, dest, destPos, length >> 1);
+                }
+            } else {
+                copyBytesDown(src, srcPos, dest, destPos, length);
+            }
+        } else {
+            if ((length & 0x01) == 0) {
+                if ((length & 0x02) == 0) {
+                    if ((length & 0x04) == 0) {
+                        copyLongsUp(src, srcPos, dest, destPos, length >> 3);
+                    } else {
+                        copyIntsUp(src, srcPos, dest, destPos, length >> 2);
+                    }
+                } else {
+                    copyShortsUp(src, srcPos, dest, destPos, length >> 1);
+                }
+            } else {
+                copyBytesUp(src, srcPos, dest, destPos, length);
+            }
+        }
+    }
+
+    @Snippet
+    public static void arraycopy(char[] src, int srcPos, char[] dest, int destPos, int length) {
+        if (src == null || dest == null) {
+            throw new NullPointerException();
+        }
+        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (src == dest && srcPos < destPos) { // bad aliased case
+            if ((length & 0x01) == 0) {
+                if ((length & 0x02) == 0) {
+                    copyLongsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 2);
+                } else {
+                    copyIntsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 1);
+                }
+            } else {
+                copyShortsDown(src, srcPos * 2L, dest, destPos * 2L, length);
+            }
+        } else {
+            if ((length & 0x01) == 0) {
+                if ((length & 0x02) == 0) {
+                    copyLongsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 2);
+                } else {
+                    copyIntsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 1);
+                }
+            } else {
+                copyShortsUp(src, srcPos * 2L, dest, destPos * 2L, length);
+            }
+        }
+    }
+
+    @Snippet
+    public static void arraycopy(short[] src, int srcPos, short[] dest, int destPos, int length) {
+        if (src == null || dest == null) {
+            throw new NullPointerException();
+        }
+        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (src == dest && srcPos < destPos) { // bad aliased case
+            if ((length & 0x01) == 0) {
+                if ((length & 0x02) == 0) {
+                    copyLongsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 2);
+                } else {
+                    copyIntsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 1);
+                }
+            } else {
+                copyShortsDown(src, srcPos * 2L, dest, destPos * 2L, length);
+            }
+        } else {
+            if ((length & 0x01) == 0) {
+                if ((length & 0x02) == 0) {
+                    copyLongsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 2);
+                } else {
+                    copyIntsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 1);
+                }
+            } else {
+                copyShortsUp(src, srcPos * 2L, dest, destPos * 2L, length);
+            }
+        }
+    }
+
+    @Snippet
+    public static void arraycopy(int[] src, int srcPos, int[] dest, int destPos, int length) {
+        if (src == null || dest == null) {
+            throw new NullPointerException();
+        }
+        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (src == dest && srcPos < destPos) { // bad aliased case
+            if ((length & 0x01) == 0) {
+                copyLongsDown(src, srcPos * 4L, dest, destPos * 4L, length >> 1);
+            } else {
+                copyIntsDown(src, srcPos * 4L, dest, destPos * 4L, length);
+            }
+        } else {
+            if ((length & 0x01) == 0) {
+                copyLongsUp(src, srcPos * 4L, dest, destPos * 4L, length >> 1);
+            } else {
+                copyIntsUp(src, srcPos * 4L, dest, destPos * 4L, length);
+            }
+        }
+    }
+
+    @Snippet
+    public static void arraycopy(float[] src, int srcPos, float[] dest, int destPos, int length) {
+        if (src == null || dest == null) {
+            throw new NullPointerException();
+        }
+        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (src == dest && srcPos < destPos) { // bad aliased case
+            if ((length & 0x01) == 0) {
+                copyLongsDown(src, srcPos * 4L, dest, destPos * 4L, length >> 1);
+            } else {
+                copyIntsDown(src, srcPos * 4L, dest, destPos * 4L, length);
+            }
+        } else {
+            if ((length & 0x01) == 0) {
+                copyLongsUp(src, srcPos * 4L, dest, destPos * 4L, length >> 1);
+            } else {
+                copyIntsUp(src, srcPos * 4L, dest, destPos * 4L, length);
+            }
+        }
+    }
+
+    @Snippet
+    public static void arraycopy(long[] src, int srcPos, long[] dest, int destPos, int length) {
+        if (src == null || dest == null) {
+            throw new NullPointerException();
+        }
+        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (src == dest && srcPos < destPos) { // bad aliased case
+            copyLongsDown(src, srcPos * 8L, dest, destPos * 8L, length);
+        } else {
+            copyLongsUp(src, srcPos * 8L, dest, destPos * 8L, length);
+        }
+    }
+
+    @Snippet
+    public static void arraycopy(double[] src, int srcPos, double[] dest, int destPos, int length) {
+        if (src == null || dest == null) {
+            throw new NullPointerException();
+        }
+        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (src == dest && srcPos < destPos) { // bad aliased case
+            copyLongsDown(src, srcPos * 8L, dest, destPos * 8L, length);
+        } else {
+            copyLongsUp(src, srcPos * 8L, dest, destPos * 8L, length);
+        }
+    }
+
+    // Does NOT perform store checks
+    @Snippet
+    public static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) {
+        if (src == null || dest == null) {
+            throw new NullPointerException();
+        }
+        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (src == dest && srcPos < destPos) { // bad aliased case
+            copyObjectsDown(src, srcPos * 8L, dest, destPos * 8L, length);
+        } else {
+            copyObjectsUp(src, srcPos * 8L, dest, destPos * 8L, length);
+        }
+        if (length > 0) {
+            long header = ArrayHeaderSizeNode.sizeFor(CiKind.Object);
+            int cardShift = CardTableShiftNode.get();
+            long cardStart = CardTableStartNode.get();
+            long dstAddr = GetObjectAddressNode.get(dest);
+            long start = (dstAddr + header + destPos * 8L) >>> cardShift;
+            long end = (dstAddr + header + (destPos + length - 1) * 8L) >>> cardShift;
+            long count = end - start + 1;
+            while (count-- > 0) {
+                DirectStoreNode.store((start + cardStart) + count, false);
+            }
+        }
+    }
+
+    @Snippet
+    public static void copyBytesDown(Object src, int srcPos, Object dest, int destPos, int length)  {
+        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Byte);
+        for (long i = length - 1; i >= 0; i--) {
+            Byte a = UnsafeLoadNode.load(src, i + (srcPos + header), CiKind.Byte);
+            UnsafeStoreNode.store(dest, i + (destPos + header), a.byteValue(), CiKind.Byte);
+        }
+    }
+
+    @Snippet
+    public static void copyShortsDown(Object src, long srcOffset, Object dest, long destOffset, int length)  {
+        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short);
+        for (long i = (length - 1) * 2; i >= 0; i -= 2) {
+            Character a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Short);
+            UnsafeStoreNode.store(dest, i + (destOffset + header), a.charValue(), CiKind.Short);
+        }
+    }
+
+    @Snippet
+    public static void copyIntsDown(Object src, long srcOffset, Object dest, long destOffset, int length)  {
+        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short);
+        for (long i = (length - 1) * 4; i >= 0; i -= 4) {
+            Integer a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Int);
+            UnsafeStoreNode.store(dest, i + (destOffset + header), a.intValue(), CiKind.Int);
+        }
+    }
+
+    @Snippet
+    public static void copyLongsDown(Object src, long srcOffset, Object dest, long destOffset, int length)  {
+        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short);
+        for (long i = (length - 1) * 8; i >= 0; i -= 8) {
+            Long a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Long);
+            UnsafeStoreNode.store(dest, i + (destOffset + header), a.longValue(), CiKind.Long);
+        }
+    }
+
+    // Does NOT perform store checks
+    @Snippet
+    public static void copyObjectsDown(Object src, long srcOffset, Object dest, long destOffset, int length)  {
+        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Object);
+        for (long i = (length - 1) * 8; i >= 0; i -= 8) {
+            Object a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Object);
+            DirectObjectStoreNode.store(dest, i + (destOffset + header), a);
+        }
+    }
+
+    /**
+     * Copies {@code length} bytes from {@code src} starting at {@code srcPos} to {@code dest} starting at {@code destPos}.
+     * @param src source object
+     * @param srcPos source offset
+     * @param dest destination object
+     * @param destPos destination offset
+     * @param length number of bytes to copy
+     */
+    @Snippet
+    public static void copyBytesUp(Object src, int srcPos, Object dest, int destPos, int length)  {
+        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Byte);
+        for (long i = 0; i < length; i++) {
+            Byte a = UnsafeLoadNode.load(src, i + (srcPos + header), CiKind.Byte);
+            UnsafeStoreNode.store(dest, i + (destPos + header), a.byteValue(), CiKind.Byte);
+        }
+    }
+
+    /**
+     * Copies {@code length} shorts from {@code src} starting at offset {@code srcOffset} (in bytes) to {@code dest} starting at offset {@code destOffset} (in bytes).
+     * @param src
+     * @param srcOffset (in bytes)
+     * @param dest
+     * @param destOffset (in bytes)
+     * @param length  (in shorts)
+     */
+    @Snippet
+    public static void copyShortsUp(Object src, long srcOffset, Object dest, long destOffset, int length)  {
+        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short);
+        for (long i = 0; i < length * 2L; i += 2) {
+            Character a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Short);
+            UnsafeStoreNode.store(dest, i + (destOffset + header), a.charValue(), CiKind.Short);
+        }
+    }
+
+    @Snippet
+    public static void copyIntsUp(Object src, long srcOffset, Object dest, long destOffset, int length)  {
+        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Int);
+        for (long i = 0; i < length * 4L; i += 4) {
+            Integer a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Int);
+            UnsafeStoreNode.store(dest, i + (destOffset + header), a.intValue(), CiKind.Int);
+        }
+    }
+
+    @Snippet
+    public static void copyLongsUp(Object src, long srcOffset, Object dest, long destOffset, int length)  {
+        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Long);
+        for (long i = 0; i < length * 8L; i += 8) {
+            Long a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Long);
+            UnsafeStoreNode.store(dest, i + (destOffset + header), a.longValue(), CiKind.Long);
+        }
+    }
+
+    // Does NOT perform store checks
+    @Snippet
+    public static void copyObjectsUp(Object src, long srcOffset, Object dest, long destOffset, int length)  {
+        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Object);
+        for (long i = 0; i < length * 8L; i += 8) {
+            Object a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Object);
+            DirectObjectStoreNode.store(dest, i + (destOffset + header), a);
+        }
+    }
+
+    private static class GetObjectAddressNode extends FixedWithNextNode implements LIRLowerable {
+        @Input private ValueNode object;
+
+        public GetObjectAddressNode(ValueNode obj) {
+            super(StampFactory.forKind(CiKind.Long));
+            this.object = obj;
+        }
+
+        @SuppressWarnings("unused")
+        @NodeIntrinsic
+        public static long get(Object array) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void generate(LIRGeneratorTool gen) {
+            CiValue obj = gen.newVariable(gen.target().wordKind);
+            gen.emitMove(gen.operand(object), obj);
+            gen.setResult(this, obj);
+        }
+    }
+
+    private static class DirectStoreNode extends FixedWithNextNode implements LIRLowerable {
+        @Input private ValueNode address;
+        @Input private ValueNode value;
+
+        public DirectStoreNode(ValueNode address, ValueNode value) {
+            super(StampFactory.illegal());
+            this.address = address;
+            this.value = value;
+        }
+
+        @SuppressWarnings("unused")
+        @NodeIntrinsic
+        public static void store(long address, long value) {
+            throw new UnsupportedOperationException();
+        }
+
+        @SuppressWarnings("unused")
+        @NodeIntrinsic
+        public static void store(long address, boolean value) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void generate(LIRGeneratorTool gen) {
+            CiValue v = gen.operand(value);
+            gen.emitStore(new CiAddress(v.kind, gen.operand(address)), v, false);
+        }
+    }
+
+    private static class DirectObjectStoreNode extends FixedWithNextNode implements Lowerable {
+        @Input private ValueNode object;
+        @Input private ValueNode value;
+        @Input private ValueNode offset;
+
+        public DirectObjectStoreNode(ValueNode object, ValueNode offset, ValueNode value) {
+            super(StampFactory.illegal());
+            this.object = object;
+            this.value = value;
+            this.offset = offset;
+        }
+
+        @SuppressWarnings("unused")
+        @NodeIntrinsic
+        public static void store(Object obj, long offset, long value) {
+            throw new UnsupportedOperationException();
+        }
+
+        @SuppressWarnings("unused")
+        @NodeIntrinsic
+        public static void store(Object obj, long offset, boolean value) {
+            throw new UnsupportedOperationException();
+        }
+
+        @SuppressWarnings("unused")
+        @NodeIntrinsic
+        public static void store(Object obj, long offset, Object value) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void lower(CiLoweringTool tool) {
+            StructuredGraph graph = (StructuredGraph) this.graph();
+            IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, value.kind(), 0, offset, graph, false);
+            WriteNode write = graph.add(new WriteNode(object, value, location));
+            graph.replaceFixedWithFixed(this, write);
+        }
+    }
+
+    private static class CardTableShiftNode extends ConstantNode {
+        public CardTableShiftNode() {
+            super(CiConstant.forInt(CompilerImpl.getInstance().getConfig().cardtableShift));
+        }
+
+        @NodeIntrinsic
+        public static int get() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    private static class CardTableStartNode extends ConstantNode {
+        public CardTableStartNode() {
+            super(CiConstant.forLong(CompilerImpl.getInstance().getConfig().cardtableStartAddress));
+        }
+
+        @NodeIntrinsic
+        public static long get() {
+            throw new UnsupportedOperationException();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java	Sun Feb 05 05:40:36 2012 +0100
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.hotspot.snippets;
+
+import java.lang.reflect.*;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
+import com.oracle.max.graal.compiler.phases.*;
+import com.oracle.max.graal.compiler.util.*;
+import com.oracle.max.graal.cri.*;
+import com.oracle.max.graal.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.nodes.*;
+import com.oracle.max.graal.nodes.java.*;
+
+public class IntrinsifyArrayCopyPhase extends Phase {
+    private final GraalRuntime runtime;
+    private RiResolvedMethod arrayCopy;
+    private RiResolvedMethod byteArrayCopy;
+    private RiResolvedMethod shortArrayCopy;
+    private RiResolvedMethod charArrayCopy;
+    private RiResolvedMethod intArrayCopy;
+    private RiResolvedMethod longArrayCopy;
+    private RiResolvedMethod floatArrayCopy;
+    private RiResolvedMethod doubleArrayCopy;
+    private RiResolvedMethod objectArrayCopy;
+
+    public IntrinsifyArrayCopyPhase(GraalRuntime runtime) {
+        this.runtime = runtime;
+        try {
+            byteArrayCopy = getArrayCopySnippet(runtime, byte.class);
+            charArrayCopy = getArrayCopySnippet(runtime, char.class);
+            shortArrayCopy = getArrayCopySnippet(runtime, short.class);
+            intArrayCopy = getArrayCopySnippet(runtime, int.class);
+            longArrayCopy = getArrayCopySnippet(runtime, long.class);
+            floatArrayCopy = getArrayCopySnippet(runtime, float.class);
+            doubleArrayCopy = getArrayCopySnippet(runtime, double.class);
+            objectArrayCopy = getArrayCopySnippet(runtime, Object.class);
+            arrayCopy = runtime.getRiMethod(System.class.getDeclaredMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class));
+        } catch (SecurityException e) {
+            e.printStackTrace();
+        } catch (NoSuchMethodException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private static RiResolvedMethod getArrayCopySnippet(RiRuntime runtime, Class<?> componentClass) throws NoSuchMethodException {
+        Class<?> arrayClass = Array.newInstance(componentClass, 0).getClass();
+        return runtime.getRiMethod(ArrayCopySnippets.class.getDeclaredMethod("arraycopy", arrayClass, int.class, arrayClass, int.class, int.class));
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        boolean hits = false;
+        for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.class)) {
+            RiResolvedMethod targetMethod = methodCallTarget.targetMethod();
+            RiResolvedMethod snippetMethod = null;
+            if (targetMethod == arrayCopy) {
+                ValueNode src = methodCallTarget.arguments().get(0);
+                ValueNode dest = methodCallTarget.arguments().get(2);
+                if (src == null || dest == null) { //TODO (gd) this should never be null : check
+                    return;
+                }
+                RiResolvedType srcDeclaredType = src.declaredType();
+                RiResolvedType destDeclaredType = dest.declaredType();
+                if (srcDeclaredType != null
+                                && srcDeclaredType.isArrayClass()
+                                && destDeclaredType != null
+                                && destDeclaredType.isArrayClass()) {
+                    CiKind componentKind = srcDeclaredType.componentType().kind(false);
+                    if (srcDeclaredType.componentType() == destDeclaredType.componentType()) {
+                        if (componentKind == CiKind.Int) {
+                            snippetMethod = intArrayCopy;
+                        } else if (componentKind == CiKind.Char) {
+                            snippetMethod = charArrayCopy;
+                        } else if (componentKind == CiKind.Long) {
+                            snippetMethod = longArrayCopy;
+                        } else if (componentKind == CiKind.Byte) {
+                            snippetMethod = byteArrayCopy;
+                        } else if (componentKind == CiKind.Short) {
+                            snippetMethod = shortArrayCopy;
+                        } else if (componentKind == CiKind.Float) {
+                            snippetMethod = floatArrayCopy;
+                        } else if (componentKind == CiKind.Double) {
+                            snippetMethod = doubleArrayCopy;
+                        } else if (componentKind == CiKind.Object) {
+                            snippetMethod = objectArrayCopy;
+                        }
+                    } else if (componentKind == CiKind.Object
+                                    && srcDeclaredType.componentType().isSubtypeOf(destDeclaredType.componentType())) {
+                        snippetMethod = objectArrayCopy;
+                    }
+                }
+            }
+
+            if (snippetMethod != null) {
+                StructuredGraph snippetGraph = (StructuredGraph) snippetMethod.compilerStorage().get(Graph.class);
+                assert snippetGraph != null : "ArrayCopySnippets should be installed";
+                hits = true;
+                Debug.log("%s > Intinsify (%s)", Debug.currentScope(), snippetMethod.signature().argumentTypeAt(0, snippetMethod.holder()).componentType());
+                InliningUtil.inline(methodCallTarget.invoke(), snippetGraph, false);
+            }
+        }
+        if (hits) {
+            new CanonicalizerPhase(null, runtime, null).apply(graph);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/SystemSnippets.java	Sun Feb 05 05:40:36 2012 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.hotspot.snippets;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.graal.nodes.extended.*;
+import com.oracle.max.graal.snippets.*;
+
+/**
+ * Snippets for {@link java.lang.System} methods.
+ */
+@ClassSubstitution(java.lang.System.class)
+public class SystemSnippets implements SnippetsInterface {
+
+    public static long currentTimeMillis() {
+        return RuntimeCallNode.performCall(CiRuntimeCall.JavaTimeMillis);
+    }
+
+    public static long nanoTime() {
+        return RuntimeCallNode.performCall(CiRuntimeCall.JavaTimeNanos);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/UnsafeSnippets.java	Sun Feb 05 05:40:36 2012 +0100
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.hotspot.snippets;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.util.*;
+import com.oracle.max.graal.nodes.extended.*;
+import com.oracle.max.graal.nodes.java.*;
+import com.oracle.max.graal.snippets.*;
+
+/**
+ * Snippets for {@link sun.misc.Unsafe} methods.
+ */
+@ClassSubstitution(sun.misc.Unsafe.class)
+public class UnsafeSnippets implements SnippetsInterface {
+
+    public boolean compareAndSwapObject(Object o, long offset, Object expected, Object x) {
+        return CompareAndSwapNode.compareAndSwap(o, offset, expected, x);
+    }
+
+    public boolean compareAndSwapInt(Object o, long offset, int expected, int x) {
+        return CompareAndSwapNode.compareAndSwap(o, offset, expected, x);
+    }
+
+    public boolean compareAndSwapLong(Object o, long offset, long expected, long x) {
+        return CompareAndSwapNode.compareAndSwap(o, offset, expected, x);
+    }
+
+    public Object getObject(Object o, long offset) {
+        return UnsafeLoadNode.load(o, offset, CiKind.Object);
+    }
+
+    public Object getObjectVolatile(Object o, long offset) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
+        Object result = getObject(o, offset);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
+        return result;
+    }
+
+    public void putObject(Object o, long offset, Object x) {
+        UnsafeStoreNode.store(o, offset, x, CiKind.Object);
+    }
+
+    public void putObjectVolatile(Object o, long offset, Object x) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
+        putObject(o, offset, x);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
+    }
+
+    public int getInt(Object o, long offset) {
+        Integer value = UnsafeLoadNode.load(o, offset, CiKind.Int);
+        return value;
+    }
+
+    public int getIntVolatile(Object o, long offset) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
+        int result = getInt(o, offset);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
+        return result;
+    }
+
+    public void putInt(Object o, long offset, int x) {
+        UnsafeStoreNode.store(o, offset, x, CiKind.Int);
+    }
+
+    public void putIntVolatile(Object o, long offset, int x) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
+        putInt(o, offset, x);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
+    }
+
+    public boolean getBoolean(Object o, long offset) {
+        @JavacBug(id = 6995200)
+        Boolean result = UnsafeLoadNode.load(o, offset, CiKind.Boolean);
+        return result;
+    }
+
+    public boolean getBooleanVolatile(Object o, long offset) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
+        boolean result = getBoolean(o, offset);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
+        return result;
+    }
+
+    public void putBoolean(Object o, long offset, boolean x) {
+        UnsafeStoreNode.store(o, offset, x, CiKind.Boolean);
+    }
+
+    public void putBooleanVolatile(Object o, long offset, boolean x) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
+        putBoolean(o, offset, x);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
+    }
+
+    public byte getByte(Object o, long offset) {
+        @JavacBug(id = 6995200)
+        Byte result = UnsafeLoadNode.load(o, offset, CiKind.Byte);
+        return result;
+    }
+
+    public byte getByteVolatile(Object o, long offset) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
+        byte result = getByte(o, offset);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
+        return result;
+    }
+
+    public void putByte(Object o, long offset, byte x) {
+        UnsafeStoreNode.store(o, offset, x, CiKind.Byte);
+    }
+
+    public void putByteVolatile(Object o, long offset, byte x) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
+        putByte(o, offset, x);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
+    }
+
+    public short getShort(Object o, long offset) {
+        @JavacBug(id = 6995200)
+        Short result = UnsafeLoadNode.load(o, offset, CiKind.Short);
+        return result;
+    }
+
+    public short getShortVolatile(Object o, long offset) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
+        short result = getShort(o, offset);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
+        return result;
+    }
+
+    public void putShort(Object o, long offset, short x) {
+        UnsafeStoreNode.store(o, offset, x, CiKind.Short);
+    }
+
+    public void putShortVolatile(Object o, long offset, short x) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
+        putShort(o, offset, x);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
+    }
+
+    public char getChar(Object o, long offset) {
+        @JavacBug(id = 6995200)
+        Character result = UnsafeLoadNode.load(o, offset, CiKind.Char);
+        return result;
+    }
+
+    public char getCharVolatile(Object o, long offset) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
+        char result = getChar(o, offset);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
+        return result;
+    }
+
+    public void putChar(Object o, long offset, char x) {
+        UnsafeStoreNode.store(o, offset, x, CiKind.Char);
+    }
+
+    public void putCharVolatile(Object o, long offset, char x) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
+        putChar(o, offset, x);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
+    }
+
+    public long getLong(Object o, long offset) {
+        @JavacBug(id = 6995200)
+        Long result = UnsafeLoadNode.load(o, offset, CiKind.Long);
+        return result;
+    }
+
+    public long getLongVolatile(Object o, long offset) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
+        long result = getLong(o, offset);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
+        return result;
+    }
+
+    public void putLong(Object o, long offset, long x) {
+        UnsafeStoreNode.store(o, offset, x, CiKind.Long);
+    }
+
+    public void putLongVolatile(Object o, long offset, long x) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
+        putLong(o, offset, x);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
+    }
+
+    public float getFloat(Object o, long offset) {
+        @JavacBug(id = 6995200)
+        Float result = UnsafeLoadNode.load(o, offset, CiKind.Float);
+        return result;
+    }
+
+    public float getFloatVolatile(Object o, long offset) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
+        float result = getFloat(o, offset);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
+        return result;
+    }
+
+    public void putFloat(Object o, long offset, float x) {
+        UnsafeStoreNode.store(o, offset, x, CiKind.Float);
+    }
+
+    public void putFloatVolatile(Object o, long offset, float x) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
+        putFloat(o, offset, x);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
+    }
+
+    public double getDouble(Object o, long offset) {
+        @JavacBug(id = 6995200)
+        Double result = UnsafeLoadNode.load(o, offset, CiKind.Double);
+        return result;
+    }
+
+    public double getDoubleVolatile(Object o, long offset) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
+        double result = getDouble(o, offset);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
+        return result;
+    }
+
+    public void putDouble(Object o, long offset, double x) {
+        UnsafeStoreNode.store(o, offset, x, CiKind.Double);
+    }
+
+    public void putDoubleVolatile(Object o, long offset, double x) {
+        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
+        putDouble(o, offset, x);
+        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
+    }
+}
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/target/amd64/AMD64TailcallOp.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/target/amd64/AMD64TailcallOp.java	Sun Feb 05 05:40:36 2012 +0100
@@ -37,9 +37,15 @@
  * Performs a hard-coded tail call to the specified target, which normally should be an RiCompiledCode instance.
  */
 public class AMD64TailcallOp extends AMD64LIRInstruction {
+
     public AMD64TailcallOp(List<CiValue> parameters, CiValue target, CiValue[] callingConvention) {
         super("TAILCALL", LIRInstruction.NO_OPERANDS, null, toArray(parameters, target), LIRInstruction.NO_OPERANDS, callingConvention.clone());
         assert inputs.length == temps.length + 1;
+
+        for (int i = 0; i < temps.length; i++) {
+            assert isRegister(temps[i]) : "too many parameters for tail call";
+            assert sameRegister(temps[i], inputs[i]) : "inputs do not match calling convention";
+        }
     }
 
     private static CiValue[] toArray(List<CiValue> parameters, CiValue target) {
@@ -51,19 +57,6 @@
 
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        // move all parameters to the correct positions, according to the calling convention
-        // TODO: These moves should not be part of the TAILCALL opcode, but emitted as separate MOVE instructions before.
-        for (int i = 0; i < inputs.length - 1; i++) {
-            assert inputs[i].kind == CiKind.Object || inputs[i].kind == CiKind.Int || inputs[i].kind == CiKind.Long : "only Object, int and long supported for now";
-            assert isRegister(temps[i]) : "too many parameters";
-            if (isRegister(inputs[i])) {
-                if (inputs[i] != temps[i]) {
-                    masm.movq(asRegister(temps[i]), asRegister(inputs[i]));
-                }
-            } else {
-                masm.movq(asRegister(temps[i]), tasm.asAddress(inputs[i]));
-            }
-        }
         // destroy the current frame (now the return address is the top of stack)
         masm.leave();
 
@@ -74,10 +67,10 @@
 
     @Override
     protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-        if (mode == OperandMode.Input && index == 0) {
-            return EnumSet.of(OperandFlag.Register, OperandFlag.Constant, OperandFlag.Stack);
-        } else if (mode == OperandMode.Temp && index == 0) {
-            return EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
+        if (mode == OperandMode.Input) {
+            return EnumSet.of(OperandFlag.Register);
+        } else if (mode == OperandMode.Temp) {
+            return EnumSet.of(OperandFlag.Register);
         }
         throw Util.shouldNotReachHere();
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BciBlockMapping.java	Sun Feb 05 05:40:36 2012 +0100
@@ -0,0 +1,631 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.java;
+
+import static com.oracle.max.graal.java.Bytecodes.*;
+
+import java.util.*;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.nodes.*;
+
+/**
+ * Builds a mapping between bytecodes and basic blocks and builds a conservative control flow
+ * graph. Note that this class serves a similar role to C1's {@code BlockListBuilder}, but makes fewer assumptions about
+ * what the compiler interface provides. It builds all basic blocks for the control flow graph without requiring the
+ * compiler interface to provide a bitmap of the beginning of basic blocks. It makes two linear passes; one over the
+ * bytecodes to build block starts and successor lists, and one pass over the block map to build the CFG.
+ *
+ * Note that the CFG built by this class is <i>not</i> connected to the actual {@code BlockBegin} instances; this class
+ * does, however, compute and assign the reverse postorder number of the blocks. This comment needs refinement. (MJJ)
+ *
+ * <H2>More Details on {@link BciBlockMapping#build}</H2>
+ *
+ * If the method has any exception handlers the {@linkplain #exceptionMap exception map} will be created (TBD).
+ *
+ * The bytecodes are then scanned linearly looking for bytecodes that contain control transfers, e.g., {@code GOTO},
+ * {@code RETURN}, {@code IFGE}, and creating the corresponding entries in {@link #successorMap} and {@link #blockMap}.
+ * In addition, if {@link #exceptionMap} is not null, entries are made for any bytecode that can cause an exception.
+ * More TBD.
+ *
+ * Observe that this process finds bytecodes that terminate basic blocks, so the {@link #moveSuccessorLists} method is
+ * called to reassign the successors to the {@code BlockBegin} node that actually starts the block.
+ *
+ * <H3>Example</H3>
+ *
+ * Consider the following source code:
+ *
+ * <pre>
+ * <code>
+ *     public static int test(int arg1, int arg2) {
+ *         int x = 0;
+ *         while (arg2 > 0) {
+ *             if (arg1 > 0) {
+ *                 x += 1;
+ *             } else if (arg1 < 0) {
+ *                 x -= 1;
+ *             }
+ *         }
+ *         return x;
+ *     }
+ * </code>
+ * </pre>
+ *
+ * This is translated by javac to the following bytecode:
+ *
+ * <pre>
+ * <code>
+ *    0:   iconst_0
+ *    1:   istore_2
+ *    2:   goto    22
+ *    5:   iload_0
+ *    6:   ifle    15
+ *    9:   iinc    2, 1
+ *    12:  goto    22
+ *    15:  iload_0
+ *    16:  ifge    22
+ *    19:  iinc    2, -1
+ *    22:  iload_1
+ *    23:  ifgt    5
+ *    26:  iload_2
+ *    27:  ireturn
+ *    </code>
+ * </pre>
+ *
+ * There are seven basic blocks in this method, 0..2, 5..6, 9..12, 15..16, 19..19, 22..23 and 26..27. Therefore, before
+ * the call to {@code moveSuccessorLists}, the {@code blockMap} array has {@code BlockBegin} nodes at indices 0, 5, 9,
+ * 15, 19, 22 and 26. The {@code successorMap} array has entries at 2, 6, 12, 16, 23, 27 corresponding to the control
+ * transfer bytecodes. The entry at index 6, for example, is a length two array of {@code BlockBegin} nodes for indices
+ * 9 and 15, which are the successors for the basic block 5..6. After the call to {@code moveSuccessors}, {@code
+ * successorMap} has entries at 0, 5, 9, 15, 19, 22 and 26, i.e, matching {@code blockMap}.
+ * <p>
+ * Next the blocks are numbered using <a href="http://en.wikipedia.org/wiki/Depth-first_search#Vertex_orderings">reverse
+ * post-order</a>. For the above example this results in the numbering 2, 4, 7, 5, 6, 3, 8. Also loop header blocks are
+ * detected during the traversal by detecting a repeat visit to a block that is still being processed. This causes the
+ * block to be flagged as a loop header and also added to the {@link #loopBlocks} list. The {@code loopBlocks} list
+ * contains the blocks at 0, 5, 9, 15, 19, 22, with 22 as the loop header. (N.B. the loop header block is added multiple
+ * (4) times to this list). (Should 0 be in? It's not inside the loop).
+ *
+ * If the {@code computeStoresInLoops} argument to {@code build} is true, the {@code loopBlocks} list is processed to
+ * mark all local variables that are stored in the blocks in the list.
+ */
+public final class BciBlockMapping {
+
+    public static class Block implements Cloneable {
+        public int startBci;
+        public int endBci;
+        public boolean isExceptionEntry;
+        public boolean isLoopHeader;
+        public int blockID;
+
+        public FixedWithNextNode firstInstruction;
+
+        public ArrayList<Block> successors = new ArrayList<>(2);
+        public int normalSuccessors;
+
+        private boolean visited;
+        private boolean active;
+        public long loops;
+
+        public HashMap<JsrScope, Block> jsrAlternatives;
+        public JsrScope jsrScope = JsrScope.EMPTY_SCOPE;
+        public Block jsrSuccessor;
+        public int jsrReturnBci;
+        public Block retSuccessor;
+        public boolean endsWithRet = false;
+
+        public Block copy() {
+            try {
+                Block block = (Block) super.clone();
+                block.successors = new ArrayList<>(successors);
+                return block;
+            } catch (CloneNotSupportedException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    public static class ExceptionBlock extends Block {
+        public RiExceptionHandler handler;
+        public int deoptBci;
+    }
+
+    public static class DeoptBlock extends Block {
+        public DeoptBlock(int startBci) {
+            this.startBci = startBci;
+        }
+    }
+
+    /**
+     * The blocks found in this method, in reverse postorder.
+     */
+    public final List<Block> blocks;
+
+    public final RiResolvedMethod method;
+
+    private final RiExceptionHandler[] exceptionHandlers;
+
+    private Block[] blockMap;
+
+    public final BitSet canTrap;
+
+    public boolean hasJsrBytecodes;
+
+    public Block startBlock;
+
+    public final boolean useBranchPrediction;
+
+    /**
+     * Creates a new BlockMap instance from bytecode of the given method .
+     * @param method the compiler interface method containing the code
+     */
+    public BciBlockMapping(RiResolvedMethod method, boolean useBranchPrediction) {
+        this.method = method;
+        exceptionHandlers = method.exceptionHandlers();
+        this.blockMap = new Block[method.codeSize()];
+        this.canTrap = new BitSet(blockMap.length);
+        this.blocks = new ArrayList<>();
+        this.useBranchPrediction = useBranchPrediction;
+    }
+
+    public RiExceptionHandler[] exceptionHandlers() {
+        return exceptionHandlers;
+    }
+
+    /**
+     * Builds the block map and conservative CFG and numbers blocks.
+     */
+    public void build() {
+        makeExceptionEntries();
+        iterateOverBytecodes();
+        addExceptionEdges();
+        if (hasJsrBytecodes) {
+            if (!GraalOptions.SupportJsrBytecodes) {
+                throw new JsrNotSupportedBailout("jsr/ret parsing disabled");
+            }
+            createJsrAlternatives(blockMap[0]);
+        }
+        computeBlockOrder();
+
+        initializeBlockIds();
+
+        startBlock = blockMap[0];
+
+        // Discard big arrays so that they can be GCed
+        blockMap = null;
+    }
+
+    private void initializeBlockIds() {
+        for (int i = 0; i < blocks.size(); i++) {
+            blocks.get(i).blockID = i;
+        }
+    }
+
+    private void makeExceptionEntries() {
+        // start basic blocks at all exception handler blocks and mark them as exception entries
+        for (RiExceptionHandler h : this.exceptionHandlers) {
+            Block xhandler = makeBlock(h.handlerBCI());
+            xhandler.isExceptionEntry = true;
+        }
+    }
+
+    private void iterateOverBytecodes() {
+        // iterate over the bytecodes top to bottom.
+        // mark the entrypoints of basic blocks and build lists of successors for
+        // all bytecodes that end basic blocks (i.e. goto, ifs, switches, throw, jsr, returns, ret)
+        byte[] code = method.code();
+        Block current = null;
+        int bci = 0;
+        while (bci < code.length) {
+            if (current == null || blockMap[bci] != null) {
+                Block b = makeBlock(bci);
+                if (current != null) {
+                    setSuccessors(current.endBci, b);
+                }
+                current = b;
+            }
+            blockMap[bci] = current;
+            current.endBci = bci;
+
+            int opcode = Bytes.beU1(code, bci);
+            switch (opcode) {
+                case IRETURN: // fall through
+                case LRETURN: // fall through
+                case FRETURN: // fall through
+                case DRETURN: // fall through
+                case ARETURN: // fall through
+                case RETURN: {
+                    current = null;
+                    break;
+                }
+                case ATHROW: {
+                    current = null;
+                    canTrap.set(bci);
+                    break;
+                }
+                case IFEQ:      // fall through
+                case IFNE:      // fall through
+                case IFLT:      // fall through
+                case IFGE:      // fall through
+                case IFGT:      // fall through
+                case IFLE:      // fall through
+                case IF_ICMPEQ: // fall through
+                case IF_ICMPNE: // fall through
+                case IF_ICMPLT: // fall through
+                case IF_ICMPGE: // fall through
+                case IF_ICMPGT: // fall through
+                case IF_ICMPLE: // fall through
+                case IF_ACMPEQ: // fall through
+                case IF_ACMPNE: // fall through
+                case IFNULL:    // fall through
+                case IFNONNULL: {
+                    current = null;
+                    double probability = useBranchPrediction ? method.branchProbability(bci) : -1;
+
+                    Block b1 = probability == 0.0 ? new DeoptBlock(bci + Bytes.beS2(code, bci + 1)) : makeBlock(bci + Bytes.beS2(code, bci + 1));
+                    Block b2 = probability == 1.0 ? new DeoptBlock(bci + 3) : makeBlock(bci + 3);
+                    setSuccessors(bci, b1, b2);
+                    break;
+                }
+                case GOTO:
+                case GOTO_W: {
+                    current = null;
+                    int target = bci + Bytes.beSVar(code, bci + 1, opcode == GOTO_W);
+                    Block b1 = makeBlock(target);
+                    setSuccessors(bci, b1);
+                    break;
+                }
+                case TABLESWITCH: {
+                    current = null;
+                    BytecodeTableSwitch sw = new BytecodeTableSwitch(code, bci);
+                    setSuccessors(bci, makeSwitchSuccessors(sw));
+                    break;
+                }
+                case LOOKUPSWITCH: {
+                    current = null;
+                    BytecodeLookupSwitch sw = new BytecodeLookupSwitch(code, bci);
+                    setSuccessors(bci, makeSwitchSuccessors(sw));
+                    break;
+                }
+                case JSR:
+                case JSR_W: {
+                    hasJsrBytecodes = true;
+                    int target = bci + Bytes.beSVar(code, bci + 1, opcode == JSR_W);
+                    if (target == 0) {
+                        throw new JsrNotSupportedBailout("jsr target bci 0 not allowed");
+                    }
+                    Block b1 = makeBlock(target);
+                    current.jsrSuccessor = b1;
+                    current.jsrReturnBci = bci + lengthOf(opcode);
+                    current = null;
+                    setSuccessors(bci, b1);
+                    break;
+                }
+                case RET: {
+                    current.endsWithRet = true;
+                    current = null;
+                    break;
+                }
+                case WIDE: {
+                    int opcode2 = Bytes.beU1(code, bci);
+                    switch (opcode2) {
+                        case RET: {
+                            current.endsWithRet = true;
+                            current = null;
+                            break;
+                        }
+                    }
+                    break;
+                }
+                case INVOKEINTERFACE:
+                case INVOKESPECIAL:
+                case INVOKESTATIC:
+                case INVOKEVIRTUAL: {
+                    current = null;
+                    int target = bci + lengthOf(code, bci);
+                    Block b1 = makeBlock(target);
+                    setSuccessors(bci, b1);
+                    canTrap.set(bci);
+                    break;
+                }
+                default: {
+                    if (canTrap(opcode, bci)) {
+                        canTrap.set(bci);
+                    }
+                }
+            }
+            bci += lengthOf(code, bci);
+        }
+    }
+
+    public boolean canTrap(int opcode, int bci) {
+        switch (opcode) {
+            case INVOKESTATIC:
+            case INVOKESPECIAL:
+            case INVOKEVIRTUAL:
+            case INVOKEINTERFACE: {
+                return true;
+            }
+            case IASTORE:
+            case LASTORE:
+            case FASTORE:
+            case DASTORE:
+            case AASTORE:
+            case BASTORE:
+            case CASTORE:
+            case SASTORE:
+            case IALOAD:
+            case LALOAD:
+            case FALOAD:
+            case DALOAD:
+            case AALOAD:
+            case BALOAD:
+            case CALOAD:
+            case SALOAD:
+            case PUTFIELD:
+            case GETFIELD: {
+                if (GraalOptions.AllowExplicitExceptionChecks) {
+                    return method.exceptionProbability(bci) > 0;
+                }
+            }
+        }
+        return false;
+    }
+
+    private Block makeBlock(int startBci) {
+        Block oldBlock = blockMap[startBci];
+        if (oldBlock == null) {
+            Block newBlock = new Block();
+            newBlock.startBci = startBci;
+            blockMap[startBci] = newBlock;
+            return newBlock;
+
+        } else if (oldBlock.startBci != startBci) {
+            // Backward branch into the middle of an already processed block.
+            // Add the correct fall-through successor.
+            Block newBlock = new Block();
+            newBlock.startBci = startBci;
+            newBlock.endBci = oldBlock.endBci;
+            newBlock.successors.addAll(oldBlock.successors);
+            newBlock.normalSuccessors = oldBlock.normalSuccessors;
+
+            oldBlock.endBci = startBci - 1;
+            oldBlock.successors.clear();
+            oldBlock.successors.add(newBlock);
+            oldBlock.normalSuccessors = 1;
+
+            for (int i = startBci; i <= newBlock.endBci; i++) {
+                blockMap[i] = newBlock;
+            }
+            return newBlock;
+
+        } else {
+            return oldBlock;
+        }
+    }
+
+    private Block[] makeSwitchSuccessors(BytecodeSwitch tswitch) {
+        int max = tswitch.numberOfCases();
+        Block[] successors = new Block[max + 1];
+        for (int i = 0; i < max; i++) {
+            successors[i] = makeBlock(tswitch.targetAt(i));
+        }
+        successors[max] = makeBlock(tswitch.defaultTarget());
+        return successors;
+    }
+
+    private void setSuccessors(int predBci, Block... successors) {
+        Block predecessor = blockMap[predBci];
+        assert predecessor.successors.size() == 0;
+        for (Block sux : successors) {
+            if (sux.isExceptionEntry) {
+                throw new CiBailout("Exception handler can be reached by both normal and exceptional control flow");
+            }
+            predecessor.successors.add(sux);
+        }
+        predecessor.normalSuccessors = successors.length;
+    }
+
+    private final HashSet<Block> jsrVisited = new HashSet<>();
+
+    private void createJsrAlternatives(Block block) {
+        jsrVisited.add(block);
+        JsrScope scope = block.jsrScope;
+
+        if (block.endsWithRet) {
+            block.retSuccessor = blockMap[scope.nextReturnAddress()];
+            block.successors.add(block.retSuccessor);
+            assert block.retSuccessor != block.jsrSuccessor;
+        }
+
+        if (block.jsrSuccessor != null || !scope.isEmpty()) {
+            for (int i = 0; i < block.successors.size(); i++) {
+                Block successor = block.successors.get(i);
+                JsrScope nextScope = scope;
+                if (successor == block.jsrSuccessor) {
+                    nextScope = scope.push(block.jsrReturnBci);
+                }
+                if (successor == block.retSuccessor) {
+                    nextScope = scope.pop();
+                }
+                if (!successor.jsrScope.isEmpty()) {
+                    throw new JsrNotSupportedBailout("unstructured control flow  (" + successor.jsrScope + " " + nextScope + ")");
+                }
+                if (!nextScope.isEmpty()) {
+                    Block clone;
+                    if (successor.jsrAlternatives != null && successor.jsrAlternatives.containsKey(nextScope)) {
+                        clone = successor.jsrAlternatives.get(nextScope);
+                    } else {
+                        if (successor.jsrAlternatives == null) {
+                            successor.jsrAlternatives = new HashMap<>();
+                        }
+                        clone = successor.copy();
+                        clone.jsrScope = nextScope;
+                        successor.jsrAlternatives.put(nextScope, clone);
+                    }
+                    block.successors.set(i, clone);
+                    if (successor == block.jsrSuccessor) {
+                        block.jsrSuccessor = clone;
+                    }
+                    if (successor == block.retSuccessor) {
+                        block.retSuccessor = clone;
+                    }
+                }
+            }
+        }
+        for (Block successor : block.successors) {
+            if (!jsrVisited.contains(successor)) {
+                createJsrAlternatives(successor);
+            }
+        }
+    }
+
+    private HashMap<RiExceptionHandler, ExceptionBlock> exceptionDispatch = new HashMap<>();
+
+    private Block makeExceptionDispatch(List<RiExceptionHandler> handlers, int index, int bci) {
+        RiExceptionHandler handler = handlers.get(index);
+        if (handler.isCatchAll()) {
+            return blockMap[handler.handlerBCI()];
+        }
+        ExceptionBlock block = exceptionDispatch.get(handler);
+        if (block == null) {
+            block = new ExceptionBlock();
+            block.startBci = -1;
+            block.endBci = -1;
+            block.deoptBci = bci;
+            block.handler = handler;
+            block.successors.add(blockMap[handler.handlerBCI()]);
+            if (index < handlers.size() - 1) {
+                block.successors.add(makeExceptionDispatch(handlers, index + 1, bci));
+            }
+            exceptionDispatch.put(handler, block);
+        }
+        return block;
+    }
+
+    private void addExceptionEdges() {
+        for (int bci = canTrap.nextSetBit(0); bci >= 0; bci = canTrap.nextSetBit(bci + 1)) {
+            Block block = blockMap[bci];
+
+            ArrayList<RiExceptionHandler> handlers = null;
+            for (RiExceptionHandler h : this.exceptionHandlers) {
+                if (h.startBCI() <= bci && bci < h.endBCI()) {
+                    if (handlers == null) {
+                        handlers = new ArrayList<>();
+                    }
+                    handlers.add(h);
+                    if (h.isCatchAll()) {
+                        break;
+                    }
+                }
+            }
+            if (handlers != null) {
+                Block dispatch = makeExceptionDispatch(handlers, 0, bci);
+                block.successors.add(dispatch);
+            }
+        }
+    }
+
+    private void computeBlockOrder() {
+        long loop = computeBlockOrder(blockMap[0]);
+
+        if (loop != 0) {
+            // There is a path from a loop end to the method entry that does not pass the loop header.
+            // Therefore, the loop is non reducible (has more than one entry).
+            // We don't want to compile such methods because the IR only supports structured loops.
+            throw new CiBailout("Non-reducible loop");
+        }
+
+        // Convert postorder to the desired reverse postorder.
+        Collections.reverse(blocks);
+    }
+
+    /**
+     * The next available loop number.
+     */
+    private int nextLoop;
+
+    /**
+     * Mark the block as a loop header, using the next available loop number.
+     * Also checks for corner cases that we don't want to compile.
+     */
+    private void makeLoopHeader(Block block) {
+        if (!block.isLoopHeader) {
+            block.isLoopHeader = true;
+
+            if (block.isExceptionEntry) {
+                // Loops that are implicitly formed by an exception handler lead to all sorts of corner cases.
+                // Don't compile such methods for now, until we see a concrete case that allows checking for correctness.
+                throw new CiBailout("Loop formed by an exception handler");
+            }
+            if (nextLoop >= Long.SIZE) {
+                // This restriction can be removed by using a fall-back to a BitSet in case we have more than 64 loops
+                // Don't compile such methods for now, until we see a concrete case that allows checking for correctness.
+                throw new CiBailout("Too many loops in method");
+            }
+
+            assert block.loops == 0;
+            block.loops = (long) 1 << (long) nextLoop;
+            nextLoop++;
+        }
+        assert Long.bitCount(block.loops) == 1;
+    }
+
+    /**
+     * Depth-first traversal of the control flow graph. The flag {@linkplain Block#visited} is used to
+     * visit every block only once. The flag {@linkplain Block#active} is used to detect cycles (backward
+     * edges).
+     */
+    private long computeBlockOrder(Block block) {
+        if (block.visited) {
+            if (block.active) {
+                // Reached block via backward branch.
+                makeLoopHeader(block);
+            }
+            // Return cached loop information for this block.
+            return block.loops;
+        }
+
+        block.visited = true;
+        block.active = true;
+
+        int loops = 0;
+        for (Block successor : block.successors) {
+            // Recursively process successors.
+            loops |= computeBlockOrder(successor);
+        }
+
+        if (block.isLoopHeader) {
+            assert Long.bitCount(block.loops) == 1;
+            loops &= ~block.loops;
+        }
+
+        block.loops = loops;
+        block.active = false;
+        blocks.add(block);
+
+        return loops;
+    }
+}
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BlockMap.java	Sun Feb 05 05:37:52 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,631 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.java;
-
-import static com.oracle.max.graal.java.Bytecodes.*;
-
-import java.util.*;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ri.*;
-import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.nodes.*;
-
-/**
- * Builds a mapping between bytecodes and basic blocks and builds a conservative control flow
- * graph. Note that this class serves a similar role to C1's {@code BlockListBuilder}, but makes fewer assumptions about
- * what the compiler interface provides. It builds all basic blocks for the control flow graph without requiring the
- * compiler interface to provide a bitmap of the beginning of basic blocks. It makes two linear passes; one over the
- * bytecodes to build block starts and successor lists, and one pass over the block map to build the CFG.
- *
- * Note that the CFG built by this class is <i>not</i> connected to the actual {@code BlockBegin} instances; this class
- * does, however, compute and assign the reverse postorder number of the blocks. This comment needs refinement. (MJJ)
- *
- * <H2>More Details on {@link BlockMap#build}</H2>
- *
- * If the method has any exception handlers the {@linkplain #exceptionMap exception map} will be created (TBD).
- *
- * The bytecodes are then scanned linearly looking for bytecodes that contain control transfers, e.g., {@code GOTO},
- * {@code RETURN}, {@code IFGE}, and creating the corresponding entries in {@link #successorMap} and {@link #blockMap}.
- * In addition, if {@link #exceptionMap} is not null, entries are made for any bytecode that can cause an exception.
- * More TBD.
- *
- * Observe that this process finds bytecodes that terminate basic blocks, so the {@link #moveSuccessorLists} method is
- * called to reassign the successors to the {@code BlockBegin} node that actually starts the block.
- *
- * <H3>Example</H3>
- *
- * Consider the following source code:
- *
- * <pre>
- * <code>
- *     public static int test(int arg1, int arg2) {
- *         int x = 0;
- *         while (arg2 > 0) {
- *             if (arg1 > 0) {
- *                 x += 1;
- *             } else if (arg1 < 0) {
- *                 x -= 1;
- *             }
- *         }
- *         return x;
- *     }
- * </code>
- * </pre>
- *
- * This is translated by javac to the following bytecode:
- *
- * <pre>
- * <code>
- *    0:   iconst_0
- *    1:   istore_2
- *    2:   goto    22
- *    5:   iload_0
- *    6:   ifle    15
- *    9:   iinc    2, 1
- *    12:  goto    22
- *    15:  iload_0
- *    16:  ifge    22
- *    19:  iinc    2, -1
- *    22:  iload_1
- *    23:  ifgt    5
- *    26:  iload_2
- *    27:  ireturn
- *    </code>
- * </pre>
- *
- * There are seven basic blocks in this method, 0..2, 5..6, 9..12, 15..16, 19..19, 22..23 and 26..27. Therefore, before
- * the call to {@code moveSuccessorLists}, the {@code blockMap} array has {@code BlockBegin} nodes at indices 0, 5, 9,
- * 15, 19, 22 and 26. The {@code successorMap} array has entries at 2, 6, 12, 16, 23, 27 corresponding to the control
- * transfer bytecodes. The entry at index 6, for example, is a length two array of {@code BlockBegin} nodes for indices
- * 9 and 15, which are the successors for the basic block 5..6. After the call to {@code moveSuccessors}, {@code
- * successorMap} has entries at 0, 5, 9, 15, 19, 22 and 26, i.e, matching {@code blockMap}.
- * <p>
- * Next the blocks are numbered using <a href="http://en.wikipedia.org/wiki/Depth-first_search#Vertex_orderings">reverse
- * post-order</a>. For the above example this results in the numbering 2, 4, 7, 5, 6, 3, 8. Also loop header blocks are
- * detected during the traversal by detecting a repeat visit to a block that is still being processed. This causes the
- * block to be flagged as a loop header and also added to the {@link #loopBlocks} list. The {@code loopBlocks} list
- * contains the blocks at 0, 5, 9, 15, 19, 22, with 22 as the loop header. (N.B. the loop header block is added multiple
- * (4) times to this list). (Should 0 be in? It's not inside the loop).
- *
- * If the {@code computeStoresInLoops} argument to {@code build} is true, the {@code loopBlocks} list is processed to
- * mark all local variables that are stored in the blocks in the list.
- */
-public final class BlockMap {
-
-    public static class Block implements Cloneable {
-        public int startBci;
-        public int endBci;
-        public boolean isExceptionEntry;
-        public boolean isLoopHeader;
-        public int blockID;
-
-        public FixedWithNextNode firstInstruction;
-
-        public ArrayList<Block> successors = new ArrayList<>(2);
-        public int normalSuccessors;
-
-        private boolean visited;
-        private boolean active;
-        public long loops;
-
-        public HashMap<JsrScope, Block> jsrAlternatives;
-        public JsrScope jsrScope = JsrScope.EMPTY_SCOPE;
-        public Block jsrSuccessor;
-        public int jsrReturnBci;
-        public Block retSuccessor;
-        public boolean endsWithRet = false;
-
-        public Block copy() {
-            try {
-                Block block = (Block) super.clone();
-                block.successors = new ArrayList<>(successors);
-                return block;
-            } catch (CloneNotSupportedException e) {
-                throw new RuntimeException(e);
-            }
-        }
-    }
-
-    public static class ExceptionBlock extends Block {
-        public RiExceptionHandler handler;
-        public int deoptBci;
-    }
-
-    public static class DeoptBlock extends Block {
-        public DeoptBlock(int startBci) {
-            this.startBci = startBci;
-        }
-    }
-
-    /**
-     * The blocks found in this method, in reverse postorder.
-     */
-    public final List<Block> blocks;
-
-    public final RiResolvedMethod method;
-
-    private final RiExceptionHandler[] exceptionHandlers;
-
-    private Block[] blockMap;
-
-    public final BitSet canTrap;
-
-    public boolean hasJsrBytecodes;
-
-    public Block startBlock;
-
-    public final boolean useBranchPrediction;
-
-    /**
-     * Creates a new BlockMap instance from bytecode of the given method .
-     * @param method the compiler interface method containing the code
-     */
-    public BlockMap(RiResolvedMethod method, boolean useBranchPrediction) {
-        this.method = method;
-        exceptionHandlers = method.exceptionHandlers();
-        this.blockMap = new Block[method.codeSize()];
-        this.canTrap = new BitSet(blockMap.length);
-        this.blocks = new ArrayList<>();
-        this.useBranchPrediction = useBranchPrediction;
-    }
-
-    public RiExceptionHandler[] exceptionHandlers() {
-        return exceptionHandlers;
-    }
-
-    /**
-     * Builds the block map and conservative CFG and numbers blocks.
-     */
-    public void build() {
-        makeExceptionEntries();
-        iterateOverBytecodes();
-        addExceptionEdges();
-        if (hasJsrBytecodes) {
-            if (!GraalOptions.SupportJsrBytecodes) {
-                throw new JsrNotSupportedBailout("jsr/ret parsing disabled");
-            }
-            createJsrAlternatives(blockMap[0]);
-        }
-        computeBlockOrder();
-
-        initializeBlockIds();
-
-        startBlock = blockMap[0];
-
-        // Discard big arrays so that they can be GCed
-        blockMap = null;
-    }
-
-    private void initializeBlockIds() {
-        for (int i = 0; i < blocks.size(); i++) {
-            blocks.get(i).blockID = i;
-        }
-    }
-
-    private void makeExceptionEntries() {
-        // start basic blocks at all exception handler blocks and mark them as exception entries
-        for (RiExceptionHandler h : this.exceptionHandlers) {
-            Block xhandler = makeBlock(h.handlerBCI());
-            xhandler.isExceptionEntry = true;
-        }
-    }
-
-    private void iterateOverBytecodes() {
-        // iterate over the bytecodes top to bottom.
-        // mark the entrypoints of basic blocks and build lists of successors for
-        // all bytecodes that end basic blocks (i.e. goto, ifs, switches, throw, jsr, returns, ret)
-        byte[] code = method.code();
-        Block current = null;
-        int bci = 0;
-        while (bci < code.length) {
-            if (current == null || blockMap[bci] != null) {
-                Block b = makeBlock(bci);
-                if (current != null) {
-                    setSuccessors(current.endBci, b);
-                }
-                current = b;
-            }
-            blockMap[bci] = current;
-            current.endBci = bci;
-
-            int opcode = Bytes.beU1(code, bci);
-            switch (opcode) {
-                case IRETURN: // fall through
-                case LRETURN: // fall through
-                case FRETURN: // fall through
-                case DRETURN: // fall through
-                case ARETURN: // fall through
-                case RETURN: {
-                    current = null;
-                    break;
-                }
-                case ATHROW: {
-                    current = null;
-                    canTrap.set(bci);
-                    break;
-                }
-                case IFEQ:      // fall through
-                case IFNE:      // fall through
-                case IFLT:      // fall through
-                case IFGE:      // fall through
-                case IFGT:      // fall through
-                case IFLE:      // fall through
-                case IF_ICMPEQ: // fall through
-                case IF_ICMPNE: // fall through
-                case IF_ICMPLT: // fall through
-                case IF_ICMPGE: // fall through
-                case IF_ICMPGT: // fall through
-                case IF_ICMPLE: // fall through
-                case IF_ACMPEQ: // fall through
-                case IF_ACMPNE: // fall through
-                case IFNULL:    // fall through
-                case IFNONNULL: {
-                    current = null;
-                    double probability = useBranchPrediction ? method.branchProbability(bci) : -1;
-
-                    Block b1 = probability == 0.0 ? new DeoptBlock(bci + Bytes.beS2(code, bci + 1)) : makeBlock(bci + Bytes.beS2(code, bci + 1));
-                    Block b2 = probability == 1.0 ? new DeoptBlock(bci + 3) : makeBlock(bci + 3);
-                    setSuccessors(bci, b1, b2);
-                    break;
-                }
-                case GOTO:
-                case GOTO_W: {
-                    current = null;
-                    int target = bci + Bytes.beSVar(code, bci + 1, opcode == GOTO_W);
-                    Block b1 = makeBlock(target);
-                    setSuccessors(bci, b1);
-                    break;
-                }
-                case TABLESWITCH: {
-                    current = null;
-                    BytecodeTableSwitch sw = new BytecodeTableSwitch(code, bci);
-                    setSuccessors(bci, makeSwitchSuccessors(sw));
-                    break;
-                }
-                case LOOKUPSWITCH: {
-                    current = null;
-                    BytecodeLookupSwitch sw = new BytecodeLookupSwitch(code, bci);
-                    setSuccessors(bci, makeSwitchSuccessors(sw));
-                    break;
-                }
-                case JSR:
-                case JSR_W: {
-                    hasJsrBytecodes = true;
-                    int target = bci + Bytes.beSVar(code, bci + 1, opcode == JSR_W);
-                    if (target == 0) {
-                        throw new JsrNotSupportedBailout("jsr target bci 0 not allowed");
-                    }
-                    Block b1 = makeBlock(target);
-                    current.jsrSuccessor = b1;
-                    current.jsrReturnBci = bci + lengthOf(opcode);
-                    current = null;
-                    setSuccessors(bci, b1);
-                    break;
-                }
-                case RET: {
-                    current.endsWithRet = true;
-                    current = null;
-                    break;
-                }
-                case WIDE: {
-                    int opcode2 = Bytes.beU1(code, bci);
-                    switch (opcode2) {
-                        case RET: {
-                            current.endsWithRet = true;
-                            current = null;
-                            break;
-                        }
-                    }
-                    break;
-                }
-                case INVOKEINTERFACE:
-                case INVOKESPECIAL:
-                case INVOKESTATIC:
-                case INVOKEVIRTUAL: {
-                    current = null;
-                    int target = bci + lengthOf(code, bci);
-                    Block b1 = makeBlock(target);
-                    setSuccessors(bci, b1);
-                    canTrap.set(bci);
-                    break;
-                }
-                default: {
-                    if (canTrap(opcode, bci)) {
-                        canTrap.set(bci);
-                    }
-                }
-            }
-            bci += lengthOf(code, bci);
-        }
-    }
-
-    public boolean canTrap(int opcode, int bci) {
-        switch (opcode) {
-            case INVOKESTATIC:
-            case INVOKESPECIAL:
-            case INVOKEVIRTUAL:
-            case INVOKEINTERFACE: {
-                return true;
-            }
-            case IASTORE:
-            case LASTORE:
-            case FASTORE:
-            case DASTORE:
-            case AASTORE:
-            case BASTORE:
-            case CASTORE:
-            case SASTORE:
-            case IALOAD:
-            case LALOAD:
-            case FALOAD:
-            case DALOAD:
-            case AALOAD:
-            case BALOAD:
-            case CALOAD:
-            case SALOAD:
-            case PUTFIELD:
-            case GETFIELD: {
-                if (GraalOptions.AllowExplicitExceptionChecks) {
-                    return method.exceptionProbability(bci) > 0;
-                }
-            }
-        }
-        return false;
-    }
-
-    private Block makeBlock(int startBci) {
-        Block oldBlock = blockMap[startBci];
-        if (oldBlock == null) {
-            Block newBlock = new Block();
-            newBlock.startBci = startBci;
-            blockMap[startBci] = newBlock;
-            return newBlock;
-
-        } else if (oldBlock.startBci != startBci) {
-            // Backward branch into the middle of an already processed block.
-            // Add the correct fall-through successor.
-            Block newBlock = new Block();
-            newBlock.startBci = startBci;
-            newBlock.endBci = oldBlock.endBci;
-            newBlock.successors.addAll(oldBlock.successors);
-            newBlock.normalSuccessors = oldBlock.normalSuccessors;
-
-            oldBlock.endBci = startBci - 1;
-            oldBlock.successors.clear();
-            oldBlock.successors.add(newBlock);
-            oldBlock.normalSuccessors = 1;
-
-            for (int i = startBci; i <= newBlock.endBci; i++) {
-                blockMap[i] = newBlock;
-            }
-            return newBlock;
-
-        } else {
-            return oldBlock;
-        }
-    }
-
-    private Block[] makeSwitchSuccessors(BytecodeSwitch tswitch) {
-        int max = tswitch.numberOfCases();
-        Block[] successors = new Block[max + 1];
-        for (int i = 0; i < max; i++) {
-            successors[i] = makeBlock(tswitch.targetAt(i));
-        }
-        successors[max] = makeBlock(tswitch.defaultTarget());
-        return successors;
-    }
-
-    private void setSuccessors(int predBci, Block... successors) {
-        Block predecessor = blockMap[predBci];
-        assert predecessor.successors.size() == 0;
-        for (Block sux : successors) {
-            if (sux.isExceptionEntry) {
-                throw new CiBailout("Exception handler can be reached by both normal and exceptional control flow");
-            }
-            predecessor.successors.add(sux);
-        }
-        predecessor.normalSuccessors = successors.length;
-    }
-
-    private final HashSet<Block> jsrVisited = new HashSet<>();
-
-    private void createJsrAlternatives(Block block) {
-        jsrVisited.add(block);
-        JsrScope scope = block.jsrScope;
-
-        if (block.endsWithRet) {
-            block.retSuccessor = blockMap[scope.nextReturnAddress()];
-            block.successors.add(block.retSuccessor);
-            assert block.retSuccessor != block.jsrSuccessor;
-        }
-
-        if (block.jsrSuccessor != null || !scope.isEmpty()) {
-            for (int i = 0; i < block.successors.size(); i++) {
-                Block successor = block.successors.get(i);
-                JsrScope nextScope = scope;
-                if (successor == block.jsrSuccessor) {
-                    nextScope = scope.push(block.jsrReturnBci);
-                }
-                if (successor == block.retSuccessor) {
-                    nextScope = scope.pop();
-                }
-                if (!successor.jsrScope.isEmpty()) {
-                    throw new JsrNotSupportedBailout("unstructured control flow  (" + successor.jsrScope + " " + nextScope + ")");
-                }
-                if (!nextScope.isEmpty()) {
-                    Block clone;
-                    if (successor.jsrAlternatives != null && successor.jsrAlternatives.containsKey(nextScope)) {
-                        clone = successor.jsrAlternatives.get(nextScope);
-                    } else {
-                        if (successor.jsrAlternatives == null) {
-                            successor.jsrAlternatives = new HashMap<>();
-                        }
-                        clone = successor.copy();
-                        clone.jsrScope = nextScope;
-                        successor.jsrAlternatives.put(nextScope, clone);
-                    }
-                    block.successors.set(i, clone);
-                    if (successor == block.jsrSuccessor) {
-                        block.jsrSuccessor = clone;
-                    }
-                    if (successor == block.retSuccessor) {
-                        block.retSuccessor = clone;
-                    }
-                }
-            }
-        }
-        for (Block successor : block.successors) {
-            if (!jsrVisited.contains(successor)) {
-                createJsrAlternatives(successor);
-            }
-        }
-    }
-
-    private HashMap<RiExceptionHandler, ExceptionBlock> exceptionDispatch = new HashMap<>();
-
-    private Block makeExceptionDispatch(List<RiExceptionHandler> handlers, int index, int bci) {
-        RiExceptionHandler handler = handlers.get(index);
-        if (handler.isCatchAll()) {
-            return blockMap[handler.handlerBCI()];
-        }
-        ExceptionBlock block = exceptionDispatch.get(handler);
-        if (block == null) {
-            block = new ExceptionBlock();
-            block.startBci = -1;
-            block.endBci = -1;
-            block.deoptBci = bci;
-            block.handler = handler;
-            block.successors.add(blockMap[handler.handlerBCI()]);
-            if (index < handlers.size() - 1) {
-                block.successors.add(makeExceptionDispatch(handlers, index + 1, bci));
-            }
-            exceptionDispatch.put(handler, block);
-        }
-        return block;
-    }
-
-    private void addExceptionEdges() {
-        for (int bci = canTrap.nextSetBit(0); bci >= 0; bci = canTrap.nextSetBit(bci + 1)) {
-            Block block = blockMap[bci];
-
-            ArrayList<RiExceptionHandler> handlers = null;
-            for (RiExceptionHandler h : this.exceptionHandlers) {
-                if (h.startBCI() <= bci && bci < h.endBCI()) {
-                    if (handlers == null) {
-                        handlers = new ArrayList<>();
-                    }
-                    handlers.add(h);
-                    if (h.isCatchAll()) {
-                        break;
-                    }
-                }
-            }
-            if (handlers != null) {
-                Block dispatch = makeExceptionDispatch(handlers, 0, bci);
-                block.successors.add(dispatch);
-            }
-        }
-    }
-
-    private void computeBlockOrder() {
-        long loop = computeBlockOrder(blockMap[0]);
-
-        if (loop != 0) {
-            // There is a path from a loop end to the method entry that does not pass the loop header.
-            // Therefore, the loop is non reducible (has more than one entry).
-            // We don't want to compile such methods because the IR only supports structured loops.
-            throw new CiBailout("Non-reducible loop");
-        }
-
-        // Convert postorder to the desired reverse postorder.
-        Collections.reverse(blocks);
-    }
-
-    /**
-     * The next available loop number.
-     */
-    private int nextLoop;
-
-    /**
-     * Mark the block as a loop header, using the next available loop number.
-     * Also checks for corner cases that we don't want to compile.
-     */
-    private void makeLoopHeader(Block block) {
-        if (!block.isLoopHeader) {
-            block.isLoopHeader = true;
-
-            if (block.isExceptionEntry) {
-                // Loops that are implicitly formed by an exception handler lead to all sorts of corner cases.
-                // Don't compile such methods for now, until we see a concrete case that allows checking for correctness.
-                throw new CiBailout("Loop formed by an exception handler");
-            }
-            if (nextLoop >= Long.SIZE) {
-                // This restriction can be removed by using a fall-back to a BitSet in case we have more than 32 loops
-                // Don't compile such methods for now, until we see a concrete case that allows checking for correctness.
-                throw new CiBailout("Too many loops in method");
-            }
-
-            assert block.loops == 0;
-            block.loops = (long) 1 << (long) nextLoop;
-            nextLoop++;
-        }
-        assert Long.bitCount(block.loops) == 1;
-    }
-
-    /**
-     * Depth-first traversal of the control flow graph. The flag {@linkplain Block#visited} is used to
-     * visit every block only once. The flag {@linkplain Block#active} is used to detect cycles (backward
-     * edges).
-     */
-    private long computeBlockOrder(Block block) {
-        if (block.visited) {
-            if (block.active) {
-                // Reached block via backward branch.
-                makeLoopHeader(block);
-            }
-            // Return cached loop information for this block.
-            return block.loops;
-        }
-
-        block.visited = true;
-        block.active = true;
-
-        int loops = 0;
-        for (Block successor : block.successors) {
-            // Recursively process successors.
-            loops |= computeBlockOrder(successor);
-        }
-
-        if (block.isLoopHeader) {
-            assert Long.bitCount(block.loops) == 1;
-            loops &= ~block.loops;
-        }
-
-        block.loops = loops;
-        block.active = false;
-        blocks.add(block);
-
-        return loops;
-    }
-}
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java	Sun Feb 05 05:40:36 2012 +0100
@@ -34,13 +34,12 @@
 import com.oracle.max.criutils.*;
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.phases.*;
-import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.debug.*;
 import com.oracle.max.graal.graph.*;
-import com.oracle.max.graal.java.BlockMap.Block;
-import com.oracle.max.graal.java.BlockMap.DeoptBlock;
-import com.oracle.max.graal.java.BlockMap.ExceptionBlock;
+import com.oracle.max.graal.java.BciBlockMapping.Block;
+import com.oracle.max.graal.java.BciBlockMapping.DeoptBlock;
+import com.oracle.max.graal.java.BciBlockMapping.ExceptionBlock;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.DeoptimizeNode.DeoptAction;
 import com.oracle.max.graal.nodes.PhiNode.PhiType;
@@ -136,8 +135,8 @@
         return getName() + " " + CiUtil.format("%H.%n(%p):%r", method);
     }
 
-    private BlockMap createBlockMap() {
-        BlockMap map = new BlockMap(method, config.useBranchPrediction());
+    private BciBlockMapping createBlockMap() {
+        BciBlockMapping map = new BciBlockMapping(method, config.useBranchPrediction());
         map.build();
 
 //        if (currentContext.isObserved()) {
@@ -155,7 +154,7 @@
         }
 
         // compute the block map, setup exception handlers and get the entrypoint(s)
-        BlockMap blockMap = createBlockMap();
+        BciBlockMapping blockMap = createBlockMap();
         this.canTrapBitSet = blockMap.canTrap;
 
         exceptionHandlers = blockMap.exceptionHandlers();
@@ -687,6 +686,32 @@
         }
     }
 
+    private static final RiResolvedType[] EMPTY_TYPE_ARRAY = new RiResolvedType[0];
+
+    private RiResolvedType[] getTypeCheckHints(RiResolvedType type, int maxHints) {
+        if (!GraalOptions.UseInstanceOfHints || Util.isFinalClass(type)) {
+            return new RiResolvedType[] {type};
+        } else {
+            RiResolvedType uniqueSubtype = type.uniqueConcreteSubtype();
+            if (uniqueSubtype != null) {
+                return new RiResolvedType[] {uniqueSubtype};
+            } else {
+                RiTypeProfile typeProfile = method.typeProfile(bci());
+                if (typeProfile != null && typeProfile.types != null && typeProfile.types.length > 0 && typeProfile.morphism <= maxHints) {
+                    RiResolvedType[] hints = new RiResolvedType[typeProfile.types.length];
+                    int hintCount = 0;
+                    for (RiResolvedType hint : typeProfile.types) {
+                        if (hint.isSubtypeOf(type)) {
+                            hints[hintCount++] = hint;
+                        }
+                    }
+                    return Arrays.copyOf(hints, Math.min(maxHints, hintCount));
+                }
+                return EMPTY_TYPE_ARRAY;
+            }
+        }
+    }
+
     private void genCheckCast() {
         int cpi = stream().readCPI();
         RiType type = lookupType(cpi, CHECKCAST);
@@ -696,7 +721,13 @@
             ValueNode object = frameState.apop();
             AnchorNode anchor = currentGraph.add(new AnchorNode());
             append(anchor);
-            CheckCastNode checkCast = currentGraph.unique(new CheckCastNode(anchor, typeInstruction, (RiResolvedType) type, object));
+            CheckCastNode checkCast;
+            if (type instanceof RiResolvedType) {
+                RiResolvedType[] hints = getTypeCheckHints((RiResolvedType) type, 2);
+                checkCast = currentGraph.unique(new CheckCastNode(anchor, typeInstruction, (RiResolvedType) type, object, hints, Util.isFinalClass((RiResolvedType) type)));
+            } else {
+                checkCast = currentGraph.unique(new CheckCastNode(anchor, typeInstruction, (RiResolvedType) type, object));
+            }
             append(currentGraph.add(new ValueAnchorNode(checkCast)));
             frameState.apush(checkCast);
         } else {
@@ -711,8 +742,12 @@
         RiType type = lookupType(cpi, INSTANCEOF);
         ValueNode object = frameState.apop();
         if (type instanceof RiResolvedType) {
-            ConstantNode hub = appendConstant(((RiResolvedType) type).getEncoding(RiType.Representation.ObjectHub));
-            frameState.ipush(append(MaterializeNode.create(currentGraph.unique(new InstanceOfNode(hub, (RiResolvedType) type, object, false)), currentGraph)));
+            RiResolvedType resolvedType = (RiResolvedType) type;
+            ConstantNode hub = appendConstant(resolvedType.getEncoding(RiType.Representation.ObjectHub));
+
+            RiResolvedType[] hints = getTypeCheckHints(resolvedType, 1);
+            InstanceOfNode instanceOfNode = new InstanceOfNode(hub, (RiResolvedType) type, object, hints, Util.isFinalClass(resolvedType), false);
+            frameState.ipush(append(MaterializeNode.create(currentGraph.unique(instanceOfNode), currentGraph)));
         } else {
             PlaceholderNode trueSucc = currentGraph.add(new PlaceholderNode());
             DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile));
@@ -1419,6 +1454,23 @@
         }
     }
 
+    private static boolean isBlockEnd(Node n) {
+        return trueSuccessorCount(n) > 1 || n instanceof ReturnNode || n instanceof UnwindNode || n instanceof DeoptimizeNode;
+    }
+
+    private static int trueSuccessorCount(Node n) {
+        if (n == null) {
+            return 0;
+        }
+        int i = 0;
+        for (Node s : n.successors()) {
+            if (Util.isFixed(s)) {
+                i++;
+            }
+        }
+        return i;
+    }
+
     private void iterateBytecodesForBlock(Block block) {
         assert frameState != null;
 
@@ -1435,7 +1487,7 @@
             traceInstruction(bci, opcode, bci == block.startBci);
             processBytecode(bci, opcode);
 
-            if (lastInstr == null || IdentifyBlocksPhase.isBlockEnd(lastInstr) || lastInstr.next() != null) {
+            if (lastInstr == null || isBlockEnd(lastInstr) || lastInstr.next() != null) {
                 break;
             }
 
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/ConstantNode.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/ConstantNode.java	Sun Feb 05 05:40:36 2012 +0100
@@ -33,11 +33,11 @@
  * long, float, object reference, address, etc.
  */
 @NodeInfo(shortName = "Const")
-public final class ConstantNode extends BooleanNode implements LIRLowerable {
+public class ConstantNode extends BooleanNode implements LIRLowerable {
 
     @Data public final CiConstant value;
 
-    private ConstantNode(CiConstant value) {
+    protected ConstantNode(CiConstant value) {
         this(value, null);
     }
 
@@ -45,7 +45,7 @@
      * Constructs a new ConstantNode representing the specified constant.
      * @param value the constant
      */
-    private ConstantNode(CiConstant value, RiRuntime runtime) {
+    protected ConstantNode(CiConstant value, RiRuntime runtime) {
         super(StampFactory.forConstant(value, runtime));
         this.value = value;
     }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/EndNode.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/EndNode.java	Sun Feb 05 05:40:36 2012 +0100
@@ -40,12 +40,7 @@
     }
 
     public MergeNode merge() {
-        if (usages().size() == 0) {
-            return null;
-        } else {
-            assert usages().size() == 1;
-            return (MergeNode) usages().iterator().next();
-        }
+        return (MergeNode) usages().first();
     }
 
     @Override
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/FrameState.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/FrameState.java	Sun Feb 05 05:40:36 2012 +0100
@@ -27,6 +27,7 @@
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.iterators.*;
 import com.oracle.max.graal.nodes.PhiNode.PhiType;
 import com.oracle.max.graal.nodes.spi.*;
 import com.oracle.max.graal.nodes.virtual.*;
@@ -74,27 +75,6 @@
 
     @Input private final NodeInputList<Node> virtualObjectMappings;
 
-    public FrameState outerFrameState() {
-        return outerFrameState;
-    }
-
-    public void setOuterFrameState(FrameState x) {
-        updateUsages(this.outerFrameState, x);
-        this.outerFrameState = x;
-    }
-
-    public FrameState outermostFrameState() {
-        FrameState fs = this;
-        while (fs.outerFrameState() != null) {
-            fs = fs.outerFrameState();
-        }
-        return fs;
-    }
-
-    public void setValueAt(int i, ValueNode x) {
-        values.set(i, x);
-    }
-
     /**
      * The bytecode index to which this frame state applies. This will be {@code -1}
      * iff this state is mutable.
@@ -142,6 +122,27 @@
         assert !rethrowException || stackSize == 1 : "must have exception on top of the stack";
     }
 
+    public FrameState outerFrameState() {
+        return outerFrameState;
+    }
+
+    public void setOuterFrameState(FrameState x) {
+        updateUsages(this.outerFrameState, x);
+        this.outerFrameState = x;
+    }
+
+    public FrameState outermostFrameState() {
+        FrameState fs = this;
+        while (fs.outerFrameState() != null) {
+            fs = fs.outerFrameState();
+        }
+        return fs;
+    }
+
+    public void setValueAt(int i, ValueNode x) {
+        values.set(i, x);
+    }
+
     public boolean rethrowException() {
         return rethrowException;
     }
@@ -455,9 +456,8 @@
     public void deleteRedundantPhi(PhiNode redundantPhi, ValueNode phiValue) {
         Collection<PhiNode> phiUsages = redundantPhi.usages().filter(PhiNode.class).snapshot();
         ((StructuredGraph) graph()).replaceFloating(redundantPhi, phiValue);
-        for (Node n : phiUsages) {
-            PhiNode phiNode = (PhiNode) n;
-            checkRedundantPhi(phiNode);
+        for (PhiNode phi : phiUsages) {
+            checkRedundantPhi(phi);
         }
     }
 
@@ -488,48 +488,11 @@
     }
 
     public StateSplit stateSplit() {
-        for (Node n : usages()) {
-            if (n instanceof StateSplit) {
-                return (StateSplit) n;
-            }
-        }
-        return null;
+        return (StateSplit) usages().filterInterface(StateSplit.class).first();
     }
 
-    public Iterable<FrameState> innerFrameStates() {
-        final Iterator<Node> iterator = usages().iterator();
-        return new Iterable<FrameState>() {
-            @Override
-            public Iterator<FrameState> iterator() {
-                return new Iterator<FrameState>() {
-                    private Node next;
-                    @Override
-                    public void remove() {
-                        throw new UnsupportedOperationException();
-                    }
-                    @Override
-                    public FrameState next() {
-                        forward();
-                        if (!hasNext()) {
-                            throw new NoSuchElementException();
-                        }
-                        FrameState res = (FrameState) next;
-                        next = null;
-                        return res;
-                    }
-                    @Override
-                    public boolean hasNext() {
-                        forward();
-                        return next != null;
-                    }
-                    private void forward() {
-                        while (!(next instanceof FrameState) && iterator.hasNext()) {
-                            next = iterator.next();
-                        }
-                    }
-                };
-            }
-        };
+    public NodeIterable<FrameState> innerFrameStates() {
+        return usages().filter(FrameState.class);
     }
 
     /**
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/LoopBeginNode.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/LoopBeginNode.java	Sun Feb 05 05:40:36 2012 +0100
@@ -45,12 +45,7 @@
     }
 
     public LoopEndNode loopEnd() {
-        for (LoopEndNode end : usages().filter(LoopEndNode.class)) {
-            if (end.loopBegin() == this) {
-                return end;
-            }
-        }
-        return null;
+        return usages().filter(LoopEndNode.class).first();
     }
 
     @Override
@@ -83,11 +78,6 @@
         throw ValueUtil.shouldNotReachHere();
     }
 
-    @Override
-    public Iterable<? extends Node> phiPredecessors() {
-        return Arrays.asList(new Node[]{this.forwardEdge(), this.loopEnd()});
-    }
-
     public EndNode forwardEdge() {
         return this.endAt(0);
     }
@@ -96,7 +86,7 @@
     public boolean verify() {
         assertTrue(loopEnd() != null, "missing loopEnd");
         assertTrue(forwardEdge() != null, "missing forwardEdge");
-        assertTrue(usages().filter(LoopEndNode.class).snapshot().size() == 1, "multiple loop ends");
+        assertTrue(usages().filter(LoopEndNode.class).count() == 1, "multiple loop ends");
         return super.verify();
     }
 
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/MergeNode.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/MergeNode.java	Sun Feb 05 05:40:36 2012 +0100
@@ -59,12 +59,8 @@
         return ends.get(index);
     }
 
-    public Iterable<? extends Node> phiPredecessors() {
-        return ends;
-    }
-
     @Override
-    public Iterable<EndNode> cfgPredecessors() {
+    public NodeIterable<EndNode> cfgPredecessors() {
         return ends;
     }
 
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/StructuredGraph.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/StructuredGraph.java	Sun Feb 05 05:40:36 2012 +0100
@@ -173,6 +173,7 @@
 
     public void replaceFixedWithFixed(FixedWithNextNode node, FixedWithNextNode replacement) {
         assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement;
+        replacement.setProbability(node.probability());
         FixedNode next = node.next();
         node.setNext(null);
         replacement.setNext(next);
@@ -268,6 +269,7 @@
     public void addAfterFixed(FixedWithNextNode node, FixedWithNextNode newNode) {
         assert node != null && newNode != null && node.isAlive() && newNode.isAlive() : "cannot add " + newNode + " after " + node;
         assert newNode.next() == null;
+        newNode.setProbability(node.probability());
         FixedNode next = node.next();
         node.setNext(newNode);
         newNode.setNext(next);
@@ -277,6 +279,7 @@
         assert node != null && newNode != null && node.isAlive() && newNode.isAlive() : "cannot add " + newNode + " before " + node;
         assert node.predecessor() != null && node.predecessor() instanceof FixedWithNextNode : "cannot add " + newNode + " before " + node;
         assert newNode.next() == null;
+        newNode.setProbability(node.probability());
         FixedWithNextNode pred = (FixedWithNextNode) node.predecessor();
         pred.setNext(newNode);
         newNode.setNext(node);
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/CheckCastNode.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/CheckCastNode.java	Sun Feb 05 05:40:36 2012 +0100
@@ -24,6 +24,7 @@
 
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
+import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.extended.*;
 import com.oracle.max.graal.nodes.spi.*;
@@ -31,11 +32,17 @@
 
 /**
  * The {@code CheckCastNode} represents a {@link Bytecodes#CHECKCAST}.
+ *
+ * The {@link #targetClass()} of a CheckCastNode can be null for array store checks!
  */
-public final class CheckCastNode extends TypeCheckNode implements Canonicalizable, LIRLowerable {
+public final class CheckCastNode extends TypeCheckNode implements Canonicalizable, LIRLowerable, Node.IterableNodeType {
 
     @Input protected final AnchorNode anchor;
 
+    public AnchorNode anchor() {
+        return anchor;
+    }
+
     /**
      * Creates a new CheckCast instruction.
      *
@@ -44,7 +51,11 @@
      * @param object the instruction producing the object
      */
     public CheckCastNode(AnchorNode anchor, ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object) {
-        super(targetClassInstruction, targetClass, object, targetClass == null ? StampFactory.forKind(CiKind.Object) : StampFactory.declared(targetClass));
+        this(anchor, targetClassInstruction, targetClass, object, EMPTY_HINTS, false);
+    }
+
+    public CheckCastNode(AnchorNode anchor, ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, RiResolvedType[] hints, boolean hintsExact) {
+        super(targetClassInstruction, targetClass, object, hints, hintsExact, targetClass == null ? StampFactory.forKind(CiKind.Object) : StampFactory.declared(targetClass));
         this.anchor = anchor;
     }
 
@@ -69,6 +80,13 @@
                 return object();
             }
         }
+
+        if (tool.assumptions() != null && hints() != null && targetClass() != null) {
+            if (!hintsExact() && hints().length == 1 && hints()[0] == targetClass().uniqueConcreteSubtype()) {
+                tool.assumptions().recordConcreteSubtype(targetClass(), hints()[0]);
+                return graph().unique(new CheckCastNode(anchor, targetClassInstruction(), targetClass(), object(), hints(), true));
+            }
+        }
         return this;
     }
 
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/InstanceOfNode.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/InstanceOfNode.java	Sun Feb 05 05:40:36 2012 +0100
@@ -48,7 +48,11 @@
      * @param object the instruction producing the object input to this instruction
      */
     public InstanceOfNode(ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, boolean negated) {
-        super(targetClassInstruction, targetClass, object, StampFactory.illegal());
+        this(targetClassInstruction, targetClass, object, EMPTY_HINTS, false, negated);
+    }
+
+    public InstanceOfNode(ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, RiResolvedType[] hints, boolean hintsExact, boolean negated) {
+        super(targetClassInstruction, targetClass, object, hints, hintsExact, StampFactory.illegal());
         this.negated = negated;
         assert targetClass != null;
     }
@@ -59,8 +63,9 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        if (object().exactType() != null) {
-            boolean result = object().exactType().isSubtypeOf(targetClass());
+        RiResolvedType exact = object().exactType();
+        if (exact != null) {
+            boolean result = exact.isSubtypeOf(targetClass());
             if (result != negated) {
                 // The instanceof check reduces to a null check.
                 return graph().unique(new NullCheckNode(object(), false));
@@ -78,11 +83,17 @@
                 assert false : "non-null constants are always expected to provide an exactType";
             }
         }
+        if (tool.assumptions() != null && hints() != null && targetClass() != null) {
+            if (!hintsExact() && hints().length == 1 && hints()[0] == targetClass().uniqueConcreteSubtype()) {
+                tool.assumptions().recordConcreteSubtype(targetClass(), hints()[0]);
+                return graph().unique(new InstanceOfNode(targetClassInstruction(), targetClass(), object(), hints(), true, negated));
+            }
+        }
         return this;
     }
 
     @Override
     public BooleanNode negate() {
-        return graph().unique(new InstanceOfNode(targetClassInstruction(), targetClass(), object(), !negated));
+        return graph().unique(new InstanceOfNode(targetClassInstruction(), targetClass(), object(), hints(), hintsExact(), !negated));
     }
 }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/MethodCallTargetNode.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/MethodCallTargetNode.java	Sun Feb 05 05:40:36 2012 +0100
@@ -106,10 +106,7 @@
     }
 
     public Invoke invoke() {
-        if (this.usages().size() == 0) {
-            return null;
-        }
-        return (Invoke) this.usages().iterator().next();
+        return (Invoke) this.usages().first();
     }
 
 
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/TypeCheckNode.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/TypeCheckNode.java	Sun Feb 05 05:40:36 2012 +0100
@@ -31,9 +31,12 @@
  */
 public abstract class TypeCheckNode extends BooleanNode {
 
+    protected static final RiResolvedType[] EMPTY_HINTS = new RiResolvedType[0];
     @Input private ValueNode object;
     @Input private ValueNode targetClassInstruction;
     @Data private final RiResolvedType targetClass;
+    @Data private final RiResolvedType[] hints;
+    @Data private final boolean hintsExact;
 
     /**
      * Creates a new TypeCheckNode.
@@ -42,11 +45,13 @@
      * @param object the node which produces the object
      * @param kind the result type of this node
      */
-    public TypeCheckNode(ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, Stamp stamp) {
+    public TypeCheckNode(ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, RiResolvedType[] hints, boolean hintsExact, Stamp stamp) {
         super(stamp);
         this.targetClassInstruction = targetClassInstruction;
         this.targetClass = targetClass;
         this.object = object;
+        this.hints = hints;
+        this.hintsExact = hintsExact;
     }
 
     public ValueNode object() {
@@ -64,4 +69,12 @@
     public RiResolvedType targetClass() {
         return targetClass;
     }
+
+    public RiResolvedType[] hints() {
+        return hints;
+    }
+
+    public boolean hintsExact() {
+        return hintsExact;
+    }
 }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/spi/EscapeOp.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/spi/EscapeOp.java	Sun Feb 05 05:40:36 2012 +0100
@@ -44,7 +44,7 @@
             assert ((IsTypeNode) usage).object() == node;
             return false;
         } else if (usage instanceof FrameState) {
-            assert ((FrameState) usage).inputs().contains(node);
+            assert usage.inputs().contains(node);
             return true;
         } else if (usage instanceof AccessMonitorNode) {
             assert ((AccessMonitorNode) usage).object() == node;
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/util/NodeIterators.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/util/NodeIterators.java	Sun Feb 05 05:40:36 2012 +0100
@@ -33,7 +33,7 @@
         return new NodeIterable<FixedNode>() {
             @Override
             public Iterator<FixedNode> iterator() {
-                return new NodeIterator<FixedNode>(until){
+                return new NodeIterator<FixedNode>(){
                     FixedNode p = n;
                     @Override
                     protected void forward() {
--- a/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinter.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinter.java	Sun Feb 05 05:40:36 2012 +0100
@@ -33,6 +33,7 @@
 import com.oracle.max.graal.alloc.util.*;
 import com.oracle.max.graal.compiler.alloc.*;
 import com.oracle.max.graal.compiler.alloc.Interval.UsePosList;
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.gen.*;
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.schedule.*;
@@ -73,10 +74,10 @@
      * @param label A label describing the compilation phase that produced the control flow graph.
      * @param blockMap A data structure describing the blocks in a method and how they are connected.
      */
-    public void printCFG(String label, BlockMap blockMap) {
+    public void printCFG(String label, BciBlockMapping blockMap) {
         begin("cfg");
         out.print("name \"").print(label).println('"');
-        for (BlockMap.Block block : blockMap.blocks) {
+        for (BciBlockMapping.Block block : blockMap.blocks) {
             begin("block");
             printBlock(block);
             end("block");
@@ -84,7 +85,7 @@
         end("cfg");
     }
 
-    private void printBlock(BlockMap.Block block) {
+    private void printBlock(BciBlockMapping.Block block) {
         out.print("name \"B").print(block.startBci).println('"');
         out.print("from_bci ").println(block.startBci);
         out.print("to_bci ").println(block.endBci);
@@ -92,7 +93,7 @@
         out.println("predecessors ");
 
         out.print("successors ");
-        for (BlockMap.Block succ : block.successors) {
+        for (BciBlockMapping.Block succ : block.successors) {
             if (!succ.isExceptionEntry) {
                 out.print("\"B").print(succ.startBci).print("\" ");
             }
@@ -100,7 +101,7 @@
         out.println();
 
         out.print("xhandlers");
-        for (BlockMap.Block succ : block.successors) {
+        for (BciBlockMapping.Block succ : block.successors) {
             if (succ.isExceptionEntry) {
                 out.print("\"B").print(succ.startBci).print("\" ");
             }
@@ -126,16 +127,16 @@
      * @param label A label describing the compilation phase that produced the control flow graph.
      * @param blocks The list of blocks to be printed.
      */
-    public void printCFG(String label, List<? extends Block> blocks) {
+    public void printCFG(String label, List<Block> blocks, SchedulePhase schedule) {
         begin("cfg");
         out.print("name \"").print(label).println('"');
         for (Block block : blocks) {
-            printBlock(block);
+            printBlock(block, schedule);
         }
         end("cfg");
     }
 
-    private void printBlock(Block block) {
+    private void printBlock(Block block, SchedulePhase schedule) {
         begin("block");
 
         out.print("name \"").print(blockToString(block)).println('"');
@@ -150,7 +151,7 @@
 
         out.print("successors ");
         for (Block succ : block.getSuccessors()) {
-            if (!succ.isExceptionBlock()) {
+            if (!succ.isExceptionEntry()) {
                 out.print("\"").print(blockToString(succ)).print("\" ");
             }
         }
@@ -158,7 +159,7 @@
 
         out.print("xhandlers");
         for (Block succ : block.getSuccessors()) {
-            if (succ.isExceptionBlock()) {
+            if (succ.isExceptionEntry()) {
                 out.print("\"").print(blockToString(succ)).print("\" ");
             }
         }
@@ -171,42 +172,43 @@
         if (block.isLoopEnd()) {
             out.print("\"lle\" ");
         }
-        if (block.isExceptionBlock()) {
+        if (block.isExceptionEntry()) {
             out.print("\"ex\" ");
         }
         out.println();
 
-        out.print("loop_index ").println(block.loopIndex());
-        out.print("loop_depth ").println(block.loopDepth());
-
-        printNodes(block);
-
-        if (block instanceof LIRBlock) {
-            printLIR((LIRBlock) block);
+        if (block.getLoop() != null) {
+            out.print("loop_index ").println(block.getLoop().index);
+            out.print("loop_depth ").println(block.getLoop().depth);
         }
 
+        printNodes(block, schedule);
+        printLIR(block);
         end("block");
     }
 
-    private void printNodes(Block block) {
+    private void printNodes(Block block, SchedulePhase schedule) {
+        if (schedule == null) {
+            return;
+        }
         begin("IR");
         out.println("HIR");
         out.disableIndentation();
 
         if (block.getPredecessors().size() == 0) {
             // Currently method parameters are not in the schedule, so print them separately here.
-            for (ValueNode param : block.firstNode().graph().getNodes(LocalNode.class)) {
+            for (ValueNode param : block.getBeginNode().graph().getNodes(LocalNode.class)) {
                 printNode(param);
             }
         }
-        if (block.firstNode() instanceof MergeNode) {
+        if (block.getBeginNode() instanceof MergeNode) {
             // Currently phi functions are not in the schedule, so print them separately here.
-            for (ValueNode phi : ((MergeNode) block.firstNode()).phis()) {
+            for (ValueNode phi : ((MergeNode) block.getBeginNode()).phis()) {
                 printNode(phi);
             }
         }
 
-        for (Node node : block.getInstructions()) {
+        for (Node node : schedule.nodesFor(block)) {
             printNode(node);
         }
         out.enableIndentation();
@@ -336,8 +338,8 @@
      *
      * @param block the block to print
      */
-    private void printLIR(LIRBlock block) {
-        List<LIRInstruction> lirInstructions = block.lir();
+    private void printLIR(Block block) {
+        List<LIRInstruction> lirInstructions = block.lir;
         if (lirInstructions == null) {
             return;
         }
@@ -349,11 +351,11 @@
             CiValue[] results = block.phis.results();
             for (int i = 0; i < results.length; i++) {
                 if (i == 0) {
-                    out.printf("nr %4d ", block.firstLirInstructionId()).print(COLUMN_END);
+                    out.printf("nr %4d ", block.getFirstLirInstructionId()).print(COLUMN_END);
                 }
                 out.print("instruction PHI ").print(results[i].toString()).print(" = (");
                 String sep = "";
-                for (LIRBlock pred : block.getLIRPredecessors()) {
+                for (Block pred : block.getPredecessors()) {
                     out.print(sep).print(block.phis.inputs(pred)[i].toString());
                     sep = ", ";
                 }
@@ -410,10 +412,10 @@
         if (lir == null) {
             // During all the front-end phases, the block schedule is built only for the debug output.
             // Therefore, the block numbers would be different for every CFG printed -> use the id of the first instruction.
-            return "B" + block.firstNode().toString(Verbosity.Id);
+            return "B" + block.getBeginNode().toString(Verbosity.Id);
         } else {
             // LIR instructions contain references to blocks and these blocks are printed as the blockID -> use the blockID.
-            return "B" + block.blockID();
+            return "B" + block.getId();
         }
     }
 
--- a/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinterObserver.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinterObserver.java	Sun Feb 05 05:40:36 2012 +0100
@@ -85,9 +85,9 @@
             cfgPrinter.lirGenerator = event.debugObject(LIRGenerator.class);
         }
 
-        BlockMap blockMap = event.debugObject(BlockMap.class);
+        BciBlockMapping blockMap = event.debugObject(BciBlockMapping.class);
         Graph graph = event.debugObject(Graph.class);
-        IdentifyBlocksPhase schedule = event.debugObject(IdentifyBlocksPhase.class);
+        SchedulePhase schedule = event.debugObject(SchedulePhase.class);
         LinearScan allocator = event.debugObject(LinearScan.class);
         Interval[] intervals = event.debugObject(Interval[].class);
         IntervalPrinter.Interval[] printIntervals = event.debugObject(IntervalPrinter.Interval[].class);
@@ -98,27 +98,20 @@
             cfgPrinter.printBytecodes(runtime.disassemble(blockMap.method));
         }
         if (cfgPrinter.lir != null) {
-            cfgPrinter.printCFG(event.label, cfgPrinter.lir.codeEmittingOrder());
+            cfgPrinter.printCFG(event.label, cfgPrinter.lir.codeEmittingOrder(), schedule);
             if (targetMethod != null) {
                 cfgPrinter.printMachineCode(runtime.disassemble(targetMethod), null);
             }
         } else if (graph != null) {
-            List<? extends Block> blocks = null;
             if (schedule == null) {
                 try {
-                    schedule = new IdentifyBlocksPhase(true, LIRBlock.FACTORY);
+                    schedule = new SchedulePhase();
                     schedule.apply((StructuredGraph) graph);
-                    blocks = schedule.getBlocks();
-
-                    ComputeLinearScanOrder clso = new ComputeLinearScanOrder(schedule.getBlocks().size(), schedule.loopCount(), (LIRBlock) schedule.getStartBlock());
-                    blocks = clso.codeEmittingOrder();
                 } catch (Throwable t) {
                     // nothing to do here...
                 }
             }
-            if (blocks != null) {
-                cfgPrinter.printCFG(event.label, blocks);
-            }
+            cfgPrinter.printCFG(event.label, Arrays.asList(schedule.getCFG().getBlocks()), schedule);
         }
         if (allocator != null && intervals != null) {
             cfgPrinter.printIntervals(event.label, intervals);
--- a/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/IdealGraphPrinter.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/IdealGraphPrinter.java	Sun Feb 05 05:40:36 2012 +0100
@@ -27,6 +27,7 @@
 import java.util.Map.Entry;
 
 import com.oracle.max.cri.ri.*;
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.graph.Node.Verbosity;
@@ -84,13 +85,13 @@
     /**
      * Prints an entire {@link Graph} with the specified title, optionally using short names for nodes.
      */
-    public void print(Graph graph, String title, IdentifyBlocksPhase predefinedSchedule) {
+    public void print(Graph graph, String title, SchedulePhase predefinedSchedule) {
         beginGraph(title);
         Set<Node> noBlockNodes = new HashSet<>();
-        IdentifyBlocksPhase schedule = predefinedSchedule;
+        SchedulePhase schedule = predefinedSchedule;
         if (schedule == null) {
             try {
-                schedule = new IdentifyBlocksPhase(true);
+                schedule = new SchedulePhase();
                 schedule.apply((StructuredGraph) graph);
             } catch (Throwable t) {
                 // nothing to do here...
@@ -98,7 +99,7 @@
         }
 
         beginNodes();
-        List<Edge> edges = printNodes(graph, schedule == null ? null : schedule.getNodeToBlock(), noBlockNodes);
+        List<Edge> edges = printNodes(graph, schedule == null ? null : schedule.getCFG().getNodeToBlock(), noBlockNodes);
         endNodes();
 
         beginEdges();
@@ -109,8 +110,8 @@
 
         if (schedule != null) {
             beginControlFlow();
-            for (Block block : schedule.getBlocks()) {
-                printBlock(graph, block, schedule.getNodeToBlock());
+            for (Block block : schedule.getCFG().getBlocks()) {
+                printBlock(graph, block, schedule.getCFG().getNodeToBlock());
             }
             printNoBlock(noBlockNodes);
             endControlFlow();
@@ -141,10 +142,10 @@
             printProperty("class", node.getClass().getSimpleName());
             Block block = nodeToBlock == null ? null : nodeToBlock.get(node);
             if (block != null) {
-                printProperty("block", Integer.toString(block.blockID()));
-                if (!(node instanceof PhiNode || node instanceof FrameState || node instanceof LocalNode) && !block.getInstructions().contains(node)) {
-                    printProperty("notInOwnBlock", "true");
-                }
+                printProperty("block", Integer.toString(block.getId()));
+//                if (!(node instanceof PhiNode || node instanceof FrameState || node instanceof LocalNode) && !block.nodes().contains(node)) {
+//                    printProperty("notInOwnBlock", "true");
+//                }
             } else {
                 printProperty("block", "noBlock");
                 noBlockNodes.add(node);
@@ -201,7 +202,7 @@
                 Position position = inputIter.nextPosition();
                 Node input = node.getNodeClass().get(node, position);
                 if (input != null) {
-                    edges.add(new Edge(input.toString(Verbosity.Id), input.successors().explicitCount(), node.toString(Verbosity.Id), toIndex, node.getNodeClass().getName(position)));
+                    edges.add(new Edge(input.toString(Verbosity.Id), input.successors().count(), node.toString(Verbosity.Id), toIndex, node.getNodeClass().getName(position)));
                 }
                 toIndex++;
             }
@@ -211,17 +212,17 @@
     }
 
     private void printBlock(Graph graph, Block block, NodeMap<Block> nodeToBlock) {
-        beginBlock(Integer.toString(block.blockID()));
+        beginBlock(Integer.toString(block.getId()));
         beginSuccessors();
         for (Block sux : block.getSuccessors()) {
             if (sux != null) {
-                printSuccessor(Integer.toString(sux.blockID()));
+                printSuccessor(Integer.toString(sux.getId()));
             }
         }
         endSuccessors();
         beginBlockNodes();
 
-        Set<Node> nodes = new HashSet<>(block.getInstructions());
+        Set<Node> nodes = new HashSet<>();
 
         if (nodeToBlock != null) {
             for (Node n : graph.getNodes()) {
@@ -234,7 +235,7 @@
 
         if (nodes.size() > 0) {
             // if this is the first block: add all locals to this block
-            if (block.getInstructions().size() > 0 && block.getInstructions().get(0) == ((StructuredGraph) graph).start()) {
+            if (block.getBeginNode() == ((StructuredGraph) graph).start()) {
                 for (Node node : graph.getNodes()) {
                     if (node instanceof LocalNode) {
                         nodes.add(node);
@@ -242,8 +243,9 @@
                 }
             }
 
+            Set<Node> snapshot = new HashSet<>(nodes);
             // add all framestates and phis to their blocks
-            for (Node node : block.getInstructions()) {
+            for (Node node : snapshot) {
                 if (node instanceof StateSplit && ((StateSplit) node).stateAfter() != null) {
                     nodes.add(((StateSplit) node).stateAfter());
                 }
--- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/ArrayCopySnippets.java	Sun Feb 05 05:37:52 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,258 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.snippets;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.nodes.extended.*;
-import com.oracle.max.graal.snippets.nodes.*;
-
-
-public class ArrayCopySnippets implements SnippetsInterface{
-
-    @Snippet
-    public static void arraycopy(byte[] src, int srcPos, byte[] dest, int destPos, int length) {
-        if (src == null || dest == null) {
-            throw new NullPointerException();
-        }
-        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
-            throw new IndexOutOfBoundsException();
-        }
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            if ((length & 0x01) == 0) {
-                if ((length & 0x02) == 0) {
-                    if ((length & 0x04) == 0) {
-                        copyLongsDown(src, srcPos, dest, destPos, length >> 3);
-                    } else {
-                        copyIntsDown(src, srcPos, dest, destPos, length >> 2);
-                    }
-                } else {
-                    copyShortsDown(src, srcPos, dest, destPos, length >> 1);
-                }
-            } else {
-                copyBytesDown(src, srcPos, dest, destPos, length);
-            }
-        } else {
-            if ((length & 0x01) == 0) {
-                if ((length & 0x02) == 0) {
-                    if ((length & 0x04) == 0) {
-                        copyLongsUp(src, srcPos, dest, destPos, length >> 3);
-                    } else {
-                        copyIntsUp(src, srcPos, dest, destPos, length >> 2);
-                    }
-                } else {
-                    copyShortsUp(src, srcPos, dest, destPos, length >> 1);
-                }
-            } else {
-                copyBytesUp(src, srcPos, dest, destPos, length);
-            }
-        }
-    }
-
-    @Snippet
-    public static void arraycopy(char[] src, int srcPos, char[] dest, int destPos, int length) {
-        if (src == null || dest == null) {
-            throw new NullPointerException();
-        }
-        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
-            throw new IndexOutOfBoundsException();
-        }
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            if ((length & 0x01) == 0) {
-                if ((length & 0x02) == 0) {
-                    copyLongsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 2);
-                } else {
-                    copyIntsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 1);
-                }
-            } else {
-                copyShortsDown(src, srcPos * 2L, dest, destPos * 2L, length);
-            }
-        } else {
-            if ((length & 0x01) == 0) {
-                if ((length & 0x02) == 0) {
-                    copyLongsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 2);
-                } else {
-                    copyIntsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 1);
-                }
-            } else {
-                copyShortsUp(src, srcPos * 2L, dest, destPos * 2L, length);
-            }
-        }
-    }
-
-    @Snippet
-    public static void arraycopy(short[] src, int srcPos, short[] dest, int destPos, int length) {
-        if (src == null || dest == null) {
-            throw new NullPointerException();
-        }
-        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
-            throw new IndexOutOfBoundsException();
-        }
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            if ((length & 0x01) == 0) {
-                if ((length & 0x02) == 0) {
-                    copyLongsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 2);
-                } else {
-                    copyIntsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 1);
-                }
-            } else {
-                copyShortsDown(src, srcPos * 2L, dest, destPos * 2L, length);
-            }
-        } else {
-            if ((length & 0x01) == 0) {
-                if ((length & 0x02) == 0) {
-                    copyLongsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 2);
-                } else {
-                    copyIntsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 1);
-                }
-            } else {
-                copyShortsUp(src, srcPos * 2L, dest, destPos * 2L, length);
-            }
-        }
-    }
-
-    @Snippet
-    public static void arraycopy(int[] src, int srcPos, int[] dest, int destPos, int length) {
-        if (src == null || dest == null) {
-            throw new NullPointerException();
-        }
-        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
-            throw new IndexOutOfBoundsException();
-        }
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            if ((length & 0x01) == 0) {
-                copyLongsDown(src, srcPos * 4L, dest, destPos * 4L, length >> 1);
-            } else {
-                copyIntsDown(src, srcPos * 4L, dest, destPos * 4L, length);
-            }
-        } else {
-            if ((length & 0x01) == 0) {
-                copyLongsUp(src, srcPos * 4L, dest, destPos * 4L, length >> 1);
-            } else {
-                copyIntsUp(src, srcPos * 4L, dest, destPos * 4L, length);
-            }
-        }
-    }
-
-    @Snippet
-    public static void arraycopy(long[] src, int srcPos, long[] dest, int destPos, int length) {
-        if (src == null || dest == null) {
-            throw new NullPointerException();
-        }
-        if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) {
-            throw new IndexOutOfBoundsException();
-        }
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            copyLongsDown(src, srcPos * 8L, dest, destPos * 8L, length);
-        } else {
-            copyLongsUp(src, srcPos * 8L, dest, destPos * 8L, length);
-        }
-    }
-
-    @Snippet
-    public static void copyBytesDown(Object src, int srcPos, Object dest, int destPos, int length)  {
-        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Byte);
-        for (long i = length - 1; i >= 0; i--) {
-            Byte a = UnsafeLoadNode.load(src, i + (srcPos + header), CiKind.Byte);
-            UnsafeStoreNode.store(dest, i + (destPos + header), a.byteValue(), CiKind.Byte);
-        }
-    }
-
-    @Snippet
-    public static void copyShortsDown(Object src, long srcOffset, Object dest, long destOffset, int length)  {
-        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short);
-        for (long i = (length - 1) * 2; i >= 0; i -= 2) {
-            Character a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Short);
-            UnsafeStoreNode.store(dest, i + (destOffset + header), a.charValue(), CiKind.Short);
-        }
-    }
-
-    @Snippet
-    public static void copyIntsDown(Object src, long srcOffset, Object dest, long destOffset, int length)  {
-        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short);
-        for (long i = (length - 1) * 4; i >= 0; i -= 4) {
-            Integer a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Int);
-            UnsafeStoreNode.store(dest, i + (destOffset + header), a.intValue(), CiKind.Int);
-        }
-    }
-
-    @Snippet
-    public static void copyLongsDown(Object src, long srcOffset, Object dest, long destOffset, int length)  {
-        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short);
-        for (long i = (length - 1) * 8; i >= 0; i -= 8) {
-            Long a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Long);
-            UnsafeStoreNode.store(dest, i + (destOffset + header), a.longValue(), CiKind.Long);
-        }
-    }
-
-    /**
-     * Copies {@code length} bytes from {@code src} starting at {@code srcPos} to {@code dest} starting at {@code destPos}.
-     * @param src source object
-     * @param srcPos source offset
-     * @param dest destination object
-     * @param destPos destination offset
-     * @param length number of bytes to copy
-     */
-    @Snippet
-    public static void copyBytesUp(Object src, int srcPos, Object dest, int destPos, int length)  {
-        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Byte);
-        for (long i = 0; i < length; i++) {
-            Byte a = UnsafeLoadNode.load(src, i + (srcPos + header), CiKind.Byte);
-            UnsafeStoreNode.store(dest, i + (destPos + header), a.byteValue(), CiKind.Byte);
-        }
-    }
-
-    /**
-     * Copies {@code length} shorts from {@code src} starting at offset {@code srcOffset} (in bytes) to {@code dest} starting at offset {@code destOffset} (in bytes).
-     * @param src
-     * @param srcOffset (in bytes)
-     * @param dest
-     * @param destOffset (in bytes)
-     * @param length  (in shorts)
-     */
-    @Snippet
-    public static void copyShortsUp(Object src, long srcOffset, Object dest, long destOffset, int length)  {
-        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short);
-        for (long i = 0; i < length * 2L; i += 2) {
-            Character a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Short);
-            UnsafeStoreNode.store(dest, i + (destOffset + header), a.charValue(), CiKind.Short);
-        }
-    }
-
-    @Snippet
-    public static void copyIntsUp(Object src, long srcOffset, Object dest, long destOffset, int length)  {
-        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Int);
-        for (long i = 0; i < length * 4L; i += 4) {
-            Integer a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Int);
-            UnsafeStoreNode.store(dest, i + (destOffset + header), a.intValue(), CiKind.Int);
-        }
-    }
-
-    @Snippet
-    public static void copyLongsUp(Object src, long srcOffset, Object dest, long destOffset, int length)  {
-        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Long);
-        for (long i = 0; i < length * 8L; i += 8) {
-            Long a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Long);
-            UnsafeStoreNode.store(dest, i + (destOffset + header), a.longValue(), CiKind.Long);
-        }
-    }
-}
--- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/GraalIntrinsics.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/GraalIntrinsics.java	Sun Feb 05 05:40:36 2012 +0100
@@ -25,7 +25,6 @@
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.phases.*;
-import com.oracle.max.graal.compiler.phases.PhasePlan.PhasePosition;
 import com.oracle.max.graal.cri.*;
 
 /**
@@ -38,8 +37,6 @@
             Snippets.install(runtime, target, new DoubleSnippets(), plan);
             Snippets.install(runtime, target, new FloatSnippets(), plan);
             Snippets.install(runtime, target, new NodeClassSnippets(), plan);
-            Snippets.install(runtime, target, new ArrayCopySnippets(), plan);
-            plan.addPhase(PhasePosition.HIGH_LEVEL, new IntrinsifyArrayCopyPhase(runtime));
         }
     }
 }
--- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/IntrinsifyArrayCopyPhase.java	Sun Feb 05 05:37:52 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.snippets;
-
-import java.lang.reflect.*;
-
-import com.oracle.max.cri.ri.*;
-import com.oracle.max.graal.compiler.phases.*;
-import com.oracle.max.graal.compiler.util.*;
-import com.oracle.max.graal.cri.*;
-import com.oracle.max.graal.graph.*;
-import com.oracle.max.graal.nodes.*;
-import com.oracle.max.graal.nodes.java.*;
-
-public class IntrinsifyArrayCopyPhase extends Phase {
-    private final GraalRuntime runtime;
-    private RiResolvedMethod arrayCopy;
-    private RiResolvedMethod byteArrayCopy;
-    private RiResolvedMethod shortArrayCopy;
-    private RiResolvedMethod charArrayCopy;
-    private RiResolvedMethod intArrayCopy;
-    private RiResolvedMethod longArrayCopy;
-
-    public IntrinsifyArrayCopyPhase(GraalRuntime runtime) {
-        this.runtime = runtime;
-        try {
-            byteArrayCopy = getArrayCopySnippet(runtime, byte.class);
-            charArrayCopy = getArrayCopySnippet(runtime, char.class);
-            shortArrayCopy = getArrayCopySnippet(runtime, short.class);
-            intArrayCopy = getArrayCopySnippet(runtime, int.class);
-            longArrayCopy = getArrayCopySnippet(runtime, long.class);
-            arrayCopy = runtime.getRiMethod(System.class.getDeclaredMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class));
-        } catch (SecurityException e) {
-            e.printStackTrace();
-        } catch (NoSuchMethodException e) {
-            e.printStackTrace();
-        }
-    }
-
-    private static RiResolvedMethod getArrayCopySnippet(RiRuntime runtime, Class<?> componentClass) throws NoSuchMethodException {
-        Class<?> arrayClass = Array.newInstance(componentClass, 0).getClass();
-        return runtime.getRiMethod(ArrayCopySnippets.class.getDeclaredMethod("arraycopy", arrayClass, int.class, arrayClass, int.class, int.class));
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.class)) {
-            RiResolvedMethod targetMethod = methodCallTarget.targetMethod();
-            RiResolvedMethod snippetMethod = null;
-            if (targetMethod == arrayCopy) {
-                ValueNode src = methodCallTarget.arguments().get(0);
-                ValueNode dest = methodCallTarget.arguments().get(2);
-                if (src == null || dest == null) { //TODO (gd) this should never be null : check
-                    return;
-                }
-                RiResolvedType srcDeclaredType = src.declaredType();
-                RiResolvedType destDeclaredType = dest.declaredType();
-                if (srcDeclaredType != null
-                                && srcDeclaredType.isArrayClass()
-                                && destDeclaredType != null
-                                && destDeclaredType.isArrayClass()
-                                && srcDeclaredType.componentType() == destDeclaredType.componentType()) {
-                    Class<?> componentType = srcDeclaredType.componentType().toJava();
-                    if (componentType.equals(int.class)) {
-                        snippetMethod = intArrayCopy;
-                    } else if (componentType.equals(char.class)) {
-                        snippetMethod = charArrayCopy;
-                    } else if (componentType.equals(long.class)) {
-                        snippetMethod = longArrayCopy;
-                    } else if (componentType.equals(byte.class)) {
-                        snippetMethod = byteArrayCopy;
-                    } else if (componentType.equals(short.class)) {
-                        snippetMethod = shortArrayCopy;
-                    }
-                }
-            }
-
-            if (snippetMethod != null) {
-                StructuredGraph snippetGraph = (StructuredGraph) snippetMethod.compilerStorage().get(Graph.class);
-                assert snippetGraph != null : "ArrayCopySnippets should be installed";
-                //TTY.println("  >  Intinsify");
-                InliningUtil.inline(methodCallTarget.invoke(), snippetGraph, false);
-            }
-        }
-        new CanonicalizerPhase(null, runtime, null).apply(graph);
-    }
-}
--- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/Snippets.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/Snippets.java	Sun Feb 05 05:40:36 2012 +0100
@@ -121,6 +121,7 @@
         for (LoopEndNode end : graph.getNodes(LoopEndNode.class)) {
             end.setSafepointPolling(false);
         }
+        new InsertStateAfterPlaceholderPhase().apply(graph);
 
         Debug.dump(graph, "%s: Final", snippetRiMethod.name());
 
@@ -128,5 +129,4 @@
 
         return graph;
     }
-
 }
--- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/SystemSnippets.java	Sun Feb 05 05:37:52 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.snippets;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.nodes.extended.*;
-
-/**
- * Snippets for {@link java.lang.System} methods.
- */
-@ClassSubstitution(java.lang.System.class)
-public class SystemSnippets implements SnippetsInterface {
-
-    // TODO: public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) { }
-
-    public static long currentTimeMillis() {
-        return RuntimeCallNode.performCall(CiRuntimeCall.JavaTimeMillis);
-    }
-
-    public static long nanoTime() {
-        return RuntimeCallNode.performCall(CiRuntimeCall.JavaTimeNanos);
-    }
-
-}
--- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/UnsafeSnippets.java	Sun Feb 05 05:37:52 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,251 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.snippets;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.util.*;
-import com.oracle.max.graal.nodes.extended.*;
-import com.oracle.max.graal.nodes.java.*;
-
-/**
- * Snippets for {@link sun.misc.Unsafe} methods.
- */
-@ClassSubstitution(sun.misc.Unsafe.class)
-public class UnsafeSnippets implements SnippetsInterface {
-
-    public boolean compareAndSwapObject(Object o, long offset, Object expected, Object x) {
-        return CompareAndSwapNode.compareAndSwap(o, offset, expected, x);
-    }
-
-    public boolean compareAndSwapInt(Object o, long offset, int expected, int x) {
-        return CompareAndSwapNode.compareAndSwap(o, offset, expected, x);
-    }
-
-    public boolean compareAndSwapLong(Object o, long offset, long expected, long x) {
-        return CompareAndSwapNode.compareAndSwap(o, offset, expected, x);
-    }
-
-    public Object getObject(Object o, long offset) {
-        return UnsafeLoadNode.load(o, offset, CiKind.Object);
-    }
-
-    public Object getObjectVolatile(Object o, long offset) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
-        Object result = getObject(o, offset);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
-        return result;
-    }
-
-    public void putObject(Object o, long offset, Object x) {
-        UnsafeStoreNode.store(o, offset, x, CiKind.Object);
-    }
-
-    public void putObjectVolatile(Object o, long offset, Object x) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
-        putObject(o, offset, x);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
-    }
-
-    public int getInt(Object o, long offset) {
-        Integer value = UnsafeLoadNode.load(o, offset, CiKind.Int);
-        return value;
-    }
-
-    public int getIntVolatile(Object o, long offset) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
-        int result = getInt(o, offset);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
-        return result;
-    }
-
-    public void putInt(Object o, long offset, int x) {
-        UnsafeStoreNode.store(o, offset, x, CiKind.Int);
-    }
-
-    public void putIntVolatile(Object o, long offset, int x) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
-        putInt(o, offset, x);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
-    }
-
-    public boolean getBoolean(Object o, long offset) {
-        @JavacBug(id = 6995200)
-        Boolean result = UnsafeLoadNode.load(o, offset, CiKind.Boolean);
-        return result;
-    }
-
-    public boolean getBooleanVolatile(Object o, long offset) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
-        boolean result = getBoolean(o, offset);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
-        return result;
-    }
-
-    public void putBoolean(Object o, long offset, boolean x) {
-        UnsafeStoreNode.store(o, offset, x, CiKind.Boolean);
-    }
-
-    public void putBooleanVolatile(Object o, long offset, boolean x) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
-        putBoolean(o, offset, x);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
-    }
-
-    public byte getByte(Object o, long offset) {
-        @JavacBug(id = 6995200)
-        Byte result = UnsafeLoadNode.load(o, offset, CiKind.Byte);
-        return result;
-    }
-
-    public byte getByteVolatile(Object o, long offset) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
-        byte result = getByte(o, offset);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
-        return result;
-    }
-
-    public void putByte(Object o, long offset, byte x) {
-        UnsafeStoreNode.store(o, offset, x, CiKind.Byte);
-    }
-
-    public void putByteVolatile(Object o, long offset, byte x) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
-        putByte(o, offset, x);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
-    }
-
-    public short getShort(Object o, long offset) {
-        @JavacBug(id = 6995200)
-        Short result = UnsafeLoadNode.load(o, offset, CiKind.Short);
-        return result;
-    }
-
-    public short getShortVolatile(Object o, long offset) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
-        short result = getShort(o, offset);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
-        return result;
-    }
-
-    public void putShort(Object o, long offset, short x) {
-        UnsafeStoreNode.store(o, offset, x, CiKind.Short);
-    }
-
-    public void putShortVolatile(Object o, long offset, short x) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
-        putShort(o, offset, x);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
-    }
-
-    public char getChar(Object o, long offset) {
-        @JavacBug(id = 6995200)
-        Character result = UnsafeLoadNode.load(o, offset, CiKind.Char);
-        return result;
-    }
-
-    public char getCharVolatile(Object o, long offset) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
-        char result = getChar(o, offset);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
-        return result;
-    }
-
-    public void putChar(Object o, long offset, char x) {
-        UnsafeStoreNode.store(o, offset, x, CiKind.Char);
-    }
-
-    public void putCharVolatile(Object o, long offset, char x) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
-        putChar(o, offset, x);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
-    }
-
-    public long getLong(Object o, long offset) {
-        @JavacBug(id = 6995200)
-        Long result = UnsafeLoadNode.load(o, offset, CiKind.Long);
-        return result;
-    }
-
-    public long getLongVolatile(Object o, long offset) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
-        long result = getLong(o, offset);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
-        return result;
-    }
-
-    public void putLong(Object o, long offset, long x) {
-        UnsafeStoreNode.store(o, offset, x, CiKind.Long);
-    }
-
-    public void putLongVolatile(Object o, long offset, long x) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
-        putLong(o, offset, x);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
-    }
-
-    public float getFloat(Object o, long offset) {
-        @JavacBug(id = 6995200)
-        Float result = UnsafeLoadNode.load(o, offset, CiKind.Float);
-        return result;
-    }
-
-    public float getFloatVolatile(Object o, long offset) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
-        float result = getFloat(o, offset);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
-        return result;
-    }
-
-    public void putFloat(Object o, long offset, float x) {
-        UnsafeStoreNode.store(o, offset, x, CiKind.Float);
-    }
-
-    public void putFloatVolatile(Object o, long offset, float x) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
-        putFloat(o, offset, x);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
-    }
-
-    public double getDouble(Object o, long offset) {
-        @JavacBug(id = 6995200)
-        Double result = UnsafeLoadNode.load(o, offset, CiKind.Double);
-        return result;
-    }
-
-    public double getDoubleVolatile(Object o, long offset) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ);
-        double result = getDouble(o, offset);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ);
-        return result;
-    }
-
-    public void putDouble(Object o, long offset, double x) {
-        UnsafeStoreNode.store(o, offset, x, CiKind.Double);
-    }
-
-    public void putDoubleVolatile(Object o, long offset, double x) {
-        MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE);
-        putDouble(o, offset, x);
-        MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE);
-    }
-}
--- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/BoxingEliminationTest.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/BoxingEliminationTest.java	Sun Feb 05 05:40:36 2012 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.max.graal.compiler.tests;
 
+import static com.oracle.max.graal.graph.iterators.NodePredicates.*;
+
 import java.util.*;
 
 import org.junit.*;
@@ -97,12 +99,8 @@
         identifyBoxingPhase.apply(graph);
         LocalNode local = graph.getNodes(LocalNode.class).iterator().next();
         ConstantNode constant = ConstantNode.forInt(0, graph);
-        for (Node n : local.usages().snapshot()) {
-            if (n instanceof FrameState) {
-                // Do not replace.
-            } else {
-                n.replaceFirstInput(local, constant);
-            }
+        for (Node n : local.usages().filter(isNotA(FrameState.class)).snapshot()) {
+            n.replaceFirstInput(local, constant);
         }
         Collection<Invoke> hints = new ArrayList<>();
         for (Invoke invoke : graph.getInvokes()) {
--- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/DegeneratedLoopsTest.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/DegeneratedLoopsTest.java	Sun Feb 05 05:40:36 2012 +0100
@@ -22,9 +22,10 @@
  */
 package com.oracle.max.graal.compiler.tests;
 
-import junit.framework.AssertionFailedError;
+import static com.oracle.max.graal.graph.iterators.NodePredicates.*;
+import junit.framework.*;
 
-import org.junit.*;
+import org.junit.Test;
 
 import com.oracle.max.graal.compiler.phases.*;
 import com.oracle.max.graal.debug.*;
@@ -84,12 +85,8 @@
         Debug.dump(graph, "Graph");
         LocalNode local = graph.getNodes(LocalNode.class).iterator().next();
         ConstantNode constant = ConstantNode.forInt(0, graph);
-        for (Node n : local.usages().snapshot()) {
-            if (n instanceof FrameState) {
-                // Do not replace.
-            } else {
-                n.replaceFirstInput(local, constant);
-            }
+        for (Node n : local.usages().filter(isNotA(FrameState.class)).snapshot()) {
+            n.replaceFirstInput(local, constant);
         }
         for (Invoke invoke : graph.getInvokes()) {
             invoke.intrinsify(null);
--- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/GraphScheduleTest.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/GraphScheduleTest.java	Sun Feb 05 05:40:36 2012 +0100
@@ -26,20 +26,21 @@
 
 import org.junit.*;
 
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 
 public class GraphScheduleTest extends GraphTest {
     protected void assertOrderedAfterSchedule(StructuredGraph graph, Node a, Node b) {
-        IdentifyBlocksPhase ibp = new IdentifyBlocksPhase(true);
+        SchedulePhase ibp = new SchedulePhase();
         ibp.apply(graph);
-        NodeMap<Block> nodeToBlock = ibp.getNodeToBlock();
+        NodeMap<Block> nodeToBlock = ibp.getCFG().getNodeToBlock();
         Block bBlock = nodeToBlock.get(b);
         Block aBlock = nodeToBlock.get(a);
 
         if (bBlock == aBlock) {
-            List<Node> instructions = bBlock.getInstructions();
+            List<Node> instructions = ibp.nodesFor(bBlock);
             Assert.assertTrue(instructions.indexOf(b) > instructions.indexOf(a));
         } else {
             Block block = bBlock;
@@ -47,7 +48,7 @@
                 if (block == aBlock) {
                     break;
                 }
-                block = block.dominator();
+                block = block.getDominator();
             }
             Assert.assertTrue(block == aBlock);
         }
--- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/GraphTest.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/GraphTest.java	Sun Feb 05 05:40:36 2012 +0100
@@ -48,7 +48,7 @@
  * <p>
  * The tests can be run in Eclipse with the "Compiler Unit Test" Eclipse
  * launch configuration found in the top level of this project or by
- * running {@code mx gcut} on the command line.
+ * running {@code mx unittest} on the command line.
  */
 public abstract class GraphTest {
 
--- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/IfCanonicalizerTest.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/IfCanonicalizerTest.java	Sun Feb 05 05:40:36 2012 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.max.graal.compiler.tests;
 
+import static com.oracle.max.graal.graph.iterators.NodePredicates.*;
+
 import org.junit.*;
 
 import com.oracle.max.graal.compiler.phases.*;
@@ -137,12 +139,8 @@
         StructuredGraph graph = parse(snippet);
         LocalNode local = graph.getNodes(LocalNode.class).iterator().next();
         ConstantNode constant = ConstantNode.forInt(0, graph);
-        for (Node n : local.usages().snapshot()) {
-            if (n instanceof FrameState) {
-                // Do not replace.
-            } else {
-                n.replaceFirstInput(local, constant);
-            }
+        for (Node n : local.usages().filter(isNotA(FrameState.class)).snapshot()) {
+            n.replaceFirstInput(local, constant);
         }
         Debug.dump(graph, "Graph");
         new CanonicalizerPhase(null, runtime(), null).apply(graph);
--- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/InvokeTest.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/InvokeTest.java	Sun Feb 05 05:40:36 2012 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.max.graal.compiler.tests;
 
+import static com.oracle.max.graal.graph.iterators.NodePredicates.*;
+
 import java.util.*;
 
 import org.junit.*;
@@ -72,12 +74,8 @@
         StructuredGraph graph = parse(snippet);
         LocalNode local = graph.getNodes(LocalNode.class).iterator().next();
         ConstantNode constant = ConstantNode.forInt(0, graph);
-        for (Node n : local.usages().snapshot()) {
-            if (n instanceof FrameState) {
-                // Do not replace.
-            } else {
-                n.replaceFirstInput(local, constant);
-            }
+        for (Node n : local.usages().filter(isNotA(FrameState.class)).snapshot()) {
+            n.replaceFirstInput(local, constant);
         }
         Collection<Invoke> hints = new ArrayList<>();
         for (Invoke invoke : graph.getInvokes()) {
--- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/MonitorTest.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/MonitorTest.java	Sun Feb 05 05:40:36 2012 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.max.graal.compiler.tests;
 
+import static com.oracle.max.graal.graph.iterators.NodePredicates.*;
+
 import java.util.*;
 
 import junit.framework.AssertionFailedError;
@@ -30,6 +32,7 @@
 
 import com.oracle.max.graal.compiler.phases.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.iterators.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.java.*;
 
@@ -64,10 +67,9 @@
     @Test
     public void test2() {
         StructuredGraph graph = parseAndProcess("test2Snippet");
-        Collection<MonitorExitNode> monitors = graph.getNodes(MonitorExitNode.class).snapshot();
-        Assert.assertEquals(1, monitors.size());
-        MonitorExitNode monitor = monitors.iterator().next();
-        Assert.assertEquals(monitor.stateAfter().bci, 3);
+        NodeIterable<MonitorExitNode> monitors = graph.getNodes(MonitorExitNode.class);
+        Assert.assertEquals(1, monitors.count());
+        Assert.assertEquals(monitors.first().stateAfter().bci, 3);
     }
 
     @SuppressWarnings("all")
@@ -81,14 +83,10 @@
 
     private StructuredGraph parseAndProcess(String snippet) {
         StructuredGraph graph = parse(snippet);
-        LocalNode local = graph.getNodes(LocalNode.class).iterator().next();
+        LocalNode local = graph.getNodes(LocalNode.class).first();
         ConstantNode constant = ConstantNode.forInt(0, graph);
-        for (Node n : local.usages().snapshot()) {
-            if (n instanceof FrameState) {
-                // Do not replace.
-            } else {
-                n.replaceFirstInput(local, constant);
-            }
+        for (Node n : local.usages().filter(isNotA(FrameState.class)).snapshot()) {
+            n.replaceFirstInput(local, constant);
         }
         Collection<Invoke> hints = new ArrayList<>();
         for (Invoke invoke : graph.getInvokes()) {
--- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/NestedLoopTest.java	Sun Feb 05 05:37:52 2012 +0100
+++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/NestedLoopTest.java	Sun Feb 05 05:40:36 2012 +0100
@@ -24,8 +24,9 @@
 
 import org.junit.*;
 
-import com.oracle.max.graal.compiler.loop.*;
+import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.debug.*;
+import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 
 public class NestedLoopTest extends GraphTest {
@@ -144,24 +145,40 @@
     private void test(String snippet, int rootExits, int nestedExits, int innerExits) {
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
-        LoopInfo loopInfo = LoopUtil.computeLoopInfo(graph);
-        loopInfo.print();
-        Loop rootLoop = loopInfo.rootLoops().get(0);
-        Loop nestedLoop = rootLoop.children().get(0);
-        Loop innerMostLoop = nestedLoop.children().get(0);
+        ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true);
+
+        Assert.assertTrue(cfg.getLoops().length == 3);
+        Loop rootLoop = cfg.getLoops()[0];
+        Loop nestedLoop = cfg.getLoops()[1];
+        Loop innerMostLoop = cfg.getLoops()[2];
         Invoke a = getInvoke("a", graph);
         Invoke b = getInvoke("b", graph);
         Invoke c = getInvoke("c", graph);
         Invoke d = getInvoke("d", graph);
-        Assert.assertTrue(rootLoop.containsDirectFixed((FixedNode) a));
-        Assert.assertTrue(nestedLoop.containsDirectFixed((FixedNode) b));
-        Assert.assertTrue(innerMostLoop.containsDirectFixed((FixedNode) c));
-        Assert.assertTrue(innerMostLoop.containsDirectFixed((FixedNode) d));
-        Assert.assertTrue(rootLoop.containsFixed((FixedNode) d));
-        Assert.assertTrue(nestedLoop.containsFixed((FixedNode) d));
-        Assert.assertEquals(rootExits, rootLoop.exits().cardinality());
-        Assert.assertEquals(nestedExits, nestedLoop.exits().cardinality());
-        Assert.assertEquals(innerExits, innerMostLoop.exits().cardinality());
+        Assert.assertTrue(containsDirect(rootLoop, a, cfg));
+        Assert.assertTrue(containsDirect(nestedLoop, b, cfg));
+        Assert.assertTrue(containsDirect(innerMostLoop, c, cfg));
+        Assert.assertTrue(containsDirect(innerMostLoop, d, cfg));
+        Assert.assertTrue(contains(rootLoop, d, cfg));
+        Assert.assertTrue(contains(nestedLoop, d, cfg));
+        Assert.assertEquals(rootExits, rootLoop.exits.size());
+        Assert.assertEquals(nestedExits, nestedLoop.exits.size());
+        Assert.assertEquals(innerExits, innerMostLoop.exits.size());
         Debug.dump(graph, "Graph");
     }
+
+    private static boolean contains(Loop loop, Invoke node, ControlFlowGraph cfg) {
+        Block block = cfg.blockFor((Node) node);
+        Assert.assertNotNull(block);
+        return loop.blocks.contains(block);
+    }
+
+    private static boolean containsDirect(Loop loop, Invoke node, ControlFlowGraph cfg) {
+        for (Loop child : loop.children) {
+            if (contains(child, node, cfg)) {
+                return false;
+            }
+        }
+        return contains(loop, node, cfg);
+    }
 }
--- a/mx/commands.py	Sun Feb 05 05:37:52 2012 +0100
+++ b/mx/commands.py	Sun Feb 05 05:40:36 2012 +0100
@@ -34,7 +34,16 @@
 import json
 
 _graal_home = dirname(dirname(__file__))
+
+""" Used to distinguish an exported GraalVM (see 'mx export'). """
 _vmSourcesAvailable = exists(join(_graal_home, 'make')) and exists(join(_graal_home, 'src')) 
+
+""" The VM that will be run by the 'vm' command: graal(default), client or server.
+    This can be set via the global '--vm' option. """
+_vm = 'graal'
+
+""" The VM build that will be run by the 'vm' command: product(default), fastdebug or debug.
+    This can be set via the global '--fastdebug' and '--debug' options. """
 _vmbuild = 'product'
 
 _copyrightTemplate = """/*
@@ -133,7 +142,7 @@
         res = []
         mx.log("=== Server VM ===")
         printArg = '-XX:+PrintCompilation' if verbose else '-XX:-PrintCompilation'
-        res.append(vm(['-cp', cp, printArg] + sharedArgs, vm="-server"))
+        res.append(vm(['-cp', cp, printArg] + sharedArgs, vm='server'))
         mx.log("=== Graal VM ===")
         printArg = '-G:+PrintCompilation' if verbose else '-G:-PrintCompilation'
         res.append(vm(['-cp', cp, printArg, '-G:-Extend', '-G:-Inline'] + sharedArgs))
@@ -204,7 +213,7 @@
     
     failed = []
     for (test, n) in numTests.items():
-        if not sanitycheck.getDacapo(test, n, dacapoArgs).test('-graal', opts=vmOpts):
+        if not sanitycheck.getDacapo(test, n, dacapoArgs).test('graal', opts=vmOpts):
             failed.append(test)
     
     if len(failed) != 0:
@@ -304,6 +313,7 @@
 
 
     parser = ArgumentParser(prog='mx build');
+    parser.add_argument('--vm', action='store', dest='vm', default='graal', choices=['graal', 'server', 'client'], help='the VM to be built')
     
     # Call mx.build to compile the Java sources        
     opts = mx.build(['--source', '1.7'] + args, parser=parser)
@@ -315,16 +325,25 @@
     if len(builds) == 0:
         builds = ['product']
 
+    vm = opts.vm
+    if vm == 'server':
+        buildSuffix = ''
+    elif vm == 'client':
+        buildSuffix = '1'
+    else:
+        assert vm is 'graal'
+        buildSuffix = 'graal'
+        
     for build in builds:
 
         jdk = _jdk(build, True)
         if build == 'debug':
             build = 'jvmg'
-        
-        graalVmDir = join(jdk, 'jre', 'lib', 'amd64', 'graal')
-        if not exists(graalVmDir):
-            mx.log('Creating Graal directory in JDK7: ' + graalVmDir)
-            os.makedirs(graalVmDir)
+            
+        vmDir = join(jdk, 'jre', 'lib', 'amd64', vm)
+        if not exists(vmDir):
+            mx.log('Creating VM directory in JDK7: ' + vmDir)
+            os.makedirs(vmDir)
     
         def filterXusage(line):
             if not 'Xusage.txt' in line:
@@ -353,17 +372,20 @@
             env.setdefault('HOTSPOT_BUILD_JOBS', '3')
             env['ALT_BOOTDIR'] = jdk
             env.setdefault('INSTALL', 'y')
-            mx.run([mx.gmake_cmd(), build + 'graal'], cwd=join(_graal_home, 'make'), err=filterXusage)
+            mx.run([mx.gmake_cmd(), build + buildSuffix], cwd=join(_graal_home, 'make'), err=filterXusage)
     
-def vm(args, vm='-graal', nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, vmbuild=None):
+def vm(args, vm=None, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, vmbuild=None):
     """run the GraalVM"""
 
+    if vm is None:
+        vm = _vm
+        
     build = vmbuild if vmbuild is not None else _vmbuild if _vmSourcesAvailable else 'product'
     mx.expand_project_in_args(args)  
     if mx.java().debug:
         args = ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000'] + args
     exe = join(_jdk(build), 'bin', mx.exe_suffix('java'))
-    return mx.run([exe, vm] + args, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout)
+    return mx.run([exe, '-' + vm] + args, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout)
 
 
 # Table of unit tests.
@@ -429,43 +451,52 @@
 def gate(args):
     """run the tests used to validate a push
 
-    If this commands exits with a 0 exit code, then the source code is in
+    If this command exits with a 0 exit code, then the source code is in
     a state that would be accepted for integration into the main repository."""
     
+    
+    
     class Task:
         def __init__(self, title):
             self.start = time.time()
             self.title = title
+            self.end = None
+            self.duration = None
             mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: BEGIN: ') + title)
         def stop(self):
-            duration = datetime.timedelta(seconds=time.time() - self.start)
-            mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: END:   ') + self.title + ' [' + str(duration) + ']')
+            self.end = time.time()
+            self.duration = datetime.timedelta(seconds=self.end - self.start)
+            mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: END:   ') + self.title + ' [' + str(self.duration) + ']')
+            return self
         def abort(self, codeOrMessage):
-            duration = datetime.timedelta(seconds=time.time() - self.start)
-            mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: ABORT: ') + self.title + ' [' + str(duration) + ']')
+            self.end = time.time()
+            self.duration = datetime.timedelta(seconds=self.end - self.start)
+            mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: ABORT: ') + self.title + ' [' + str(self.duration) + ']')
             mx.abort(codeOrMessage)
+            return self
              
+    tasks = []             
     total = Task('Gate')
     try:
         
-        t = Task('CleanJava')
-        clean(['--no-native'])
-        t.stop()
+        t = Task('Clean')
+        clean([])
+        tasks.append(t.stop())
         
         t = Task('Checkstyle')
         if mx.checkstyle([]) != 0:
             t.abort('Checkstyle warnings were found')
-        t.stop()
+        tasks.append(t.stop())
     
         t = Task('Canonicalization Check')
         mx.log(time.strftime('%d %b %Y %H:%M:%S - Ensuring mx/projects files are canonicalized...'))
         if mx.canonicalizeprojects([]) != 0:
             t.abort('Rerun "mx canonicalizeprojects" and check-in the modified mx/projects files.')
-        t.stop()
+        tasks.append(t.stop())
     
         t = Task('BuildJava')
         build(['--no-native'])
-        t.stop()
+        tasks.append(t.stop())
     
         for vmbuild in ['product', 'fastdebug']:
             global _vmbuild
@@ -473,21 +504,21 @@
             
             t = Task('BuildHotSpot:' + vmbuild)
             build(['--no-java', vmbuild])
-            t.stop()
+            tasks.append(t.stop())
             
             t = Task('BootstrapWithSystemAssertions:' + vmbuild)
             vm(['-esa', '-version'])
-            t.stop()
+            tasks.append(t.stop())
             
             t = Task('UnitTests:' + vmbuild)
             unittest([])
-            t.stop()
+            tasks.append(t.stop())
             
             for test in sanitycheck.getDacapos(level=sanitycheck.SanityCheckLevel.Gate, gateBuildLevel=vmbuild):
                 t = Task(str(test) + ':' + vmbuild)
-                if not test.test('-graal'):
+                if not test.test('graal'):
                     t.abort(test.group + ' ' + test.name + ' Failed')
-                t.stop()
+                tasks.append(t.stop())
     except KeyboardInterrupt:
         total.abort(1)
     
@@ -497,6 +528,12 @@
         total.abort(str(e))
 
     total.stop()
+    
+    mx.log('Gate task times:')
+    for t in tasks:
+        mx.log('  ' + str(t.duration) + '\t' + t.title)
+    mx.log('  =======')
+    mx.log('  ' + str(total.duration))
 
 def bench(args):
     """run benchmarks and parse their output for results
@@ -549,7 +586,7 @@
     for test in benchmarks:
         if not results.has_key(test.group):
             results[test.group] = {}
-        results[test.group].update(test.bench('-' + vm))
+        results[test.group].update(test.bench(vm))
     mx.log(json.dumps(results))
     if resultFile:
         with open(resultFile, 'w') as f:
@@ -558,7 +595,7 @@
 def specjvm2008(args):
     benchArgs = [a[1:] for a in args if a[0] == '@']
     vmArgs = [a for a in args if a[0] != '@']
-    sanitycheck.getSPECjvm2008(benchArgs).bench('-graal', opts=vmArgs)
+    sanitycheck.getSPECjvm2008(benchArgs).bench('graal', opts=vmArgs)
     
 def mx_init():
     _vmbuild = 'product'
@@ -576,9 +613,10 @@
     }
 
     if (_vmSourcesAvailable):
-        mx.add_argument('--product', action='store_const', dest='vmbuild', const='product', help='select the product VM')
-        mx.add_argument('--debug', action='store_const', dest='vmbuild', const='debug', help='select the debug VM')
-        mx.add_argument('--fastdebug', action='store_const', dest='vmbuild', const='fastdebug', help='select the fast debug VM')
+        mx.add_argument('--vm', action='store', dest='vm', default='graal', choices=['graal', 'server', 'client'], help='the VM to run (default: graal)')
+        mx.add_argument('--product', action='store_const', dest='vmbuild', const='product', help='select the product build of the VM')
+        mx.add_argument('--debug', action='store_const', dest='vmbuild', const='debug', help='select the debug build of the VM')
+        mx.add_argument('--fastdebug', action='store_const', dest='vmbuild', const='fastdebug', help='select the fast debug build of the VM')
         
         commands.update({
             'export': [export, '[-options] [zipfile]'],
@@ -597,6 +635,8 @@
         mx.abort('Requires Java version 1.7 or greater, got version ' + version)
     
     if (_vmSourcesAvailable):
+        global _vm
+        _vm = opts.vm
         if hasattr(opts, 'vmbuild') and opts.vmbuild is not None:
             global _vmbuild
             _vmbuild = opts.vmbuild
--- a/mx/sanitycheck.py	Sun Feb 05 05:37:52 2012 +0100
+++ b/mx/sanitycheck.py	Sun Feb 05 05:40:36 2012 +0100
@@ -134,7 +134,7 @@
         self.name = name
         self.group = group
         self.successREs = successREs
-        self.failureREs = failureREs
+        self.failureREs = failureREs + [re.compile(r"Exception occured in scope: ")]
         self.scoreMatchers = scoreMatchers
         self.vmOpts = vmOpts
         self.cmd = cmd
--- a/src/share/vm/code/debugInfoRec.hpp	Sun Feb 05 05:37:52 2012 +0100
+++ b/src/share/vm/code/debugInfoRec.hpp	Sun Feb 05 05:40:36 2012 +0100
@@ -101,7 +101,7 @@
                       methodHandle   method,
                       int         bci,
                       bool        reexecute,
-                      bool        rethrow_exception,
+                      bool        rethrow_exception = false,
                       bool        is_method_handle_invoke = false,
                       bool        return_oop = false,
                       DebugToken* locals      = NULL,