changeset 5029:74f47ef37394

Fix and enable liveness analysis to prune unnecessary frame state entries
author Christian Wimmer <Christian.Wimmer@Oracle.com>
date Mon, 05 Mar 2012 16:09:49 -0800
parents a775efb8fcec
children f4fb1af02e4c
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/DebugInfoBuilder.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BciBlockMapping.java graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/FrameStateBuilder.java graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinterObserver.java
diffstat 7 files changed, 65 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Mon Mar 05 16:09:07 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Mon Mar 05 16:09:49 2012 -0800
@@ -186,7 +186,7 @@
     public static boolean OptReorderLoops                    = true;
     public static boolean OptEliminateGuards                 = true;
     public static boolean OptImplicitNullChecks              = true;
-    public static boolean OptLivenessAnalysis                = false;
+    public static boolean OptLivenessAnalysis                = true;
 
     /**
      * Flag to turn on SSA-based register allocation, which is currently under development.
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/DebugInfoBuilder.java	Mon Mar 05 16:09:07 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/DebugInfoBuilder.java	Mon Mar 05 16:09:49 2012 -0800
@@ -27,6 +27,7 @@
 
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.graal.compiler.gen.LIRGenerator.LockScope;
+import com.oracle.max.graal.debug.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.lir.*;
 import com.oracle.max.graal.nodes.*;
@@ -151,18 +152,22 @@
                 ciObj = CiVirtualObject.get(obj.type(), null, virtualObjects.size());
                 virtualObjects.put(obj, ciObj);
             }
+            Debug.metric("StateVirtualObjects").increment();
             return ciObj;
 
         } else if (value instanceof ConstantNode) {
+            Debug.metric("StateConstants").increment();
             return ((ConstantNode) value).value;
 
         } else if (value != null) {
+            Debug.metric("StateVariables").increment();
             CiValue operand = nodeOperands.get(value);
             assert operand != null && (operand instanceof Variable || operand instanceof CiConstant);
             return operand;
 
         } else {
             // return a dummy value because real value not needed
+            Debug.metric("StateIllegals").increment();
             return CiValue.IllegalValue;
         }
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Mon Mar 05 16:09:07 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Mon Mar 05 16:09:49 2012 -0800
@@ -28,7 +28,6 @@
 import static com.oracle.max.cri.util.MemoryBarriers.*;
 import static com.oracle.max.graal.lir.ValueUtil.*;
 
-import java.lang.reflect.*;
 import java.util.*;
 
 import com.oracle.max.asm.*;
@@ -50,7 +49,11 @@
 import com.oracle.max.graal.debug.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.lir.*;
-import com.oracle.max.graal.lir.StandardOp.*;
+import com.oracle.max.graal.lir.StandardOp.JumpOp;
+import com.oracle.max.graal.lir.StandardOp.LabelOp;
+import com.oracle.max.graal.lir.StandardOp.ParametersOp;
+import com.oracle.max.graal.lir.StandardOp.PhiJumpOp;
+import com.oracle.max.graal.lir.StandardOp.PhiLabelOp;
 import com.oracle.max.graal.lir.cfg.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.DeoptimizeNode.DeoptAction;
@@ -395,7 +398,6 @@
             }
             if (stateAfter != null) {
                 lastState = stateAfter;
-                assert checkStartOperands(instr, lastState);
                 assert checkStateReady(lastState);
                 if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
                     TTY.println("STATE CHANGE");
@@ -491,25 +493,6 @@
         }
     }
 
-    private boolean checkStartOperands(Node node, FrameState fs) {
-        if (!Modifier.isNative(method.accessFlags())) {
-            if (node == ((StructuredGraph) node.graph()).start()) {
-                CiKind[] arguments = CiUtil.signatureToKinds(method);
-                int slot = 0;
-                for (CiKind kind : arguments) {
-                    ValueNode arg = fs.localAt(slot);
-                    assert arg != null && arg.kind() == kind.stackKind() : "No valid local in framestate for slot #" + slot + " (" + arg + ")";
-                    slot++;
-                    if (slot < fs.localsSize() && fs.localAt(slot) == null) {
-                        slot++;
-                    }
-                }
-            }
-        }
-        return true;
-    }
-
-
     @Override
     public void visitArrayLength(ArrayLengthNode x) {
         XirArgument array = toXirArgument(x.array());
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BciBlockMapping.java	Mon Mar 05 16:09:07 2012 -0800
+++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BciBlockMapping.java	Mon Mar 05 16:09:49 2012 -0800
@@ -177,12 +177,6 @@
         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.
      */
@@ -320,10 +314,8 @@
                 case IFNULL:    // fall through
                 case IFNONNULL: {
                     current = null;
-                    double probability = useBranchPrediction ? profilingInfo.getBranchTakenProbability(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);
+                    Block b1 = makeBlock(bci + Bytes.beS2(code, bci + 1));
+                    Block b2 = makeBlock(bci + 3);
                     setSuccessors(bci, b1, b2);
                     break;
                 }
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/FrameStateBuilder.java	Mon Mar 05 16:09:07 2012 -0800
+++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/FrameStateBuilder.java	Mon Mar 05 16:09:49 2012 -0800
@@ -195,6 +195,9 @@
     }
 
     private void deletePhi(Node phi) {
+        if (phi.isDeleted()) {
+            return;
+        }
         // Collect all phi functions that use this phi so that we can delete them recursively (after we delete ourselfs to avoid circles).
         List<Node> phiUsages = phi.usages().filter(NodePredicates.isA(PhiNode.class)).snapshot();
 
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java	Mon Mar 05 16:09:07 2012 -0800
+++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java	Mon Mar 05 16:09:49 2012 -0800
@@ -38,7 +38,6 @@
 import com.oracle.max.graal.debug.*;
 import com.oracle.max.graal.graph.*;
 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;
@@ -536,6 +535,14 @@
 
     private void ifNode(ValueNode x, Condition cond, ValueNode y) {
         assert !x.isDeleted() && !y.isDeleted();
+        assert currentBlock.normalSuccessors == 2 : currentBlock.normalSuccessors;
+        Block trueBlock = currentBlock.successors.get(0);
+        Block falseBlock = currentBlock.successors.get(1);
+        if (trueBlock == falseBlock) {
+            appendGoto(createTarget(trueBlock, frameState));
+            return;
+        }
+
         double probability = profilingInfo.getBranchTakenProbability(bci());
         if (probability < 0) {
             assert probability == -1 : "invalid probability";
@@ -544,15 +551,9 @@
         }
 
         CompareNode condition = currentGraph.unique(new CompareNode(x, cond, y));
-        FixedNode trueSuccessor = createTarget(currentBlock.successors.get(0), frameState);
-        FixedNode falseSuccessor = createTarget(currentBlock.successors.get(1), frameState);
-        if (trueSuccessor == falseSuccessor) {
-            appendGoto(trueSuccessor);
-        } else {
-            append(currentGraph.add(new IfNode(condition, trueSuccessor, falseSuccessor, probability)));
-        }
-
-        assert currentBlock.normalSuccessors == 2 : currentBlock.normalSuccessors;
+        BeginNode trueSuccessor = createBlockTarget(probability, trueBlock, frameState);
+        BeginNode falseSuccessor = createBlockTarget(1 - probability, falseBlock, frameState);
+        append(currentGraph.add(new IfNode(condition, trueSuccessor, falseSuccessor, probability)));
     }
 
     private void genIfZero(Condition cond) {
@@ -1117,9 +1118,10 @@
         int nofCases = ts.numberOfCases() + 1; // including default case
         assert currentBlock.normalSuccessors == nofCases;
 
-        TableSwitchNode tableSwitch = currentGraph.add(new TableSwitchNode(value, ts.lowKey(), switchProbability(nofCases, bci)));
+        double[] probabilities = switchProbability(nofCases, bci);
+        TableSwitchNode tableSwitch = currentGraph.add(new TableSwitchNode(value, ts.lowKey(), probabilities));
         for (int i = 0; i < nofCases; ++i) {
-            tableSwitch.setBlockSuccessor(i, BeginNode.begin(createTarget(currentBlock.successors.get(i), frameState)));
+            tableSwitch.setBlockSuccessor(i, createBlockTarget(probabilities[i], currentBlock.successors.get(i), frameState));
         }
         append(tableSwitch);
     }
@@ -1150,9 +1152,10 @@
         for (int i = 0; i < nofCases - 1; ++i) {
             keys[i] = ls.keyAt(i);
         }
-        LookupSwitchNode lookupSwitch = currentGraph.add(new LookupSwitchNode(value, keys, switchProbability(nofCases, bci)));
+        double[] probabilities = switchProbability(nofCases, bci);
+        LookupSwitchNode lookupSwitch = currentGraph.add(new LookupSwitchNode(value, keys, probabilities));
         for (int i = 0; i < nofCases; ++i) {
-            lookupSwitch.setBlockSuccessor(i, BeginNode.begin(createTarget(currentBlock.successors.get(i), frameState)));
+            lookupSwitch.setBlockSuccessor(i, createBlockTarget(probabilities[i], currentBlock.successors.get(i), frameState));
         }
         append(lookupSwitch);
     }
@@ -1245,6 +1248,30 @@
         return result;
     }
 
+    /**
+     * Returns a block begin node with the specified state.  If the specified probability is 0, the block
+     * deoptimizes immediately.
+     */
+    private BeginNode createBlockTarget(double probability, Block block, FrameStateBuilder stateAfter) {
+        assert probability >= 0 && probability <= 1;
+        if (probability == 0) {
+            FrameStateBuilder state = stateAfter.copy();
+            state.clearNonLiveLocals(block.localsLiveIn);
+
+            BeginNode begin = currentGraph.add(new BeginNode());
+            DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateReprofile));
+            begin.setNext(deopt);
+            begin.setStateAfter(state.create(block.startBci));
+            return begin;
+        }
+
+        FixedNode target = createTarget(block, stateAfter);
+        assert !(target instanceof BeginNode);
+        BeginNode begin = currentGraph.add(new BeginNode());
+        begin.setNext(target);
+        return begin;
+    }
+
     private ValueNode synchronizedObject(FrameStateBuilder state, RiResolvedMethod target) {
         if (isStatic(target.accessFlags())) {
             return append(ConstantNode.forCiConstant(target.holder().getEncoding(Representation.JavaClass), runtime, currentGraph));
@@ -1282,8 +1309,6 @@
             createUnwind();
         } else if (block instanceof ExceptionBlock) {
             createExceptionDispatch((ExceptionBlock) block);
-        } else if (block instanceof DeoptBlock) {
-            createDeopt();
         } else {
             frameState.setRethrowException(false);
             iterateBytecodesForBlock(block);
@@ -1327,10 +1352,6 @@
         }
     }
 
-    private void createDeopt() {
-        append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateReprofile)));
-    }
-
     private void createUnwind() {
         synchronizedEpilogue(FrameState.AFTER_EXCEPTION_BCI);
         UnwindNode unwindNode = currentGraph.add(new UnwindNode(frameState.apop()));
--- a/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinterObserver.java	Mon Mar 05 16:09:07 2012 -0800
+++ b/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinterObserver.java	Mon Mar 05 16:09:49 2012 -0800
@@ -50,6 +50,14 @@
 
     @Override
     public void dump(Object object, String message) {
+        try {
+            dumpSandboxed(object, message);
+        } catch (Throwable ex) {
+            TTY.println("CFGPrinter: Exception during output of " + message + ": " + ex);
+        }
+    }
+
+    public void dumpSandboxed(Object object, String message) {
         GraalCompiler compiler = Debug.contextLookup(GraalCompiler.class);
         if (compiler == null) {
             return;