Mercurial > hg > graal-compiler
changeset 20985:eebb05f2d1e8
Fixes for GraphPE
author | Christian Wimmer <christian.wimmer@oracle.com> |
---|---|
date | Wed, 15 Apr 2015 21:01:33 -0700 |
parents | 6361fa2e3321 |
children | ec91b758ebc7 |
files | graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java graal/com.oracle.graal.truffle.test/sl/TestDeoptInInlinedFunction.output graal/com.oracle.graal.truffle.test/sl/TestDeoptInInlinedFunction.sl graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/SLTruffleGraalTestSuite.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLCallUntilOptimizedBuiltin.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLDeoptimizeWhenCompiledBuiltin.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PEGraphDecoder.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java |
diffstat | 8 files changed, 128 insertions(+), 26 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java Wed Apr 15 21:13:43 2015 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java Wed Apr 15 21:01:33 2015 -0700 @@ -252,11 +252,12 @@ public final void decode(StructuredGraph graph, EncodedGraph encodedGraph) { MethodScope methodScope = new MethodScope(graph, encodedGraph, LoopExplosionKind.NONE); decode(methodScope, null); - cleanupGraph(methodScope); + cleanupGraph(methodScope, null); methodScope.graph.verify(); } protected final void decode(MethodScope methodScope, FixedWithNextNode startNode) { + Graph.Mark start = methodScope.graph.getMark(); LoopScope loopScope = new LoopScope(methodScope); FixedNode firstNode; if (startNode != null) { @@ -284,9 +285,14 @@ } if (methodScope.loopExplosion == LoopExplosionKind.MERGE_EXPLODE) { - cleanupGraph(methodScope); + /* + * The startNode can get deleted during graph cleanup, so we use its predecessor (if + * available) as the starting point for loop detection. + */ + FixedNode detectLoopsStart = startNode.predecessor() != null ? (FixedNode) startNode.predecessor() : startNode; + cleanupGraph(methodScope, start); Debug.dump(methodScope.graph, "Before loop detection"); - detectLoops(methodScope.graph, firstNode); + detectLoops(methodScope.graph, detectLoopsStart); } } @@ -1111,18 +1117,21 @@ } } - protected void cleanupGraph(MethodScope methodScope) { + protected void cleanupGraph(MethodScope methodScope, Graph.Mark start) { assert verifyEdges(methodScope); Debug.dump(methodScope.graph, "Before removing redundant merges"); - for (MergeNode mergeNode : methodScope.graph.getNodes(MergeNode.TYPE)) { - if (mergeNode.forwardEndCount() == 1) { - methodScope.graph.reduceTrivialMerge(mergeNode); + for (Node node : methodScope.graph.getNewNodes(start)) { + if (node instanceof MergeNode) { + MergeNode mergeNode = (MergeNode) node; + if (mergeNode.forwardEndCount() == 1) { + methodScope.graph.reduceTrivialMerge(mergeNode); + } } } Debug.dump(methodScope.graph, "Before removing redundant begins"); - for (Node node : methodScope.graph.getNodes()) { + for (Node node : methodScope.graph.getNewNodes(start)) { if (node instanceof BeginNode || node instanceof KillingBeginNode) { if (!(node.predecessor() instanceof ControlSplitNode) && node.hasNoUsages()) { GraphUtil.unlinkFixedNode((AbstractBeginNode) node); @@ -1132,7 +1141,7 @@ } Debug.dump(methodScope.graph, "Before removing unused non-fixed nodes"); - for (Node node : methodScope.graph.getNodes()) { + for (Node node : methodScope.graph.getNewNodes(start)) { if (!(node instanceof FixedNode) && node.hasNoUsages()) { GraphUtil.killCFG(node); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/sl/TestDeoptInInlinedFunction.output Wed Apr 15 21:01:33 2015 -0700 @@ -0,0 +1,2 @@ +[deoptimizeWhenCompiled] +[deoptimizeWhenCompiled]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/sl/TestDeoptInInlinedFunction.sl Wed Apr 15 21:01:33 2015 -0700 @@ -0,0 +1,21 @@ +/* + * This tests that simple arithmetic gets inlined. + */ +function add(a, b) { + deoptimizeWhenCompiled(a == 50); + return a + b; +} + + +function test() { + i = 0; + while (i < 100) { + i = add(i, 1); + } + return i; +} + +function main() { + waitForOptimization(callUntilOptimized(test, 1 == 2)); + test(); +}
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/SLTruffleGraalTestSuite.java Wed Apr 15 21:13:43 2015 +0200 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/SLTruffleGraalTestSuite.java Wed Apr 15 21:01:33 2015 -0700 @@ -49,6 +49,7 @@ SLTestRunner.installBuiltin(SLGenerateDummyNodesBuiltinFactory.getInstance()); SLTestRunner.installBuiltin(SLCallFunctionsWithBuiltinFactory.getInstance()); SLTestRunner.installBuiltin(SLIsCompilationConstantBuiltinFactory.getInstance()); + SLTestRunner.installBuiltin(SLDeoptimizeWhenCompiledBuiltinFactory.getInstance()); /* test specific builtins */ SLTestRunner.installBuiltin(SLTestTruffleBoundary01BuiltinFactory.getInstance());
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLCallUntilOptimizedBuiltin.java Wed Apr 15 21:13:43 2015 +0200 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLCallUntilOptimizedBuiltin.java Wed Apr 15 21:01:33 2015 -0700 @@ -49,7 +49,12 @@ @Child private IndirectCallNode indirectCall = Truffle.getRuntime().createIndirectCallNode(); @Specialization - public SLFunction callUntilCompiled(VirtualFrame frame, SLFunction function) { + public SLFunction callUntilCompiled(VirtualFrame frame, SLFunction function, @SuppressWarnings("unused") SLNull checkTarget) { + return callUntilCompiled(frame, function, false); + } + + @Specialization + public SLFunction callUntilCompiled(VirtualFrame frame, SLFunction function, boolean checkTarget) { OptimizedCallTarget target = ((OptimizedCallTarget) function.getCallTarget()); for (int i = 0; i < MAX_CALLS; i++) { if (isCompiling(target)) { @@ -63,7 +68,9 @@ // call one more in compiled indirectCall.call(frame, target, EMPTY_ARGS); - checkTarget(target); + if (checkTarget) { + checkTarget(target); + } return function; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLDeoptimizeWhenCompiledBuiltin.java Wed Apr 15 21:01:33 2015 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2015, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.truffle.test.builtins; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.sl.runtime.*; + +/** + * Forces a deoptimization as soon as the method runs in compiled code. + */ +@NodeInfo(shortName = "deoptimizeWhenCompiled") +public abstract class SLDeoptimizeWhenCompiledBuiltin extends SLGraalRuntimeBuiltin { + + @Specialization + public SLNull deoptimzeWhenCompiled(boolean condition) { + if (CompilerDirectives.inCompiledCode()) { + if (condition) { + printMessage(); + CompilerDirectives.transferToInterpreterAndInvalidate(); + } + } + return SLNull.SINGLETON; + } + + @TruffleBoundary + private void printMessage() { + getContext().getOutput().println("[deoptimizeWhenCompiled]"); + } +}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PEGraphDecoder.java Wed Apr 15 21:13:43 2015 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PEGraphDecoder.java Wed Apr 15 21:01:33 2015 -0700 @@ -128,9 +128,11 @@ protected class PENonAppendGraphBuilderContext implements GraphBuilderContext { protected final PEMethodScope methodScope; + protected final Invoke invoke; - public PENonAppendGraphBuilderContext(PEMethodScope methodScope) { + public PENonAppendGraphBuilderContext(PEMethodScope methodScope, Invoke invoke) { this.methodScope = methodScope; + this.invoke = invoke; } @Override @@ -210,7 +212,7 @@ @Override public int bci() { - throw unimplemented(); + return invoke.bci(); } @Override @@ -228,8 +230,8 @@ protected FixedWithNextNode lastInstr; protected ValueNode pushedNode; - public PEAppendGraphBuilderContext(PEMethodScope methodScope, FixedWithNextNode lastInstr) { - super(methodScope); + public PEAppendGraphBuilderContext(PEMethodScope inlineScope, FixedWithNextNode lastInstr) { + super(inlineScope, inlineScope.invokeData.invoke); this.lastInstr = lastInstr; } @@ -319,14 +321,14 @@ PEMethodScope methodScope = new PEMethodScope(targetGraph, null, null, lookupEncodedGraph(method), method, null, 0, loopExplosionPlugin, invocationPlugins, inlineInvokePlugin, parameterPlugin, null); decode(methodScope, null); - cleanupGraph(methodScope); + cleanupGraph(methodScope, null); methodScope.graph.verify(); } @Override - protected void cleanupGraph(MethodScope methodScope) { + protected void cleanupGraph(MethodScope methodScope, Graph.Mark start) { GraphBuilderPhase.connectLoopEndToBegin(methodScope.graph); - super.cleanupGraph(methodScope); + super.cleanupGraph(methodScope, start); } @Override @@ -378,7 +380,7 @@ } if (methodScope.inlineInvokePlugin != null) { - methodScope.inlineInvokePlugin.notifyOfNoninlinedInvoke(new PENonAppendGraphBuilderContext(methodScope), callTarget.targetMethod(), invokeData.invoke); + methodScope.inlineInvokePlugin.notifyOfNoninlinedInvoke(new PENonAppendGraphBuilderContext(methodScope, invokeData.invoke), callTarget.targetMethod(), invokeData.invoke); } return false; } @@ -439,7 +441,7 @@ } ValueNode[] arguments = callTarget.arguments().toArray(new ValueNode[0]); - GraphBuilderContext graphBuilderContext = new PENonAppendGraphBuilderContext(methodScope); + GraphBuilderContext graphBuilderContext = new PENonAppendGraphBuilderContext(methodScope, invokeData.invoke); InlineInfo inlineInfo = methodScope.inlineInvokePlugin.getInlineInfo(graphBuilderContext, targetMethod, arguments, callTarget.returnType()); if (inlineInfo == null) { return false; @@ -619,7 +621,7 @@ return result; } else if (methodScope.parameterPlugin != null) { - GraphBuilderContext graphBuilderContext = new PENonAppendGraphBuilderContext(methodScope); + GraphBuilderContext graphBuilderContext = new PENonAppendGraphBuilderContext(methodScope, null); Node result = methodScope.parameterPlugin.interceptParameter(graphBuilderContext, ((ParameterNode) node).index(), ((ParameterNode) node).stamp()); if (result != null) { return result; @@ -657,7 +659,11 @@ Kind invokeReturnKind = methodScope.invokeData.invoke.asNode().getKind(); FrameState outerState = stateAtReturn.duplicateModified(methodScope.graph, methodScope.invokeData.invoke.bci(), stateAtReturn.rethrowException(), true, invokeReturnKind); - if (methodScope.caller != null) { + /* + * When the encoded graph has methods inlining, we can already have a proper caller + * state. If not, we set the caller state here. + */ + if (outerState.outerFrameState() == null && methodScope.caller != null) { ensureOuterStateDecoded(methodScope.caller); outerState.setOuterFrameState(methodScope.caller.outerState); } @@ -680,7 +686,7 @@ registerNode(methodScope.callerLoopScope, methodScope.invokeData.exceptionOrderId, methodScope.exceptionPlaceholderNode, false, false); FrameState exceptionState = (FrameState) ensureNodeCreated(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData.exceptionStateOrderId); - if (methodScope.caller != null) { + if (exceptionState.outerFrameState() == null && methodScope.caller != null) { ensureOuterStateDecoded(methodScope.caller); exceptionState.setOuterFrameState(methodScope.caller.outerState); }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Wed Apr 15 21:13:43 2015 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Wed Apr 15 21:01:33 2015 -0700 @@ -184,7 +184,9 @@ if (original.getAnnotation(TruffleBoundary.class) != null) { return null; } - assert !replacements.hasSubstitution(original, builder.bci()) : "Replacements must have been processed by now"; + if (replacements.hasSubstitution(original, builder.bci())) { + return null; + } assert !builder.parsingReplacement(); if (TruffleCompilerOptions.TruffleFunctionInlining.getValue()) { @@ -260,7 +262,9 @@ if (original.getAnnotation(TruffleBoundary.class) != null) { return null; } - assert !replacements.hasSubstitution(original, builder.bci()) : "Replacements must have been processed by now"; + if (replacements.hasSubstitution(original, builder.bci())) { + return null; + } if (original.equals(callSiteProxyMethod) || original.equals(callDirectMethod)) { return null; @@ -337,7 +341,7 @@ ParameterPlugin parameterPlugin = new InterceptReceiverPlugin(callTarget); - InvocationPlugins decodingInvocationPlugins = new InvocationPlugins(parsingInvocationPlugins.getParent()); + InvocationPlugins decodingInvocationPlugins = new InvocationPlugins(providers.getMetaAccess()); TruffleGraphBuilderPlugins.registerInvocationPlugins(providers.getMetaAccess(), decodingInvocationPlugins, false, snippetReflection); InlineInvokePlugin decodingInlinePlugin = new PEInlineInvokePlugin(callTarget.getInlining(), (ReplacementsImpl) providers.getReplacements()); if (PrintTruffleExpansionHistogram.getValue()) {