# HG changeset patch # User Christian Humer # Date 1401993213 -7200 # Node ID 2662fb9c37e2fcc699df6eb2f2d814dc8eada25e # Parent 369a3f9d1ceb2dd92fb8bf569f0701f7bda32354 Truffle: invalidate inlining decisions on rewrites. diff -r 369a3f9d1ceb -r 2662fb9c37e2 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultInliningPolicy.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultInliningPolicy.java Thu Jun 05 19:13:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultInliningPolicy.java Thu Jun 05 20:33:33 2014 +0200 @@ -34,9 +34,8 @@ return profile.getFrequency() / profile.getDeepNodeCount(); } - public boolean isAllowed(TruffleInliningProfile profile, int currentBudgetLeft) { + public boolean isAllowed(TruffleInliningProfile profile, int currentNodeCount) { if (profile.isRecursiveCall()) { - // recursive call found profile.setFailedReason(REASON_RECURSION); return false; } @@ -45,7 +44,7 @@ return true; } - if (currentBudgetLeft - profile.getDeepNodeCount() < 0) { + if (currentNodeCount + profile.getDeepNodeCount() > TruffleInliningMaxCallerSize.getValue()) { profile.setFailedReason(REASON_MAXIMUM_TOTAL_NODE_COUNT); return false; } diff -r 369a3f9d1ceb -r 2662fb9c37e2 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Thu Jun 05 19:13:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Thu Jun 05 20:33:33 2014 +0200 @@ -121,6 +121,7 @@ @Override public void invalidate() { this.runtime.invalidateInstalledCode(this); + invalidateInlining(); } protected void invalidate(Node oldNode, Node newNode, CharSequence reason) { @@ -133,6 +134,23 @@ cancelInstalledTask(oldNode, newNode, reason); } + public void invalidateInlining() { + if (inliningPerformed) { + inliningPerformed = false; + getRootNode().accept(new NodeVisitor() { + public boolean visit(Node node) { + if (node instanceof OptimizedDirectCallNode) { + OptimizedDirectCallNode callNode = (OptimizedDirectCallNode) node; + if (callNode.isInlined()) { + callNode.resetInlining(); + } + } + return true; + } + }); + } + } + private void cancelInstalledTask(Node oldNode, Node newNode, CharSequence reason) { if (this.runtime.cancelInstalledTask(this)) { logOptimizingUnqueued(this, oldNode, newNode, reason); @@ -242,19 +260,19 @@ return; } TruffleInliningHandler handler = new TruffleInliningHandler(new DefaultInliningPolicy()); - TruffleInliningResult result = handler.decideInlining(this, 0); + TruffleInliningDecision result = handler.decideInlining(this, 0); performInlining(result); logInliningDecision(result); } - private static void performInlining(TruffleInliningResult result) { + private static void performInlining(TruffleInliningDecision result) { if (result.getCallTarget().inliningPerformed) { return; } result.getCallTarget().inliningPerformed = true; for (TruffleInliningProfile profile : result) { profile.getCallNode().inline(); - TruffleInliningResult recursiveResult = profile.getRecursiveResult(); + TruffleInliningDecision recursiveResult = profile.getRecursiveResult(); if (recursiveResult != null) { performInlining(recursiveResult); } diff -r 369a3f9d1ceb -r 2662fb9c37e2 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java Thu Jun 05 19:13:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java Thu Jun 05 20:33:33 2014 +0200 @@ -53,7 +53,7 @@ private OptimizedCallTargetLog() { } - public static void logInliningDecision(TruffleInliningResult result) { + public static void logInliningDecision(TruffleInliningDecision result) { if (!TraceTruffleInlining.getValue()) { return; } @@ -63,7 +63,7 @@ logInliningDone(result.getCallTarget()); } - private static void logInliningDecisionRecursive(TruffleInliningResult result, int depth) { + private static void logInliningDecisionRecursive(TruffleInliningDecision result, int depth) { List callNodes = searchCallNodes(result.getCallTarget()); for (OptimizedDirectCallNode callNode : callNodes) { TruffleInliningProfile profile = result.getProfiles().get(callNode); diff -r 369a3f9d1ceb -r 2662fb9c37e2 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedDirectCallNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedDirectCallNode.java Thu Jun 05 19:13:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedDirectCallNode.java Thu Jun 05 20:33:33 2014 +0200 @@ -72,6 +72,14 @@ } } + public void resetInlining() { + CompilerAsserts.neverPartOfCompilation(); + if (inlined) { + inlined = false; + getCurrentCallTarget().invalidateInlining(); + } + } + @Override public boolean isInlinable() { return true; @@ -219,4 +227,5 @@ public static OptimizedDirectCallNode create(OptimizedCallTarget target) { return new OptimizedDirectCallNode(target); } + } diff -r 369a3f9d1ceb -r 2662fb9c37e2 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningDecision.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningDecision.java Thu Jun 05 20:33:33 2014 +0200 @@ -0,0 +1,72 @@ +/* + * 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.*; + +public final class TruffleInliningDecision implements Iterable { + + private final OptimizedCallTarget callTarget; + private final Map profiles; + private final Set inlined; + private final int nodeCount; + + public TruffleInliningDecision(OptimizedCallTarget callTarget, List profiles, Set inlined, int nodeCount) { + this.callTarget = callTarget; + this.profiles = new HashMap<>(); + for (TruffleInliningProfile profile : profiles) { + this.profiles.put(profile.getCallNode(), profile); + } + this.nodeCount = nodeCount; + this.inlined = inlined; + } + + public Map getProfiles() { + return profiles; + } + + public int getNodeCount() { + return nodeCount; + } + + public OptimizedCallTarget getCallTarget() { + return callTarget; + } + + public boolean isInlined(OptimizedDirectCallNode path) { + return inlined.contains(profiles.get(path)); + } + + public int size() { + return inlined.size(); + } + + public Iterator iterator() { + return Collections.unmodifiableSet(inlined).iterator(); + } + + @Override + public String toString() { + return inlined.toString(); + } +} diff -r 369a3f9d1ceb -r 2662fb9c37e2 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningHandler.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningHandler.java Thu Jun 05 19:13:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningHandler.java Thu Jun 05 20:33:33 2014 +0200 @@ -31,68 +31,62 @@ private static final int MAXIMUM_RECURSIVE_DEPTH = 15; private static final ProfileScoreComparator INLINING_SCORE = new ProfileScoreComparator(); private final TruffleInliningPolicy policy; - private final Map resultCache; + private final Map resultCache; public TruffleInliningHandler(TruffleInliningPolicy policy) { this.policy = policy; this.resultCache = new HashMap<>(); } - public TruffleInliningResult decideInlining(OptimizedCallTarget target, int depth) { + public TruffleInliningDecision 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, null); // important for recursion detection + TruffleInliningDecision result = createInliningDecision(target, depth); resultCache.put(target, result); return result; } - private TruffleInliningResult decideInliningImpl(OptimizedCallTarget target, int depth) { - List profiles = lookupProfiles(target, depth); + private TruffleInliningDecision createInliningDecision(OptimizedCallTarget target, int depth) { + List profiles = createProfiles(target, depth); Set inlined = new HashSet<>(); Collections.sort(profiles, INLINING_SCORE); - int budget = TruffleCompilerOptions.TruffleInliningMaxCallerSize.getValue() - OptimizedCallUtils.countNonTrivialNodes(target, true); + int deepNodeCount = OptimizedCallUtils.countNonTrivialNodes(target, true); int index = 0; + for (TruffleInliningProfile profile : profiles) { profile.setQueryIndex(index++); - if (policy.isAllowed(profile, budget)) { + if (policy.isAllowed(profile, deepNodeCount)) { inlined.add(profile); - budget -= profile.getDeepNodeCount(); + deepNodeCount += profile.getDeepNodeCount(); } } - int deepNodeCount = TruffleCompilerOptions.TruffleInliningMaxCallerSize.getValue() - budget; - return new TruffleInliningResult(target, profiles, inlined, deepNodeCount); + return new TruffleInliningDecision(target, profiles, inlined, deepNodeCount); } - private List lookupProfiles(final OptimizedCallTarget target, int depth) { - final List callNodes = new ArrayList<>(); + private List createProfiles(final OptimizedCallTarget target, final int depth) { + final List profiles = new ArrayList<>(); target.getRootNode().accept(new NodeVisitor() { public boolean visit(Node node) { if (node instanceof OptimizedDirectCallNode) { - callNodes.add((OptimizedDirectCallNode) node); + profiles.add(createProfile(target, (OptimizedDirectCallNode) node, depth)); } return true; } }); - final List profiles = new ArrayList<>(); - for (OptimizedDirectCallNode callNode : callNodes) { - profiles.add(lookupProfile(target, callNode, depth)); - } return profiles; } - public TruffleInliningProfile lookupProfile(OptimizedCallTarget parentTarget, OptimizedDirectCallNode ocn, int depth) { + public TruffleInliningProfile createProfile(OptimizedCallTarget parentTarget, OptimizedDirectCallNode 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; + TruffleInliningDecision recursiveResult; boolean recursiveCall = false; if (target.inliningPerformed || depth > MAXIMUM_RECURSIVE_DEPTH) { deepNodeCount = OptimizedCallUtils.countNonTrivialNodes(target, true); @@ -107,7 +101,7 @@ } } - TruffleInliningProfile profile = new TruffleInliningProfile(ocn, callSites, nodeCount, deepNodeCount, frequency, forced, recursiveCall, recursiveResult); + TruffleInliningProfile profile = new TruffleInliningProfile(ocn, nodeCount, deepNodeCount, frequency, recursiveCall, recursiveResult); profile.setScore(policy.calculateScore(profile)); return profile; } diff -r 369a3f9d1ceb -r 2662fb9c37e2 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningPolicy.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningPolicy.java Thu Jun 05 19:13:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningPolicy.java Thu Jun 05 20:33:33 2014 +0200 @@ -24,7 +24,7 @@ public interface TruffleInliningPolicy { - boolean isAllowed(TruffleInliningProfile profile, int currentBudgetLeft); + boolean isAllowed(TruffleInliningProfile profile, int currentNodeCount); double calculateScore(TruffleInliningProfile profile); diff -r 369a3f9d1ceb -r 2662fb9c37e2 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningProfile.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningProfile.java Thu Jun 05 19:13:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningProfile.java Thu Jun 05 20:33:33 2014 +0200 @@ -29,25 +29,20 @@ private final OptimizedDirectCallNode 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 final TruffleInliningDecision recursiveResult; private String failedReason; private int queryIndex = -1; private double score; - public TruffleInliningProfile(OptimizedDirectCallNode callNode, int callSites, int nodeCount, int deepNodeCount, double frequency, boolean forced, boolean recursiveCall, - TruffleInliningResult recursiveResult) { + public TruffleInliningProfile(OptimizedDirectCallNode callNode, int nodeCount, int deepNodeCount, double frequency, boolean recursiveCall, TruffleInliningDecision recursiveResult) { this.callNode = callNode; - this.callSites = callSites; this.nodeCount = nodeCount; this.deepNodeCount = deepNodeCount; this.frequency = frequency; this.recursiveCall = recursiveCall; - this.forced = forced; this.recursiveResult = recursiveResult; } @@ -60,14 +55,14 @@ } public int getCallSites() { - return callSites; + return callNode.getCurrentCallTarget().getKnownCallSiteCount(); } public int getNodeCount() { return nodeCount; } - public TruffleInliningResult getRecursiveResult() { + public TruffleInliningDecision getRecursiveResult() { return recursiveResult; } @@ -96,7 +91,7 @@ } public boolean isForced() { - return forced; + return callNode.isInliningForced(); } public double getFrequency() { @@ -112,7 +107,7 @@ properties.put("nodeCount", String.format("%5d/%5d", deepNodeCount, nodeCount)); properties.put("frequency", frequency); 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(String.format("index=%3d, force=%s, callSites=%2d", queryIndex, (isForced() ? "Y" : "N"), getCallSites()), ""); properties.put("reason", failedReason); return properties; } diff -r 369a3f9d1ceb -r 2662fb9c37e2 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningResult.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningResult.java Thu Jun 05 19:13:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +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.*; - -public final class TruffleInliningResult implements Iterable { - - private final OptimizedCallTarget callTarget; - private final Map profiles; - private final Set inlined; - private final int nodeCount; - - public TruffleInliningResult(OptimizedCallTarget callTarget, List profiles, Set inlined, int nodeCount) { - this.callTarget = callTarget; - this.profiles = new HashMap<>(); - for (TruffleInliningProfile profile : profiles) { - this.profiles.put(profile.getCallNode(), profile); - } - this.nodeCount = nodeCount; - this.inlined = inlined; - } - - public Map getProfiles() { - return profiles; - } - - public int getNodeCount() { - return nodeCount; - } - - public OptimizedCallTarget getCallTarget() { - return callTarget; - } - - public boolean isInlined(OptimizedDirectCallNode path) { - return inlined.contains(profiles.get(path)); - } - - public int size() { - return inlined.size(); - } - - public Iterator iterator() { - return Collections.unmodifiableSet(inlined).iterator(); - } - - @Override - public String toString() { - return inlined.toString(); - } -}