# HG changeset patch # User Thomas Wuerthinger # Date 1379598806 -7200 # Node ID 7778a0f2999a6df1d16198fcb681d987d0652826 # Parent 271ffa2d36b38656bb946597aa540ffc8b60e2c3 Run partial escape analysis on Truffle cache methods. diff -r 271ffa2d36b3 -r 7778a0f2999a graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Thu Sep 19 15:53:09 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Thu Sep 19 15:53:26 2013 +0200 @@ -360,6 +360,10 @@ return true; } + public boolean isNew(int mark, Node node) { + return node.id >= mark; + } + /** * Gets a mark that can be used with {@link #getNewNodes(int)}. */ diff -r 271ffa2d36b3 -r 7778a0f2999a graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Thu Sep 19 15:53:09 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Thu Sep 19 15:53:26 2013 +0200 @@ -43,6 +43,7 @@ import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.truffle.phases.*; +import com.oracle.graal.virtual.phases.ea.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.nodes.*; @@ -109,43 +110,70 @@ new ConvertDeoptimizeToGuardPhase().apply(graph); CanonicalizerPhase canonicalizerPhase = new CanonicalizerPhase(!AOTCompilation.getValue()); + PartialEscapePhase partialEscapePhase = new PartialEscapePhase(false, canonicalizerPhase); - // Canonicalize / constant propagate. - canonicalizerPhase.apply(graph, context); + int mark = 0; + while (true) { + + partialEscapePhase.apply(graph, context); - int mark = graph.getMark(); - for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.class)) { - if (graph.getMark() != mark) { - canonicalizerPhase.applyIncremental(graph, context, mark); + // Conditional elimination. + ConditionalEliminationPhase conditionalEliminationPhase = new ConditionalEliminationPhase(metaAccessProvider); + conditionalEliminationPhase.apply(graph); + + // Canonicalize / constant propagate. + canonicalizerPhase.apply(graph, context); - // Make sure macro substitutions such as - // CompilerDirectives.transferToInterpreter get processed first. - for (Node newNode : graph.getNewNodes(mark)) { - if (newNode instanceof MethodCallTargetNode) { - MethodCallTargetNode methodCallTargetNode = (MethodCallTargetNode) newNode; - Class macroSubstitution = replacements.getMacroSubstitution(methodCallTargetNode.targetMethod()); - if (macroSubstitution != null) { - InliningUtil.inlineMacroNode(methodCallTargetNode.invoke(), methodCallTargetNode.targetMethod(), methodCallTargetNode.graph(), macroSubstitution); + boolean inliningProgress = false; + for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.class)) { + if (graph.getMark() != mark) { + // Make sure macro substitutions such as + // CompilerDirectives.transferToInterpreter get processed first. + for (Node newNode : graph.getNewNodes(mark)) { + if (newNode instanceof MethodCallTargetNode) { + MethodCallTargetNode methodCallTargetNode = (MethodCallTargetNode) newNode; + Class macroSubstitution = replacements.getMacroSubstitution(methodCallTargetNode.targetMethod()); + if (macroSubstitution != null) { + InliningUtil.inlineMacroNode(methodCallTargetNode.invoke(), methodCallTargetNode.targetMethod(), methodCallTargetNode.graph(), macroSubstitution); + } else { + tryCutOffRuntimeExceptions(methodCallTargetNode); + } } } + mark = graph.getMark(); } - mark = graph.getMark(); + if (methodCallTarget.isAlive() && methodCallTarget.invoke() != null && shouldInline(methodCallTarget)) { + inliningProgress = true; + List canonicalizerUsages = new ArrayList(); + for (Node n : methodCallTarget.invoke().asNode().usages()) { + if (n instanceof Canonicalizable) { + canonicalizerUsages.add(n); + } + } + List argumentSnapshot = methodCallTarget.arguments().snapshot(); + int beforeInvokeMark = graph.getMark(); + expandInvoke(methodCallTarget); + for (Node arg : argumentSnapshot) { + if (arg != null) { + for (Node argUsage : arg.usages()) { + if (graph.isNew(beforeInvokeMark, argUsage) && argUsage instanceof Canonicalizable) { + canonicalizerUsages.add(argUsage); + } + } + } + } + canonicalizerPhase.applyIncremental(graph, context, canonicalizerUsages); + } } - if (methodCallTarget.isAlive() && methodCallTarget.invoke() != null) { - expandInvoke(methodCallTarget.invoke()); + + // Convert deopt to guards. + new ConvertDeoptimizeToGuardPhase().apply(graph); + + if (!inliningProgress) { + break; } } - // Convert deopt to guards. - new ConvertDeoptimizeToGuardPhase().apply(graph); - - // Canonicalize / constant propagate. - canonicalizerPhase.apply(graph, context); - - // Conditional elimination. - ConditionalEliminationPhase conditionalEliminationPhase = new ConditionalEliminationPhase(metaAccessProvider); - conditionalEliminationPhase.apply(graph); - if (TruffleCompilerOptions.TraceTruffleCacheDetails.getValue()) { TTY.println(String.format("[truffle] added to graph cache method %s with %d nodes.", method, graph.getNodeCount())); } @@ -156,42 +184,36 @@ return resultGraph; } - private FixedNode expandInvoke(Invoke invoke) { - if (invoke.callTarget() instanceof MethodCallTargetNode) { - final MethodCallTargetNode methodCallTargetNode = (MethodCallTargetNode) invoke.callTarget(); + private void expandInvoke(MethodCallTargetNode methodCallTargetNode) { + StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod()); + if (inlineGraph == null) { + inlineGraph = TruffleCache.this.lookup(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), null, null); + } + if (inlineGraph == this.markerGraph) { + // Can happen for recursive calls. + throw new IllegalStateException("Found illegal recursive call to " + methodCallTargetNode.targetMethod() + ", must annotate such calls with @CompilerDirectives.Slowpath!"); + } + Invoke invoke = methodCallTargetNode.invoke(); + InliningUtil.inline(invoke, inlineGraph, true); + } - if ((methodCallTargetNode.invokeKind() == InvokeKind.Special || methodCallTargetNode.invokeKind() == InvokeKind.Static) && - !Modifier.isNative(methodCallTargetNode.targetMethod().getModifiers()) && methodCallTargetNode.targetMethod().getAnnotation(ExplodeLoop.class) == null && - methodCallTargetNode.targetMethod().getAnnotation(CompilerDirectives.SlowPath.class) == null) { - if (methodCallTargetNode.targetMethod().isConstructor()) { - ResolvedJavaType runtimeException = metaAccessProvider.lookupJavaType(RuntimeException.class); - if (runtimeException.isAssignableFrom(methodCallTargetNode.targetMethod().getDeclaringClass())) { - DeoptimizeNode deoptNode = invoke.asNode().graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode)); - FixedNode invokeNode = methodCallTargetNode.invoke().asNode(); - invokeNode.replaceAtPredecessor(deoptNode); - GraphUtil.killCFG(invokeNode); - return deoptNode; - } - } - StructuredGraph inlinedGraph = Debug.scope("ExpandInvoke", methodCallTargetNode.targetMethod(), new Callable() { - - public StructuredGraph call() { - StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod()); - if (inlineGraph == null) { - inlineGraph = TruffleCache.this.lookup(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), null, null); - } - return inlineGraph; - } - }); - if (inlinedGraph == this.markerGraph) { - // Can happen for recursive calls. - throw new IllegalStateException("Found illegal recursive call to " + methodCallTargetNode.targetMethod() + ", must annotate such calls with @CompilerDirectives.Slowpath!"); - } - FixedNode fixedNode = (FixedNode) invoke.predecessor(); - InliningUtil.inline(invoke, inlinedGraph, true); - return fixedNode; + private boolean tryCutOffRuntimeExceptions(MethodCallTargetNode methodCallTargetNode) { + if (methodCallTargetNode.targetMethod().isConstructor()) { + ResolvedJavaType runtimeException = metaAccessProvider.lookupJavaType(RuntimeException.class); + if (runtimeException.isAssignableFrom(methodCallTargetNode.targetMethod().getDeclaringClass())) { + DeoptimizeNode deoptNode = methodCallTargetNode.graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode)); + FixedNode invokeNode = methodCallTargetNode.invoke().asNode(); + invokeNode.replaceAtPredecessor(deoptNode); + GraphUtil.killCFG(invokeNode); + return true; } } - return invoke.asNode(); + return false; + } + + private static boolean shouldInline(final MethodCallTargetNode methodCallTargetNode) { + return (methodCallTargetNode.invokeKind() == InvokeKind.Special || methodCallTargetNode.invokeKind() == InvokeKind.Static) && + !Modifier.isNative(methodCallTargetNode.targetMethod().getModifiers()) && methodCallTargetNode.targetMethod().getAnnotation(ExplodeLoop.class) == null && + methodCallTargetNode.targetMethod().getAnnotation(CompilerDirectives.SlowPath.class) == null; } }