changeset 17307:4bea75e99249

Truffle: fixed callsite argument profiling was still done for inlined calls using context sensitive inlining.
author Christian Humer <christian.humer@gmail.com>
date Wed, 01 Oct 2014 19:45:11 +0200
parents 3bde3e643528
children 8b4364df9bd3
files graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java
diffstat 4 files changed, 72 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Wed Oct 01 19:45:05 2014 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Wed Oct 01 19:45:11 2014 +0200
@@ -76,6 +76,7 @@
 
     private HotSpotTruffleRuntime() {
         installOptimizedCallTargetCallMethod();
+        installOptimizedCallTargetCallDirect();
         lookupCallMethods(getGraalProviders().getMetaAccess());
 
         // Create compilation queue.
@@ -93,6 +94,10 @@
         compileQueue = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), factory);
     }
 
+    private static void installOptimizedCallTargetCallDirect() {
+        ((HotSpotResolvedJavaMethod) getGraalProviders().getMetaAccess().lookupJavaMethod(OptimizedCallTarget.getCallDirectMethod())).setNotInlineable();
+    }
+
     @Override
     public String getName() {
         return "Graal Truffle Runtime";
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Wed Oct 01 19:45:05 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Wed Oct 01 19:45:11 2014 +0200
@@ -26,10 +26,12 @@
 import static com.oracle.graal.truffle.TruffleCompilerOptions.*;
 
 import java.io.*;
+import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.atomic.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.truffle.ContextSensitiveInlining.InliningDecision;
 import com.oracle.truffle.api.*;
@@ -126,7 +128,7 @@
         return doInvoke(args);
     }
 
-    public Object callDirect(Object... args) {
+    public final Object callDirect(Object... args) {
         profileArguments(args);
         Object result = doInvoke(args);
         Class<?> klass = profiledReturnType;
@@ -136,6 +138,14 @@
         return result;
     }
 
+    public final Object callInlined(Object... arguments) {
+        if (CompilerDirectives.inInterpreter()) {
+            compilationProfile.reportInlinedCall();
+        }
+        VirtualFrame frame = createFrame(getRootNode().getFrameDescriptor(), arguments);
+        return callProxy(frame);
+    }
+
     @ExplodeLoop
     private void profileArguments(Object[] args) {
         if (profiledArgumentTypesAssumption == null) {
@@ -216,7 +226,8 @@
                 args1 = castArguments(args1);
             }
         }
-        Object result = callRoot(args1);
+        VirtualFrame frame = createFrame(getRootNode().getFrameDescriptor(), args);
+        Object result = callProxy(frame);
 
         // Profile call return type
         if (profiledReturnTypeAssumption == null) {
@@ -236,11 +247,6 @@
         return result;
     }
 
-    private Object callRoot(Object[] args) {
-        VirtualFrame frame = createFrame(getRootNode().getFrameDescriptor(), args);
-        return callProxy(frame);
-    }
-
     @Override
     public void invalidate() {
         this.runtime.invalidateInstalledCode(this);
@@ -405,14 +411,6 @@
         return compilationProfile;
     }
 
-    public final Object callInlined(Object[] arguments) {
-        if (CompilerDirectives.inInterpreter()) {
-            compilationProfile.reportInlinedCall();
-        }
-        VirtualFrame frame = createFrame(getRootNode().getFrameDescriptor(), arguments);
-        return callProxy(frame);
-    }
-
     public final void performInlining() {
         if (!TruffleFunctionInlining.getValue() || TruffleContextSensitiveInlining.getValue()) {
             return;
@@ -480,4 +478,20 @@
 
     }
 
+    public static Method getCallDirectMethod() {
+        try {
+            return OptimizedCallTarget.class.getDeclaredMethod("callDirect", Object[].class);
+        } catch (NoSuchMethodException | SecurityException e) {
+            throw new GraalInternalError(e);
+        }
+    }
+
+    public static Method getCallInlinedMethod() {
+        try {
+            return OptimizedCallTarget.class.getDeclaredMethod("callInlined", Object[].class);
+        } catch (NoSuchMethodException | SecurityException e) {
+            throw new GraalInternalError(e);
+        }
+    }
+
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Wed Oct 01 19:45:05 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Wed Oct 01 19:45:11 2014 +0200
@@ -73,7 +73,8 @@
     private Set<Constant> constantReceivers;
     private final TruffleCache truffleCache;
     private final SnippetReflectionProvider snippetReflection;
-    private final ResolvedJavaMethod directCallMethod;
+    private final ResolvedJavaMethod callDirectMethod;
+    private final ResolvedJavaMethod callSiteProxyMethod;
 
     public PartialEvaluator(Providers providers, TruffleCache truffleCache) {
         this.providers = providers;
@@ -81,7 +82,8 @@
         this.canonicalizer = new CanonicalizerPhase(!ImmutableCode.getValue(), customCanonicalizer);
         this.snippetReflection = Graal.getRequiredCapability(SnippetReflectionProvider.class);
         this.truffleCache = truffleCache;
-        this.directCallMethod = providers.getMetaAccess().lookupJavaMethod(GraalFrameInstance.CallNodeFrame.METHOD);
+        this.callDirectMethod = providers.getMetaAccess().lookupJavaMethod(OptimizedCallTarget.getCallDirectMethod());
+        this.callSiteProxyMethod = providers.getMetaAccess().lookupJavaMethod(GraalFrameInstance.CallNodeFrame.METHOD);
     }
 
     public StructuredGraph createGraph(final OptimizedCallTarget callTarget, final Assumptions assumptions, ContextSensitiveInlining inlining) {
@@ -107,7 +109,7 @@
 
             expandTree(graph, assumptions);
 
-            expandCallBoundaries(graph, assumptions, inlining != null ? new TruffleInliningCache() : null, inlining);
+            expandDirectCalls(graph, assumptions, inlining != null ? new TruffleInliningCache() : null, inlining);
 
             if (Thread.currentThread().isInterrupted()) {
                 return null;
@@ -172,7 +174,7 @@
         return graph;
     }
 
-    private void expandCallBoundaries(StructuredGraph graph, Assumptions assumptions, TruffleInliningCache inliningCache, ContextSensitiveInlining inlining) {
+    private void expandDirectCalls(StructuredGraph graph, Assumptions assumptions, TruffleInliningCache inliningCache, ContextSensitiveInlining inlining) {
         if (inlining == null) {
             return;
         }
@@ -180,12 +182,24 @@
         TruffleExpansionLogger expansionLogger = new TruffleExpansionLogger(providers, graph);
 
         for (MethodCallTargetNode methodCallTargetNode : graph.getNodes(MethodCallTargetNode.class).snapshot()) {
-            StructuredGraph inlineGraph = parseInlineGraph(phaseContext, assumptions, inliningCache, inlining, methodCallTargetNode);
+            StructuredGraph inlineGraph = parseDirectCallGraph(phaseContext, assumptions, inliningCache, inlining, methodCallTargetNode);
 
             if (inlineGraph != null) {
                 expandTreeInline(graph, phaseContext, expansionLogger, methodCallTargetNode, inlineGraph);
             }
         }
+        // non inlined direct calls need to be expanded until TruffleCallBoundary.
+        expandTree(graph, assumptions);
+        assert noDirectCallsLeft(graph);
+    }
+
+    private boolean noDirectCallsLeft(StructuredGraph graph) {
+        for (MethodCallTargetNode methodCallTargetNode : graph.getNodes(MethodCallTargetNode.class).snapshot()) {
+            if (methodCallTargetNode.targetMethod().equals(callDirectMethod)) {
+                return false;
+            }
+        }
+        return true;
     }
 
     private void injectConstantCallTarget(final StructuredGraph graph, final OptimizedCallTarget constantCallTarget, PhaseContext baseContext) {
@@ -247,7 +261,8 @@
                         }
                         StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod());
 
-                        if (inlineGraph == null && !methodCallTargetNode.targetMethod().isNative() && methodCallTargetNode.targetMethod().canBeInlined()) {
+                        ResolvedJavaMethod targetMethod = methodCallTargetNode.targetMethod();
+                        if (inlineGraph == null && !targetMethod.isNative() && targetMethod.canBeInlined()) {
                             inlineGraph = parseGraph(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), assumptions, phaseContext);
                         }
 
@@ -271,7 +286,7 @@
         return changed;
     }
 
-    private StructuredGraph parseInlineGraph(PhaseContext phaseContext, Assumptions assumptions, TruffleInliningCache inliningCache, ContextSensitiveInlining inlining,
+    private StructuredGraph parseDirectCallGraph(PhaseContext phaseContext, Assumptions assumptions, TruffleInliningCache inliningCache, ContextSensitiveInlining inlining,
                     MethodCallTargetNode methodCallTargetNode) {
         OptimizedDirectCallNode callNode = resolveConstantCallNode(methodCallTargetNode);
         if (callNode == null) {
@@ -289,10 +304,6 @@
 
         assert decision.getProfile().getCallNode() == callNode;
 
-        if (!decision.isInline()) {
-            return null;
-        }
-
         OptimizedCallTarget currentTarget = decision.getProfile().getCallNode().getCurrentCallTarget();
         if (decision.getTarget() != currentTarget) {
             if (TruffleCompilerOptions.PrintTrufflePerformanceWarnings.getValue()) {
@@ -304,14 +315,17 @@
         }
 
         StructuredGraph graph;
-        if (inliningCache == null) {
-            graph = createInlineGraph(phaseContext, assumptions, null, decision);
+        if (decision.isInline()) {
+            if (inliningCache == null) {
+                graph = createInlineGraph(phaseContext, assumptions, null, decision);
+            } else {
+                graph = inliningCache.getCachedGraph(phaseContext, assumptions, decision);
+            }
+            decision.getProfile().setGraalDeepNodeCount(graph.getNodeCount());
         } else {
-            graph = inliningCache.getCachedGraph(phaseContext, assumptions, decision);
+            graph = parseGraph(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), assumptions, phaseContext);
         }
 
-        decision.getProfile().setGraalDeepNodeCount(graph.getNodeCount());
-
         return graph;
     }
 
@@ -320,12 +334,12 @@
         StructuredGraph inlineGraph = truffleCache.createInlineGraph(target.toString());
         injectConstantCallTarget(inlineGraph, decision.getTarget(), phaseContext);
         expandTree(inlineGraph, assumptions);
-        expandCallBoundaries(inlineGraph, assumptions, cache, decision);
+        expandDirectCalls(inlineGraph, assumptions, cache, decision);
         return inlineGraph;
     }
 
     private OptimizedDirectCallNode resolveConstantCallNode(MethodCallTargetNode methodCallTargetNode) {
-        if (methodCallTargetNode.targetMethod().getAnnotation(TruffleCallBoundary.class) == null) {
+        if (!methodCallTargetNode.targetMethod().equals(callDirectMethod)) {
             return null;
         }
 
@@ -335,7 +349,7 @@
         }
 
         FrameState directCallState = invoke.stateAfter();
-        while (directCallState != null && directCallState.method() != directCallMethod) {
+        while (directCallState != null && directCallState.method() != callSiteProxyMethod) {
             directCallState = directCallState.outerFrameState();
         }
 
@@ -345,12 +359,12 @@
         }
 
         if (directCallState.values().isEmpty()) {
-            throw new AssertionError(String.format("Frame state of method '%s' is invalid.", directCallMethod.toString()));
+            throw new AssertionError(String.format("Frame state of method '%s' is invalid.", callDirectMethod.toString()));
         }
 
         ValueNode node = directCallState.values().get(0);
         if (!node.isConstant()) {
-            throw new AssertionError(String.format("Method argument for method '%s' is not constant.", directCallMethod.toString()));
+            throw new AssertionError(String.format("Method argument for method '%s' is not constant.", callDirectMethod.toString()));
         }
 
         Constant constantCallNode = node.asConstant();
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java	Wed Oct 01 19:45:05 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java	Wed Oct 01 19:45:11 2014 +0200
@@ -69,7 +69,7 @@
     private final ResolvedJavaType controlFlowExceptionClass;
 
     private final ResolvedJavaMethod callBoundaryMethod;
-    private final ResolvedJavaMethod inlineCallBoundaryMethod;
+    private final ResolvedJavaMethod callInlinedMethod;
 
     private long counter;
 
@@ -89,15 +89,11 @@
         } catch (NoSuchMethodException ex) {
             throw new RuntimeException(ex);
         }
-        try {
-            inlineCallBoundaryMethod = providers.getMetaAccess().lookupJavaMethod(OptimizedCallTarget.class.getDeclaredMethod("callRoot", Object[].class));
-        } catch (NoSuchMethodException ex) {
-            throw new RuntimeException(ex);
-        }
+        this.callInlinedMethod = providers.getMetaAccess().lookupJavaMethod(OptimizedCallTarget.getCallInlinedMethod());
     }
 
     public StructuredGraph createInlineGraph(String name) {
-        StructuredGraph graph = new StructuredGraph(name, inlineCallBoundaryMethod);
+        StructuredGraph graph = new StructuredGraph(name, callInlinedMethod);
         new GraphBuilderPhase.Instance(providers.getMetaAccess(), config, TruffleCompilerImpl.Optimizations).apply(graph);
         return graph;
     }