changeset 5022:cbedef8b4d15

Merge
author Christian Haeubl <christian.haeubl@oracle.com>
date Sun, 04 Mar 2012 18:56:25 -0800
parents a7c079d5dc87 (current diff) 0b781cdb0cfb (diff)
children db072eec897e 8e6db1a5c537
files
diffstat 14 files changed, 330 insertions(+), 200 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/simple/LinearScanAllocator.java	Fri Mar 02 18:50:51 2012 -0800
+++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/simple/LinearScanAllocator.java	Sun Mar 04 18:56:25 2012 -0800
@@ -144,11 +144,18 @@
     private CiValue[] curInRegisterState;
     private CiValue[] curOutRegisterState;
     private BitSet curLiveIn;
-    private int curOpId;
-    private boolean curPhiDefs;
+    private LIRInstruction curOp;
 
+    /**
+     * The spill slot for a variable, if the variable has ever been spilled.
+     */
     private LocationMap canonicalSpillLocations;
 
+    /**
+     * The register that a variable got assigned at its definition, and so it should get that register when reloading after spilling.
+     */
+    private LocationMap hintRegisterLocations;
+
     public void execute() {
         assert LIRVerifier.verify(true, lir, frameMap);
 
@@ -184,6 +191,7 @@
 
         Debug.log("==== start linear scan allocation ====");
         canonicalSpillLocations = new LocationMap(lir.numVariables());
+        hintRegisterLocations = new LocationMap(lir.numVariables());
         curInRegisterState = new CiValue[maxRegisterNum()];
         curOutRegisterState = new CiValue[maxRegisterNum()];
         for (Block block : lir.linearScanOrder()) {
@@ -204,8 +212,7 @@
 
             for (int opIdx = 0; opIdx < block.lir.size(); opIdx++) {
                 LIRInstruction op = block.lir.get(opIdx);
-                curOpId = op.id();
-                curPhiDefs = opIdx == 0;
+                curOp = op;
 
                 Debug.log("  op %d %s", op.id(), op);
 
@@ -230,9 +237,13 @@
                 if (op.hasCall()) {
                     spillCallerSaveRegisters();
                 }
+                if (op instanceof StandardOp.PhiLabelOp) {
+                    assert opIdx == 0;
+                    phiRegisterHints(block);
+                }
 
+                op.forEachOutput(defProc);
                 op.forEachTemp(defProc);
-                op.forEachOutput(defProc);
 
                 // Fixed temp and output registers can evict variables from their assigned register, allocate new location for them.
                 fixupEvicted();
@@ -248,7 +259,7 @@
                 dataFlow.forEachKilled(op, true, unblockProc);
                 dataFlow.forEachKilled(op, true, killProc);
 
-                curOpId = -1;
+                curOp = null;
             }
 
             assert endLocationsFor(block) == null;
@@ -323,8 +334,8 @@
 
     private CiValue recordUse(CiValue value) {
         if (isVariable(value)) {
-            assert lastUseFor(asVariable(value)) <= curOpId;
-            setLastUseFor(asVariable(value), curOpId);
+            assert lastUseFor(asVariable(value)) <= curOp.id();
+            setLastUseFor(asVariable(value), curOp.id());
 
         }
         return value;
@@ -396,30 +407,61 @@
     }
 
 
-    private Location allocateRegister(final Variable variable, OperandMode mode, EnumSet<OperandFlag> flags) {
-//        if (flags.contains(OperandFlag.RegisterHint)) {
-//            CiValue result = curInstruction.forEachRegisterHint(variable, mode, new ValueProcedure() {
-//                @Override
-//                public CiValue doValue(CiValue registerHint) {
-//                    Debug.log("      registerHint %s", registerHint);
-//                    CiRegister hint = null;
-//                    if (isRegister(registerHint)) {
-//                        hint = asRegister(registerHint);
-//                    } else if (isLocation(registerHint) && isRegister(asLocation(registerHint).location)) {
-//                        hint = asRegister(asLocation(registerHint).location);
-//                    }
-//                    if (hint != null && hint.isSet(variable.flag) && isFree(hint, inRegisterState, outRegisterState)) {
-//                        return selectRegister(hint, variable, inRegisterState, outRegisterState);
-//                    }
-//                    return null;
-//                }
-//            });
-//
-//            if (result != null) {
-//                return asLocation(result);
-//            }
-//        }
-//
+    private void phiRegisterHints(Block block) {
+        Debug.log("    phi register hints for %s", block);
+        CiValue[] phiDefinitions = ((StandardOp.PhiLabelOp) block.lir.get(0)).getPhiDefinitions();
+        for (Block pred : block.getPredecessors()) {
+            CiValue[] phiInputs = ((StandardOp.PhiJumpOp) pred.lir.get(pred.lir.size() - 1)).getPhiInputs();
+
+            for (int i = 0; i < phiDefinitions.length; i++) {
+                CiValue phiDefinition = phiDefinitions[i];
+                CiValue phiInput = phiInputs[i];
+
+                if (isVariable(phiDefinition)) {
+                    Location hintResult = processRegisterHint(asVariable(phiDefinition), OperandMode.Output, phiInput);
+                    if (hintResult != null) {
+                        phiDefinitions[i] = hintResult;
+                    }
+                }
+            }
+        }
+    }
+
+    private Location processRegisterHint(Variable variable, OperandMode mode, CiValue registerHint) {
+        if (registerHint == null) {
+            return null;
+        }
+        Debug.log("      try registerHint for %s %s: %s", mode, variable, registerHint);
+        CiRegister hint = null;
+        if (isRegister(registerHint)) {
+            hint = asRegister(registerHint);
+        } else if (isLocation(registerHint) && isRegister(asLocation(registerHint).location)) {
+            hint = asRegister(asLocation(registerHint).location);
+        }
+        if (hint != null && hint.isSet(variable.flag) && isFree(hint, mode)) {
+            return selectRegister(hint, variable, mode);
+        }
+        return null;
+    }
+
+    private Location allocateRegister(final Variable variable, final OperandMode mode, EnumSet<OperandFlag> flags) {
+        if (flags.contains(OperandFlag.RegisterHint)) {
+            CiValue hintResult = curOp.forEachRegisterHint(variable, mode, new ValueProcedure() {
+                @Override
+                public CiValue doValue(CiValue registerHint) {
+                    return processRegisterHint(variable, mode, registerHint);
+                }
+            });
+            if (hintResult != null) {
+                return asLocation(hintResult);
+            }
+        }
+
+        CiValue hintResult = processRegisterHint(variable, mode, hintRegisterLocations.get(variable));
+        if (hintResult != null) {
+            return asLocation(hintResult);
+        }
+
         EnumMap<RegisterFlag, CiRegister[]> categorizedRegs = frameMap.registerConfig.getCategorizedAllocatableRegisters();
         CiRegister[] availableRegs = categorizedRegs.get(variable.flag);
 
@@ -440,10 +482,6 @@
         }
 
         if (bestSpillCandidate == null) {
-            if (curPhiDefs) {
-                return selectSpillSlot(variable);
-            }
-
             // 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 GraalInternalError("No register available");
@@ -457,7 +495,7 @@
     private void spill(Location value) {
         Location newLoc = spillLocation(value.variable);
         Debug.log("      spill %s to %s", value, newLoc);
-        if (!curPhiDefs) {
+        if (!(curOp instanceof StandardOp.PhiLabelOp)) {
             moveResolver.add(value, newLoc);
         }
         curLocations.put(newLoc);
@@ -483,7 +521,7 @@
     private Location spillCandidate(CiRegister reg) {
         CiValue in = curInRegisterState[reg.number];
         CiValue out = curOutRegisterState[reg.number];
-        if (in == out && in != null && isLocation(in) && lastUseFor(asLocation(in).variable) < curOpId) {
+        if (in == out && in != null && isLocation(in) && lastUseFor(asLocation(in).variable) < curOp.id()) {
             return asLocation(in);
         }
         return null;
@@ -521,6 +559,9 @@
         curOutRegisterState[reg.number] = loc;
         curLocations.put(loc);
         recordUse(variable);
+        if (hintRegisterLocations.get(variable) == null) {
+            hintRegisterLocations.put(loc);
+        }
 
         Debug.log("      selected register %s", loc);
         return loc;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java	Fri Mar 02 18:50:51 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java	Sun Mar 04 18:56:25 2012 -0800
@@ -81,10 +81,8 @@
         if (osrBCI != -1) {
             throw new CiBailout("No OSR supported");
         }
-        Debug.dump(this, "compiler");
-        Debug.dump(method, "method");
 
-        return Debug.scope(createScopeName(method), graph, new Callable<CiTargetMethod>() {
+        return Debug.scope(createScopeName(method), new Object[] {graph, method, this}, new Callable<CiTargetMethod>() {
             public CiTargetMethod call() {
                 final CiAssumptions assumptions = GraalOptions.OptAssumptions ? new CiAssumptions() : null;
                 final LIR lir = Debug.scope("FrontEnd", new Callable<LIR>() {
@@ -213,7 +211,7 @@
         assert startBlock != null;
         assert startBlock.numberOfPreds() == 0;
 
-        return Debug.scope("Compute Linear Scan Order", new Callable<LIR>() {
+        return Debug.scope("ComputeLinearScanOrder", new Callable<LIR>() {
 
             @Override
             public LIR call() {
@@ -237,9 +235,8 @@
     public FrameMap emitLIR(final LIR lir, StructuredGraph graph, final RiResolvedMethod method) {
         final FrameMap frameMap = backend.newFrameMap(runtime.getRegisterConfig(method));
         final LIRGenerator lirGenerator = backend.newLIRGenerator(graph, frameMap, method, lir, xir);
-        Debug.dump(lirGenerator, "LIRGenerator");
 
-        Debug.scope("LIRGen", new Runnable() {
+        Debug.scope("LIRGen", lirGenerator, new Runnable() {
             public void run() {
                 for (Block b : lir.linearScanOrder()) {
                     lirGenerator.doBlock(b);
--- a/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/Debug.java	Fri Mar 02 18:50:51 2012 -0800
+++ b/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/Debug.java	Sun Mar 04 18:56:25 2012 -0800
@@ -64,16 +64,20 @@
     }
 
     public static void scope(String name, Runnable runnable) {
-        scope(name, null, runnable);
+        scope(name, new Object[0], runnable);
     }
 
     public static <T> T scope(String name, Callable<T> callable) {
-        return scope(name, null, callable);
+        return scope(name, new Object[0], callable);
     }
 
     public static void scope(String name, Object context, Runnable runnable) {
+        scope(name, new Object[] {context}, runnable);
+    }
+
+    public static void scope(String name, Object[] context, Runnable runnable) {
         if (ENABLED) {
-            DebugScope.getInstance().scope(name, runnable, null, false, new Object[] {context});
+            DebugScope.getInstance().scope(name, runnable, null, false, context);
         } else {
             runnable.run();
         }
@@ -88,8 +92,12 @@
     }
 
     public static <T> T scope(String name, Object context, Callable<T> callable) {
+        return scope(name, new Object[] {context}, callable);
+    }
+
+    public static <T> T scope(String name, Object[] context, Callable<T> callable) {
         if (ENABLED) {
-            return DebugScope.getInstance().scope(name, null, callable, false, new Object[] {context});
+            return DebugScope.getInstance().scope(name, null, callable, false, context);
         } else {
             return DebugScope.call(callable);
         }
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/BitMap.java	Fri Mar 02 18:50:51 2012 -0800
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/BitMap.java	Sun Mar 04 18:56:25 2012 -0800
@@ -261,6 +261,27 @@
     }
 
     /**
+     * Performs the union operation on this bitmap with the specified bitmap. That is, all bits set in either of the two
+     * bitmaps will be set in this bitmap following this operation. It returns whether this bitmap was changed by the operation.
+     *
+     * @param other the other bitmap for the union operation
+     */
+    public boolean setUnionWithResult(BitMap other) {
+        long temp = low | other.low;
+        boolean changed = temp != low;
+        low = temp;
+
+        if (extra != null && other.extra != null) {
+            for (int i = 0; i < extra.length && i < other.extra.length; i++) {
+                temp = extra[i] | other.extra[i];
+                changed = changed || temp != extra[i];
+                extra[i] |= temp;
+            }
+        }
+        return changed;
+    }
+
+    /**
      * Performs the union operation on this bitmap with the specified bitmap. That is, a bit is set in this
      * bitmap if and only if it is set in both this bitmap and the specified bitmap.
      *
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeList.java	Fri Mar 02 18:50:51 2012 -0800
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeList.java	Sun Mar 04 18:56:25 2012 -0800
@@ -363,6 +363,15 @@
 
     @Override
     public String toString() {
-        return Arrays.toString(nodes);
+        StringBuilder sb = new StringBuilder();
+        sb.append('[');
+        for (int i = 0; i < size; i++) {
+            if (i != 0) {
+                sb.append(", ");
+            }
+            sb.append(nodes[i]);
+        }
+        sb.append(']');
+        return sb.toString();
     }
 }
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeMap.java	Fri Mar 02 18:50:51 2012 -0800
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeMap.java	Sun Mar 04 18:56:25 2012 -0800
@@ -39,6 +39,12 @@
         size = values.length;
     }
 
+    public NodeMap(NodeMap<T> copyFrom) {
+        this.graph = copyFrom.graph;
+        this.values = Arrays.copyOf(copyFrom.values, copyFrom.values.length);
+        this.size = copyFrom.size;
+    }
+
     @SuppressWarnings("unchecked")
     public T get(Node node) {
         check(node);
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/ArrayCopySnippets.java	Fri Mar 02 18:50:51 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/ArrayCopySnippets.java	Sun Mar 04 18:56:25 2012 -0800
@@ -259,7 +259,7 @@
 
     @Snippet
     public static void copyIntsDown(Object src, long srcOffset, Object dest, long destOffset, int length)  {
-        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short);
+        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Int);
         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);
@@ -268,7 +268,7 @@
 
     @Snippet
     public static void copyLongsDown(Object src, long srcOffset, Object dest, long destOffset, int length)  {
-        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short);
+        long header = ArrayHeaderSizeNode.sizeFor(CiKind.Long);
         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);
--- a/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/cfg/ControlFlowGraph.java	Fri Mar 02 18:50:51 2012 -0800
+++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/cfg/ControlFlowGraph.java	Sun Mar 04 18:56:25 2012 -0800
@@ -123,10 +123,8 @@
             }
         }
 
-        // Compute reverse postorder.
-        reversePostOrder = new Block[numBlocks];
-        int reversePostOrderId = numBlocks - 1;
-
+        // Compute postorder.
+        ArrayList<Block> postOrder = new ArrayList<>(numBlocks);
         ArrayList<Block> stack = new ArrayList<>();
         stack.add(blockFor(graph.start()));
 
@@ -136,45 +134,60 @@
                 // First time we see this block: push all successors.
                 for (Node suxNode : block.getEndNode().cfgSuccessors()) {
                     Block suxBlock = blockFor(suxNode);
-                    assert suxBlock.id != BLOCK_ID_VISITED : "Sux already visited?? from " + block.getEndNode() + " to " + suxNode;
                     if (suxBlock.id == BLOCK_ID_INITIAL) {
                         stack.add(suxBlock);
                     }
                 }
                 block.id = BLOCK_ID_VISITED;
             } else if (block.id == BLOCK_ID_VISITED) {
-                // Second time we see this block: All successors haved been processed, so insert block into reverse postorder list.
+                // Second time we see this block: All successors have been processed, so add block to postorder list.
                 stack.remove(stack.size() - 1);
-                reversePostOrder[reversePostOrderId] = block;
-                block.id = reversePostOrderId;
-                reversePostOrderId--;
+                postOrder.add(block);
             } else {
                 throw GraalInternalError.shouldNotReachHere();
             }
         } while (!stack.isEmpty());
-        assert reversePostOrderId == -1;
+
+        // Compute reverse postorder and number blocks.
+        assert postOrder.size() <= numBlocks : "some blocks originally created can be unreachable, so actual block list can be shorter";
+        numBlocks = postOrder.size();
+        reversePostOrder = new Block[numBlocks];
+        for (int i = 0; i < numBlocks; i++) {
+            reversePostOrder[i] = postOrder.get(numBlocks - i - 1);
+            reversePostOrder[i].id = i;
+        }
     }
 
-    // Connect blocks (including loop backward edges).
+    // Connect blocks (including loop backward edges), but ignoring dead code (blocks with id < 0).
     private void connectBlocks() {
         for (Block block : reversePostOrder) {
             List<Block> predecessors = new ArrayList<>();
             for (Node predNode : block.getBeginNode().cfgPredecessors()) {
-                predecessors.add(nodeToBlock.get(predNode));
+                Block predBlock = nodeToBlock.get(predNode);
+                if (predBlock.id >= 0) {
+                    predecessors.add(predBlock);
+                }
             }
             if (block.getBeginNode() instanceof LoopBeginNode) {
                 for (LoopEndNode predNode : ((LoopBeginNode) block.getBeginNode()).orderedLoopEnds()) {
-                    predecessors.add(nodeToBlock.get(predNode));
+                    Block predBlock = nodeToBlock.get(predNode);
+                    if (predBlock.id >= 0) {
+                        predecessors.add(predBlock);
+                    }
                 }
             }
             block.predecessors = predecessors;
 
             List<Block> successors = new ArrayList<>();
             for (Node suxNode : block.getEndNode().cfgSuccessors()) {
-                successors.add(nodeToBlock.get(suxNode));
+                Block suxBlock = nodeToBlock.get(suxNode);
+                assert suxBlock.id >= 0;
+                successors.add(suxBlock);
             }
             if (block.getEndNode() instanceof LoopEndNode) {
-                successors.add(nodeToBlock.get(((LoopEndNode) block.getEndNode()).loopBegin()));
+                Block suxBlock = nodeToBlock.get(((LoopEndNode) block.getEndNode()).loopBegin());
+                assert suxBlock.id >= 0;
+                successors.add(suxBlock);
             }
             block.successors = successors;
         }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/LoopBeginNode.java	Fri Mar 02 18:50:51 2012 -0800
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/LoopBeginNode.java	Sun Mar 04 18:56:25 2012 -0800
@@ -126,7 +126,6 @@
     @Override
     public boolean verify() {
         assertTrue(loopEnds().isNotEmpty(), "missing loopEnd");
-        assertTrue(forwardEndCount() == 1, "LoopBegin should only have one forward edge");
         return super.verify();
     }
 
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/ConditionalNode.java	Fri Mar 02 18:50:51 2012 -0800
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/ConditionalNode.java	Sun Mar 04 18:56:25 2012 -0800
@@ -22,10 +22,7 @@
  */
 package com.oracle.max.graal.nodes.calc;
 
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
-import com.oracle.max.graal.nodes.PhiNode.PhiType;
 import com.oracle.max.graal.nodes.spi.*;
 
 /**
@@ -54,41 +51,6 @@
         return y();
     }
 
-    public static class ConditionalStructure {
-
-        public final IfNode ifNode;
-        public final PhiNode phi;
-        public final MergeNode merge;
-
-        public ConditionalStructure(IfNode ifNode, PhiNode phi, MergeNode merge) {
-            this.ifNode = ifNode;
-            this.phi = phi;
-            this.merge = merge;
-        }
-    }
-
-    public static ConditionalStructure createConditionalStructure(BooleanNode condition, ValueNode trueValue, ValueNode falseValue) {
-        return createConditionalStructure(condition, trueValue, falseValue, 0.5);
-    }
-
-    public static ConditionalStructure createConditionalStructure(BooleanNode condition, ValueNode trueValue, ValueNode falseValue, double trueProbability) {
-        Graph graph = condition.graph();
-        assert trueValue.kind() == falseValue.kind();
-        CiKind kind = trueValue.kind();
-        IfNode ifNode = graph.add(new IfNode(condition, trueProbability));
-        EndNode trueEnd = graph.add(new EndNode());
-        EndNode falseEnd = graph.add(new EndNode());
-        ifNode.setTrueSuccessor(BeginNode.begin(trueEnd));
-        ifNode.setFalseSuccessor(BeginNode.begin(falseEnd));
-        MergeNode merge = graph.add(new MergeNode());
-        merge.addForwardEnd(trueEnd);
-        merge.addForwardEnd(falseEnd);
-        PhiNode phi = graph.unique(new PhiNode(kind, merge, PhiType.Value));
-        phi.addInput(trueValue);
-        phi.addInput(falseValue);
-        return new ConditionalStructure(ifNode, phi, merge);
-    }
-
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (condition instanceof ConstantNode) {
--- a/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinter.java	Fri Mar 02 18:50:51 2012 -0800
+++ b/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinter.java	Sun Mar 04 18:56:25 2012 -0800
@@ -28,13 +28,11 @@
 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.alloc.util.*;
 import com.oracle.max.graal.compiler.alloc.*;
 import com.oracle.max.graal.compiler.alloc.Interval.UsePosList;
 import com.oracle.max.graal.compiler.gen.*;
-import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.graph.Node.Verbosity;
 import com.oracle.max.graal.graph.NodeClass.NodeClassIterator;
@@ -50,20 +48,18 @@
  */
 class CFGPrinter extends CompilationPrinter {
 
-    public final CiTarget target;
-    public final RiRuntime runtime;
-    public LIR lir;
-    public LIRGenerator lirGenerator;
+    protected CiTarget target;
+    protected LIR lir;
+    protected LIRGenerator lirGenerator;
+    protected ControlFlowGraph cfg;
 
     /**
      * Creates a control flow graph printer.
      *
      * @param buffer where the output generated via this printer shown be written
      */
-    public CFGPrinter(OutputStream out, CiTarget target, RiRuntime runtime) {
+    public CFGPrinter(OutputStream out) {
         super(out);
-        this.target = target;
-        this.runtime = runtime;
     }
 
     /**
@@ -119,22 +115,78 @@
     }
 
 
+    private NodeMap<Block> latestScheduling;
+    private NodeBitMap printedNodes;
+
+    private boolean inFixedSchedule(Node node) {
+        return lir != null || node.isDeleted() || cfg.getNodeToBlock().get(node) != null;
+    }
+
     /**
      * Prints the specified list of blocks.
      *
      * @param label A label describing the compilation phase that produced the control flow graph.
      * @param blocks The list of blocks to be printed.
      */
-    public void printCFG(String label, List<Block> blocks, SchedulePhase schedule) {
+    public void printCFG(String label, List<Block> blocks) {
+        if (lir == null) {
+            latestScheduling = new NodeMap<>(cfg.getNodeToBlock());
+            for (Block block : blocks) {
+                Node cur = block.getBeginNode();
+                while (true) {
+                    assert inFixedSchedule(cur) && latestScheduling.get(cur) == block;
+                    scheduleInputs(cur, block);
+
+                    if (cur == block.getEndNode()) {
+                        break;
+                    }
+                    assert cur.successors().count() == 1;
+                    cur = cur.successors().first();
+                }
+            }
+        }
+        printedNodes = new NodeBitMap(cfg.graph);
+
         begin("cfg");
         out.print("name \"").print(label).println('"');
         for (Block block : blocks) {
-            printBlock(block, schedule);
+            printBlock(block);
         }
         end("cfg");
+
+        latestScheduling = null;
+        printedNodes = null;
     }
 
-    private void printBlock(Block block, SchedulePhase schedule) {
+    private void scheduleInputs(Node node, Block nodeBlock) {
+        if (node instanceof PhiNode) {
+            PhiNode phi = (PhiNode) node;
+            assert nodeBlock.getBeginNode() == phi.merge();
+            for (Block pred : nodeBlock.getPredecessors()) {
+                schedule(phi.valueAt((EndNode) pred.getEndNode()), pred);
+            }
+
+        } else {
+            for (Node input : node.inputs()) {
+                schedule(input, nodeBlock);
+            }
+        }
+    }
+
+    private void schedule(Node input, Block block) {
+        if (!inFixedSchedule(input)) {
+            Block inputBlock = block;
+            if (latestScheduling.get(input) != null) {
+                inputBlock = ControlFlowGraph.commonDominator(inputBlock, latestScheduling.get(input));
+            }
+            if (inputBlock != latestScheduling.get(input)) {
+                latestScheduling.set(input, inputBlock);
+                scheduleInputs(input, inputBlock);
+            }
+        }
+    }
+
+    private void printBlock(Block block) {
         begin("block");
 
         out.print("name \"").print(blockToString(block)).println('"');
@@ -180,15 +232,12 @@
             out.print("loop_depth ").println(block.getLoop().depth);
         }
 
-        printNodes(block, schedule);
+        printNodes(block);
         printLIR(block);
         end("block");
     }
 
-    private void printNodes(Block block, SchedulePhase schedule) {
-        if (schedule == null) {
-            return;
-        }
+    private void printNodes(Block block) {
         begin("IR");
         out.println("HIR");
         out.disableIndentation();
@@ -196,25 +245,59 @@
         if (block.getPredecessors().size() == 0) {
             // Currently method parameters are not in the schedule, so print them separately here.
             for (ValueNode param : block.getBeginNode().graph().getNodes(LocalNode.class)) {
-                printNode(param);
+                printNode(param, false);
             }
         }
         if (block.getBeginNode() instanceof MergeNode) {
             // Currently phi functions are not in the schedule, so print them separately here.
             for (ValueNode phi : ((MergeNode) block.getBeginNode()).phis()) {
-                printNode(phi);
+                printNode(phi, false);
             }
         }
 
-        for (Node node : schedule.nodesFor(block)) {
-            printNode(node);
+        if (lir != null) {
+            for (Node node : lir.nodesFor(block)) {
+                printNode(node, false);
+            }
+        } else {
+            Node cur = block.getBeginNode();
+            while (true) {
+                printNode(cur, false);
+
+                if (cur == block.getEndNode()) {
+                    for (Map.Entry<Node, Block> entry : latestScheduling.entries()) {
+                        if (entry.getValue() == block && !inFixedSchedule(entry.getKey()) && !printedNodes.isMarked(entry.getKey())) {
+                            printNode(entry.getKey(), true);
+                        }
+                    }
+                    break;
+                }
+                assert cur.successors().count() == 1;
+                cur = cur.successors().first();
+            }
+
         }
+
         out.enableIndentation();
         end("IR");
     }
 
-    private void printNode(Node node) {
-        if (node instanceof FixedWithNextNode) {
+    private void printNode(Node node, boolean unscheduled) {
+        assert !printedNodes.isMarked(node);
+        printedNodes.mark(node);
+
+        if (!(node instanceof PhiNode)) {
+            for (Node input : node.inputs()) {
+                if (!inFixedSchedule(input) && !printedNodes.isMarked(input)) {
+                    printNode(input, true);
+                }
+            }
+        }
+
+        if (unscheduled) {
+            assert lir == null : "unscheduled nodes can only be present before LIR generation";
+            out.print("f ").print(HOVER_START).print("u").print(HOVER_SEP).print("unscheduled").print(HOVER_END).println(COLUMN_END);
+        } else if (node instanceof FixedWithNextNode) {
             out.print("f ").print(HOVER_START).print("#").print(HOVER_SEP).print("fixed with next").print(HOVER_END).println(COLUMN_END);
         } else if (node instanceof FixedNode) {
             out.print("f ").print(HOVER_START).print("*").print(HOVER_SEP).print("fixed").print(HOVER_END).println(COLUMN_END);
--- a/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinterObserver.java	Fri Mar 02 18:50:51 2012 -0800
+++ b/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinterObserver.java	Sun Mar 04 18:56:25 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -32,10 +32,11 @@
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.alloc.*;
 import com.oracle.max.graal.compiler.gen.*;
-import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.debug.*;
+import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.java.*;
 import com.oracle.max.graal.lir.*;
+import com.oracle.max.graal.lir.cfg.*;
 import com.oracle.max.graal.nodes.*;
 
 /**
@@ -45,30 +46,11 @@
 public class CFGPrinterObserver implements DebugDumpHandler {
 
     private CFGPrinter cfgPrinter;
-
-    private GraalCompiler compiler;
-    private RiResolvedMethod method;
-    private SchedulePhase schedule;
+    private Graph curGraph;
 
     @Override
-    public void dump(final Object object, final String message) {
-        Debug.sandbox("CFGPrinter", new Runnable() {
-            @Override
-            public void run() {
-                dumpSandboxed(object, message);
-            }
-        });
-    }
-
-    private void dumpSandboxed(final Object object, final String message) {
-        if (object instanceof GraalCompiler) {
-            compiler = (GraalCompiler) object;
-            return;
-        } else if (object instanceof SchedulePhase) {
-            schedule = (SchedulePhase) object;
-            return;
-        }
-
+    public void dump(Object object, String message) {
+        GraalCompiler compiler = Debug.contextLookup(GraalCompiler.class);
         if (compiler == null) {
             return;
         }
@@ -77,57 +59,61 @@
             File file = new File("compilations-" + System.currentTimeMillis() + ".cfg");
             try {
                 OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
-                cfgPrinter = new CFGPrinter(out, compiler.target, compiler.runtime);
+                cfgPrinter = new CFGPrinter(out);
             } catch (FileNotFoundException e) {
-                throw new InternalError("Could not open " + file.getAbsolutePath());
+                throw new GraalInternalError("Could not open " + file.getAbsolutePath());
             }
             TTY.println("CFGPrinter: Output to file %s", file);
         }
 
-        RiRuntime runtime = cfgPrinter.runtime;
-        if (object instanceof LIRGenerator) {
-            cfgPrinter.lirGenerator = (LIRGenerator) object;
-        } else if (object instanceof RiResolvedMethod) {
-            method = (RiResolvedMethod) object;
-            cfgPrinter.printCompilation(method);
+        StructuredGraph newGraph = Debug.contextLookup(StructuredGraph.class);
+        if (newGraph != curGraph) {
+            cfgPrinter.printCompilation(newGraph.method());
+            TTY.println("CFGPrinter: Dumping method %s", newGraph.method());
+            curGraph = newGraph;
+        }
 
-            cfgPrinter.lir = null;
-            cfgPrinter.lirGenerator = null;
-            schedule = null;
-            TTY.println("CFGPrinter: Dumping method %s", method);
+        cfgPrinter.target = compiler.target;
+        if (object instanceof LIR) {
+            cfgPrinter.lir = (LIR) object;
+        } else {
+            cfgPrinter.lir = Debug.contextLookup(LIR.class);
+        }
+        cfgPrinter.lirGenerator = Debug.contextLookup(LIRGenerator.class);
+        if (cfgPrinter.lir != null) {
+            cfgPrinter.cfg = cfgPrinter.lir.cfg;
+        }
 
-        } else if (object instanceof BciBlockMapping) {
+        RiRuntime runtime = compiler.runtime;
+
+        if (object instanceof BciBlockMapping) {
             BciBlockMapping blockMap = (BciBlockMapping) object;
             cfgPrinter.printCFG(message, blockMap);
             cfgPrinter.printBytecodes(runtime.disassemble(blockMap.method));
 
         } else if (object instanceof LIR) {
-            cfgPrinter.lir = (LIR) object;
-            cfgPrinter.printCFG(message, ((LIR) object).codeEmittingOrder(), schedule);
+            cfgPrinter.printCFG(message, cfgPrinter.lir.codeEmittingOrder());
 
         } else if (object instanceof StructuredGraph) {
-            SchedulePhase curSchedule = schedule;
-            if (curSchedule == null) {
-                try {
-                    curSchedule = new SchedulePhase();
-                    curSchedule.apply((StructuredGraph) object);
-                } catch (Throwable ex) {
-                    curSchedule = null;
-                    // ignore
-                }
+            if (cfgPrinter.cfg == null) {
+                cfgPrinter.cfg = ControlFlowGraph.compute((StructuredGraph) object, true, true, true, false);
             }
-            if (curSchedule != null && curSchedule.getCFG() != null) {
-                cfgPrinter.printCFG(message, Arrays.asList(curSchedule.getCFG().getBlocks()), curSchedule);
-            }
+            cfgPrinter.printCFG(message, Arrays.asList(cfgPrinter.cfg.getBlocks()));
 
         } else if (object instanceof CiTargetMethod) {
             cfgPrinter.printMachineCode(runtime.disassemble((CiTargetMethod) object), null);
+
         } else if (object instanceof Interval[]) {
             cfgPrinter.printIntervals(message, (Interval[]) object);
+
         } else if (object instanceof IntervalPrinter.Interval[]) {
             cfgPrinter.printIntervals(message, (IntervalPrinter.Interval[]) object);
         }
 
+        cfgPrinter.target = null;
+        cfgPrinter.lir = null;
+        cfgPrinter.lirGenerator = null;
+        cfgPrinter.cfg = null;
         cfgPrinter.flush();
     }
 }
--- a/mx/commands.py	Fri Mar 02 18:50:51 2012 -0800
+++ b/mx/commands.py	Sun Mar 04 18:56:25 2012 -0800
@@ -656,31 +656,10 @@
         clean([] if args.buildNative else ['--no-native'])
         tasks.append(t.stop())
         
-        t = Task('Checkstyle')
-        if mx.checkstyle([]) != 0:
-            t.abort('Checkstyle warnings were found')
-        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.')
-        tasks.append(t.stop())
-    
         t = Task('BuildJava')
         build(['--no-native'])
         tasks.append(t.stop())
     
-        t = Task('CleanAndBuildGraalVisualizer')
-        mx.run(['ant', '-f', join(_graal_home, 'visualizer', 'build.xml'), '-q', 'clean', 'build'])
-        tasks.append(t.stop())
-
-        # Prevent Graal modifications from breaking the standard builds
-        if args.buildNative and args.buildNonGraal:
-            t = Task('BuildHotSpotVarieties')
-            buildvms(['--vms', 'client,server', '--builds', 'fastdebug,product'])
-            tasks.append(t.stop())
-        
         for vmbuild in ['fastdebug', 'product']:
             global _vmbuild
             _vmbuild = vmbuild
@@ -707,6 +686,28 @@
                 if not test.test('graal'):
                     t.abort(test.group + ' ' + test.name + ' Failed')
                 tasks.append(t.stop())
+
+        t = Task('Checkstyle')
+        if mx.checkstyle([]) != 0:
+            t.abort('Checkstyle warnings were found')
+        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.')
+        tasks.append(t.stop())
+    
+        t = Task('CleanAndBuildGraalVisualizer')
+        mx.run(['ant', '-f', join(_graal_home, 'visualizer', 'build.xml'), '-q', 'clean', 'build'])
+        tasks.append(t.stop())
+
+        # Prevent Graal modifications from breaking the standard builds
+        if args.buildNative and args.buildNonGraal:
+            t = Task('BuildHotSpotVarieties')
+            buildvms(['--vms', 'client,server', '--builds', 'fastdebug,product'])
+            tasks.append(t.stop())
+        
     except KeyboardInterrupt:
         total.abort(1)
     
--- a/mxtool/URLConnectionDownload.java	Fri Mar 02 18:50:51 2012 -0800
+++ b/mxtool/URLConnectionDownload.java	Sun Mar 04 18:56:25 2012 -0800
@@ -53,6 +53,10 @@
         System.setProperty("java.net.useSystemProxies", "true");
 
         String proxy = System.getenv("HTTP_PROXY");
+        if (proxy == null) {
+            String proxy = System.getenv("http_proxy");
+        }
+
         String proxyMsg = "";
         if (proxy != null) {
             Pattern p = Pattern.compile("(?:http://)?([^:]+)(:\\d+)?");