# HG changeset patch # User Christian Haeubl # Date 1358323704 -3600 # Node ID 42b6e090588193f3538a2d922ec255dc205dc6c9 # Parent 36dafe48bc38d463cb767ebada66e859b61374b1# Parent 6ad818b8892e655ff3b0eb6b6a0e245fc379a052 Merge. diff -r 6ad818b8892e -r 42b6e0905881 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Tue Jan 15 21:11:45 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Wed Jan 16 09:08:24 2013 +0100 @@ -93,6 +93,8 @@ assertInlined(getGraph("invokeSingleImplementorInterfaceSnippet")); // assertInlined(getGraph("invokeConcreteInterfaceMethodSnippet")); + assertNotInlined(getGraph("invokeOverriddenPublicMethodSnippet")); + assertNotInlined(getGraph("invokeOverriddenProtectedMethodSnippet")); assertNotInlined(getGraph("invokeOverriddenInterfaceMethodSnippet")); } @@ -120,6 +122,14 @@ public static int invokeOverriddenInterfaceMethodSnippet(MultipleImplementorsInterface testInterface) { return testInterface.publicOverriddenMethod(); } + @SuppressWarnings("all") + public static int invokeOverriddenPublicMethodSnippet(SuperClass superClass) { + return superClass.publicOverriddenMethod(); + } + @SuppressWarnings("all") + public static int invokeOverriddenProtectedMethodSnippet(SuperClass superClass) { + return superClass.protectedOverriddenMethod(); + } private StructuredGraph getGraph(final String snippet) { return Debug.scope("InliningTest", new DebugDumpScope(snippet), new Callable() { diff -r 6ad818b8892e -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java Tue Jan 15 21:11:45 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java Wed Jan 16 09:08:24 2013 +0100 @@ -379,6 +379,7 @@ Arrays.sort(ptypes); double notRecordedTypeProbability = entries < config.typeProfileWidth ? 0.0 : Math.min(1.0, Math.max(0.0, 1.0 - totalProbability)); + assert notRecordedTypeProbability == 0 || entries == config.typeProfileWidth; return new JavaTypeProfile(notRecordedTypeProbability, ptypes); } diff -r 6ad818b8892e -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java Tue Jan 15 21:11:45 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java Wed Jan 16 09:08:24 2013 +0100 @@ -118,8 +118,10 @@ StructuredGraph snippetGraph = (StructuredGraph) snippetMethod.getCompilerStorage().get(Graph.class); assert snippetGraph != null : "ArrayCopySnippets should be installed"; hits = true; - Debug.log("%s > Intinsify (%s)", Debug.currentScope(), snippetMethod.getSignature().getParameterType(0, snippetMethod.getDeclaringClass()).getComponentType()); + Debug.log("%s > Intrinsify (%s)", Debug.currentScope(), snippetMethod.getSignature().getParameterType(0, snippetMethod.getDeclaringClass()).getComponentType()); InliningUtil.inline(methodCallTarget.invoke(), snippetGraph, false); + } else { + Debug.log("%s > not intrinsifying arraycopy", Debug.currentScope()); } } if (GraalOptions.OptCanonicalizer && hits) { diff -r 6ad818b8892e -r 42b6e0905881 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java Tue Jan 15 21:11:45 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java Wed Jan 16 09:08:24 2013 +0100 @@ -43,6 +43,7 @@ public void setProbability(double probability) { assert probability >= 0 : String.format("Invalid argument %f, because the probability of a node must not be negative.", probability); this.probability = probability; + assert !Double.isNaN(probability); } protected void copyInto(FixedNode newNode) { diff -r 6ad818b8892e -r 42b6e0905881 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java Tue Jan 15 21:11:45 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java Wed Jan 16 09:08:24 2013 +0100 @@ -57,6 +57,10 @@ void setProbability(double value); + double inliningRelevance(); + + void setInliningRelevance(double value); + boolean useForInlining(); void setUseForInlining(boolean value); diff -r 6ad818b8892e -r 42b6e0905881 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Tue Jan 15 21:11:45 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Wed Jan 16 09:08:24 2013 +0100 @@ -42,6 +42,7 @@ private boolean polymorphic; private boolean useForInlining; private final long leafGraphId; + private double inliningRelevance; /** * Constructs a new Invoke instruction. @@ -56,6 +57,7 @@ this.leafGraphId = leafGraphId; this.polymorphic = false; this.useForInlining = true; + this.inliningRelevance = Double.NaN; } @Override @@ -88,6 +90,16 @@ } @Override + public double inliningRelevance() { + return inliningRelevance; + } + + @Override + public void setInliningRelevance(double value) { + inliningRelevance = value; + } + + @Override public long leafGraphId() { return leafGraphId; } diff -r 6ad818b8892e -r 42b6e0905881 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Tue Jan 15 21:11:45 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Wed Jan 16 09:08:24 2013 +0100 @@ -41,6 +41,7 @@ private boolean polymorphic; private boolean useForInlining; private final long leafGraphId; + private double inliningRelevance; public InvokeWithExceptionNode(CallTargetNode callTarget, DispatchBeginNode exceptionEdge, int bci, long leafGraphId) { super(callTarget.returnStamp()); @@ -50,6 +51,7 @@ this.leafGraphId = leafGraphId; this.polymorphic = false; this.useForInlining = true; + this.inliningRelevance = Double.NaN; } public DispatchBeginNode exceptionEdge() { @@ -99,6 +101,16 @@ } @Override + public double inliningRelevance() { + return inliningRelevance; + } + + @Override + public void setInliningRelevance(double value) { + inliningRelevance = value; + } + + @Override public long leafGraphId() { return leafGraphId; } diff -r 6ad818b8892e -r 42b6e0905881 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java Tue Jan 15 21:11:45 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java Wed Jan 16 09:08:24 2013 +0100 @@ -65,6 +65,8 @@ } } } + + new ComputeInliningRelevanceIterator(graph).apply(); } private void correctLoopFrequencies(Loop loop, double parentFrequency, BitSet visitedBlocks) { @@ -369,4 +371,74 @@ return probability; } } + + private static class ComputeInliningRelevanceIterator extends ScopedPostOrderNodeIterator { + private final HashMap lowestPathProbabilities; + private double currentProbability; + + public ComputeInliningRelevanceIterator(StructuredGraph graph) { + super(graph); + this.lowestPathProbabilities = computeLowestPathProbabilities(graph); + } + + @Override + protected void initializeScope() { + currentProbability = lowestPathProbabilities.get(currentScope); + } + + @Override + protected void invoke(Invoke invoke) { + assert !Double.isNaN(invoke.probability()); + invoke.setInliningRelevance(invoke.probability() / currentProbability); + } + + private HashMap computeLowestPathProbabilities(StructuredGraph graph) { + HashMap result = new HashMap<>(); + Deque scopes = getScopes(graph); + + while (!scopes.isEmpty()) { + FixedNode scopeBegin = scopes.pop(); + double probability = computeLowestPathProbability(scopeBegin); + result.put(scopeBegin, probability); + } + + return result; + } + + private static double computeLowestPathProbability(FixedNode scopeStart) { + double minPathProbability = scopeStart.probability(); + Node current = scopeStart; + + while (current != null) { + if (current instanceof ControlSplitNode) { + ControlSplitNode controlSplit = (ControlSplitNode) current; + current = getMaxProbabilitySux(controlSplit); + if (((FixedNode) current).probability() < minPathProbability) { + minPathProbability = ((FixedNode) current).probability(); + } + } else { + assert current.successors().count() <= 1; + current = current.successors().first(); + } + } + + return minPathProbability; + } + + private static Node getMaxProbabilitySux(ControlSplitNode controlSplit) { + Node maxSux = null; + double maxProbability = 0.0; + + // TODO: process recursively if we have multiple successors with same probability + for (Node sux: controlSplit.successors()) { + double probability = controlSplit.probability((BeginNode) sux); + if (probability > maxProbability) { + maxProbability = probability; + maxSux = sux; + } + } + + return maxSux; + } + } } diff -r 6ad818b8892e -r 42b6e0905881 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Tue Jan 15 21:11:45 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Wed Jan 16 09:08:24 2013 +0100 @@ -81,6 +81,7 @@ while (inliningPolicy.continueInlining(graph)) { final InlineInfo candidate = inliningPolicy.next(); + if (candidate != null) { boolean isWorthInlining = inliningPolicy.isWorthInlining(candidate); @@ -149,7 +150,8 @@ } private abstract static class AbstractInliningDecision implements InliningDecision { - public static boolean decideSizeBasedInlining(InlineInfo info, double maxSize) { + protected static boolean decideSizeBasedInlining(InlineInfo info, double maxSize) { + assert !Double.isNaN(info.weight()) && !Double.isNaN(maxSize); boolean success = info.weight() <= maxSize; if (GraalOptions.Debug) { String formatterString = success ? "(size %f <= %f)" : "(too large %f > %f)"; @@ -158,13 +160,21 @@ return success; } - public static boolean checkCompiledCodeSize(InlineInfo info) { + protected static boolean checkCompiledCodeSize(InlineInfo info) { if (GraalOptions.SmallCompiledCodeSize >= 0 && info.compiledCodeSize() > GraalOptions.SmallCompiledCodeSize) { InliningUtil.logNotInlinedMethod(info, "(CompiledCodeSize %d > %d)", info.compiledCodeSize(), GraalOptions.SmallCompiledCodeSize); return false; } return true; } + + protected static double getRelevance(Invoke invoke) { + if (GraalOptions.UseRelevanceBasedInlining) { + return invoke.inliningRelevance(); + } else { + return invoke.probability(); + } + } } private static class C1StaticSizeBasedInliningDecision extends AbstractInliningDecision { @@ -183,7 +193,7 @@ return false; } - double inlineWeight = Math.min(GraalOptions.ProbabilityCapForInlining, info.invoke().probability()); + double inlineWeight = Math.min(GraalOptions.RatioCapForInlining, getRelevance(info.invoke())); double maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * GraalOptions.MaximumInlineSize * inlineWeight; maxSize = Math.max(GraalOptions.MaximumTrivialSize, maxSize); @@ -199,7 +209,8 @@ return false; } - double inlineBoost = Math.min(GraalOptions.ProbabilityCapForInlining, info.invoke().probability()) + Math.log10(Math.max(1, info.invoke().probability() - GraalOptions.ProbabilityCapForInlining + 1)); + double relevance = getRelevance(info.invoke()); + double inlineBoost = Math.min(GraalOptions.RatioCapForInlining, relevance) + Math.log10(Math.max(1, relevance - GraalOptions.RatioCapForInlining + 1)); double maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * GraalOptions.MaximumInlineSize; maxSize = maxSize + maxSize * inlineBoost; maxSize = Math.min(GraalOptions.MaximumGreedyInlineSize, Math.max(GraalOptions.MaximumTrivialSize, maxSize)); @@ -226,7 +237,7 @@ maxSize += transferredValues * GraalOptions.InliningBonusPerTransferredValue; } - double inlineRatio = Math.min(GraalOptions.ProbabilityCapForInlining, info.invoke().probability()); + double inlineRatio = Math.min(GraalOptions.RatioCapForInlining, getRelevance(info.invoke())); maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * maxSize * inlineRatio; maxSize = Math.max(maxSize, GraalOptions.MaximumTrivialSize); @@ -240,7 +251,7 @@ assert GraalOptions.ProbabilityAnalysis; double maxSize = GraalOptions.MaximumGreedyInlineSize; - double inlineRatio = Math.min(GraalOptions.ProbabilityCapForInlining, info.invoke().probability()); + double inlineRatio = Math.min(GraalOptions.RatioCapForInlining, getRelevance(info.invoke())); maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * maxSize * inlineRatio; maxSize = Math.max(maxSize, GraalOptions.MaximumTrivialSize); @@ -251,6 +262,10 @@ private static class BytecodeSizeBasedWeightComputationPolicy implements WeightComputationPolicy { @Override public double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke) { + if (GraalOptions.AlwaysInlineIntrinsics && InliningUtil.canIntrinsify(method)) { + return 0; + } + double codeSize = method.getCodeSize(); if (preferredInvoke) { codeSize = codeSize / GraalOptions.BoostInliningForEscapeAnalysis; @@ -262,6 +277,10 @@ private static class ComplexityBasedWeightComputationPolicy implements WeightComputationPolicy { @Override public double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke) { + if (GraalOptions.AlwaysInlineIntrinsics && InliningUtil.canIntrinsify(method)) { + return 0; + } + double complexity = method.getCompilationComplexity(); if (preferredInvoke) { complexity = complexity / GraalOptions.BoostInliningForEscapeAnalysis; @@ -273,6 +292,10 @@ private static class CompiledCodeSizeWeightComputationPolicy implements WeightComputationPolicy { @Override public double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke) { + if (GraalOptions.AlwaysInlineIntrinsics && InliningUtil.canIntrinsify(method)) { + return 0; + } + int compiledCodeSize = method.getCompiledCodeSize(); return compiledCodeSize > 0 ? compiledCodeSize : method.getCodeSize() * 10; } diff -r 6ad818b8892e -r 42b6e0905881 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Tue Jan 15 21:11:45 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Wed Jan 16 09:08:24 2013 +0100 @@ -84,7 +84,7 @@ private static boolean logNotInlinedMethodAndReturnFalse(Invoke invoke, String msg) { if (shouldLogInliningDecision()) { - String methodString = invoke.callTarget() == null ? "callTarget=null" : invoke.callTarget().targetName(); + String methodString = invoke.toString() + (invoke.callTarget() == null ? " callTarget=null" : invoke.callTarget().targetName()); logInliningDecision(methodString, false, msg, new Object[0]); } return false; @@ -200,11 +200,11 @@ return computeInliningLevel(invoke); } - protected static StructuredGraph getGraph(final Invoke invoke, final ResolvedJavaMethod concrete, final InliningCallback callback) { + protected static StructuredGraph getGraph(final ResolvedJavaMethod concrete, final InliningCallback callback) { return Debug.scope("GetInliningGraph", concrete, new Callable() { @Override public StructuredGraph call() throws Exception { - StructuredGraph result = getIntrinsicGraph(invoke, concrete); + StructuredGraph result = getIntrinsicGraph(concrete); if (result == null) { assert !Modifier.isNative(concrete.getModifiers()); result = callback.buildGraph(concrete); @@ -229,14 +229,14 @@ @Override public void inline(StructuredGraph compilerGraph, GraalCodeCacheProvider runtime, InliningCallback callback, Assumptions assumptions) { - StructuredGraph graph = getGraph(invoke, concrete, callback); + StructuredGraph graph = getGraph(concrete, callback); assumptions.recordMethodContents(concrete); InliningUtil.inline(invoke, graph, true); } @Override public int compiledCodeSize() { - return concrete.getCompiledCodeSize(); + return InliningUtil.compiledCodeSize(concrete); } @Override @@ -261,7 +261,7 @@ @Override public int compiledCodeSize() { - return concrete.getCompiledCodeSize(); + return InliningUtil.compiledCodeSize(concrete); } @Override @@ -283,7 +283,7 @@ graph.addBeforeFixed(invoke.node(), guard); graph.addBeforeFixed(invoke.node(), anchor); - StructuredGraph calleeGraph = getGraph(invoke, concrete, callback); + StructuredGraph calleeGraph = getGraph(concrete, callback); assumptions.recordMethodContents(concrete); InliningUtil.inline(invoke, calleeGraph, false); } @@ -320,7 +320,7 @@ public int compiledCodeSize() { int result = 0; for (ResolvedJavaMethod m: concretes) { - result += m.getCompiledCodeSize(); + result += InliningUtil.compiledCodeSize(m); } return result; } @@ -410,7 +410,7 @@ StructuredGraph[] calleeGraphs = new StructuredGraph[numberOfMethods]; for (int i = 0; i < numberOfMethods; i++) { ResolvedJavaMethod concrete = concretes.get(i); - calleeGraphs[i] = getGraph(invoke, concrete, callback); + calleeGraphs[i] = getGraph(concrete, callback); assumptions.recordMethodContents(concrete); } @@ -512,7 +512,7 @@ calleeEntryNode.setNext(invoke.node()); ResolvedJavaMethod concrete = concretes.get(0); - StructuredGraph calleeGraph = getGraph(invoke, concrete, callback); + StructuredGraph calleeGraph = getGraph(concrete, callback); assumptions.recordMethodContents(concrete); InliningUtil.inline(invoke, calleeGraph, false); } @@ -563,6 +563,7 @@ result.node().replaceFirstInput(result.callTarget(), callTarget); result.setUseForInlining(useForInlining); result.setProbability(probability); + result.setInliningRelevance(invoke.inliningRelevance() * probability); Kind kind = invoke.node().kind(); if (kind != Kind.Void) { @@ -757,6 +758,7 @@ return logNotInlinedMethodAndReturnNull(invoke, targetMethod, "inlining polymorphic calls is disabled (%d types)", ptypes.size()); } if (!optimisticOpts.inlineMegamorphicCalls() && notRecordedTypeProbability > 0) { + // due to filtering impossible types, notRecordedTypeProbability can be > 0 although the number of types is lower than what can be recorded in a type profile return logNotInlinedMethodAndReturnNull(invoke, targetMethod, "inlining megamorphic calls is disabled (%d types, %f %% not recorded types)", ptypes.size(), notRecordedTypeProbability * 100); } @@ -799,7 +801,7 @@ ProfiledType ptype = types[i]; ResolvedJavaType type = ptype.getType(); assert !type.isInterface() && (type.isArray() || !Modifier.isAbstract(type.getModifiers())) : type; - if (holder.isAssignableFrom(type)) { + if (!GraalOptions.OptFilterProfiledTypes || holder.isAssignableFrom(type)) { result.add(ptype); } } @@ -816,14 +818,14 @@ } private static boolean checkInvokeConditions(Invoke invoke) { - if (!(invoke.callTarget() instanceof MethodCallTargetNode)) { + if (invoke.predecessor() == null || !invoke.node().isAlive()) { + return logNotInlinedMethodAndReturnFalse(invoke, "the invoke is dead code"); + } else if (!(invoke.callTarget() instanceof MethodCallTargetNode)) { return logNotInlinedMethodAndReturnFalse(invoke, "the invoke has already been lowered, or has been created as a low-level node"); } else if (invoke.methodCallTarget().targetMethod() == null) { return logNotInlinedMethodAndReturnFalse(invoke, "target method is null"); } else if (invoke.stateAfter() == null) { return logNotInlinedMethodAndReturnFalse(invoke, "the invoke has no after state"); - } else if (invoke.predecessor() == null || !invoke.node().isAlive()) { - return logNotInlinedMethodAndReturnFalse(invoke, "the invoke is dead code"); } else if (!invoke.useForInlining()) { return logNotInlinedMethodAndReturnFalse(invoke, "the invoke is marked to be not used for inlining"); } else if (invoke.methodCallTarget().receiver() != null && invoke.methodCallTarget().receiver().isConstant() && invoke.methodCallTarget().receiver().asConstant().isNull()) { @@ -836,7 +838,7 @@ private static boolean checkTargetConditions(Invoke invoke, ResolvedJavaMethod method, OptimisticOptimizations optimisticOpts) { if (method == null) { return logNotInlinedMethodAndReturnFalse(invoke, method, "the method is not resolved"); - } else if (Modifier.isNative(method.getModifiers()) && (!GraalOptions.Intrinsify || !InliningUtil.canIntrinsify(invoke, method))) { + } else if (Modifier.isNative(method.getModifiers()) && (!GraalOptions.Intrinsify || !InliningUtil.canIntrinsify(method))) { return logNotInlinedMethodAndReturnFalse(invoke, method, "it is a non-intrinsic native method"); } else if (Modifier.isAbstract(method.getModifiers())) { return logNotInlinedMethodAndReturnFalse(invoke, method, "it is an abstract method"); @@ -974,6 +976,14 @@ } fixed.setProbability(newProbability); } + if (node instanceof Invoke) { + Invoke newInvoke = (Invoke) node; + double newRelevance = newInvoke.inliningRelevance() * invoke.inliningRelevance(); + if (GraalOptions.LimitInlinedProbability) { + newRelevance = Math.min(newRelevance, invoke.inliningRelevance()); + } + newInvoke.setInliningRelevance(newRelevance); + } } if (node instanceof FrameState) { FrameState frameState = (FrameState) node; @@ -1032,13 +1042,20 @@ } } - public static boolean canIntrinsify(Invoke invoke, ResolvedJavaMethod target) { - StructuredGraph intrinsicGraph = getIntrinsicGraph(invoke, target); + public static boolean canIntrinsify(ResolvedJavaMethod target) { + StructuredGraph intrinsicGraph = getIntrinsicGraph(target); return intrinsicGraph != null; } - public static StructuredGraph getIntrinsicGraph(Invoke invoke, ResolvedJavaMethod target) { - assert invoke.node().isAlive(); + public static StructuredGraph getIntrinsicGraph(ResolvedJavaMethod target) { return (StructuredGraph) target.getCompilerStorage().get(Graph.class); } + + private static int compiledCodeSize(ResolvedJavaMethod target) { + if (GraalOptions.AlwaysInlineIntrinsics && canIntrinsify(target)) { + return 0; + } else { + return target.getCompiledCodeSize(); + } + } } diff -r 6ad818b8892e -r 42b6e0905881 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Tue Jan 15 21:11:45 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Wed Jan 16 09:08:24 2013 +0100 @@ -39,6 +39,7 @@ // inlining settings public static boolean Inline = true; + public static boolean AlwaysInlineIntrinsics = ____; public static boolean Intrinsify = true; static boolean InlineMonomorphicCalls = true; static boolean InlinePolymorphicCalls = true; @@ -52,6 +53,7 @@ public static int MaximumRecursiveInlining = 1; public static int SmallCompiledCodeSize = 2200; public static boolean LimitInlinedProbability = ____; + public static boolean UseRelevanceBasedInlining = true; // WeightBasedInliningPolicy (0) public static float InliningSizePenaltyExp = 20; public static float MaximumInlineWeight = 1.25f; @@ -65,7 +67,7 @@ // Common options for inlining policies 1 to 4 public static float NestedInliningSizeRatio = 1f; public static float BoostInliningForEscapeAnalysis = 2f; - public static float ProbabilityCapForInlining = 1f; + public static float RatioCapForInlining = 1f; // escape analysis settings public static boolean PartialEscapeAnalysis = true; @@ -199,6 +201,7 @@ public static boolean OptFloatingReads = true; public static boolean OptTailDuplication = true; public static boolean OptEliminatePartiallyRedundantGuards = true; + public static boolean OptFilterProfiledTypes = true; // Intrinsification settings public static boolean IntrinsifyArrayCopy = true; diff -r 6ad818b8892e -r 42b6e0905881 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScopedPostOrderNodeIterator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScopedPostOrderNodeIterator.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,175 @@ +/* + * 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.phases.graph; + +import java.util.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.iterators.*; +import com.oracle.graal.nodes.*; + +public abstract class ScopedPostOrderNodeIterator { + private final NodeBitMap processedNodes; + private final Deque nodeQueue; + private final NodeBitMap queuedNodes; + private final Deque scopes; + + protected FixedNode currentScope; + + public ScopedPostOrderNodeIterator(StructuredGraph graph) { + this.processedNodes = graph.createNodeBitMap(); + this.queuedNodes = graph.createNodeBitMap(); + this.nodeQueue = new ArrayDeque<>(); + this.scopes = getScopes(graph); + } + + public void apply() { + while (!scopes.isEmpty()) { + processedNodes.clearAll(); + queuedNodes.clearAll(); + this.currentScope = scopes.pop(); + initializeScope(); + processScope(); + } + } + + public void processScope() { + FixedNode current = currentScope; + do { + assert current.isAlive(); + processedNodes.mark(current); + + if (current instanceof Invoke) { + invoke((Invoke) current); + queueSuccessors(current); + current = nextQueuedNode(); + } else if (current instanceof LoopBeginNode) { + queueLoopBeginSuccessors((LoopBeginNode) current); + current = nextQueuedNode(); + } else if (current instanceof LoopExitNode) { + queueLoopExitSuccessors((LoopExitNode) current); + current = nextQueuedNode(); + } else if (current instanceof LoopEndNode) { + current = nextQueuedNode(); + } else if (current instanceof MergeNode) { + current = ((MergeNode) current).next(); + assert current != null; + } else if (current instanceof FixedWithNextNode) { + queueSuccessors(current); + current = nextQueuedNode(); + } else if (current instanceof EndNode) { + queueMerge((EndNode) current); + current = nextQueuedNode(); + } else if (current instanceof DeoptimizeNode) { + current = nextQueuedNode(); + } else if (current instanceof ReturnNode) { + current = nextQueuedNode(); + } else if (current instanceof UnwindNode) { + current = nextQueuedNode(); + } else if (current instanceof ControlSplitNode) { + queueSuccessors(current); + current = nextQueuedNode(); + } else { + assert false : current; + } + } while(current != null); + } + + protected void queueLoopBeginSuccessors(LoopBeginNode node) { + if (currentScope == node) { + queue(node.next()); + } else if (currentScope instanceof LoopBeginNode) { + // so we are currently processing loop A and found another loop B + // -> queue all loop exits of B except those that also exit loop A + for (LoopExitNode loopExit: node.loopExits()) { + if (!((LoopBeginNode) currentScope).loopExits().contains(loopExit)) { + queue(loopExit); + } + } + } else { + queue(node.loopExits()); + } + } + + protected void queueLoopExitSuccessors(LoopExitNode node) { + if (!(currentScope instanceof LoopBeginNode) || !((LoopBeginNode) currentScope).loopExits().contains(node)) { + queueSuccessors(node); + } + } + + protected Deque getScopes(StructuredGraph graph) { + Deque result = new ArrayDeque<>(); + result.push(graph.start()); + for (LoopBeginNode loopBegin: graph.getNodes(LoopBeginNode.class)) { + result.push(loopBegin); + } + return result; + } + + private void queueSuccessors(FixedNode x) { + queue(x.successors()); + } + + private void queue(NodeIterable iter) { + for (Node node : iter) { + queue(node); + } + } + + private void queue(Node node) { + if (node != null && !queuedNodes.isMarked(node)) { + queuedNodes.mark(node); + nodeQueue.addFirst((FixedNode) node); + } + } + + private FixedNode nextQueuedNode() { + if (nodeQueue.isEmpty()) { + return null; + } + + FixedNode result = nodeQueue.removeFirst(); + assert queuedNodes.isMarked(result); + return result; + } + + private void queueMerge(EndNode end) { + MergeNode merge = end.merge(); + if (!queuedNodes.isMarked(merge) && visitedAllEnds(merge)) { + queuedNodes.mark(merge); + nodeQueue.add(merge); + } + } + + private boolean visitedAllEnds(MergeNode merge) { + for (int i = 0; i < merge.forwardEndCount(); i++) { + if (!processedNodes.isMarked(merge.forwardEndAt(i))) { + return false; + } + } + return true; + } + + protected abstract void initializeScope(); + protected abstract void invoke(Invoke invoke); +} diff -r 6ad818b8892e -r 42b6e0905881 src/cpu/x86/vm/graalRuntime_x86.cpp --- a/src/cpu/x86/vm/graalRuntime_x86.cpp Tue Jan 15 21:11:45 2013 +0100 +++ b/src/cpu/x86/vm/graalRuntime_x86.cpp Wed Jan 16 09:08:24 2013 +0100 @@ -188,25 +188,46 @@ int GraalStubAssembler::call_RT(Register oop_result1, Register metadata_result, address entry, Register arg1, Register arg2, Register arg3, Register arg4) { #ifdef _LP64 - // if there is any conflict use the stack - if (arg1 == c_rarg2 || arg1 == c_rarg3 || arg1 == c_rarg4 || - arg2 == c_rarg1 || arg2 == c_rarg3 || arg2 == c_rarg4 || - arg3 == c_rarg1 || arg3 == c_rarg2 || arg3 == c_rarg4 || - arg4 == c_rarg1 || arg4 == c_rarg2 || arg4 == c_rarg3) { - push(arg4); - push(arg3); - push(arg2); - push(arg1); - pop(c_rarg1); - pop(c_rarg2); - pop(c_rarg3); - pop(c_rarg4); - } else { - mov(c_rarg1, arg1); - mov(c_rarg2, arg2); - mov(c_rarg3, arg3); - mov(c_rarg4, arg4); - } + #ifdef _WIN64 + // on windows we only have the registers c_rarg0 to c_rarg3 for transferring parameters -> remaining parameters are on the stack + if (arg1 == c_rarg2 || arg1 == c_rarg3 || + arg2 == c_rarg1 || arg2 == c_rarg3 || + arg3 == c_rarg1 || arg3 == c_rarg2 || + arg4 == c_rarg1 || arg4 == c_rarg2) { + push(arg4); + push(arg3); + push(arg2); + push(arg1); + pop(c_rarg1); + pop(c_rarg2); + pop(c_rarg3); + } else { + mov(c_rarg1, arg1); + mov(c_rarg2, arg2); + mov(c_rarg3, arg3); + push(arg4); + } + #else + // if there is any conflict use the stack + if (arg1 == c_rarg2 || arg1 == c_rarg3 || arg1 == c_rarg4 || + arg2 == c_rarg1 || arg2 == c_rarg3 || arg2 == c_rarg4 || + arg3 == c_rarg1 || arg3 == c_rarg2 || arg3 == c_rarg4 || + arg4 == c_rarg1 || arg4 == c_rarg2 || arg4 == c_rarg3) { + push(arg4); + push(arg3); + push(arg2); + push(arg1); + pop(c_rarg1); + pop(c_rarg2); + pop(c_rarg3); + pop(c_rarg4); + } else { + mov(c_rarg1, arg1); + mov(c_rarg2, arg2); + mov(c_rarg3, arg3); + mov(c_rarg4, arg4); + } + #endif #else push(arg4); push(arg3); diff -r 6ad818b8892e -r 42b6e0905881 src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Tue Jan 15 21:11:45 2013 +0100 +++ b/src/share/vm/graal/graalRuntime.cpp Wed Jan 16 09:08:24 2013 +0100 @@ -588,11 +588,9 @@ JRT_ENTRY(jboolean, GraalRuntime::graal_thread_is_interrupted(JavaThread* thread, oop receiver, jboolean clear_interrupted)) // Ensure that the C++ Thread and OSThread structures aren't freed before we operate Handle receiverHandle(thread, receiver); - JRT_BLOCK - MutexLockerEx ml(thread->threadObj() == receiver ? NULL : Threads_lock); - JavaThread* receiverThread = java_lang_Thread::thread(receiverHandle()); - return (jint) Thread::is_interrupted(receiverThread, clear_interrupted != 0); - JRT_BLOCK_END + MutexLockerEx ml(thread->threadObj() == receiver ? NULL : Threads_lock); + JavaThread* receiverThread = java_lang_Thread::thread(receiverHandle()); + return (jint) Thread::is_interrupted(receiverThread, clear_interrupted != 0); JRT_END // JVM_InitializeGraalRuntime