# HG changeset patch # User Doug Simon # Date 1397070652 -7200 # Node ID 90e8e3b905584b8bfcc9e643eebc35cf8e190529 # Parent f4186cbd8a20b3a15e597d776002773b85c9d046 prevent recursive inlining when a method substitution calls the original (i.e., substituted) method diff -r f4186cbd8a20 -r 90e8e3b90558 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Wed Apr 09 18:53:48 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Wed Apr 09 21:10:52 2014 +0200 @@ -39,6 +39,7 @@ import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.java.*; import com.oracle.graal.java.GraphBuilderPhase.Instance; import com.oracle.graal.nodes.*; @@ -460,17 +461,30 @@ private StructuredGraph buildGraph(final ResolvedJavaMethod methodToParse, final SnippetInliningPolicy policy, int inliningDepth) { assert inliningDepth < MAX_GRAPH_INLINING_DEPTH : "inlining limit exceeded"; - assert isInlinableSnippet(methodToParse) : methodToParse; + assert isInlinable(methodToParse) : methodToParse; final StructuredGraph graph = buildInitialGraph(methodToParse); try (Scope s = Debug.scope("buildGraph", graph)) { - + Set doNotInline = null; for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.class)) { + if (doNotInline != null && doNotInline.contains(callTarget)) { + continue; + } ResolvedJavaMethod callee = callTarget.targetMethod(); if (callee.equals(recursiveEntry)) { - if (isInlinableSnippet(substitutedMethod)) { + if (isInlinable(substitutedMethod)) { final StructuredGraph originalGraph = buildInitialGraph(substitutedMethod); + Mark mark = graph.getMark(); InliningUtil.inline(callTarget.invoke(), originalGraph, true); - + for (MethodCallTargetNode inlinedCallTarget : graph.getNewNodes(mark).filter(MethodCallTargetNode.class)) { + if (doNotInline == null) { + doNotInline = new HashSet<>(); + } + // We do not want to do further inlining (now) for calls + // in the original method as this can cause unlimited + // recursive inlining given an eager inlining policy such + // as DefaultSnippetInliningPolicy. + doNotInline.add(inlinedCallTarget); + } Debug.dump(graph, "after inlining %s", callee); afterInline(graph, originalGraph, null); } @@ -516,8 +530,8 @@ } } - private static boolean isInlinableSnippet(final ResolvedJavaMethod methodToParse) { - return !Modifier.isAbstract(methodToParse.getModifiers()) && !Modifier.isNative(methodToParse.getModifiers()); + private static boolean isInlinable(final ResolvedJavaMethod method) { + return !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()); } private static String originalName(Method substituteMethod, String methodSubstitution) {