# HG changeset patch # User Christian Haeubl # Date 1328305365 28800 # Node ID 87a12a816e9964ac9235d456d3219ec13200e439 # Parent ed73455e9c037c26f396b1b64aff029bacc4ab9f added C1 inlining policy for comparison, bugfixes diff -r ed73455e9c03 -r 87a12a816e99 graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiKind.java --- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiKind.java Fri Feb 03 13:41:59 2012 -0800 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiKind.java Fri Feb 03 13:42:45 2012 -0800 @@ -311,6 +311,7 @@ } public CiConstant readUnsafeConstant(Object value, long displacement) { + assert value != null; Unsafe u = Unsafe.getUnsafe(); switch(this) { case Boolean: diff -r ed73455e9c03 -r 87a12a816e99 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java Fri Feb 03 13:41:59 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java Fri Feb 03 13:42:45 2012 -0800 @@ -44,8 +44,10 @@ public static boolean CacheGraphs = ____; public static boolean InlineMonomorphicCalls = true; public static boolean InlinePolymorphicCalls = true; + public static int InliningPolicy = 0; public static int MaximumInlineSize = 35; public static int MaximumFreqInlineSize = 300; + public static float NestedInliningSizeRatio = 0.9f; public static int FreqInlineRatio = 20; public static int MaximumTrivialSize = 6; public static int MaximumInlineLevel = 30; diff -r ed73455e9c03 -r 87a12a816e99 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java Fri Feb 03 13:41:59 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java Fri Feb 03 13:42:45 2012 -0800 @@ -53,6 +53,7 @@ private CiAssumptions assumptions; private final PhasePlan plan; + private final InliningPolicy inliningPolicy; // Metrics private static final DebugMetric metricInliningPerformed = Debug.metric("InliningPerformed"); @@ -64,6 +65,7 @@ this.hints = hints; this.assumptions = assumptions; this.plan = plan; + this.inliningPolicy = createInliningPolicy(); } @SuppressWarnings("unchecked") @@ -80,39 +82,36 @@ while (!inlineCandidates.isEmpty() && graph.getNodeCount() < GraalOptions.MaximumDesiredSize) { InlineInfo info = inlineCandidates.remove(); - double penalty = Math.pow(GraalOptions.InliningSizePenaltyExp, graph.getNodeCount() / (double) GraalOptions.MaximumDesiredSize) / GraalOptions.InliningSizePenaltyExp; - if (info.weight > GraalOptions.MaximumInlineWeight / (1 + penalty * GraalOptions.InliningSizePenalty)) { - Debug.log("not inlining (cut off by weight): %e", info.weight); - return; - } - Iterable newNodes = null; - if (info.invoke.node().isAlive()) { - try { - info.inline(graph, runtime, this); - Debug.log("inlining %f: %s", info.weight, info); - Debug.dump(graph, "after inlining %s", info); - // get the new nodes here, the canonicalizer phase will reset the mark - newNodes = graph.getNewNodes(); - if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, true, assumptions).apply(graph); + if (inliningPolicy.isWorthInlining(graph, info)) { + Iterable newNodes = null; + if (info.invoke.node().isAlive()) { + try { + info.inline(graph, runtime, this); + Debug.log("inlining %f: %s", info.weight, info); + Debug.dump(graph, "after inlining %s", info); + // get the new nodes here, the canonicalizer phase will reset the mark + newNodes = graph.getNewNodes(); + if (GraalOptions.OptCanonicalizer) { + new CanonicalizerPhase(target, runtime, true, assumptions).apply(graph); + } + if (GraalOptions.Intrinsify) { + new IntrinsificationPhase(runtime).apply(graph); + } + metricInliningPerformed.increment(); + } catch (CiBailout bailout) { + // TODO determine if we should really bail out of the whole compilation. + throw bailout; + } catch (AssertionError e) { + throw new GraalInternalError(e).addContext(info.toString()); + } catch (RuntimeException e) { + throw new GraalInternalError(e).addContext(info.toString()); + } catch (GraalInternalError e) { + throw e.addContext(info.toString()); } - if (GraalOptions.Intrinsify) { - new IntrinsificationPhase(runtime).apply(graph); - } - metricInliningPerformed.increment(); - } catch (CiBailout bailout) { - // TODO determine if we should really bail out of the whole compilation. - throw bailout; - } catch (AssertionError e) { - throw new GraalInternalError(e).addContext(info.toString()); - } catch (RuntimeException e) { - throw new GraalInternalError(e).addContext(info.toString()); - } catch (GraalInternalError e) { - throw e.addContext(info.toString()); } - } - if (newNodes != null && info.level <= GraalOptions.MaximumInlineLevel) { - scanInvokes(newNodes, info.level + 1, graph); + if (newNodes != null && info.level <= GraalOptions.MaximumInlineLevel) { + scanInvokes(newNodes, info.level + 1, graph); + } } } } @@ -160,62 +159,10 @@ @Override public double inliningWeight(RiResolvedMethod caller, RiResolvedMethod method, Invoke invoke) { - double ratio; - if (hints != null && hints.contains(invoke)) { - ratio = 1000000; - } else { - if (GraalOptions.ProbabilityAnalysis) { - ratio = invoke.node().probability(); - } else { - RiProfilingInfo profilingInfo = method.profilingInfo(); - int executionCount = profilingInfo.getExecutionCount(invoke.bci()); - if (executionCount > 0) { - RiResolvedMethod parent = invoke.stateAfter().method(); - ratio = executionCount / (float) parent.invocationCount(); - } else { - ratio = 1; - } - } - } - - final double normalSize; - // TODO(ls) get rid of this magic, it's here to emulate the old behavior for the time being - if (ratio < 0.01) { - ratio = 0.01; - } - if (ratio < 0.5) { - normalSize = 10 * ratio / 0.5; - } else if (ratio < 2) { - normalSize = 10 + (35 - 10) * (ratio - 0.5) / 1.5; - } else if (ratio < 20) { - normalSize = 35; - } else if (ratio < 40) { - normalSize = 35 + (350 - 35) * (ratio - 20) / 20; - } else { - normalSize = 350; - } - - int count; - if (GraalOptions.ParseBeforeInlining) { - if (!parsedMethods.containsKey(method)) { - StructuredGraph newGraph = new StructuredGraph(method); - if (plan != null) { - plan.runPhases(PhasePosition.AFTER_PARSING, newGraph); - } - new CanonicalizerPhase(target, runtime, assumptions).apply(newGraph); - count = graphComplexity(newGraph); - parsedMethods.put(method, count); - } else { - count = parsedMethods.get(method); - } - } else { - count = method.codeSize(); - } - - return count / normalSize; + boolean preferred = hints != null && hints.contains(invoke); + return inliningPolicy.computeWeight(caller, method, invoke, preferred); } - public static int graphComplexity(StructuredGraph graph) { int result = 0; for (Node node : graph.getNodes()) { @@ -240,4 +187,105 @@ assumptions.recordConcreteMethod(method, context, impl); } + private InliningPolicy createInliningPolicy() { + if (GraalOptions.InliningPolicy == 0) { + return new WeightBasedInliningPolicy(); + } else if (GraalOptions.InliningPolicy == 1) { + return new SizeBasedInliningPolicy(); + } else { + Util.shouldNotReachHere(); + return null; + } + } + + private interface InliningPolicy { + double computeWeight(RiResolvedMethod caller, RiResolvedMethod method, Invoke invoke, boolean preferredInvoke); + boolean isWorthInlining(StructuredGraph callerGraph, InlineInfo info); + } + + private class WeightBasedInliningPolicy implements InliningPolicy { + @Override + public double computeWeight(RiResolvedMethod caller, RiResolvedMethod method, Invoke invoke, boolean preferredInvoke) { + double ratio; + if (preferredInvoke) { + ratio = 1000000; + } else { + if (GraalOptions.ProbabilityAnalysis) { + ratio = invoke.node().probability(); + } else { + RiProfilingInfo profilingInfo = method.profilingInfo(); + int executionCount = profilingInfo.getExecutionCount(invoke.bci()); + if (executionCount > 0) { + RiResolvedMethod parent = invoke.stateAfter().method(); + ratio = executionCount / (float) parent.invocationCount(); + } else { + ratio = 1; + } + } + } + + final double normalSize; + // TODO(ls) get rid of this magic, it's here to emulate the old behavior for the time being + if (ratio < 0.01) { + ratio = 0.01; + } + if (ratio < 0.5) { + normalSize = 10 * ratio / 0.5; + } else if (ratio < 2) { + normalSize = 10 + (35 - 10) * (ratio - 0.5) / 1.5; + } else if (ratio < 20) { + normalSize = 35; + } else if (ratio < 40) { + normalSize = 35 + (350 - 35) * (ratio - 20) / 20; + } else { + normalSize = 350; + } + + int count; + if (GraalOptions.ParseBeforeInlining) { + if (!parsedMethods.containsKey(method)) { + StructuredGraph newGraph = new StructuredGraph(method); + if (plan != null) { + plan.runPhases(PhasePosition.AFTER_PARSING, newGraph); + } + new CanonicalizerPhase(target, runtime, assumptions).apply(newGraph); + count = graphComplexity(newGraph); + parsedMethods.put(method, count); + } else { + count = parsedMethods.get(method); + } + } else { + count = method.codeSize(); + } + + return count / normalSize; + } + + @Override + public boolean isWorthInlining(StructuredGraph callerGraph, InlineInfo info) { + double penalty = Math.pow(GraalOptions.InliningSizePenaltyExp, callerGraph.getNodeCount() / (double) GraalOptions.MaximumDesiredSize) / GraalOptions.InliningSizePenaltyExp; + if (info.weight > GraalOptions.MaximumInlineWeight / (1 + penalty * GraalOptions.InliningSizePenalty)) { + Debug.log("not inlining (cut off by weight): %e", info.weight); + return false; + } + return true; + } + } + + private class SizeBasedInliningPolicy implements InliningPolicy { + @Override + public double computeWeight(RiResolvedMethod caller, RiResolvedMethod method, Invoke invoke, boolean preferredInvoke) { + if (preferredInvoke) { + return method.codeSize() / 2; + } else { + return method.codeSize(); + } + } + + @Override + public boolean isWorthInlining(StructuredGraph callerGraph, InlineInfo info) { + double maxSize = Math.max(GraalOptions.MaximumTrivialSize, Math.pow(GraalOptions.NestedInliningSizeRatio, info.level) * GraalOptions.MaximumInlineSize); + return info.weight <= maxSize; + } + } } diff -r ed73455e9c03 -r 87a12a816e99 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java Fri Feb 03 13:41:59 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java Fri Feb 03 13:42:45 2012 -0800 @@ -268,6 +268,7 @@ } compiler.getRuntime().installMethod(method, result); } catch (CiBailout bailout) { + Debug.metric("Bailouts").increment(); if (GraalOptions.ExitVMOnBailout) { bailout.printStackTrace(TTY.cachedOut); System.exit(-1); diff -r ed73455e9c03 -r 87a12a816e99 graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/ArrayLengthNode.java --- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/ArrayLengthNode.java Fri Feb 03 13:41:59 2012 -0800 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/ArrayLengthNode.java Fri Feb 03 13:42:45 2012 -0800 @@ -58,7 +58,7 @@ return length; } CiConstant constantValue = null; - if (array().isConstant()) { + if (array().isConstant() && !array().isNullConstant()) { constantValue = array().asConstant(); if (constantValue != null && constantValue.isNonNull()) { RiRuntime runtime = tool.runtime(); diff -r ed73455e9c03 -r 87a12a816e99 graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/LoadFieldNode.java --- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/LoadFieldNode.java Fri Feb 03 13:41:59 2012 -0800 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/LoadFieldNode.java Fri Feb 03 13:42:45 2012 -0800 @@ -69,7 +69,7 @@ CiConstant constant = null; if (isStatic()) { constant = field().constantValue(null); - } else if (object().isConstant()) { + } else if (object().isConstant() && !object().isNullConstant()) { constant = field().constantValue(object().asConstant()); } if (constant != null) {