changeset 22490:386dddf89b6f

Improve stamps of phi functions during bytecode parsing
author Christian Wimmer <christian.wimmer@oracle.com>
date Wed, 19 Aug 2015 16:12:13 -0700
parents 8b24fab0a573
children e6a7022319a9
files graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParser.java graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java
diffstat 2 files changed, 39 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParser.java	Wed Aug 19 16:11:29 2015 -0700
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParser.java	Wed Aug 19 16:12:13 2015 -0700
@@ -2258,7 +2258,7 @@
             lastInstr = loopBegin;
 
             // Create phi functions for all local variables and operand stack slots.
-            frameState.insertLoopPhis(liveness, block.loopId, loopBegin, forceLoopPhis());
+            frameState.insertLoopPhis(liveness, block.loopId, loopBegin, forceLoopPhis(), stampFromValueForForcedPhis());
             loopBegin.setStateAfter(createFrameState(block.startBci, loopBegin));
 
             /*
@@ -2275,6 +2275,12 @@
             Debug.log("  created loop header %s", loopBegin);
         } else if (block.isLoopHeader && explodeLoops && this.mergeExplosions) {
             frameState = frameState.copy();
+        } else if (lastInstr instanceof MergeNode) {
+            /*
+             * All inputs of non-loop phi nodes are known by now. We can infer the stamp for the
+             * phi, so that parsing continues with more precise type information.
+             */
+            frameState.inferPhiStamps((AbstractMergeNode) lastInstr);
         }
         assert lastInstr.next() == null : "instructions already appended at block " + block;
         Debug.log("  frameState: %s", frameState);
@@ -2347,6 +2353,11 @@
         return graph.isOSR();
     }
 
+    /* Hook for subclasses. */
+    protected boolean stampFromValueForForcedPhis() {
+        return false;
+    }
+
     protected boolean checkLastInstruction() {
         if (lastInstr instanceof BeginNode) {
             // ignore
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Wed Aug 19 16:11:29 2015 -0700
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Wed Aug 19 16:12:13 2015 -0700
@@ -383,12 +383,12 @@
             ((PhiNode) currentValue).addInput(otherValue);
             return currentValue;
         } else if (currentValue != otherValue) {
-            assert !(block instanceof LoopBeginNode) : String.format("Phi functions for loop headers are create eagerly for changed locals and all stack slots: %s != %s", currentValue, otherValue);
             if (currentValue == TWO_SLOT_MARKER || otherValue == TWO_SLOT_MARKER) {
                 return null;
             } else if (otherValue == null || otherValue.isDeleted() || currentValue.getStackKind() != otherValue.getStackKind()) {
                 return null;
             }
+            assert !(block instanceof LoopBeginNode) : String.format("Phi functions for loop headers are create eagerly for changed locals and all stack slots: %s != %s", currentValue, otherValue);
             return createValuePhi(currentValue, otherValue, block);
         } else {
             return currentValue;
@@ -424,18 +424,36 @@
         }
     }
 
-    public void insertLoopPhis(LocalLiveness liveness, int loopId, LoopBeginNode loopBegin, boolean forcePhis) {
+    public void inferPhiStamps(AbstractMergeNode block) {
         for (int i = 0; i < localsSize(); i++) {
-            boolean needPhi = forcePhis || liveness.localIsChangedInLoop(loopId, i);
-            if (needPhi) {
-                locals[i] = createLoopPhi(loopBegin, locals[i]);
+            inferPhiStamp(block, locals[i]);
+        }
+        for (int i = 0; i < stackSize(); i++) {
+            inferPhiStamp(block, stack[i]);
+        }
+        for (int i = 0; i < lockedObjects.length; i++) {
+            inferPhiStamp(block, lockedObjects[i]);
+        }
+    }
+
+    private static void inferPhiStamp(AbstractMergeNode block, ValueNode node) {
+        if (block.isPhiAtMerge(node)) {
+            node.inferStamp();
+        }
+    }
+
+    public void insertLoopPhis(LocalLiveness liveness, int loopId, LoopBeginNode loopBegin, boolean forcePhis, boolean stampFromValueForForcedPhis) {
+        for (int i = 0; i < localsSize(); i++) {
+            boolean changedInLoop = liveness.localIsChangedInLoop(loopId, i);
+            if (forcePhis || changedInLoop) {
+                locals[i] = createLoopPhi(loopBegin, locals[i], stampFromValueForForcedPhis && !changedInLoop);
             }
         }
         for (int i = 0; i < stackSize(); i++) {
-            stack[i] = createLoopPhi(loopBegin, stack[i]);
+            stack[i] = createLoopPhi(loopBegin, stack[i], false);
         }
         for (int i = 0; i < lockedObjects.length; i++) {
-            lockedObjects[i] = createLoopPhi(loopBegin, lockedObjects[i]);
+            lockedObjects[i] = createLoopPhi(loopBegin, lockedObjects[i], false);
         }
     }
 
@@ -487,13 +505,13 @@
         }
     }
 
-    private ValueNode createLoopPhi(AbstractMergeNode block, ValueNode value) {
+    private ValueNode createLoopPhi(AbstractMergeNode block, ValueNode value, boolean stampFromValue) {
         if (value == null || value == TWO_SLOT_MARKER) {
             return value;
         }
         assert !block.isPhiAtMerge(value) : "phi function for this block already created";
 
-        ValuePhiNode phi = graph.addWithoutUnique(new ValuePhiNode(value.stamp().unrestricted(), block));
+        ValuePhiNode phi = graph.addWithoutUnique(new ValuePhiNode(stampFromValue ? value.stamp() : value.stamp().unrestricted(), block));
         phi.addInput(value);
         return phi;
     }