changeset 15216:d59f48be0ed6

Truffle: Speculate on the return type of calls.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Thu, 17 Apr 2014 23:16:21 +0200
parents ca250afc78ec
children ec7d8b646b9f
files graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotFrameInstance.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedDirectCallNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedIndirectCallNode.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 8 files changed, 56 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotFrameInstance.java	Thu Apr 17 22:14:29 2014 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotFrameInstance.java	Thu Apr 17 23:16:21 2014 +0200
@@ -99,14 +99,14 @@
 
     /**
      * This class represents a frame that is taken from the
-     * {@link OptimizedDirectCallNode#callProxy(MaterializedFrameNotify, CallTarget, VirtualFrame, Object[], boolean)}
+     * {@link OptimizedDirectCallNode#callProxy(MaterializedFrameNotify, CallTarget, VirtualFrame, Object[], boolean, boolean)}
      * method.
      */
     public static final class CallNodeFrame extends HotSpotFrameInstance {
         public static final Method METHOD;
         static {
             try {
-                METHOD = OptimizedDirectCallNode.class.getDeclaredMethod("callProxy", MaterializedFrameNotify.class, CallTarget.class, VirtualFrame.class, Object[].class, boolean.class);
+                METHOD = OptimizedDirectCallNode.class.getDeclaredMethod("callProxy", MaterializedFrameNotify.class, CallTarget.class, VirtualFrame.class, Object[].class, boolean.class, boolean.class);
             } catch (NoSuchMethodException | SecurityException e) {
                 throw new GraalInternalError(e);
             }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java	Thu Apr 17 22:14:29 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java	Thu Apr 17 23:16:21 2014 +0200
@@ -45,10 +45,11 @@
     public FrameWithoutBoxing(FrameDescriptor descriptor, Object[] arguments) {
         this.descriptor = descriptor;
         this.arguments = arguments;
-        this.locals = new Object[descriptor.getSize()];
+        int size = descriptor.getSize();
+        this.locals = new Object[size];
         Arrays.fill(locals, descriptor.getTypeConversion().getDefaultValue());
-        this.primitiveLocals = new long[descriptor.getSize()];
-        this.tags = new byte[descriptor.getSize()];
+        this.primitiveLocals = new long[size];
+        this.tags = new byte[size];
     }
 
     @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Thu Apr 17 22:14:29 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Thu Apr 17 23:16:21 2014 +0200
@@ -32,6 +32,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.debug.*;
 import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 
@@ -50,6 +51,8 @@
     protected final CompilationPolicy compilationPolicy;
     private OptimizedCallTarget splitSource;
     private final AtomicInteger callSitesKnown = new AtomicInteger(0);
+    @CompilationFinal private Class<?> profiledReturnType;
+    @CompilationFinal private Assumption profiledReturnTypeAssumption;
 
     private final RootNode rootNode;
 
@@ -57,6 +60,17 @@
         return rootNode;
     }
 
+    public Class<?> getProfiledReturnType() {
+        Class<?> result = profiledReturnType;
+        if (result != null) {
+            try {
+                profiledReturnTypeAssumption.check();
+            } catch (InvalidAssumptionException e) {
+            }
+        }
+        return result;
+    }
+
     public OptimizedCallTarget(RootNode rootNode, GraalTruffleRuntime runtime, int invokeCounter, int compilationThreshold, CompilationPolicy compilationPolicy, SpeculationLog speculationLog) {
         this.runtime = runtime;
         this.speculationLog = speculationLog;
@@ -83,11 +97,13 @@
     private Object callBoundary(Object[] args) {
         if (CompilerDirectives.inInterpreter()) {
             // We are called and we are still in Truffle interpreter mode.
+            CompilerDirectives.transferToInterpreter();
             interpreterCall();
         } else {
             // We come here from compiled code (i.e., we have been inlined).
         }
-        return executeHelper(args);
+
+        return callRoot(args);
     }
 
     @Override
@@ -198,7 +214,8 @@
         if (CompilerDirectives.inInterpreter()) {
             compilationProfile.reportInlinedCall();
         }
-        return executeHelper(arguments);
+        VirtualFrame frame = createFrame(getRootNode().getFrameDescriptor(), arguments);
+        return callProxy(frame);
     }
 
     public final void performInlining() {
@@ -228,19 +245,30 @@
         }
     }
 
-    public final Object executeHelper(Object[] args) {
+    public final Object callRoot(Object[] args) {
         VirtualFrame frame = createFrame(getRootNode().getFrameDescriptor(), args);
-        return callProxy(frame);
+        Object result = callProxy(frame);
+
+        // Profile call return type
+        if (profiledReturnTypeAssumption == null) {
+            CompilerDirectives.transferToInterpreter();
+            profiledReturnType = result.getClass();
+            profiledReturnTypeAssumption = Truffle.getRuntime().createAssumption("Profiled Return Type");
+        } else if (profiledReturnType != null) {
+            if (result == null || profiledReturnType != result.getClass()) {
+                CompilerDirectives.transferToInterpreter();
+                profiledReturnType = null;
+                profiledReturnTypeAssumption.invalidate();
+            }
+        }
+
+        return result;
     }
 
     public static FrameWithoutBoxing createFrame(FrameDescriptor descriptor, Object[] args) {
         return new FrameWithoutBoxing(descriptor, args);
     }
 
-    public static FrameWithoutBoxing createMaterializedFrame(FrameDescriptor descriptor, Object[] args) {
-        return new FrameWithoutBoxing(descriptor, args);
-    }
-
     @Override
     public void reportLoopCount(int count) {
         compilationProfile.reportLoopCount(count);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedDirectCallNode.java	Thu Apr 17 22:14:29 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedDirectCallNode.java	Thu Apr 17 23:16:21 2014 +0200
@@ -51,16 +51,23 @@
         if (CompilerDirectives.inInterpreter()) {
             onInterpreterCall();
         }
-        return callProxy(this, getCurrentCallTarget(), frame, arguments, inlined);
+        return callProxy(this, getCurrentCallTarget(), frame, arguments, inlined, true);
     }
 
-    public static Object callProxy(MaterializedFrameNotify notify, CallTarget callTarget, VirtualFrame frame, Object[] arguments, boolean inlined) {
+    public static Object callProxy(MaterializedFrameNotify notify, CallTarget callTarget, VirtualFrame frame, Object[] arguments, boolean inlined, boolean direct) {
         try {
             if (notify.getOutsideFrameAccess() != FrameAccess.NONE) {
                 CompilerDirectives.materialize(frame);
             }
             if (inlined) {
                 return ((OptimizedCallTarget) callTarget).callInlined(arguments);
+            } else if (direct) {
+                Object result = ((OptimizedCallTarget) callTarget).call(arguments);
+                Class<?> klass = ((OptimizedCallTarget) callTarget).getProfiledReturnType();
+                if (klass != null) {
+                    result = CompilerDirectives.unsafeCast(result, klass, true, true);
+                }
+                return result;
             } else {
                 return callTarget.call(arguments);
             }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedIndirectCallNode.java	Thu Apr 17 22:14:29 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedIndirectCallNode.java	Thu Apr 17 23:16:21 2014 +0200
@@ -37,7 +37,7 @@
 
     @Override
     public Object call(VirtualFrame frame, CallTarget target, Object[] arguments) {
-        return OptimizedDirectCallNode.callProxy(this, target, frame, arguments, false);
+        return OptimizedDirectCallNode.callProxy(this, target, frame, arguments, false, false);
     }
 
     @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Thu Apr 17 22:14:29 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Thu Apr 17 23:16:21 2014 +0200
@@ -32,7 +32,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.debug.internal.*;
@@ -114,11 +113,6 @@
             // Intrinsify methods.
             new ReplaceIntrinsicsPhase(providers.getReplacements()).apply(graph);
 
-            NewFrameNode newFrameNode = graph.getNodes(NewFrameNode.class).first();
-            if (newFrameNode == null) {
-                throw GraalInternalError.shouldNotReachHere("frame not found");
-            }
-
             Debug.dump(graph, "Before inlining");
 
             // Make sure frame does not escape.
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Thu Apr 17 22:14:29 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Thu Apr 17 23:16:21 2014 +0200
@@ -31,7 +31,7 @@
 public interface TruffleCache {
 
     /**
-     * Creates the graph for the root method, i.e. {@link OptimizedCallTarget#executeHelper}.
+     * Creates the graph for the root method, i.e. {@link OptimizedCallTarget#callBoundary}.
      */
     StructuredGraph createRootGraph();
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java	Thu Apr 17 22:14:29 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java	Thu Apr 17 23:16:21 2014 +0200
@@ -65,7 +65,7 @@
     private final HashMap<List<Object>, Long> lastUsed = new HashMap<>();
     private final StructuredGraph markerGraph = new StructuredGraph();
     private final ResolvedJavaType stringBuilderClass;
-    private final ResolvedJavaMethod executeHelperMethod;
+    private final ResolvedJavaMethod callBoundaryMethod;
     private long counter;
 
     public TruffleCacheImpl(Providers providers, GraphBuilderConfiguration config, GraphBuilderConfiguration configForRootGraph, OptimisticOptimizations optimisticOptimizations) {
@@ -75,14 +75,14 @@
         this.optimisticOptimizations = optimisticOptimizations;
         this.stringBuilderClass = providers.getMetaAccess().lookupJavaType(StringBuilder.class);
         try {
-            executeHelperMethod = providers.getMetaAccess().lookupJavaMethod(OptimizedCallTarget.class.getDeclaredMethod("executeHelper", Object[].class));
+            callBoundaryMethod = providers.getMetaAccess().lookupJavaMethod(OptimizedCallTarget.class.getDeclaredMethod("callRoot", Object[].class));
         } catch (NoSuchMethodException ex) {
             throw new RuntimeException(ex);
         }
     }
 
     public StructuredGraph createRootGraph() {
-        StructuredGraph graph = new StructuredGraph(executeHelperMethod);
+        StructuredGraph graph = new StructuredGraph(callBoundaryMethod);
         new GraphBuilderPhase.Instance(providers.getMetaAccess(), configForRootGraph, TruffleCompilerImpl.Optimizations).apply(graph);
         return graph;
     }