Mercurial > hg > graal-compiler
changeset 15089:448338c9ce96
Truffle: Made inlining context-insensitive again to reduce complexity.
line wrap: on
line diff
--- a/CHANGELOG.md Mon Apr 14 18:20:09 2014 +0200 +++ b/CHANGELOG.md Mon Apr 14 18:25:23 2014 +0200 @@ -12,6 +12,7 @@ ### Truffle * Support for collecting stack traces and for accessing the current frame in slow paths +* CallNode#inline was renamed to CallNode#forceInlining(). * ... ## Version 0.2
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotOptimizedCallTarget.java Mon Apr 14 18:20:09 2014 +0200 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotOptimizedCallTarget.java Mon Apr 14 18:25:23 2014 +0200 @@ -97,15 +97,13 @@ if (m != null) { CompilerAsserts.neverPartOfCompilation(); installedCode = null; - inliningResult = null; compilationProfile.reportInvalidated(); logOptimizedInvalidated(this, oldNode, newNode, reason); } cancelInstalledTask(oldNode, newNode, reason); } - @Override - protected void cancelInstalledTask(Node oldNode, Node newNode, CharSequence reason) { + private void cancelInstalledTask(Node oldNode, Node newNode, CharSequence reason) { Future<InstalledCode> task = this.installedCodeTask; if (task != null) { task.cancel(true); @@ -154,7 +152,7 @@ return null; } else { performInlining(); - cancelInlinedCallOptimization(); +// cancelInlinedCallOptimization(); logOptimizingQueued(this); this.installedCodeTask = compiler.compile(this); if (!TruffleBackgroundCompilation.getValue()) { @@ -181,8 +179,6 @@ } } return null; - } finally { - onCompilationDone(); } }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultInliningPolicy.java Mon Apr 14 18:20:09 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultInliningPolicy.java Mon Apr 14 18:25:23 2014 +0200 @@ -27,29 +27,25 @@ public class DefaultInliningPolicy implements TruffleInliningPolicy { private static final String REASON_RECURSION = "recursion"; - private static final String REASON_MAXIMUM_NODE_COUNT = "nodeCount * callSites > " + TruffleInliningMaxCallerSize.getValue(); + private static final String REASON_MAXIMUM_NODE_COUNT = "deepNodeCount * callSites > " + TruffleInliningMaxCallerSize.getValue(); private static final String REASON_MAXIMUM_TOTAL_NODE_COUNT = "totalNodeCount > " + TruffleInliningMaxCallerSize.getValue(); public double calculateScore(TruffleInliningProfile profile) { return profile.getFrequency() / profile.getDeepNodeCount(); } - public boolean isAllowed(TruffleInliningResult state, TruffleInliningProfile profile, int nodeCountBudget) { - TruffleCallPath callPath = profile.getCallPath(); - OptimizedCallTarget inlineTarget = callPath.getCallTarget(); - for (TruffleCallPath path : callPath.getParent().toList()) { - if (path.getCallTarget() == inlineTarget) { - // recursive call found - profile.setFailedReason(REASON_RECURSION); - return false; - } + public boolean isAllowed(TruffleInliningProfile profile, int currentBudgetLeft) { + if (profile.isRecursiveCall()) { + // recursive call found + profile.setFailedReason(REASON_RECURSION); + return false; } if (profile.isForced()) { return true; } - if (nodeCountBudget - profile.getDeepNodeCount() < 0) { + if (currentBudgetLeft - profile.getDeepNodeCount() < 0) { profile.setFailedReason(REASON_MAXIMUM_TOTAL_NODE_COUNT); return false; } @@ -62,9 +58,4 @@ return true; } - - public boolean isAllowedDeep(TruffleInliningResult state, TruffleInliningProfile profile, int nodeCountBudget) { - return true; - } - }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNode.java Mon Apr 14 18:20:09 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNode.java Mon Apr 14 18:25:23 2014 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.truffle; -import java.util.concurrent.atomic.*; - import com.oracle.truffle.api.*; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.frame.*; @@ -32,15 +30,15 @@ import com.oracle.truffle.api.nodes.NodeUtil.NodeCountFilter; /** - * Call target that is optimized by Graal upon surpassing a specific invocation threshold. + * A call node with a constant {@link CallTarget} that can be optimized by Graal. */ public final class OptimizedCallNode extends DefaultCallNode { - protected int callCount; + private int callCount; private boolean trySplit = true; - private boolean inliningForced; + + @CompilationFinal private boolean inlined; @CompilationFinal private OptimizedCallTarget splitCallTarget; - private final AtomicInteger inliningCounter = new AtomicInteger(0); private OptimizedCallNode(OptimizedCallTarget target) { super(target); @@ -70,29 +68,27 @@ return splitCallTarget; } - public static OptimizedCallNode create(OptimizedCallTarget target) { - return new OptimizedCallNode(target); - } - @Override public Object call(VirtualFrame frame, Object[] arguments) { if (CompilerDirectives.inInterpreter()) { - interpreterCall(); - if (inliningCounter.get() > 0 || inliningForced) { - return getCurrentCallTarget().callInlined(arguments); - } + onInterpreterCall(); } - return callProxy(this, getCurrentCallTarget(), frame, arguments); + OptimizedCallTarget target = getCurrentCallTarget(); + if (inlined) { + return target.callInlined(arguments); + } else { + return super.call(frame, arguments); + } } - private void interpreterCall() { + private void onInterpreterCall() { callCount++; if (trySplit) { if (callCount == 1) { // on first call - getCurrentCallTarget().incrementKnownCallSite(); + getCurrentCallTarget().incrementKnownCallSites(); } - if (callCount > 1) { + if (callCount > 1 && !inlined) { trySplit = false; if (shouldSplit()) { splitImpl(true); @@ -101,22 +97,20 @@ } } - void notifyInlining() { - inliningCounter.incrementAndGet(); - } - - void notifyInliningDone() { - inliningCounter.decrementAndGet(); - } - - @Override - public void inline() { - inliningForced = true; + /* Called by the runtime system if this CallNode is really going to be inlined. */ + void inline() { + inlined = true; } @Override public boolean isInlined() { - return inliningForced; + return inlined; + } + + @Override + public boolean split() { + splitImpl(false); + return true; } private void splitImpl(boolean heuristic) { @@ -128,8 +122,8 @@ OptimizedCallTarget.logSplit(this, getCallTarget(), splitTarget); } if (callCount >= 1) { - getCallTarget().decrementKnownCallSite(); - splitTarget.incrementKnownCallSite(); + getCallTarget().decrementKnownCallSites(); + splitTarget.incrementKnownCallSites(); } this.splitCallTarget = splitTarget; } @@ -145,7 +139,7 @@ return false; } OptimizedCallTarget splitTarget = getCallTarget(); - int nodeCount = OptimizedCallUtils.countNonTrivialNodes(null, new TruffleCallPath(splitTarget)); + int nodeCount = OptimizedCallUtils.countNonTrivialNodes(splitTarget, false); if (nodeCount > TruffleCompilerOptions.TruffleSplittingMaxCalleeSize.getValue()) { return false; } @@ -173,7 +167,7 @@ } private int countPolymorphic() { - return NodeUtil.countNodes(getCallTarget().getRootNode(), new NodeCountFilter() { + return NodeUtil.countNodes(getCurrentCallTarget().getRootNode(), new NodeCountFilter() { public boolean isCounted(Node node) { NodeCost cost = node.getCost(); boolean polymorphic = cost == NodeCost.POLYMORPHIC || cost == NodeCost.MEGAMORPHIC; @@ -182,10 +176,7 @@ }); } - @SuppressWarnings("unused") - public void nodeReplaced(Node oldNode, Node newNode, CharSequence reason) { - if (!isSplit() && isSplittable()) { - trySplit = true; - } + public static OptimizedCallNode create(OptimizedCallTarget target) { + return new OptimizedCallNode(target); } }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Mon Apr 14 18:20:09 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Mon Apr 14 18:25:23 2014 +0200 @@ -30,11 +30,11 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; -import com.oracle.graal.truffle.OptimizedCallUtils.InlinedNodeCountFilter; import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.impl.*; import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.NodeUtil.NodeCountFilter; /** * Call target that is optimized by Graal upon surpassing a specific invocation threshold. @@ -46,11 +46,10 @@ protected InstalledCode installedCode; protected boolean compilationEnabled; protected int callCount; - protected TruffleInliningResult inliningResult; + protected boolean inliningPerformed; protected final CompilationProfile compilationProfile; protected final CompilationPolicy compilationPolicy; private OptimizedCallTarget splitSource; - private final AtomicInteger callSitesKnown = new AtomicInteger(0); public OptimizedCallTarget(RootNode rootNode, int invokeCounter, int compilationThreshold, boolean compilationEnabled, CompilationPolicy compilationPolicy) { @@ -67,18 +66,14 @@ return callSitesKnown.get(); } - public final void incrementKnownCallSite() { + public final void incrementKnownCallSites() { callSitesKnown.incrementAndGet(); } - public final void decrementKnownCallSite() { + public final void decrementKnownCallSites() { callSitesKnown.decrementAndGet(); } - public final TruffleInliningResult getInliningResult() { - return inliningResult; - } - public final OptimizedCallTarget getSplitSource() { return splitSource; } @@ -116,48 +111,33 @@ } public final void performInlining() { - if (!shouldInline()) { + if (!TruffleFunctionInlining.getValue()) { return; } - - if (inliningResult != null) { + if (inliningPerformed) { return; } - TruffleInliningHandler handler = new TruffleInliningHandler(this, new DefaultInliningPolicy(), new HashMap<OptimizedCallTarget, TruffleInliningResult>()); - int startNodeCount = OptimizedCallUtils.countNonTrivialNodes(null, new TruffleCallPath(this)); - this.inliningResult = handler.inline(startNodeCount); - logInliningDecision(this, inliningResult, handler); - } - - protected boolean shouldCompile() { - return compilationPolicy.shouldCompile(compilationProfile); + TruffleInliningHandler handler = new TruffleInliningHandler(new DefaultInliningPolicy()); + TruffleInliningResult result = handler.decideInlining(this, 0); + performInlining(result); + logInliningDecision(result, 0); } - protected static boolean shouldInline() { - return TruffleFunctionInlining.getValue(); - } - - protected final void cancelInlinedCallOptimization() { - if (getInliningResult() != null) { - for (TruffleCallPath path : getInliningResult()) { - OptimizedCallNode top = path.getCallNode(); - top.notifyInlining(); - top.getCurrentCallTarget().cancelInstalledTask(top, top, "Inlined"); + private void performInlining(TruffleInliningResult result) { + if (inliningPerformed) { + return; + } + inliningPerformed = true; + for (TruffleInliningProfile profile : result) { + profile.getCallNode().inline(); + TruffleInliningResult recursiveResult = profile.getRecursiveResult(); + if (recursiveResult != null) { + recursiveResult.getCallTarget().performInlining(recursiveResult); } } } - protected final void onCompilationDone() { - if (inliningResult != null) { - for (TruffleCallPath path : inliningResult) { - path.getCallNode().notifyInliningDone(); - } - } - } - - protected abstract void cancelInstalledTask(Node oldNode, Node newNode, CharSequence reason); - protected abstract void invalidate(Node oldNode, Node newNode, CharSequence reason); public final Object executeHelper(Object[] args) { @@ -188,39 +168,55 @@ public Map<String, Object> getDebugProperties() { Map<String, Object> properties = new LinkedHashMap<>(); - addASTSizeProperty(getInliningResult(), new TruffleCallPath(this), properties); + addASTSizeProperty(this, properties); properties.putAll(getCompilationProfile().getDebugProperties()); return properties; } - private static void logInliningDecision(OptimizedCallTarget target, TruffleInliningResult result, TruffleInliningHandler handler) { + private static void logInliningDecision(TruffleInliningResult result, int depth) { if (!TraceTruffleInlining.getValue()) { return; } - List<TruffleInliningProfile> profiles = handler.lookupProfiles(result, new TruffleCallPath(target)); - - Collections.sort(profiles); // sorts by hierarchy and source section + logInliningStart(result.getCallTarget()); + logInliningDecisionRecursive(result, depth); + logInliningDone(result.getCallTarget()); + } - logInliningStart(target); - for (TruffleInliningProfile profile : profiles) { - TruffleCallPath path = profile.getCallPath(); - if (path.getRootCallTarget() == target) { - String msg = result.isInlined(path) ? "inline success" : "inline failed"; - logInlinedImpl(msg, result, handler.getProfiles().get(path), path); + private static void logInliningDecisionRecursive(TruffleInliningResult result, int depth) { + List<OptimizedCallNode> callNodes = searchCallNodes(result.getCallTarget()); + for (OptimizedCallNode callNode : callNodes) { + TruffleInliningProfile profile = result.getProfiles().get(callNode); + boolean inlined = result.isInlined(callNode); + String msg = inlined ? "inline success" : "inline failed"; + logInlinedImpl(msg, profile, depth); + if (profile.getRecursiveResult() != null && inlined) { + logInliningDecisionRecursive(profile.getRecursiveResult(), depth + 1); } } - logInliningDone(target); } - private static void logInlinedImpl(String status, TruffleInliningResult result, TruffleInliningProfile profile, TruffleCallPath path) { + private static List<OptimizedCallNode> searchCallNodes(final OptimizedCallTarget target) { + final List<OptimizedCallNode> callNodes = new ArrayList<>(); + target.getRootNode().accept(new NodeVisitor() { + public boolean visit(Node node) { + if (node instanceof OptimizedCallNode) { + callNodes.add((OptimizedCallNode) node); + } + return true; + } + }); + return callNodes; + } + + private static void logInlinedImpl(String status, TruffleInliningProfile profile, int depth) { Map<String, Object> properties = new LinkedHashMap<>(); - addASTSizeProperty(result, path, properties); + addASTSizeProperty(profile.getCallNode().getCurrentCallTarget(), properties); if (profile != null) { properties.putAll(profile.getDebugProperties()); } - log((path.getDepth() * 2), status, path.getCallTarget().toString(), properties); + log((depth * 2), status, profile.getCallNode().getCurrentCallTarget().toString(), properties); } private static void logInliningStart(OptimizedCallTarget target) { @@ -296,7 +292,7 @@ } if (node instanceof CallNode) { CallNode callNode = (CallNode) node; - if (callNode.isInlined()) { + if (callNode.isInliningForced()) { callNode.getCurrentRootNode().accept(this); } } @@ -312,27 +308,27 @@ static void logSplit(OptimizedCallNode callNode, OptimizedCallTarget target, OptimizedCallTarget newTarget) { if (TraceTruffleSplitting.getValue()) { Map<String, Object> properties = new LinkedHashMap<>(); - addASTSizeProperty(target.getInliningResult(), new TruffleCallPath(target), properties); + addASTSizeProperty(target, properties); properties.put("Split#", ++splitCount); properties.put("Source", callNode.getEncapsulatingSourceSection()); log(0, "split", newTarget.toString(), properties); } } - static void addASTSizeProperty(TruffleInliningResult inliningResult, TruffleCallPath countedPath, Map<String, Object> properties) { - int polymorphicCount = OptimizedCallUtils.countNodes(inliningResult, countedPath, new InlinedNodeCountFilter() { - public boolean isCounted(TruffleCallPath path, Node node) { + static void addASTSizeProperty(OptimizedCallTarget target, Map<String, Object> properties) { + int polymorphicCount = OptimizedCallUtils.countNodes(target, new NodeCountFilter() { + public boolean isCounted(Node node) { return node.getCost() == NodeCost.POLYMORPHIC; } - }); + }, true); - int megamorphicCount = OptimizedCallUtils.countNodes(inliningResult, countedPath, new InlinedNodeCountFilter() { - public boolean isCounted(TruffleCallPath path, Node node) { + int megamorphicCount = OptimizedCallUtils.countNodes(target, new NodeCountFilter() { + public boolean isCounted(Node node) { return node.getCost() == NodeCost.MEGAMORPHIC; } - }); + }, true); - String value = String.format("%4d (%d/%d)", OptimizedCallUtils.countNonTrivialNodes(inliningResult, countedPath), polymorphicCount, megamorphicCount); + String value = String.format("%4d (%d/%d)", OptimizedCallUtils.countNonTrivialNodes(target, true), polymorphicCount, megamorphicCount); properties.put("ASTSize", value); } @@ -390,7 +386,7 @@ continue; } - int nodeCount = OptimizedCallUtils.countNonTrivialNodes(callTarget.getInliningResult(), new TruffleCallPath(callTarget)); + int nodeCount = OptimizedCallUtils.countNonTrivialNodes(callTarget, true); String comment = callTarget.installedCode == null ? " int" : ""; comment += callTarget.compilationEnabled ? "" : " fail"; OUT.printf("%-50s | %10d | %15d | %10d | %3d%s\n", callTarget.getRootNode(), callTarget.callCount, nodeCount, nodeCount, callTarget.getCompilationProfile().getInvalidationCount(), comment);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallUtils.java Mon Apr 14 18:20:09 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallUtils.java Mon Apr 14 18:25:23 2014 +0200 @@ -23,98 +23,70 @@ package com.oracle.graal.truffle; import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.NodeUtil.NodeCountFilter; class OptimizedCallUtils { - public abstract static class InlinedCallVisitor implements NodeVisitor { - - private TruffleCallPath currentPath; - private final TruffleInliningResult inliningDecision; - - public InlinedCallVisitor(TruffleInliningResult inliningDecision, TruffleCallPath initialPath) { - this.inliningDecision = inliningDecision; - this.currentPath = initialPath; - } - - public final TruffleInliningResult getInliningDecision() { - return inliningDecision; - } - - public final boolean visit(Node node) { - if (node instanceof OptimizedCallNode) { - OptimizedCallNode callNode = ((OptimizedCallNode) node); - this.currentPath = new TruffleCallPath(this.currentPath, callNode); - try { - boolean result = visit(currentPath, node); - TruffleInliningResult decision = inliningDecision; - if (decision != null && decision.isInlined(currentPath)) { - callNode.getCurrentRootNode().accept(this); - } - return result; - } finally { - this.currentPath = this.currentPath.getParent(); - } - } else { - return visit(currentPath, node); - } - } - - public abstract boolean visit(TruffleCallPath path, Node node); - - } - - public static int countNodes(TruffleInliningResult decision, TruffleCallPath path, InlinedNodeCountFilter filter) { - InlinedNodeCountVisitor nodeCount = new InlinedNodeCountVisitor(decision, path, filter); - path.getCallTarget().getRootNode().accept(nodeCount); + public static int countNodes(OptimizedCallTarget target, NodeCountFilter filter, boolean inlined) { + NodeCountVisitorImpl nodeCount = new NodeCountVisitorImpl(filter, inlined); + target.getRootNode().accept(nodeCount); return nodeCount.nodeCount; } - public static int countCalls(TruffleInliningResult decision, TruffleCallPath path) { - InlinedNodeCountVisitor nodeCount = new InlinedNodeCountVisitor(decision, path, new InlinedNodeCountFilter() { - public boolean isCounted(TruffleCallPath p, Node node) { + public static int countCalls(OptimizedCallTarget target) { + return countNodes(target, new NodeCountFilter() { + public boolean isCounted(Node node) { return node instanceof CallNode; } - }); - path.getCallTarget().getRootNode().accept(nodeCount); - return nodeCount.nodeCount; + }, true); } - public interface InlinedNodeCountFilter { - - boolean isCounted(TruffleCallPath path, Node node); + public static int countCallsInlined(OptimizedCallTarget target) { + return countNodes(target, new NodeCountFilter() { + public boolean isCounted(Node node) { + return (node instanceof OptimizedCallNode) && ((OptimizedCallNode) node).isInlined(); + } + }, true); } - private static final class InlinedNodeCountVisitor extends InlinedCallVisitor { + public static int countNonTrivialNodes(final OptimizedCallTarget target, final boolean inlined) { + return countNodes(target, new NodeCountFilter() { + public boolean isCounted(Node node) { + NodeCost cost = node.getCost(); + if (cost != null && cost != NodeCost.NONE && cost != NodeCost.UNINITIALIZED) { + return true; + } + return false; + } + }, inlined); + } - private final InlinedNodeCountFilter filter; - int nodeCount; + private static final class NodeCountVisitorImpl implements NodeVisitor { - private InlinedNodeCountVisitor(TruffleInliningResult decision, TruffleCallPath initialPath, InlinedNodeCountFilter filter) { - super(decision, initialPath); + private final NodeCountFilter filter; + private int nodeCount; + private boolean followInlined; + + private NodeCountVisitorImpl(NodeCountFilter filter, boolean followInlined) { this.filter = filter; + this.followInlined = followInlined; } - @Override - public boolean visit(TruffleCallPath path, Node node) { - if (filter == null || filter.isCounted(path, node)) { + public boolean visit(Node node) { + if (filter == null || filter.isCounted(node)) { nodeCount++; } + if (followInlined) { + if (node instanceof OptimizedCallNode) { + OptimizedCallNode ocn = (OptimizedCallNode) node; + if (ocn.isInlined()) { + ocn.getCurrentRootNode().accept(this); + } + } + } return true; } } - static int countNonTrivialNodes(TruffleInliningResult state, TruffleCallPath path) { - return countNodes(state, path, new InlinedNodeCountFilter() { - - public boolean isCounted(TruffleCallPath p, Node node) { - NodeCost cost = node.getCost(); - if (cost != null && cost != NodeCost.NONE && cost != NodeCost.UNINITIALIZED) { - return true; - } - return false; - } - }); - } - }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Mon Apr 14 18:20:09 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Mon Apr 14 18:25:23 2014 +0200 @@ -121,7 +121,7 @@ Debug.dump(graph, "Before inlining"); // Make sure frame does not escape. - expandTree(callTarget, graph, assumptions); + expandTree(graph, assumptions); if (Thread.currentThread().isInterrupted()) { return null; @@ -175,14 +175,12 @@ return graph; } - private void expandTree(OptimizedCallTarget target, StructuredGraph graph, Assumptions assumptions) { + private void expandTree(StructuredGraph graph, Assumptions assumptions) { PhaseContext phaseContext = new PhaseContext(providers, assumptions); TruffleExpansionLogger expansionLogger = null; if (TraceTruffleExpansion.getValue()) { expansionLogger = new TruffleExpansionLogger(providers, graph); } - boolean inliningEnabled = target.getInliningResult() != null && target.getInliningResult().size() > 0; - Map<Node, TruffleCallPath> methodTargetToStack = new HashMap<>(); boolean changed; do { changed = false; @@ -203,19 +201,13 @@ } StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod()); - if (inliningEnabled && inlineGraph == null) { - inlineGraph = expandInlinableCallNode(target, methodTargetToStack, assumptions, phaseContext, methodCallTargetNode); - } - if (inlineGraph == null && !Modifier.isNative(methodCallTargetNode.targetMethod().getModifiers())) { inlineGraph = parseGraph(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), assumptions, phaseContext, false); } if (inlineGraph != null) { try (Indent indent = Debug.logAndIndent("inline graph %s", methodCallTargetNode.targetMethod())) { - if (inliningEnabled) { - preExpandTruffleCallPath(inlineGraph, methodTargetToStack, methodTargetToStack.get(methodCallTargetNode)); - } + int nodeCountBefore = graph.getNodeCount(); Mark mark = graph.getMark(); if (TraceTruffleExpansion.getValue()) { @@ -226,9 +218,6 @@ if (TraceTruffleExpansion.getValue()) { expansionLogger.postExpand(inlined); } - if (inliningEnabled) { - postExpandTruffleCallPath(methodTargetToStack, inlined); - } if (Debug.isDumpEnabled()) { Debug.log("dump enabled"); int nodeCountAfter = graph.getNodeCount(); @@ -253,76 +242,6 @@ } } - private static void preExpandTruffleCallPath(StructuredGraph inlineGraph, Map<Node, TruffleCallPath> methodTargetToCallPath, TruffleCallPath truffleCallPath) { - for (MethodCallTargetNode methodTargetNode : inlineGraph.getNodes(MethodCallTargetNode.class)) { - methodTargetToCallPath.put(methodTargetNode, truffleCallPath); - } - } - - private static void postExpandTruffleCallPath(Map<Node, TruffleCallPath> methodCallTargetToCallPath, Map<Node, Node> nodeUpdates) { - for (Object key : methodCallTargetToCallPath.keySet().toArray()) { - if (nodeUpdates.containsKey(key)) { - methodCallTargetToCallPath.put(nodeUpdates.get(key), methodCallTargetToCallPath.get(key)); - methodCallTargetToCallPath.remove(key); - } - } - } - - private StructuredGraph expandInlinableCallNode(OptimizedCallTarget target, Map<Node, TruffleCallPath> methodCallToCallPath, Assumptions assumptions, PhaseContext phaseContext, - MethodCallTargetNode methodCallTargetNode) { - - ValueNode receiverNode = methodCallTargetNode.receiver(); - if (receiverNode == null || !receiverNode.isConstant() || !receiverNode.asConstant().getKind().isObject()) { - return null; - } - - ResolvedJavaMethod method = methodCallTargetNode.targetMethod(); - - /* - * Accessing the constant using the SnippetReflectionProvider is a workaround, we should - * think about a better solution. Since object constants are VM-specific, only the hosting - * VM knows how to do the conversion. - */ - SnippetReflectionProvider snippetReflection = Graal.getRequiredCapability(SnippetReflectionProvider.class); - Object receiverValue = snippetReflection.asObject(receiverNode.asConstant()); - if (receiverValue instanceof OptimizedCallNode) { - if (!method.getName().equals("call") || method.getSignature().getParameterCount(false) != 2) { // FIXME - return null; - } - - OptimizedCallNode callNode = (OptimizedCallNode) receiverValue; - TruffleCallPath callPath = methodCallToCallPath.get(methodCallTargetNode); - if (callPath == null) { - callPath = new TruffleCallPath(target); - } - callPath = new TruffleCallPath(callPath, callNode); - methodCallToCallPath.put(methodCallTargetNode, callPath); - // let the normal expansion do the work - return null; - } else if (receiverValue instanceof OptimizedCallTarget) { - TruffleCallPath path = methodCallToCallPath.get(methodCallTargetNode); - // path unknown. direct call to OptimizedCallTarget without OptimizedCallNode? - if (path == null) { - return null; - } - - TruffleInliningResult decision = target.getInliningResult(); - if (decision == null) { // no inlining decision. inlining disabled? - return null; - } - - if (!decision.isInlined(path)) { - // the OptimizedCallTarget has decided not to inline this call path - return null; - } - - // inline truffle call - return parseGraph(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), assumptions, phaseContext, true); - } - - return null; - } - private boolean isFrame(ValueNode receiver) { return receiver instanceof NewFrameNode || Objects.equals(ObjectStamp.typeOrNull(receiver.stamp()), frameType); }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCallPath.java Mon Apr 14 18:20:09 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,219 +0,0 @@ -/* - * Copyright (c) 2013, 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; - -import java.util.*; - -import com.oracle.truffle.api.*; - -public final class TruffleCallPath implements Iterable<TruffleCallPath>, Comparable<TruffleCallPath> { - - private final OptimizedCallNode callNode; - private final TruffleCallPath parent; - private final OptimizedCallTarget rootCallTarget; - - public TruffleCallPath(OptimizedCallTarget parent) { - this.rootCallTarget = Objects.requireNonNull(parent); - this.callNode = null; - this.parent = null; - } - - public TruffleCallPath(TruffleCallPath parent, OptimizedCallNode node) { - this.parent = Objects.requireNonNull(parent); - assert !parent.containsPath(this) : "cyclic path detected"; - this.callNode = Objects.requireNonNull(node); - this.rootCallTarget = parent.getRootCallTarget(); - } - - public boolean isRoot() { - return parent == null && rootCallTarget != null; - } - - private boolean containsPath(TruffleCallPath p) { - return p == this || (getParent() != null && this.getParent().containsPath(p)); - } - - public OptimizedCallTarget getRootCallTarget() { - return rootCallTarget; - } - - @Override - public String toString() { - return (parent != null ? (parent.toString() + " -> ") : "") + getCallTarget().toString(); - } - - public Iterator<TruffleCallPath> iterator() { - return toList().iterator(); - } - - public OptimizedCallTarget getCallTarget() { - return parent == null ? rootCallTarget : callNode.getCurrentCallTarget(); - } - - public List<TruffleCallPath> toList() { - List<TruffleCallPath> list = new ArrayList<>(); - toListImpl(list); - return list; - } - - private void toListImpl(List<TruffleCallPath> list) { - if (parent != null) { - parent.toListImpl(list); - } - list.add(this); - } - - public TruffleCallPath getParent() { - return parent; - } - - public OptimizedCallNode getCallNode() { - return callNode; - } - - public int getDepth() { - return parent == null ? 0 : (parent.getDepth() + 1); - } - - public int compareTo(TruffleCallPath o) { - return Objects.compare(this, o, new PathComparator()); - } - - private static class PathComparator implements Comparator<TruffleCallPath> { - public int compare(TruffleCallPath c1, TruffleCallPath c2) { - if (c1 == c2) { - return 0; - } - - Iterator<TruffleCallPath> p1 = c1.toList().iterator(); - Iterator<TruffleCallPath> p2 = c2.toList().iterator(); - - int cmp = 0; - while (cmp == 0 && (p1.hasNext() || p2.hasNext())) { - TruffleCallPath o1; - TruffleCallPath o2; - if (p1.hasNext()) { - o1 = p1.next(); - } else { - return -1; - } - if (p2.hasNext()) { - o2 = p2.next(); - } else { - return 1; - } - - if (o1 == o2) { - continue; - } - - SourceSection s1; - if (o1.callNode != null) { - s1 = o1.callNode.getEncapsulatingSourceSection(); - } else { - s1 = o1.getCallTarget().getRootNode().getSourceSection(); - } - - SourceSection s2; - if (o2.callNode != null) { - s2 = o2.callNode.getEncapsulatingSourceSection(); - } else { - s2 = o2.getCallTarget().getRootNode().getSourceSection(); - } - cmp = compareSourceSection(s2, s1); - - if (cmp == 0) { - cmp = o1.getCallTarget().toString().compareTo(o2.getCallTarget().toString()); - } - } - return cmp; - } - } - - private static int compareSourceSection(SourceSection s1, SourceSection s2) { - return Objects.compare(s1, s2, new Comparator<SourceSection>() { - public int compare(SourceSection o1, SourceSection o2) { - if (o1 == o2) { - return 0; - } - if (o1 == null || o2 == null) { - return 0; - } - int cmp = 0; - if (o1.getSource() != null && o2.getSource() != null && !Objects.equals(o1.getSource().getName(), o2.getSource().getName())) { - cmp = o2.getSource().getName().compareTo(o1.getSource().getName()); - } - if (cmp == 0) { - cmp = o2.getStartLine() - o1.getStartLine(); - } - if (cmp == 0) { - cmp = o2.getStartColumn() - o1.getStartColumn(); - } - return cmp; - } - }); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((callNode == null) ? 0 : callNode.hashCode()); - result = prime * result + ((parent == null) ? 0 : parent.hashCode()); - result = prime * result + ((rootCallTarget == null) ? 0 : rootCallTarget.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof TruffleCallPath) { - TruffleCallPath other = (TruffleCallPath) obj; - if (other.callNode != callNode) { - return false; - } - if (!Objects.equals(other.parent, parent)) { - return false; - } - if (!Objects.equals(other.rootCallTarget, rootCallTarget)) { - return false; - } - return true; - } - return false; - } - - public TruffleCallPath append(TruffleCallPath path) { - if (getCallTarget() != path.getRootCallTarget()) { - throw new IllegalArgumentException("Pathes are not compatible and can therfore not be appended."); - } - - TruffleCallPath append = this; - for (TruffleCallPath childPath : path) { - if (!childPath.isRoot()) { - append = new TruffleCallPath(append, childPath.getCallNode()); - } - } - return append; - } - -}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Mon Apr 14 18:20:09 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Mon Apr 14 18:25:23 2014 +0200 @@ -165,11 +165,11 @@ if (TraceTruffleCompilation.getValue()) { byte[] code = compiledMethod.getCode(); - int calls = OptimizedCallUtils.countCalls(compilable.getInliningResult(), new TruffleCallPath(compilable)); - int inlinedCalls = (compilable.getInliningResult() != null ? compilable.getInliningResult().size() : 0); + int calls = OptimizedCallUtils.countCalls(compilable); + int inlinedCalls = OptimizedCallUtils.countCallsInlined(compilable); int dispatchedCalls = calls - inlinedCalls; Map<String, Object> properties = new LinkedHashMap<>(); - OptimizedCallTarget.addASTSizeProperty(compilable.getInliningResult(), new TruffleCallPath(compilable), properties); + OptimizedCallTarget.addASTSizeProperty(compilable, properties); properties.put("Time", String.format("%5.0f(%4.0f+%-4.0f)ms", // (timeCompilationFinished - timeCompilationStarted) / 1e6, // (timePartialEvaluationFinished - timeCompilationStarted) / 1e6, //
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningHandler.java Mon Apr 14 18:20:09 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningHandler.java Mon Apr 14 18:25:23 2014 +0200 @@ -24,164 +24,103 @@ import java.util.*; -import com.oracle.graal.truffle.OptimizedCallUtils.InlinedCallVisitor; import com.oracle.truffle.api.nodes.*; public final class TruffleInliningHandler { - private final ProfileScoreComparator inliningOrder = new ProfileScoreComparator(); - - private final OptimizedCallTarget callTarget; + private static final int MAXIMUM_RECURSIVE_DEPTH = 15; + private static final ProfileScoreComparator INLINING_SCORE = new ProfileScoreComparator(); private final TruffleInliningPolicy policy; - private final Map<TruffleCallPath, TruffleInliningProfile> profiles; - private final Map<OptimizedCallTarget, TruffleInliningResult> inliningResultCache; + private final Map<OptimizedCallTarget, TruffleInliningResult> resultCache; - public TruffleInliningHandler(OptimizedCallTarget callTarget, TruffleInliningPolicy policy, Map<OptimizedCallTarget, TruffleInliningResult> inliningResultCache) { - this.callTarget = callTarget; + public TruffleInliningHandler(TruffleInliningPolicy policy) { this.policy = policy; - this.profiles = new HashMap<>(); - this.inliningResultCache = inliningResultCache; + this.resultCache = new HashMap<>(); } - public TruffleInliningResult inline(int originalTotalNodeCount) { - Set<TruffleCallPath> inlinedPathes = new HashSet<>(); - TruffleInliningResult result = new TruffleInliningResult(callTarget, inlinedPathes); - TruffleCallPath startPath = new TruffleCallPath(callTarget); - - PriorityQueue<TruffleInliningProfile> queue = new PriorityQueue<>(10, inliningOrder); - queueCallSitesForInlining(result, startPath, queue); - - int budget = TruffleCompilerOptions.TruffleInliningMaxCallerSize.getValue() - originalTotalNodeCount; - int index = 0; - while (!queue.isEmpty()) { - TruffleInliningProfile profile = queue.poll(); - profile.setQueryIndex(index); - budget = tryInline(queue, result, inlinedPathes, profile, budget); - profiles.put(profile.getCallPath(), profile); - index++; + public TruffleInliningResult decideInlining(OptimizedCallTarget target, int depth) { + if (resultCache.containsKey(target)) { + return resultCache.get(target); } + resultCache.put(target, null); + TruffleInliningResult result = decideInliningImpl(target, depth); + resultCache.put(target, result); return result; } - private int tryInline(PriorityQueue<TruffleInliningProfile> queue, TruffleInliningResult result, Set<TruffleCallPath> inlinedPathes, TruffleInliningProfile profile, int budget) { - - if (policy.isAllowed(result, profile, budget)) { - int remainingBudget; - inlinedPathes.add(profile.getCallPath()); - if (policy.isAllowedDeep(result, profile, budget)) { - if (profile.getRecursiveResult() != null) { - TruffleInliningResult inliningResult = profile.getRecursiveResult(); - for (TruffleCallPath recursiveInlinedPath : inliningResult) { - inlinedPathes.add(profile.getCallPath().append(recursiveInlinedPath)); - } - } - remainingBudget = budget - profile.getDeepNodeCount(); - } else { - remainingBudget = budget - profile.getNodeCount(); + private TruffleInliningResult decideInliningImpl(OptimizedCallTarget target, int depth) { + List<TruffleInliningProfile> profiles = lookupProfiles(target, depth); + Set<TruffleInliningProfile> inlined = new HashSet<>(); + Collections.sort(profiles, INLINING_SCORE); + int budget = TruffleCompilerOptions.TruffleInliningMaxCallerSize.getValue() - OptimizedCallUtils.countNonTrivialNodes(target, true); + int index = 0; + for (TruffleInliningProfile profile : profiles) { + profile.setQueryIndex(index++); + if (policy.isAllowed(profile, budget)) { + inlined.add(profile); + budget -= profile.getDeepNodeCount(); } - - queueCallSitesForInlining(result, profile.getCallPath(), queue); - return remainingBudget; } - return budget; + int deepNodeCount = TruffleCompilerOptions.TruffleInliningMaxCallerSize.getValue() - budget; + return new TruffleInliningResult(target, profiles, inlined, deepNodeCount); + } + + private List<TruffleInliningProfile> lookupProfiles(final OptimizedCallTarget target, int depth) { + final List<OptimizedCallNode> callNodes = new ArrayList<>(); + target.getRootNode().accept(new NodeVisitor() { + public boolean visit(Node node) { + if (node instanceof OptimizedCallNode) { + callNodes.add((OptimizedCallNode) node); + } + return true; + } + }); + final List<TruffleInliningProfile> profiles = new ArrayList<>(); + for (OptimizedCallNode callNode : callNodes) { + profiles.add(lookupProfile(target, callNode, depth)); + } + return profiles; + } + + public TruffleInliningProfile lookupProfile(OptimizedCallTarget parentTarget, OptimizedCallNode ocn, int depth) { + OptimizedCallTarget target = ocn.getCurrentCallTarget(); + + int callSites = ocn.getCurrentCallTarget().getKnownCallSiteCount(); + int nodeCount = OptimizedCallUtils.countNonTrivialNodes(target, false); + double frequency = calculateFrequency(parentTarget, ocn); + boolean forced = ocn.isInliningForced(); + + int deepNodeCount; + TruffleInliningResult recursiveResult; + boolean recursiveCall = false; + if (target.inliningPerformed || depth > MAXIMUM_RECURSIVE_DEPTH) { + deepNodeCount = OptimizedCallUtils.countNonTrivialNodes(target, true); + recursiveResult = null; + } else { + recursiveResult = decideInlining(ocn.getCurrentCallTarget(), depth + 1); + if (recursiveResult == null) { + recursiveCall = true; + deepNodeCount = Integer.MAX_VALUE; + } else { + deepNodeCount = recursiveResult.getNodeCount(); + } + } + + TruffleInliningProfile profile = new TruffleInliningProfile(ocn, callSites, nodeCount, deepNodeCount, frequency, forced, recursiveCall, recursiveResult); + profile.setScore(policy.calculateScore(profile)); + return profile; } public TruffleInliningPolicy getPolicy() { return policy; } - public Map<TruffleCallPath, TruffleInliningProfile> getProfiles() { - return profiles; - } - - private void queueCallSitesForInlining(final TruffleInliningResult currentDecision, TruffleCallPath fromPath, final Collection<TruffleInliningProfile> queue) { - fromPath.getCallTarget().getRootNode().accept(new InlinedCallVisitor(currentDecision, fromPath) { - @Override - public boolean visit(TruffleCallPath path, Node node) { - if (node instanceof OptimizedCallNode) { - if (!currentDecision.isInlined(path)) { - addToQueue(queue, currentDecision, path); - } - } - return true; - } - }); - } - - private void addToQueue(final Collection<TruffleInliningProfile> queue, final TruffleInliningResult currentDecision, TruffleCallPath path) { - queue.add(lookupProfile(currentDecision, path)); - } - - public List<TruffleInliningProfile> lookupProfiles(final TruffleInliningResult currentDecision, TruffleCallPath fromPath) { - final List<TruffleInliningProfile> pathes = new ArrayList<>(); - fromPath.getCallTarget().getRootNode().accept(new InlinedCallVisitor(currentDecision, fromPath) { - @Override - public boolean visit(TruffleCallPath path, Node node) { - if (node instanceof OptimizedCallNode) { - pathes.add(lookupProfile(currentDecision, path)); - } - return true; - } - }); - return pathes; + private static double calculateFrequency(OptimizedCallTarget target, OptimizedCallNode ocn) { + return (double) Math.max(1, target.getCompilationProfile().getCallCount()) / Math.max(1, ocn.getCallCount()); } - public TruffleInliningProfile lookupProfile(TruffleInliningResult state, TruffleCallPath callPath) { - TruffleInliningProfile profile = profiles.get(callPath); - if (profile != null) { - return profile; - } - - int callSites = callPath.getCallTarget().getKnownCallSiteCount(); - int nodeCount = OptimizedCallUtils.countNonTrivialNodes(state, callPath); - double frequency = calculatePathFrequency(callPath); - boolean forced = callPath.getCallNode().isInlined(); - TruffleInliningResult recursiveResult = lookupChildResult(callPath, nodeCount); - int deepNodeCount = OptimizedCallUtils.countNonTrivialNodes(recursiveResult, new TruffleCallPath(callPath.getCallTarget())); - - profile = new TruffleInliningProfile(callPath, callSites, nodeCount, deepNodeCount, frequency, forced, recursiveResult); - profile.setScore(policy.calculateScore(profile)); - profiles.put(callPath, profile); - - return profile; - } - - private TruffleInliningResult lookupChildResult(TruffleCallPath callPath, int nodeCount) { - OptimizedCallTarget target = callPath.getCallTarget(); - - TruffleInliningResult recursiveResult = target.getInliningResult(); - - if (recursiveResult == null) { - recursiveResult = inliningResultCache.get(callPath.getCallTarget()); - - if (recursiveResult == null) { - if (inliningResultCache.containsKey(target)) { - // cancel on recursion - return new TruffleInliningResult(target, new HashSet<TruffleCallPath>()); - } - inliningResultCache.put(target, null); - TruffleInliningHandler handler = new TruffleInliningHandler(target, policy, inliningResultCache); - recursiveResult = handler.inline(nodeCount); - inliningResultCache.put(callPath.getCallTarget(), recursiveResult); - } - } - return recursiveResult; - } - - private static double calculatePathFrequency(TruffleCallPath callPath) { - int parentCallCount = -1; - double f = 1.0d; - for (TruffleCallPath path : callPath.toList()) { - if (parentCallCount != -1) { - f *= path.getCallNode().getCallCount() / (double) parentCallCount; - } - parentCallCount = path.getCallTarget().getCompilationProfile().getCallCount(); - } - return f; - } - - private final class ProfileScoreComparator implements Comparator<TruffleInliningProfile> { + private final static class ProfileScoreComparator implements Comparator<TruffleInliningProfile> { public int compare(TruffleInliningProfile o1, TruffleInliningProfile o2) { return Double.compare(o2.getScore(), o1.getScore());
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningPolicy.java Mon Apr 14 18:20:09 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningPolicy.java Mon Apr 14 18:25:23 2014 +0200 @@ -24,9 +24,7 @@ public interface TruffleInliningPolicy { - boolean isAllowed(TruffleInliningResult state, TruffleInliningProfile profile, int nodeCountBudget); - - boolean isAllowedDeep(TruffleInliningResult state, TruffleInliningProfile profile, int nodeCountBudget); + boolean isAllowed(TruffleInliningProfile profile, int currentBudgetLeft); double calculateScore(TruffleInliningProfile profile);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningProfile.java Mon Apr 14 18:20:09 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningProfile.java Mon Apr 14 18:25:23 2014 +0200 @@ -24,34 +24,41 @@ import java.util.*; -public class TruffleInliningProfile implements Comparable<TruffleInliningProfile> { +public class TruffleInliningProfile { - private final TruffleCallPath callPath; - + private final OptimizedCallNode callNode; private final int nodeCount; private final int deepNodeCount; private final int callSites; private final double frequency; private final boolean forced; + private final boolean recursiveCall; private final TruffleInliningResult recursiveResult; private String failedReason; private int queryIndex = -1; private double score; - public TruffleInliningProfile(TruffleCallPath callPath, int callSites, int nodeCount, int deepNodeCount, double frequency, boolean forced, TruffleInliningResult recursiveResult) { - if (callPath.isRoot()) { - throw new IllegalArgumentException("Root call path not profilable."); - } + public TruffleInliningProfile(OptimizedCallNode callNode, int callSites, int nodeCount, int deepNodeCount, double frequency, boolean forced, boolean recursiveCall, + TruffleInliningResult recursiveResult) { + this.callNode = callNode; this.callSites = callSites; - this.callPath = callPath; this.nodeCount = nodeCount; this.deepNodeCount = deepNodeCount; this.frequency = frequency; + this.recursiveCall = recursiveCall; this.forced = forced; this.recursiveResult = recursiveResult; } + public boolean isRecursiveCall() { + return recursiveCall; + } + + public OptimizedCallNode getCallNode() { + return callNode; + } + public int getCallSites() { return callSites; } @@ -100,21 +107,12 @@ return deepNodeCount; } - public TruffleCallPath getCallPath() { - return callPath; - } - - public int compareTo(TruffleInliningProfile o) { - return callPath.compareTo(o.callPath); - } - public Map<String, Object> getDebugProperties() { Map<String, Object> properties = new LinkedHashMap<>(); - properties.put("callSites", callSites); - properties.put("nodeCount", nodeCount); + properties.put("nodeCount", String.format("%5d/%5d", deepNodeCount, nodeCount)); properties.put("frequency", frequency); - properties.put("score", score); - properties.put(String.format("index=%3d, force=%s", queryIndex, (forced ? "Y" : "N")), ""); + properties.put("score", String.format("%8.4f", getScore())); + properties.put(String.format("index=%3d, force=%s, callSites=%2d", queryIndex, (forced ? "Y" : "N"), callSites), ""); properties.put("reason", failedReason); return properties; }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningResult.java Mon Apr 14 18:20:09 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningResult.java Mon Apr 14 18:25:23 2014 +0200 @@ -24,34 +24,49 @@ import java.util.*; -public final class TruffleInliningResult implements Iterable<TruffleCallPath> { +public final class TruffleInliningResult implements Iterable<TruffleInliningProfile> { private final OptimizedCallTarget callTarget; - private final Set<TruffleCallPath> inlinedPathes; + private final Map<OptimizedCallNode, TruffleInliningProfile> profiles; + private final Set<TruffleInliningProfile> inlined; + private final int nodeCount; - public TruffleInliningResult(OptimizedCallTarget callTarget, Set<TruffleCallPath> pathes) { + public TruffleInliningResult(OptimizedCallTarget callTarget, List<TruffleInliningProfile> profiles, Set<TruffleInliningProfile> inlined, int nodeCount) { this.callTarget = callTarget; - this.inlinedPathes = pathes; + this.profiles = new HashMap<>(); + for (TruffleInliningProfile profile : profiles) { + this.profiles.put(profile.getCallNode(), profile); + } + this.nodeCount = nodeCount; + this.inlined = inlined; + } + + public Map<OptimizedCallNode, TruffleInliningProfile> getProfiles() { + return profiles; + } + + public int getNodeCount() { + return nodeCount; } public OptimizedCallTarget getCallTarget() { return callTarget; } - public boolean isInlined(TruffleCallPath path) { - return inlinedPathes.contains(path); + public boolean isInlined(OptimizedCallNode path) { + return inlined.contains(profiles.get(path)); } public int size() { - return inlinedPathes.size(); + return inlined.size(); } - public Iterator<TruffleCallPath> iterator() { - return Collections.unmodifiableSet(inlinedPathes).iterator(); + public Iterator<TruffleInliningProfile> iterator() { + return Collections.unmodifiableSet(inlined).iterator(); } @Override public String toString() { - return inlinedPathes.toString(); + return inlined.toString(); } }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleTreeDumpHandler.java Mon Apr 14 18:20:09 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleTreeDumpHandler.java Mon Apr 14 18:25:23 2014 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.truffle; -import java.util.*; - import com.oracle.graal.debug.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.nodes.*; @@ -46,7 +44,6 @@ final OptimizedCallTarget oct = (OptimizedCallTarget) callTarget; visitor.beginGroup(callTarget.toString()); - dumpInlinedCalls(visitor, oct); dumpFullTree(visitor, message, oct); visitor.printToNetwork(false); } @@ -54,12 +51,10 @@ private static void dumpFullTree(final GraphPrintVisitor visitor, final String message, final OptimizedCallTarget oct) { visitor.setChildSupplier(new ChildSupplier() { - private TruffleCallPath currentPath = new TruffleCallPath(oct); public Object startNode(Object callNode) { if (callNode instanceof OptimizedCallNode) { - currentPath = new TruffleCallPath(currentPath, (OptimizedCallNode) callNode); - if (oct.getInliningResult() != null && oct.getInliningResult().isInlined(currentPath)) { + if (((OptimizedCallNode) callNode).isInlined()) { return ((OptimizedCallNode) callNode).getCurrentRootNode(); } } @@ -67,9 +62,6 @@ } public void endNode(Object callNode) { - if (callNode instanceof OptimizedCallNode) { - currentPath = currentPath.getParent(); - } } }); @@ -77,23 +69,6 @@ visitor.setChildSupplier(null); } - private static void dumpInlinedCalls(final GraphPrintVisitor visitor, final OptimizedCallTarget oct) { - final Set<OptimizedCallTarget> visitedRoots = new HashSet<>(); - oct.getRootNode().accept(new OptimizedCallUtils.InlinedCallVisitor(oct.getInliningResult(), new TruffleCallPath(oct)) { - @Override - public boolean visit(TruffleCallPath path, Node node) { - if (node instanceof OptimizedCallNode) { - OptimizedCallTarget target = ((OptimizedCallNode) node).getCurrentCallTarget(); - if (!visitedRoots.contains(target)) { - visitor.beginGraph("inlined " + target.toString()).visit(target.getRootNode()); - visitedRoots.add(target); - } - } - return true; - } - }); - } - public void close() { // nothing to do }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallNode.java Mon Apr 14 18:20:09 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallNode.java Mon Apr 14 18:25:23 2014 +0200 @@ -34,6 +34,8 @@ @CompilationFinal private FrameAccess outsideFrameAccess = FrameAccess.NONE; + private boolean inliningForced; + public DefaultCallNode(CallTarget target) { super(target); } @@ -66,7 +68,8 @@ } @Override - public void inline() { + public void forceInlining() { + inliningForced = true; } @Override @@ -80,13 +83,18 @@ } @Override + public boolean isInlined() { + return false; + } + + @Override public boolean isSplittable() { return false; } @Override - public boolean isInlined() { - return false; + public boolean isInliningForced() { + return inliningForced; } @Override
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/CallNode.java Mon Apr 14 18:20:09 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/CallNode.java Mon Apr 14 18:25:23 2014 +0200 @@ -25,8 +25,6 @@ package com.oracle.truffle.api.nodes; import com.oracle.truffle.api.*; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.frame.FrameInstance.FrameAccess; import com.oracle.truffle.api.frame.*; /** @@ -40,7 +38,7 @@ * Please note: This class is not intended to be subclassed by guest language implementations. * * @see TruffleRuntime#createCallNode(CallTarget) - * @see #inline() + * @see #forceInlining() * @see #split() */ public abstract class CallNode extends Node { @@ -79,19 +77,28 @@ public abstract boolean isInlinable(); /** - * Returns <code>true</code> if the {@link CallTarget} in this {@link CallNode} is inlined. A - * {@link CallNode} can either be inlined manually by invoking {@link #inline()} or by the - * runtime system which may at any point decide to inline. + * Returns <code>true</code> if the {@link CallTarget} is forced to be inlined. A + * {@link CallNode} can either be inlined manually by invoking {@link #forceInlining()} or by + * the runtime system which may at any point decide to inline. * * @return true if this method was inlined else false. */ - public abstract boolean isInlined(); + public abstract boolean isInliningForced(); /** * Enforces the runtime system to inline the {@link CallTarget} at this call site. If the * runtime system does not support inlining or it is already inlined this method has no effect. */ - public abstract void inline(); + public abstract void forceInlining(); + + /** + * Returns true if the runtime system has decided to inline this call-site. If the + * {@link CallNode} was forced to inline then this does not necessarily mean that the + * {@link CallNode} is really going to be inlined. This depends on whether or not the runtime + * system supports inlining or not. The runtime system may also decide to ignore calls to + * {@link #forceInlining()}. + */ + public abstract boolean isInlined(); /** * Returns <code>true</code> if this {@link CallNode} can be split. A {@link CallNode} can only
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Mon Apr 14 18:20:09 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Mon Apr 14 18:25:23 2014 +0200 @@ -638,7 +638,7 @@ if (visitInlinedCallNodes && node instanceof CallNode) { CallNode call = (CallNode) node; - if (call.isInlined()) { + if (call.isInliningForced()) { Node target = ((RootCallTarget) call.getCurrentCallTarget()).getRootNode(); if (target != null) { target.accept(this);