# HG changeset patch # User Miguel Garcia # Date 1400614711 -7200 # Node ID bde6fbdbbe38325fc51fb39fa4153b6a55cbef55 # Parent f6942501f010df4cdb929717a3f18245b4a52deb# Parent 11e11c6dba7908354b5be945bddd0d7d9d350efc Merge diff -r 11e11c6dba79 -r bde6fbdbbe38 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Tue May 20 20:32:05 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Tue May 20 21:38:31 2014 +0200 @@ -46,9 +46,7 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; -import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.inlining.info.*; -import com.oracle.graal.phases.common.inlining.walker.InliningData; public class InliningUtil { @@ -60,59 +58,6 @@ */ public static final DebugMetric InlinedBytecodes = Debug.metric("InlinedBytecodes"); - public interface Inlineable { - - int getNodeCount(); - - Iterable getInvokes(); - } - - public static class InlineableGraph implements Inlineable { - - private final StructuredGraph graph; - - public InlineableGraph(StructuredGraph graph) { - this.graph = graph; - } - - @Override - public int getNodeCount() { - return graph.getNodeCount(); - } - - @Override - public Iterable getInvokes() { - return graph.getInvokes(); - } - - public StructuredGraph getGraph() { - return graph; - } - } - - public static class InlineableMacroNode implements Inlineable { - - private final Class macroNodeClass; - - public InlineableMacroNode(Class macroNodeClass) { - this.macroNodeClass = macroNodeClass; - } - - @Override - public int getNodeCount() { - return 1; - } - - @Override - public Iterable getInvokes() { - return Collections.emptyList(); - } - - public Class getMacroNodeClass() { - return macroNodeClass; - } - } - /** * Print a HotSpot-style inlining message to the console. */ @@ -271,31 +216,6 @@ return null; } - public static boolean checkTargetConditions(InliningData data, Replacements replacements, Invoke invoke, ResolvedJavaMethod method, OptimisticOptimizations optimisticOpts) { - String failureMessage = null; - if (method == null) { - failureMessage = "the method is not resolved"; - } else if (method.isNative() && (!Intrinsify.getValue() || !InliningUtil.canIntrinsify(replacements, method))) { - failureMessage = "it is a non-intrinsic native method"; - } else if (method.isAbstract()) { - failureMessage = "it is an abstract method"; - } else if (!method.getDeclaringClass().isInitialized()) { - failureMessage = "the method's class is not initialized"; - } else if (!method.canBeInlined()) { - failureMessage = "it is marked non-inlinable"; - } else if (data.countRecursiveInlining(method) > MaximumRecursiveInlining.getValue()) { - failureMessage = "it exceeds the maximum recursive inlining depth"; - } else if (new OptimisticOptimizations(method.getProfilingInfo()).lessOptimisticThan(optimisticOpts)) { - failureMessage = "the callee uses less optimistic optimizations than caller"; - } - if (failureMessage == null) { - return true; - } else { - logNotInlined(invoke, data.inliningDepth(), method, failureMessage); - return false; - } - } - /** * Performs an actual inlining, thereby replacing the given invoke with the given inlineGraph. * diff -r 11e11c6dba79 -r bde6fbdbbe38 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java Tue May 20 20:32:05 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java Tue May 20 21:38:31 2014 +0200 @@ -29,9 +29,9 @@ import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.phases.common.inlining.InliningUtil; -import com.oracle.graal.phases.common.inlining.InliningUtil.Inlineable; -import com.oracle.graal.phases.common.inlining.InliningUtil.InlineableMacroNode; -import com.oracle.graal.phases.common.inlining.InliningUtil.InlineableGraph; +import com.oracle.graal.phases.common.inlining.info.elem.Inlineable; +import com.oracle.graal.phases.common.inlining.info.elem.InlineableMacroNode; +import com.oracle.graal.phases.common.inlining.info.elem.InlineableGraph; public abstract class AbstractInlineInfo implements InlineInfo { diff -r 11e11c6dba79 -r bde6fbdbbe38 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/ExactInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/ExactInlineInfo.java Tue May 20 20:32:05 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/ExactInlineInfo.java Tue May 20 21:38:31 2014 +0200 @@ -27,8 +27,8 @@ import com.oracle.graal.api.meta.MetaUtil; import com.oracle.graal.api.meta.ResolvedJavaMethod; import com.oracle.graal.nodes.Invoke; +import com.oracle.graal.phases.common.inlining.info.elem.Inlineable; import com.oracle.graal.phases.util.Providers; -import com.oracle.graal.phases.common.inlining.InliningUtil.Inlineable; /** * Represents an inlining opportunity where the compiler can statically determine a monomorphic diff -r 11e11c6dba79 -r bde6fbdbbe38 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/InlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/InlineInfo.java Tue May 20 20:32:05 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/InlineInfo.java Tue May 20 21:38:31 2014 +0200 @@ -27,7 +27,7 @@ import com.oracle.graal.api.meta.ResolvedJavaMethod; import com.oracle.graal.nodes.Invoke; import com.oracle.graal.nodes.StructuredGraph; -import com.oracle.graal.phases.common.inlining.InliningUtil; +import com.oracle.graal.phases.common.inlining.info.elem.Inlineable; import com.oracle.graal.phases.util.Providers; /** @@ -56,13 +56,13 @@ ResolvedJavaMethod methodAt(int index); - InliningUtil.Inlineable inlineableElementAt(int index); + Inlineable inlineableElementAt(int index); double probabilityAt(int index); double relevanceAt(int index); - void setInlinableElement(int index, InliningUtil.Inlineable inlineableElement); + void setInlinableElement(int index, Inlineable inlineableElement); /** * Performs the inlining described by this object and returns the node that represents the diff -r 11e11c6dba79 -r bde6fbdbbe38 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Tue May 20 20:32:05 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Tue May 20 21:38:31 2014 +0200 @@ -41,7 +41,7 @@ import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.common.inlining.*; -import com.oracle.graal.phases.common.inlining.InliningUtil.Inlineable; +import com.oracle.graal.phases.common.inlining.info.elem.Inlineable; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; diff -r 11e11c6dba79 -r bde6fbdbbe38 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java Tue May 20 20:32:05 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java Tue May 20 21:38:31 2014 +0200 @@ -29,8 +29,8 @@ import com.oracle.graal.nodes.calc.CompareNode; import com.oracle.graal.nodes.extended.LoadHubNode; import com.oracle.graal.phases.common.inlining.InliningUtil; +import com.oracle.graal.phases.common.inlining.info.elem.Inlineable; import com.oracle.graal.phases.util.Providers; -import com.oracle.graal.phases.common.inlining.InliningUtil.Inlineable; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; /** diff -r 11e11c6dba79 -r bde6fbdbbe38 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/Inlineable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/Inlineable.java Tue May 20 21:38:31 2014 +0200 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2012, 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.phases.common.inlining.info.elem; + +import com.oracle.graal.api.meta.ResolvedJavaMethod; +import com.oracle.graal.nodes.FixedWithNextNode; +import com.oracle.graal.nodes.Invoke; +import com.oracle.graal.phases.common.CanonicalizerPhase; +import com.oracle.graal.phases.common.inlining.InliningUtil; +import com.oracle.graal.phases.tiers.HighTierContext; + +public interface Inlineable { + + static Inlineable getInlineableElement(final ResolvedJavaMethod method, Invoke invoke, HighTierContext context, CanonicalizerPhase canonicalizer) { + Class macroNodeClass = InliningUtil.getMacroNodeClass(context.getReplacements(), method); + if (macroNodeClass != null) { + return new InlineableMacroNode(macroNodeClass); + } else { + return new InlineableGraph(method, invoke, context, canonicalizer); + } + } + + int getNodeCount(); + + Iterable getInvokes(); +} diff -r 11e11c6dba79 -r bde6fbdbbe38 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java Tue May 20 21:38:31 2014 +0200 @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2012, 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.phases.common.inlining.info.elem; + +import com.oracle.graal.api.meta.Constant; +import com.oracle.graal.api.meta.ResolvedJavaMethod; +import com.oracle.graal.compiler.common.type.Stamp; +import com.oracle.graal.debug.Debug; +import com.oracle.graal.graph.NodeInputList; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.common.CanonicalizerPhase; +import com.oracle.graal.phases.common.DeadCodeEliminationPhase; +import com.oracle.graal.phases.common.inlining.InliningUtil; +import com.oracle.graal.phases.tiers.HighTierContext; + +import static com.oracle.graal.compiler.common.GraalOptions.OptCanonicalizer; + +public class InlineableGraph implements Inlineable { + + private final StructuredGraph graph; + + public InlineableGraph(final ResolvedJavaMethod method, final Invoke invoke, final HighTierContext context, CanonicalizerPhase canonicalizer) { + this.graph = buildGraph(method, invoke, context, canonicalizer); + } + + private static StructuredGraph buildGraph(final ResolvedJavaMethod method, final Invoke invoke, final HighTierContext context, CanonicalizerPhase canonicalizer) { + final StructuredGraph newGraph; + final boolean parseBytecodes; + + // TODO (chaeubl): copying the graph is only necessary if it is modified or if it contains + // any invokes + StructuredGraph intrinsicGraph = InliningUtil.getIntrinsicGraph(context.getReplacements(), method); + if (intrinsicGraph != null) { + newGraph = intrinsicGraph.copy(); + parseBytecodes = false; + } else { + StructuredGraph cachedGraph = getCachedGraph(method, context); + if (cachedGraph != null) { + newGraph = cachedGraph.copy(); + parseBytecodes = false; + } else { + newGraph = new StructuredGraph(method); + parseBytecodes = true; + } + } + + try (Debug.Scope s = Debug.scope("InlineGraph", newGraph)) { + if (parseBytecodes) { + parseBytecodes(newGraph, context, canonicalizer); + } + + boolean callerHasMoreInformationAboutArguments = false; + NodeInputList args = invoke.callTarget().arguments(); + for (ParameterNode param : newGraph.getNodes(ParameterNode.class).snapshot()) { + ValueNode arg = args.get(param.index()); + if (arg.isConstant()) { + Constant constant = arg.asConstant(); + newGraph.replaceFloating(param, ConstantNode.forConstant(constant, context.getMetaAccess(), newGraph)); + callerHasMoreInformationAboutArguments = true; + } else { + Stamp joinedStamp = param.stamp().join(arg.stamp()); + if (joinedStamp != null && !joinedStamp.equals(param.stamp())) { + param.setStamp(joinedStamp); + callerHasMoreInformationAboutArguments = true; + } + } + } + + if (!callerHasMoreInformationAboutArguments) { + // TODO (chaeubl): if args are not more concrete, inlining should be avoided + // in most cases or we could at least use the previous graph size + invoke + // probability to check the inlining + } + + if (OptCanonicalizer.getValue()) { + canonicalizer.apply(newGraph, context); + } + + return newGraph; + } catch (Throwable e) { + throw Debug.handle(e); + } + } + + private static StructuredGraph getCachedGraph(ResolvedJavaMethod method, HighTierContext context) { + if (context.getGraphCache() != null) { + StructuredGraph cachedGraph = context.getGraphCache().get(method); + if (cachedGraph != null) { + return cachedGraph; + } + } + return null; + } + + /** + * This method builds the IR nodes for newGraph and canonicalizes them. Provided + * profiling info is mature, the resulting graph is cached. + */ + private static StructuredGraph parseBytecodes(StructuredGraph newGraph, HighTierContext context, CanonicalizerPhase canonicalizer) { + final boolean hasMatureProfilingInfo = newGraph.method().getProfilingInfo().isMature(); + + if (context.getGraphBuilderSuite() != null) { + context.getGraphBuilderSuite().apply(newGraph, context); + } + assert newGraph.start().next() != null : "graph needs to be populated during PhasePosition.AFTER_PARSING"; + + new DeadCodeEliminationPhase().apply(newGraph); + + if (OptCanonicalizer.getValue()) { + canonicalizer.apply(newGraph, context); + } + + if (hasMatureProfilingInfo && context.getGraphCache() != null) { + context.getGraphCache().put(newGraph.method(), newGraph.copy()); + } + return newGraph; + } + + @Override + public int getNodeCount() { + return graph.getNodeCount(); + } + + @Override + public Iterable getInvokes() { + return graph.getInvokes(); + } + + public StructuredGraph getGraph() { + return graph; + } +} diff -r 11e11c6dba79 -r bde6fbdbbe38 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableMacroNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableMacroNode.java Tue May 20 21:38:31 2014 +0200 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012, 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.phases.common.inlining.info.elem; + +import com.oracle.graal.nodes.FixedWithNextNode; +import com.oracle.graal.nodes.Invoke; + +import java.util.Collections; + +public class InlineableMacroNode implements Inlineable { + + private final Class macroNodeClass; + + public InlineableMacroNode(Class macroNodeClass) { + this.macroNodeClass = macroNodeClass; + } + + @Override + public int getNodeCount() { + return 1; + } + + @Override + public Iterable getInvokes() { + return Collections.emptyList(); + } + + public Class getMacroNodeClass() { + return macroNodeClass; + } +} diff -r 11e11c6dba79 -r bde6fbdbbe38 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/AbstractInliningPolicy.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/AbstractInliningPolicy.java Tue May 20 20:32:05 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/AbstractInliningPolicy.java Tue May 20 21:38:31 2014 +0200 @@ -30,6 +30,7 @@ import com.oracle.graal.nodes.spi.Replacements; import com.oracle.graal.phases.common.inlining.InliningUtil; import com.oracle.graal.phases.common.inlining.info.InlineInfo; +import com.oracle.graal.phases.common.inlining.info.elem.Inlineable; import java.util.Map; import java.util.function.ToDoubleFunction; @@ -102,7 +103,7 @@ protected static int determineNodeCount(InlineInfo info) { int nodes = 0; for (int i = 0; i < info.numberOfMethods(); i++) { - InliningUtil.Inlineable elem = info.inlineableElementAt(i); + Inlineable elem = info.inlineableElementAt(i); if (elem != null) { nodes += elem.getNodeCount(); } @@ -113,7 +114,7 @@ protected static double determineInvokeProbability(ToDoubleFunction probabilities, InlineInfo info) { double invokeProbability = 0; for (int i = 0; i < info.numberOfMethods(); i++) { - InliningUtil.Inlineable callee = info.inlineableElementAt(i); + Inlineable callee = info.inlineableElementAt(i); Iterable invokes = callee.getInvokes(); if (invokes.iterator().hasNext()) { for (Invoke invoke : invokes) { diff -r 11e11c6dba79 -r bde6fbdbbe38 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/DepthSearchUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/DepthSearchUtil.java Tue May 20 20:32:05 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2011, 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.phases.common.inlining.walker; - -import com.oracle.graal.api.meta.Constant; -import com.oracle.graal.api.meta.ResolvedJavaMethod; -import com.oracle.graal.compiler.common.type.Stamp; -import com.oracle.graal.debug.Debug; -import com.oracle.graal.graph.NodeInputList; -import com.oracle.graal.nodes.*; -import com.oracle.graal.phases.common.CanonicalizerPhase; -import com.oracle.graal.phases.common.DeadCodeEliminationPhase; -import com.oracle.graal.phases.common.inlining.InliningUtil; -import com.oracle.graal.phases.tiers.HighTierContext; - -import static com.oracle.graal.compiler.common.GraalOptions.OptCanonicalizer; - -/** - * The workings of {@link InliningData} include delving into a callsite to explore inlining - * opportunities. The utilities used for that are grouped in this class. - */ -public class DepthSearchUtil { - - private DepthSearchUtil() { - // no instances - } - - public static InliningUtil.Inlineable getInlineableElement(final ResolvedJavaMethod method, Invoke invoke, HighTierContext context, CanonicalizerPhase canonicalizer) { - Class macroNodeClass = InliningUtil.getMacroNodeClass(context.getReplacements(), method); - if (macroNodeClass != null) { - return new InliningUtil.InlineableMacroNode(macroNodeClass); - } else { - return new InliningUtil.InlineableGraph(buildGraph(method, invoke, context, canonicalizer)); - } - } - - private static StructuredGraph buildGraph(final ResolvedJavaMethod method, final Invoke invoke, final HighTierContext context, CanonicalizerPhase canonicalizer) { - final StructuredGraph newGraph; - final boolean parseBytecodes; - - // TODO (chaeubl): copying the graph is only necessary if it is modified or if it contains - // any invokes - StructuredGraph intrinsicGraph = InliningUtil.getIntrinsicGraph(context.getReplacements(), method); - if (intrinsicGraph != null) { - newGraph = intrinsicGraph.copy(); - parseBytecodes = false; - } else { - StructuredGraph cachedGraph = getCachedGraph(method, context); - if (cachedGraph != null) { - newGraph = cachedGraph.copy(); - parseBytecodes = false; - } else { - newGraph = new StructuredGraph(method); - parseBytecodes = true; - } - } - - try (Debug.Scope s = Debug.scope("InlineGraph", newGraph)) { - if (parseBytecodes) { - parseBytecodes(newGraph, context, canonicalizer); - } - - boolean callerHasMoreInformationAboutArguments = false; - NodeInputList args = invoke.callTarget().arguments(); - for (ParameterNode param : newGraph.getNodes(ParameterNode.class).snapshot()) { - ValueNode arg = args.get(param.index()); - if (arg.isConstant()) { - Constant constant = arg.asConstant(); - newGraph.replaceFloating(param, ConstantNode.forConstant(constant, context.getMetaAccess(), newGraph)); - callerHasMoreInformationAboutArguments = true; - } else { - Stamp joinedStamp = param.stamp().join(arg.stamp()); - if (joinedStamp != null && !joinedStamp.equals(param.stamp())) { - param.setStamp(joinedStamp); - callerHasMoreInformationAboutArguments = true; - } - } - } - - if (!callerHasMoreInformationAboutArguments) { - // TODO (chaeubl): if args are not more concrete, inlining should be avoided - // in most cases or we could at least use the previous graph size + invoke - // probability to check the inlining - } - - if (OptCanonicalizer.getValue()) { - canonicalizer.apply(newGraph, context); - } - - return newGraph; - } catch (Throwable e) { - throw Debug.handle(e); - } - } - - private static StructuredGraph getCachedGraph(ResolvedJavaMethod method, HighTierContext context) { - if (context.getGraphCache() != null) { - StructuredGraph cachedGraph = context.getGraphCache().get(method); - if (cachedGraph != null) { - return cachedGraph; - } - } - return null; - } - - /** - * This method builds the IR nodes for newGraph and canonicalizes them. Provided - * profiling info is mature, the resulting graph is cached. - */ - private static StructuredGraph parseBytecodes(StructuredGraph newGraph, HighTierContext context, CanonicalizerPhase canonicalizer) { - final boolean hasMatureProfilingInfo = newGraph.method().getProfilingInfo().isMature(); - - if (context.getGraphBuilderSuite() != null) { - context.getGraphBuilderSuite().apply(newGraph, context); - } - assert newGraph.start().next() != null : "graph needs to be populated during PhasePosition.AFTER_PARSING"; - - new DeadCodeEliminationPhase().apply(newGraph); - - if (OptCanonicalizer.getValue()) { - canonicalizer.apply(newGraph, context); - } - - if (hasMatureProfilingInfo && context.getGraphCache() != null) { - context.getGraphCache().put(newGraph.method(), newGraph.copy()); - } - return newGraph; - } -} diff -r 11e11c6dba79 -r bde6fbdbbe38 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 Tue May 20 20:32:05 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java Tue May 20 21:38:31 2014 +0200 @@ -39,6 +39,9 @@ import com.oracle.graal.phases.common.CanonicalizerPhase; import com.oracle.graal.phases.common.inlining.InliningUtil; import com.oracle.graal.phases.common.inlining.info.*; +import com.oracle.graal.phases.common.inlining.info.elem.Inlineable; +import com.oracle.graal.phases.common.inlining.info.elem.InlineableGraph; +import com.oracle.graal.phases.common.inlining.info.elem.InlineableMacroNode; import com.oracle.graal.phases.common.inlining.policy.InliningPolicy; import com.oracle.graal.phases.graph.FixedNodeProbabilityCache; import com.oracle.graal.phases.tiers.HighTierContext; @@ -49,8 +52,7 @@ import java.util.List; import java.util.function.ToDoubleFunction; -import static com.oracle.graal.compiler.common.GraalOptions.MegamorphicInliningMinMethodProbability; -import static com.oracle.graal.compiler.common.GraalOptions.OptCanonicalizer; +import static com.oracle.graal.compiler.common.GraalOptions.*; /** * Holds the data for building the callee graphs recursively: graphs and invocations (each @@ -91,6 +93,36 @@ pushGraph(rootGraph, 1.0, 1.0); } + private String checkTargetConditionsHelper(ResolvedJavaMethod method) { + if (method == null) { + return "the method is not resolved"; + } else if (method.isNative() && (!Intrinsify.getValue() || !InliningUtil.canIntrinsify(context.getReplacements(), method))) { + return "it is a non-intrinsic native method"; + } else if (method.isAbstract()) { + return "it is an abstract method"; + } else if (!method.getDeclaringClass().isInitialized()) { + return "the method's class is not initialized"; + } else if (!method.canBeInlined()) { + return "it is marked non-inlinable"; + } else if (countRecursiveInlining(method) > MaximumRecursiveInlining.getValue()) { + return "it exceeds the maximum recursive inlining depth"; + } else if (new OptimisticOptimizations(method.getProfilingInfo()).lessOptimisticThan(context.getOptimisticOptimizations())) { + return "the callee uses less optimistic optimizations than caller"; + } else { + return null; + } + } + + private boolean checkTargetConditions(Invoke invoke, ResolvedJavaMethod method) { + final String failureMessage = checkTargetConditionsHelper(method); + if (failureMessage == null) { + return true; + } else { + InliningUtil.logNotInlined(invoke, inliningDepth(), method, failureMessage); + return false; + } + } + /** * Determines if inlining is possible at the given invoke node. * @@ -193,7 +225,7 @@ ResolvedJavaType type = ptypes[0].getType(); assert type.isArray() || !type.isAbstract(); ResolvedJavaMethod concrete = type.resolveMethod(targetMethod, contextType); - if (!InliningUtil.checkTargetConditions(this, context.getReplacements(), invoke, concrete, optimisticOpts)) { + if (!checkTargetConditions(invoke, concrete)) { return null; } return new TypeGuardInlineInfo(invoke, concrete, type); @@ -281,7 +313,7 @@ } for (ResolvedJavaMethod concrete : concreteMethods) { - if (!InliningUtil.checkTargetConditions(this, context.getReplacements(), invoke, concrete, optimisticOpts)) { + if (!checkTargetConditions(invoke, concrete)) { InliningUtil.logNotInlined(invoke, inliningDepth(), targetMethod, "it is a polymorphic method call and at least one invoked method cannot be inlined"); return null; } @@ -292,7 +324,7 @@ private InlineInfo getAssumptionInlineInfo(Invoke invoke, ResolvedJavaMethod concrete, Assumptions.Assumption takenAssumption) { assert !concrete.isAbstract(); - if (!InliningUtil.checkTargetConditions(this, context.getReplacements(), invoke, concrete, context.getOptimisticOptimizations())) { + if (!checkTargetConditions(invoke, concrete)) { return null; } return new AssumptionInlineInfo(invoke, concrete, takenAssumption); @@ -300,7 +332,7 @@ private InlineInfo getExactInlineInfo(Invoke invoke, ResolvedJavaMethod targetMethod) { assert !targetMethod.isAbstract(); - if (!InliningUtil.checkTargetConditions(this, context.getReplacements(), invoke, targetMethod, context.getOptimisticOptimizations())) { + if (!checkTargetConditions(invoke, targetMethod)) { return null; } return new ExactInlineInfo(invoke, targetMethod); @@ -379,12 +411,12 @@ MethodInvocation calleeInvocation = pushInvocation(info, parentAssumptions, invokeProbability, invokeRelevance); for (int i = 0; i < info.numberOfMethods(); i++) { - InliningUtil.Inlineable elem = DepthSearchUtil.getInlineableElement(info.methodAt(i), info.invoke(), context.replaceAssumptions(calleeInvocation.assumptions()), canonicalizer); + Inlineable elem = Inlineable.getInlineableElement(info.methodAt(i), info.invoke(), context.replaceAssumptions(calleeInvocation.assumptions()), canonicalizer); info.setInlinableElement(i, elem); - if (elem instanceof InliningUtil.InlineableGraph) { - pushGraph(((InliningUtil.InlineableGraph) elem).getGraph(), invokeProbability * info.probabilityAt(i), invokeRelevance * info.relevanceAt(i)); + if (elem instanceof InlineableGraph) { + pushGraph(((InlineableGraph) elem).getGraph(), invokeProbability * info.probabilityAt(i), invokeRelevance * info.relevanceAt(i)); } else { - assert elem instanceof InliningUtil.InlineableMacroNode; + assert elem instanceof InlineableMacroNode; pushDummyGraph(); } }