# HG changeset patch # User Christian Wimmer # Date 1431645257 25200 # Node ID e4eae0fb72d02c398ba83d4aa3e51e0bfe3b9735 # Parent 3bf051bb2691e8652c1b1da3d168e8dbdab92cc1 Always do liveness analysis, but allow non-clearing of local variables; centralize omitAssertion code in bytecode parser diff -r 3bf051bb2691 -r e4eae0fb72d0 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java --- 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 OptImplicitNullChecks = new OptionValue<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptLivenessAnalysis = new OptionValue<>(true); + public static final OptionValue OptClearNonLiveLocals = new OptionValue<>(true); @Option(help = "", type = OptionType.Debug) public static final OptionValue OptLoopTransform = new OptionValue<>(true); diff -r 3bf051bb2691 -r e4eae0fb72d0 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderConfiguration.java --- 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); } /** diff -r 3bf051bb2691 -r e4eae0fb72d0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoadFieldPlugin.java --- 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; diff -r 3bf051bb2691 -r e4eae0fb72d0 graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java --- 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) { diff -r 3bf051bb2691 -r e4eae0fb72d0 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- 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);