changeset 14984:a5bebb69dc78

Truffle: instead of redirecting the call method. inlining is now performed by ignoring @SlowPath.
author Christian Humer <christian.humer@gmail.com>
date Sat, 05 Apr 2014 03:18:48 +0200
parents a31d807757ee
children cceed4ebedb9
files graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetImpl.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java
diffstat 6 files changed, 62 insertions(+), 62 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNode.java	Thu Apr 03 19:06:58 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNode.java	Sat Apr 05 03:18:48 2014 +0200
@@ -25,7 +25,7 @@
 import java.util.concurrent.atomic.*;
 
 import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.CompilerDirectives.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.impl.*;
 import com.oracle.truffle.api.nodes.*;
@@ -109,17 +109,6 @@
         inliningCounter.decrementAndGet();
     }
 
-    /**
-     * If the method was inlined the truffle magic redirects calls to
-     * {@link #call(PackedFrame, Arguments)} to this method. You should not call this method
-     * directly.
-     *
-     * @see PartialEvaluator#expandInlinableCallNode
-     */
-    public Object callInlined(PackedFrame caller, Arguments arguments) {
-        return getCurrentCallTarget().callInlined(caller, arguments);
-    }
-
     @Override
     public void inline() {
         inliningForced = true;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Thu Apr 03 19:06:58 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Sat Apr 05 03:18:48 2014 +0200
@@ -46,7 +46,7 @@
     protected InstalledCode installedCode;
     protected boolean compilationEnabled;
     protected int callCount;
-    private TruffleInliningResult inliningResult;
+    protected TruffleInliningResult inliningResult;
     protected final CompilationProfile compilationProfile;
     protected final CompilationPolicy compilationPolicy;
     private final SpeculationLog speculationLog = new SpeculationLog();
@@ -64,27 +64,27 @@
         }
     }
 
-    public int getKnownCallSiteCount() {
+    public final int getKnownCallSiteCount() {
         return callSitesKnown.get();
     }
 
-    public void incrementKnownCallSite() {
+    public final void incrementKnownCallSite() {
         callSitesKnown.incrementAndGet();
     }
 
-    public void decrementKnownCallSite() {
+    public final void decrementKnownCallSite() {
         callSitesKnown.decrementAndGet();
     }
 
-    public TruffleInliningResult getInliningResult() {
+    public final TruffleInliningResult getInliningResult() {
         return inliningResult;
     }
 
-    public OptimizedCallTarget getSplitSource() {
+    public final OptimizedCallTarget getSplitSource() {
         return splitSource;
     }
 
-    public void setSplitSource(OptimizedCallTarget splitSource) {
+    public final void setSplitSource(OptimizedCallTarget splitSource) {
         this.splitSource = splitSource;
     }
 
@@ -109,7 +109,7 @@
 
     public abstract InstalledCode compile();
 
-    public Object callInlined(PackedFrame caller, Arguments arguments) {
+    public final Object callInlined(PackedFrame caller, Arguments arguments) {
         if (CompilerDirectives.inInterpreter()) {
             compilationProfile.reportInlinedCall();
         }
@@ -161,7 +161,7 @@
 
     protected abstract void invalidate(Node oldNode, Node newNode, CharSequence reason);
 
-    public Object executeHelper(PackedFrame caller, Arguments args) {
+    public final Object executeHelper(PackedFrame caller, Arguments args) {
         VirtualFrame frame = createFrame(getRootNode().getFrameDescriptor(), caller, args);
         return getRootNode().execute(frame);
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetImpl.java	Thu Apr 03 19:06:58 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetImpl.java	Sat Apr 05 03:18:48 2014 +0200
@@ -51,7 +51,7 @@
     @CompilerDirectives.SlowPath
     @Override
     public Object call(PackedFrame caller, Arguments args) {
-        return callHelper(caller, args);
+        return CompilerDirectives.inInterpreter() ? callHelper(caller, args) : executeHelper(caller, args);
     }
 
     private Object callHelper(PackedFrame caller, Arguments args) {
@@ -90,6 +90,7 @@
         if (m != null) {
             CompilerAsserts.neverPartOfCompilation();
             installedCode = null;
+            inliningResult = null;
             compilationProfile.reportInvalidated();
             logOptimizedInvalidated(this, oldNode, newNode, reason);
         }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Thu Apr 03 19:06:58 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Sat Apr 05 03:18:48 2014 +0200
@@ -56,7 +56,6 @@
 import com.oracle.graal.truffle.phases.*;
 import com.oracle.graal.virtual.phases.ea.*;
 import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 
 /**
@@ -69,7 +68,6 @@
     private Set<Constant> constantReceivers;
     private final TruffleCache truffleCache;
     private final ResolvedJavaType frameType;
-    private final ResolvedJavaMethod callInlinedMethod;
 
     public PartialEvaluator(Providers providers, TruffleCache truffleCache) {
         this.providers = providers;
@@ -77,11 +75,6 @@
         this.canonicalizer = new CanonicalizerPhase(!ImmutableCode.getValue(), customCanonicalizer);
         this.truffleCache = truffleCache;
         this.frameType = providers.getMetaAccess().lookupJavaType(FrameWithoutBoxing.class);
-        try {
-            callInlinedMethod = providers.getMetaAccess().lookupJavaMethod(OptimizedCallNode.class.getDeclaredMethod("callInlined", PackedFrame.class, Arguments.class));
-        } catch (NoSuchMethodException ex) {
-            throw new RuntimeException(ex);
-        }
     }
 
     public StructuredGraph createGraph(final OptimizedCallTarget callTarget, final Assumptions assumptions) {
@@ -179,6 +172,7 @@
         if (TraceTruffleExpansion.getValue()) {
             expansionLogger = new TruffleExpansionLogger(graph);
         }
+        boolean inliningEnabled = target.getInliningResult() != null && target.getInliningResult().size() > 0;
         Map<Node, TruffleCallPath> methodTargetToStack = new HashMap<>();
         boolean changed;
         do {
@@ -205,18 +199,19 @@
                         }
 
                         StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod());
-
-                        if (inlineGraph == null) {
+                        if (inliningEnabled && inlineGraph == null) {
                             inlineGraph = expandInlinableCallNode(target, methodTargetToStack, assumptions, phaseContext, methodCallTargetNode);
                         }
 
                         if (inlineGraph == null && !Modifier.isNative(methodCallTargetNode.targetMethod().getModifiers())) {
-                            inlineGraph = parseGraph(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), assumptions, phaseContext);
+                            inlineGraph = parseGraph(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), assumptions, phaseContext, false);
                         }
 
                         if (inlineGraph != null) {
                             try (Indent indent = Debug.logAndIndent("inline graph %s", methodCallTargetNode.targetMethod())) {
-                                preExpandTruffleCallPath(inlineGraph, methodTargetToStack, methodTargetToStack.get(methodCallTargetNode));
+                                if (inliningEnabled) {
+                                    preExpandTruffleCallPath(inlineGraph, methodTargetToStack, methodTargetToStack.get(methodCallTargetNode));
+                                }
                                 int nodeCountBefore = graph.getNodeCount();
                                 Mark mark = graph.getMark();
                                 if (TraceTruffleExpansion.getValue()) {
@@ -228,14 +223,16 @@
                                 if (TraceTruffleExpansion.getValue()) {
                                     expansionLogger.postExpand(inlined);
                                 }
-                                postExpandTruffleCallPath(methodTargetToStack, inlined);
-                                // }
+                                if (inliningEnabled) {
+                                    postExpandTruffleCallPath(methodTargetToStack, inlined);
+                                }
                                 if (Debug.isDumpEnabled()) {
                                     Debug.log("dump enabled");
                                     int nodeCountAfter = graph.getNodeCount();
                                     Debug.dump(graph, "After inlining %s %+d (%d)", methodCallTargetNode.targetMethod().toString(), nodeCountAfter - nodeCountBefore, nodeCountAfter);
                                 }
                                 canonicalizer.applyIncremental(graph, phaseContext, invokeUsages, mark);
+
                                 changed = true;
                             }
                         }
@@ -270,49 +267,60 @@
 
     private StructuredGraph expandInlinableCallNode(OptimizedCallTarget target, Map<Node, TruffleCallPath> methodCallToCallPath, Assumptions assumptions, PhaseContext phaseContext,
                     MethodCallTargetNode methodCallTargetNode) {
+
         ValueNode receiverNode = methodCallTargetNode.receiver();
         if (receiverNode == null || !receiverNode.isConstant() || !receiverNode.asConstant().getKind().isObject()) {
             return null;
         }
-        Object receiverValue = receiverNode.asConstant().asObject();
-        if (!(receiverValue instanceof OptimizedCallNode)) {
-            return null;
-        }
 
         ResolvedJavaMethod method = methodCallTargetNode.targetMethod();
         if (!method.getName().equals("call") || method.getSignature().getParameterCount(false) != 2) {
             return null;
         }
-        assert method.getSignature().equals(callInlinedMethod.getSignature()) : "Signature of original and inlined method must match.";
 
-        OptimizedCallNode callNode = (OptimizedCallNode) receiverValue;
-        TruffleCallPath callPath = methodCallToCallPath.get(methodCallTargetNode);
-        if (callPath == null) {
-            callPath = new TruffleCallPath(target);
-        }
-        callPath = new TruffleCallPath(callPath, callNode);
+        Object receiverValue = receiverNode.asConstant().asObject();
+        if (receiverValue instanceof OptimizedCallNode) {
+            OptimizedCallNode callNode = (OptimizedCallNode) receiverValue;
+            TruffleCallPath callPath = methodCallToCallPath.get(methodCallTargetNode);
+            if (callPath == null) {
+                callPath = new TruffleCallPath(target);
+            }
+            callPath = new TruffleCallPath(callPath, callNode);
+            methodCallToCallPath.put(methodCallTargetNode, callPath);
+            // let the normal expansion do the work
+            return null;
+        } else if (receiverValue instanceof OptimizedCallTarget) {
+            TruffleCallPath path = methodCallToCallPath.get(methodCallTargetNode);
+            // path unknown. direct call to OptimizedCallTarget without OptimizedCallNode?
+            if (path == null) {
+                return null;
+            }
 
-        TruffleInliningResult decision = target.getInliningResult();
-        if (decision == null || !decision.isInlined(callPath)) {
-            // the call target decided not to inline this call
-            return null;
+            TruffleInliningResult decision = target.getInliningResult();
+            if (decision == null) { // no inlining decision. inlining disabled?
+                return null;
+            }
+
+            if (!decision.isInlined(path)) {
+                // the OptimizedCallTarget has decided not to inline this call path
+                return null;
+            }
+
+            // inline truffle call
+            return parseGraph(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), assumptions, phaseContext, true);
         }
 
-        // inline truffle call -> redirect OptimizedCallNode#ca to OptimizedCallNode#inlinedCall
-        StructuredGraph graph = parseGraph(callInlinedMethod, methodCallTargetNode.arguments(), assumptions, phaseContext);
-
-        methodCallToCallPath.put(methodCallTargetNode, callPath);
-
-        return graph;
+        return null;
     }
 
     private boolean isFrame(ValueNode receiver) {
         return receiver instanceof NewFrameNode || Objects.equals(ObjectStamp.typeOrNull(receiver.stamp()), frameType);
     }
 
-    private StructuredGraph parseGraph(final ResolvedJavaMethod targetMethod, final NodeInputList<ValueNode> arguments, final Assumptions assumptions, final PhaseContext phaseContext) {
+    private StructuredGraph parseGraph(final ResolvedJavaMethod targetMethod, final NodeInputList<ValueNode> arguments, final Assumptions assumptions, final PhaseContext phaseContext,
+                    boolean ignoreSlowPath) {
 
-        StructuredGraph graph = truffleCache.lookup(targetMethod, arguments, assumptions, canonicalizer);
+        StructuredGraph graph = truffleCache.lookup(targetMethod, arguments, assumptions, canonicalizer, ignoreSlowPath);
 
         if (graph != null && targetMethod.getAnnotation(ExplodeLoop.class) != null) {
             assert graph.hasLoops() : graph + " does not contain a loop";
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Thu Apr 03 19:06:58 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Sat Apr 05 03:18:48 2014 +0200
@@ -37,6 +37,7 @@
 
     /**
      * Returns a cached graph for a method with given arguments.
+     * @param ignoreSlowPath TODO
      */
-    StructuredGraph lookup(final ResolvedJavaMethod method, final NodeInputList<ValueNode> arguments, final Assumptions assumptions, final CanonicalizerPhase finalCanonicalizer);
+    StructuredGraph lookup(final ResolvedJavaMethod method, final NodeInputList<ValueNode> arguments, final Assumptions assumptions, final CanonicalizerPhase finalCanonicalizer, boolean ignoreSlowPath);
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java	Thu Apr 03 19:06:58 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java	Sat Apr 05 03:18:48 2014 +0200
@@ -89,9 +89,10 @@
     }
 
     @SuppressWarnings("unused")
-    public StructuredGraph lookup(final ResolvedJavaMethod method, final NodeInputList<ValueNode> arguments, final Assumptions assumptions, final CanonicalizerPhase finalCanonicalizer) {
+    public StructuredGraph lookup(final ResolvedJavaMethod method, final NodeInputList<ValueNode> arguments, final Assumptions assumptions, final CanonicalizerPhase finalCanonicalizer,
+                    boolean ignoreSlowPath) {
 
-        if (method.getAnnotation(CompilerDirectives.SlowPath.class) != null) {
+        if (!ignoreSlowPath && method.getAnnotation(CompilerDirectives.SlowPath.class) != null) {
             return null;
         }
 
@@ -236,7 +237,7 @@
     private void expandInvoke(MethodCallTargetNode methodCallTargetNode) {
         StructuredGraph inlineGraph = providers.getReplacements().getMethodSubstitution(methodCallTargetNode.targetMethod());
         if (inlineGraph == null) {
-            inlineGraph = TruffleCacheImpl.this.lookup(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), null, null);
+            inlineGraph = TruffleCacheImpl.this.lookup(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), null, null, false);
         }
         if (inlineGraph == this.markerGraph) {
             // Can happen for recursive calls.