# HG changeset patch # User Miguel Garcia # Date 1403093526 -7200 # Node ID f98b033b60507c1c7f255a41fe66574ee67991d9 # Parent c64c5f5913fd7add8af99e1a3a567f0ebafbdc9a [inliner] propagating fresh-instantiation info through call-hierarchy diff -r c64c5f5913fd -r f98b033b6050 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/Inlineable.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/Inlineable.java Sat Jun 14 17:10:43 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/Inlineable.java Wed Jun 18 14:12:06 2014 +0200 @@ -32,6 +32,8 @@ public interface Inlineable { static Inlineable getInlineableElement(final ResolvedJavaMethod method, Invoke invoke, HighTierContext context, CanonicalizerPhase canonicalizer) { + assert method != null; + assert invoke != null; Class macroNodeClass = InliningUtil.getMacroNodeClass(context.getReplacements(), method); if (macroNodeClass != null) { return new InlineableMacroNode(macroNodeClass); diff -r c64c5f5913fd -r f98b033b6050 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolderExplorable.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolderExplorable.java Sat Jun 14 17:10:43 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolderExplorable.java Wed Jun 18 14:12:06 2014 +0200 @@ -24,12 +24,10 @@ import com.oracle.graal.api.meta.MetaUtil; import com.oracle.graal.api.meta.ResolvedJavaMethod; -import com.oracle.graal.nodes.FixedNode; -import com.oracle.graal.nodes.Invoke; -import com.oracle.graal.nodes.StructuredGraph; +import com.oracle.graal.nodes.*; import com.oracle.graal.phases.graph.FixedNodeProbabilityCache; -import java.util.LinkedList; +import java.util.*; import java.util.function.ToDoubleFunction; import static com.oracle.graal.compiler.common.GraalOptions.CapInheritedRelevance; @@ -52,19 +50,30 @@ */ public final class CallsiteHolderExplorable extends CallsiteHolder { + /** + * Graph in which inlining may be performed at one or more of the callsites containined in + * {@link #remainingInvokes} + */ private final StructuredGraph graph; + private final LinkedList remainingInvokes; private final double probability; private final double relevance; + /** + * @see #getFixedParams() + */ + private final Set fixedParams; + private final ToDoubleFunction probabilities; private final ComputeInliningRelevance computeInliningRelevance; - public CallsiteHolderExplorable(StructuredGraph graph, double probability, double relevance) { + public CallsiteHolderExplorable(StructuredGraph graph, double probability, double relevance, BitSet freshlyInstantiatedArguments) { assert graph != null; this.graph = graph; this.probability = probability; this.relevance = relevance; + this.fixedParams = fixedParamsAt(freshlyInstantiatedArguments); remainingInvokes = new InliningIterator(graph).apply(); if (remainingInvokes.isEmpty()) { probabilities = null; @@ -74,6 +83,65 @@ computeInliningRelevance = new ComputeInliningRelevance(graph, probabilities); computeProbabilities(); } + assert repOK(); + } + + /** + * @see #getFixedParams() + */ + @SuppressWarnings("unchecked") + private Set fixedParamsAt(BitSet freshlyInstantiatedArguments) { + if (freshlyInstantiatedArguments == null || freshlyInstantiatedArguments.isEmpty()) { + return Collections.EMPTY_SET; + } + Set result = new HashSet<>(); + for (ParameterNode p : graph.getNodes(ParameterNode.class)) { + if (freshlyInstantiatedArguments.get(p.index())) { + result.add(p); + } + } + return result; + } + + /** + *

+ * Parameters for which the callsite targeting {@link #graph()} provides "fixed" arguments. That + * callsite isn't referenced by this instance. Instead, it belongs to the graph of the caller of + * this {@link CallsiteHolderExplorable} + *

+ * + *

+ * Constant arguments don't contribute to fixed-params: those params have been removed already, + * see {@link com.oracle.graal.phases.common.inlining.info.elem.InlineableGraph}. + *

+ * + *

+ * Instead, fixed-params are those receiving freshly instantiated arguments (possibly + * instantiated several levels up in the call-hierarchy) + *

+ * */ + public Set getFixedParams() { + return fixedParams; + } + + public boolean repOK() { + for (Invoke invoke : remainingInvokes) { + if (!invoke.asNode().isAlive() || !containsInvoke(invoke)) { + assert false; + return false; + } + if (!allArgsNonNull(invoke)) { + assert false; + return false; + } + } + for (ParameterNode fixedParam : fixedParams) { + if (!containsParam(fixedParam)) { + assert false; + return false; + } + } + return true; } @Override @@ -99,6 +167,16 @@ remainingInvokes.push(invoke); } + public static boolean allArgsNonNull(Invoke invoke) { + for (ValueNode arg : invoke.callTarget().arguments()) { + if (arg == null) { + assert false; + return false; + } + } + return true; + } + public boolean containsInvoke(Invoke invoke) { for (Invoke i : graph().getInvokes()) { if (i == invoke) { @@ -108,6 +186,15 @@ return false; } + public boolean containsParam(ParameterNode param) { + for (ParameterNode p : graph.getNodes(ParameterNode.class)) { + if (p == param) { + return true; + } + } + return false; + } + public void computeProbabilities() { computeInliningRelevance.compute(); } diff -r c64c5f5913fd -r f98b033b6050 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java Sat Jun 14 17:10:43 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java Wed Jun 18 14:12:06 2014 +0200 @@ -34,7 +34,9 @@ import com.oracle.graal.graph.Graph; import com.oracle.graal.graph.Node; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.AbstractNewObjectNode; import com.oracle.graal.nodes.java.MethodCallTargetNode; +import com.oracle.graal.nodes.virtual.VirtualObjectNode; import com.oracle.graal.phases.OptimisticOptimizations; import com.oracle.graal.phases.common.CanonicalizerPhase; import com.oracle.graal.phases.common.inlining.InliningUtil; @@ -110,8 +112,12 @@ this.maxGraphs = 1; Assumptions rootAssumptions = context.getAssumptions(); - invocationQueue.push(new MethodInvocation(null, rootAssumptions, 1.0, 1.0)); - graphQueue.push(new CallsiteHolderExplorable(rootGraph, 1.0, 1.0)); + invocationQueue.push(new MethodInvocation(null, rootAssumptions, 1.0, 1.0, null)); + graphQueue.push(new CallsiteHolderExplorable(rootGraph, 1.0, 1.0, null)); + } + + public static boolean isFreshInstantiation(ValueNode arg) { + return (arg instanceof AbstractNewObjectNode) || (arg instanceof VirtualObjectNode); } private String checkTargetConditionsHelper(ResolvedJavaMethod method) { @@ -468,11 +474,53 @@ info.populateInlinableElements(context, calleeAssumptions, canonicalizer); double invokeProbability = callsiteHolder.invokeProbability(invoke); double invokeRelevance = callsiteHolder.invokeRelevance(invoke); - MethodInvocation methodInvocation = new MethodInvocation(info, calleeAssumptions, invokeProbability, invokeRelevance); + MethodInvocation methodInvocation = new MethodInvocation(info, calleeAssumptions, invokeProbability, invokeRelevance, freshlyInstantiatedArguments(invoke, callsiteHolder.getFixedParams())); pushInvocationAndGraphs(methodInvocation); } } + /** + *

+ * A freshly instantiated argument is either: + *

    + *
  • an {@link InliningData#isFreshInstantiation(com.oracle.graal.nodes.ValueNode)}
  • + *
  • a fixed-param, ie a {@link ParameterNode} receiving a freshly instantiated argument
  • + *
+ *

+ * + * @return the positions of freshly instantiated arguments in the argument list of the + * invoke, or null if no such positions exist. + */ + public static BitSet freshlyInstantiatedArguments(Invoke invoke, Set fixedParams) { + assert fixedParams != null; + assert paramsAndInvokeAreInSameGraph(invoke, fixedParams); + BitSet result = null; + int argIdx = 0; + for (ValueNode arg : invoke.callTarget().arguments()) { + assert arg != null; + if (isFreshInstantiation(arg) || fixedParams.contains(arg)) { + if (result == null) { + result = new BitSet(); + } + result.set(argIdx); + } + argIdx++; + } + return result; + } + + private static boolean paramsAndInvokeAreInSameGraph(Invoke invoke, Set fixedParams) { + if (fixedParams.isEmpty()) { + return true; + } + for (ParameterNode p : fixedParams) { + if (p.graph() != invoke.asNode().graph()) { + return false; + } + } + return true; + } + public int graphCount() { return graphQueue.size(); } diff -r c64c5f5913fd -r f98b033b6050 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/MethodInvocation.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/MethodInvocation.java Sat Jun 14 17:10:43 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/MethodInvocation.java Wed Jun 18 14:12:06 2014 +0200 @@ -32,6 +32,8 @@ import com.oracle.graal.phases.common.inlining.info.elem.InlineableGraph; import com.oracle.graal.phases.common.inlining.info.elem.InlineableMacroNode; +import java.util.BitSet; + /** *

* An instance of this class denotes a callsite being analyzed for inlining. @@ -52,11 +54,39 @@ private int processedGraphs; - public MethodInvocation(InlineInfo info, Assumptions assumptions, double probability, double relevance) { + /** + *

+ * The immutable positions of freshly instantiated arguments (ie, positions in + * callee.invoke.callTarget.arguments). + *

+ * + *

+ * A freshly instantiated argument is either: + *

    + *
  • an {@link InliningData#isFreshInstantiation(com.oracle.graal.nodes.ValueNode)}
  • + *
  • a fixed-param of the graph containing the callsite (ie, of callee.graph() + * that contains callee.invoke)
  • + *
+ *

+ * + *

+ * Given those positions, the + * {@link com.oracle.graal.phases.common.inlining.walker.CallsiteHolderExplorable} instantiated + * in {@link #buildCallsiteHolderForElement(int)} can determine which of its parameters + * are fixed. + *

+ */ + private final BitSet freshlyInstantiatedArguments; + + private final int sizeFreshArgs; + + public MethodInvocation(InlineInfo info, Assumptions assumptions, double probability, double relevance, BitSet freshlyInstantiatedArguments) { this.callee = info; this.assumptions = assumptions; this.probability = probability; this.relevance = relevance; + this.freshlyInstantiatedArguments = freshlyInstantiatedArguments; + this.sizeFreshArgs = freshlyInstantiatedArguments == null ? 0 : freshlyInstantiatedArguments.cardinality(); } public void incrementProcessedGraphs() { @@ -93,11 +123,21 @@ return callee == null; } + public BitSet getFreshlyInstantiatedArguments() { + return freshlyInstantiatedArguments; + } + + public int getSizeFreshArgs() { + return sizeFreshArgs; + } + public CallsiteHolder buildCallsiteHolderForElement(int index) { Inlineable elem = callee.inlineableElementAt(index); if (elem instanceof InlineableGraph) { InlineableGraph ig = (InlineableGraph) elem; - return new CallsiteHolderExplorable(ig.getGraph(), probability * callee.probabilityAt(index), relevance * callee.relevanceAt(index)); + final double invokeProbability = probability * callee.probabilityAt(index); + final double invokeRelevance = relevance * callee.relevanceAt(index); + return new CallsiteHolderExplorable(ig.getGraph(), invokeProbability, invokeRelevance, freshlyInstantiatedArguments); } else { assert elem instanceof InlineableMacroNode; return CallsiteHolderDummy.DUMMY_CALLSITE_HOLDER;