# HG changeset patch # User Thomas Wuerthinger # Date 1397769381 -7200 # Node ID d59f48be0ed6a35ac78a2a1aa5d25b0189af05b3 # Parent ca250afc78ec0a5f5cb1e7dab82dee7e474bd7df Truffle: Speculate on the return type of calls. diff -r ca250afc78ec -r d59f48be0ed6 graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotFrameInstance.java --- 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); } diff -r ca250afc78ec -r d59f48be0ed6 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java --- 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 diff -r ca250afc78ec -r d59f48be0ed6 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java --- 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); diff -r ca250afc78ec -r d59f48be0ed6 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedDirectCallNode.java --- 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); } diff -r ca250afc78ec -r d59f48be0ed6 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedIndirectCallNode.java --- 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 diff -r ca250afc78ec -r d59f48be0ed6 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- 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. diff -r ca250afc78ec -r d59f48be0ed6 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 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(); diff -r ca250afc78ec -r d59f48be0ed6 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java --- 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, 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; }