changeset 21388:e4eae0fb72d0

Always do liveness analysis, but allow non-clearing of local variables; centralize omitAssertion code in bytecode parser
author Christian Wimmer <christian.wimmer@oracle.com>
date Thu, 14 May 2015 16:14:17 -0700
parents 3bf051bb2691
children 77a775ebd6d4
files graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderConfiguration.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoadFieldPlugin.java graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java
diffstat 5 files changed, 67 insertions(+), 50 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Thu May 14 16:11:58 2015 -0700
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Thu May 14 16:14:17 2015 -0700
@@ -286,7 +286,7 @@
     public static final OptionValue<Boolean> OptImplicitNullChecks = new OptionValue<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> OptLivenessAnalysis = new OptionValue<>(true);
+    public static final OptionValue<Boolean> OptClearNonLiveLocals = new OptionValue<>(true);
 
     @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> OptLoopTransform = new OptionValue<>(true);
--- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderConfiguration.java	Thu May 14 16:11:58 2015 -0700
+++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderConfiguration.java	Thu May 14 16:14:17 2015 -0700
@@ -131,9 +131,10 @@
 
     private final boolean eagerResolving;
     private final boolean omitAllExceptionEdges;
+    private final boolean omitAssertions;
     private final ResolvedJavaType[] skippedExceptionTypes;
     private final DebugInfoMode debugInfoMode;
-    private final boolean doLivenessAnalysis;
+    private final boolean clearNonLiveLocals;
     private boolean useProfiling;
     private final Plugins plugins;
 
@@ -161,13 +162,14 @@
         Full,
     }
 
-    protected GraphBuilderConfiguration(boolean eagerResolving, boolean omitAllExceptionEdges, DebugInfoMode debugInfoMode, ResolvedJavaType[] skippedExceptionTypes, boolean doLivenessAnalysis,
-                    Plugins plugins) {
+    protected GraphBuilderConfiguration(boolean eagerResolving, boolean omitAllExceptionEdges, boolean omitAssertions, DebugInfoMode debugInfoMode, ResolvedJavaType[] skippedExceptionTypes,
+                    boolean clearNonLiveLocals, Plugins plugins) {
         this.eagerResolving = eagerResolving;
         this.omitAllExceptionEdges = omitAllExceptionEdges;
+        this.omitAssertions = omitAssertions;
         this.debugInfoMode = debugInfoMode;
         this.skippedExceptionTypes = skippedExceptionTypes;
-        this.doLivenessAnalysis = doLivenessAnalysis;
+        this.clearNonLiveLocals = clearNonLiveLocals;
         this.useProfiling = true;
         this.plugins = plugins;
     }
@@ -179,7 +181,7 @@
      */
     public GraphBuilderConfiguration copy() {
         Plugins newPlugins = new Plugins(plugins);
-        GraphBuilderConfiguration result = new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, skippedExceptionTypes, doLivenessAnalysis, newPlugins);
+        GraphBuilderConfiguration result = new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, omitAssertions, debugInfoMode, skippedExceptionTypes, clearNonLiveLocals, newPlugins);
         result.useProfiling = useProfiling;
         return result;
     }
@@ -193,20 +195,24 @@
     }
 
     public GraphBuilderConfiguration withSkippedExceptionTypes(ResolvedJavaType[] newSkippedExceptionTypes) {
-        return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, newSkippedExceptionTypes, doLivenessAnalysis, plugins);
+        return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, omitAssertions, debugInfoMode, newSkippedExceptionTypes, clearNonLiveLocals, plugins);
     }
 
     public GraphBuilderConfiguration withOmitAllExceptionEdges(boolean newOmitAllExceptionEdges) {
-        return new GraphBuilderConfiguration(eagerResolving, newOmitAllExceptionEdges, debugInfoMode, skippedExceptionTypes, doLivenessAnalysis, plugins);
+        return new GraphBuilderConfiguration(eagerResolving, newOmitAllExceptionEdges, omitAssertions, debugInfoMode, skippedExceptionTypes, clearNonLiveLocals, plugins);
+    }
+
+    public GraphBuilderConfiguration withOmitAssertions(boolean newOmitAssertions) {
+        return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, newOmitAssertions, debugInfoMode, skippedExceptionTypes, clearNonLiveLocals, plugins);
     }
 
     public GraphBuilderConfiguration withDebugInfoMode(DebugInfoMode newDebugInfoMode) {
         ResolvedJavaType[] newSkippedExceptionTypes = skippedExceptionTypes == EMPTY ? EMPTY : Arrays.copyOf(skippedExceptionTypes, skippedExceptionTypes.length);
-        return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, newDebugInfoMode, newSkippedExceptionTypes, doLivenessAnalysis, plugins);
+        return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, omitAssertions, newDebugInfoMode, newSkippedExceptionTypes, clearNonLiveLocals, plugins);
     }
 
-    public GraphBuilderConfiguration withDoLivenessAnalysis(boolean newLivenessAnalysis) {
-        return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, skippedExceptionTypes, newLivenessAnalysis, plugins);
+    public GraphBuilderConfiguration withClearNonLiveLocals(boolean newClearNonLiveLocals) {
+        return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, omitAssertions, debugInfoMode, skippedExceptionTypes, newClearNonLiveLocals, plugins);
     }
 
     public ResolvedJavaType[] getSkippedExceptionTypes() {
@@ -221,6 +227,10 @@
         return omitAllExceptionEdges;
     }
 
+    public boolean omitAssertions() {
+        return omitAssertions;
+    }
+
     public boolean insertNonSafepointDebugInfo() {
         return debugInfoMode.ordinal() >= DebugInfoMode.Simple.ordinal();
     }
@@ -233,32 +243,32 @@
         return debugInfoMode == DebugInfoMode.Simple;
     }
 
-    public boolean doLivenessAnalysis() {
-        return doLivenessAnalysis;
+    public boolean clearNonLiveLocals() {
+        return clearNonLiveLocals;
     }
 
     public static GraphBuilderConfiguration getDefault(Plugins plugins) {
-        return new GraphBuilderConfiguration(false, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptLivenessAnalysis.getValue(), plugins);
+        return new GraphBuilderConfiguration(false, false, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins);
     }
 
     public static GraphBuilderConfiguration getInfopointDefault(Plugins plugins) {
-        return new GraphBuilderConfiguration(true, false, DebugInfoMode.Simple, EMPTY, GraalOptions.OptLivenessAnalysis.getValue(), plugins);
+        return new GraphBuilderConfiguration(true, false, false, DebugInfoMode.Simple, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins);
     }
 
     public static GraphBuilderConfiguration getEagerDefault(Plugins plugins) {
-        return new GraphBuilderConfiguration(true, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptLivenessAnalysis.getValue(), plugins);
+        return new GraphBuilderConfiguration(true, false, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins);
     }
 
     public static GraphBuilderConfiguration getInfopointEagerDefault(Plugins plugins) {
-        return new GraphBuilderConfiguration(true, false, DebugInfoMode.Simple, EMPTY, GraalOptions.OptLivenessAnalysis.getValue(), plugins);
+        return new GraphBuilderConfiguration(true, false, false, DebugInfoMode.Simple, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins);
     }
 
     public static GraphBuilderConfiguration getSnippetDefault(Plugins plugins) {
-        return new GraphBuilderConfiguration(true, true, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptLivenessAnalysis.getValue(), plugins);
+        return new GraphBuilderConfiguration(true, true, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins);
     }
 
     public static GraphBuilderConfiguration getFullDebugDefault(Plugins plugins) {
-        return new GraphBuilderConfiguration(true, false, DebugInfoMode.Full, EMPTY, GraalOptions.OptLivenessAnalysis.getValue(), plugins);
+        return new GraphBuilderConfiguration(true, false, false, DebugInfoMode.Full, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins);
     }
 
     /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoadFieldPlugin.java	Thu May 14 16:11:58 2015 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoadFieldPlugin.java	Thu May 14 16:14:17 2015 -0700
@@ -25,7 +25,6 @@
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.graphbuilderconf.*;
 import com.oracle.graal.nodes.*;
 
@@ -65,18 +64,6 @@
 
     public boolean apply(GraphBuilderContext b, ResolvedJavaField staticField) {
         if (!ImmutableCode.getValue() || b.parsingIntrinsic()) {
-            // Javac does not allow use of "$assertionsDisabled" for a field name but
-            // Eclipse does in which case a suffix is added to the generated field.
-            if (b.parsingIntrinsic() && staticField.isSynthetic() && staticField.getName().startsWith("$assertionsDisabled")) {
-                // For methods called indirectly from intrinsics, we (silently) disable
-                // assertions so that the parser won't see calls to the AssertionError
-                // constructor (all Invokes must be removed from intrinsics - see
-                // HotSpotInlineInvokePlugin.notifyOfNoninlinedInvoke). Direct use of
-                // assertions in intrinsics is forbidden.
-                assert b.getMethod().getAnnotation(MethodSubstitution.class) == null : "cannot use assertions in " + b.getMethod().format("%H.%n(%p)");
-                b.addPush(ConstantNode.forBoolean(true));
-                return true;
-            }
             return tryReadField(b, staticField, null);
         }
         return false;
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Thu May 14 16:11:58 2015 -0700
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Thu May 14 16:14:17 2015 -0700
@@ -377,17 +377,18 @@
         }
     }
 
-    public void insertLoopPhis(LocalLiveness liveness, int loopId, LoopBeginNode loopBegin) {
+    public void insertLoopPhis(LocalLiveness liveness, int loopId, LoopBeginNode loopBegin, boolean forcePhis) {
         for (int i = 0; i < localsSize(); i++) {
-            if (loopBegin.graph().isOSR() || liveness.localIsChangedInLoop(loopId, i)) {
-                storeLocal(i, createLoopPhi(loopBegin, localAt(i)));
+            boolean changedInLoop = liveness.localIsChangedInLoop(loopId, i);
+            if (changedInLoop || forcePhis) {
+                storeLocal(i, createLoopPhi(loopBegin, localAt(i), !changedInLoop));
             }
         }
         for (int i = 0; i < stackSize(); i++) {
-            storeStack(i, createLoopPhi(loopBegin, stackAt(i)));
+            storeStack(i, createLoopPhi(loopBegin, stackAt(i), false));
         }
         for (int i = 0; i < lockedObjects.length; i++) {
-            lockedObjects[i] = createLoopPhi(loopBegin, lockedObjects[i]);
+            lockedObjects[i] = createLoopPhi(loopBegin, lockedObjects[i], false);
         }
     }
 
@@ -439,13 +440,13 @@
         }
     }
 
-    private ValuePhiNode createLoopPhi(AbstractMergeNode block, ValueNode value) {
+    private ValuePhiNode createLoopPhi(AbstractMergeNode block, ValueNode value, boolean stampFromValue) {
         if (value == null) {
             return null;
         }
         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;
     }
@@ -518,7 +519,7 @@
          * slots at the OSR entry aren't cleared. it is also not enough to rely on PiNodes with
          * Kind.Illegal, because the conflicting branch might not have been parsed.
          */
-        if (liveness == null) {
+        if (!parser.graphBuilderConfig.clearNonLiveLocals()) {
             return;
         }
         if (liveIn) {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu May 14 16:11:58 2015 -0700
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu May 14 16:14:17 2015 -0700
@@ -540,13 +540,11 @@
                     this.firstInstructionArray = new FixedWithNextNode[blockMap.getBlockCount()];
                     this.entryStateArray = new FrameStateBuilder[blockMap.getBlockCount()];
 
-                    if (graphBuilderConfig.doLivenessAnalysis()) {
-                        try (Scope s = Debug.scope("LivenessAnalysis")) {
-                            int maxLocals = method.getMaxLocals();
-                            liveness = LocalLiveness.compute(stream, blockMap.getBlocks(), maxLocals, blockMap.getLoopCount());
-                        } catch (Throwable e) {
-                            throw Debug.handle(e);
-                        }
+                    try (Scope s = Debug.scope("LivenessAnalysis")) {
+                        int maxLocals = method.getMaxLocals();
+                        liveness = LocalLiveness.compute(stream, blockMap.getBlocks(), maxLocals, blockMap.getLoopCount());
+                    } catch (Throwable e) {
+                        throw Debug.handle(e);
                     }
 
                     lastInstr = startInstruction;
@@ -1633,6 +1631,14 @@
             }
 
             protected InvokeWithExceptionNode createInvokeWithException(CallTargetNode callTarget, Kind resultType) {
+                if (currentBlock != null && stream.nextBCI() > currentBlock.endBci) {
+                    /*
+                     * Clear non-live locals early so that the exception handler entry gets the
+                     * cleared state.
+                     */
+                    frameState.clearNonLiveLocals(currentBlock, liveness, false);
+                }
+
                 DispatchBeginNode exceptionEdge = handleException(null, bci());
                 InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, bci()));
                 frameState.pushReturn(resultType, invoke);
@@ -2289,7 +2295,7 @@
                     lastInstr = loopBegin;
 
                     // Create phi functions for all local variables and operand stack slots.
-                    frameState.insertLoopPhis(liveness, block.loopId, loopBegin);
+                    frameState.insertLoopPhis(liveness, block.loopId, loopBegin, forceLoopPhis());
                     loopBegin.setStateAfter(createFrameState(block.startBci, loopBegin));
 
                     /*
@@ -2374,6 +2380,11 @@
                 }
             }
 
+            /* Also a hook for subclasses. */
+            protected boolean forceLoopPhis() {
+                return graph.isOSR();
+            }
+
             protected boolean checkLastInstruction() {
                 if (lastInstr instanceof BeginNode) {
                     // ignore
@@ -3182,9 +3193,17 @@
             private void genGetStatic(JavaField field) {
                 Kind kind = field.getKind();
                 if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) {
+                    ResolvedJavaField resolvedField = (ResolvedJavaField) field;
+                    // Javac does not allow use of "$assertionsDisabled" for a field name but
+                    // Eclipse does in which case a suffix is added to the generated field.
+                    if ((parsingIntrinsic() || graphBuilderConfig.omitAssertions()) && resolvedField.isSynthetic() && resolvedField.getName().startsWith("$assertionsDisabled")) {
+                        appendOptimizedLoadField(kind, ConstantNode.forBoolean(true));
+                        return;
+                    }
+
                     LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getPlugins().getLoadFieldPlugin();
-                    if (loadFieldPlugin == null || !loadFieldPlugin.apply((GraphBuilderContext) this, (ResolvedJavaField) field)) {
-                        appendOptimizedLoadField(kind, genLoadField(null, (ResolvedJavaField) field));
+                    if (loadFieldPlugin == null || !loadFieldPlugin.apply(this, resolvedField)) {
+                        appendOptimizedLoadField(kind, genLoadField(null, resolvedField));
                     }
                 } else {
                     handleUnresolvedLoadField(field, null);