The result of this "optimization" is that everytime the RootNode 1 case runs in compiled for it will deoptimize immediatly and then mements later compile again since nothing was changed.
Last active
August 3, 2017 14:53
-
-
Save arthurp/20d0643d5eb8aadc912640d372e87113 to your computer and use it in GitHub Desktop.
A small Truffle test program which demonstrates that Truffle will never include exception handlers in compiled code in some cases
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.singingwizard.exception; | |
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; | |
import com.oracle.truffle.api.RootCallTarget; | |
import com.oracle.truffle.api.Truffle; | |
import com.oracle.truffle.api.frame.VirtualFrame; | |
import com.oracle.truffle.api.nodes.RootNode; | |
public class ExceptionOnOnlyPath { | |
/** A simple exception which doesn't capture a stack. | |
*/ | |
final static class TestException extends RuntimeException { | |
@Override | |
public synchronized Throwable fillInStackTrace() { | |
return this; | |
} | |
} | |
///// A root node with an exception on the normal path, but throwsControlFlowException = false | |
// This case is optimized to an immediate deopt everytime it compiles, so it will repeatedly recompile. | |
// This case is shown in RootNode1_*.png. | |
@TruffleBoundary(allowInlining = true, throwsControlFlowException = false) | |
private static Object doAThing1() { | |
throw new TestException(); | |
} | |
private static RootNode createRootNode1() { | |
return new RootNode(null) { | |
@Override | |
public Object execute(VirtualFrame frame) { | |
try { | |
return doAThing1(); | |
} catch (RuntimeException e) { | |
return "Success"; | |
} | |
} | |
}; | |
} | |
///// A root node with an exception on the normal path, but throwsControlFlowException = true | |
// This case is optimized to as `return "Success"` since the exception handling is inlined instead of ignored. | |
// This case is shown in RootNode2_*.png. | |
@TruffleBoundary(allowInlining = true, throwsControlFlowException = true) | |
private static Object doAThing2() { | |
throw new TestException(); | |
} | |
private static RootNode createRootNode2() { | |
return new RootNode(null) { | |
@Override | |
public Object execute(VirtualFrame frame) { | |
try { | |
return doAThing2(); | |
} catch (RuntimeException e) { | |
return "Success"; | |
} | |
} | |
}; | |
} | |
///// A trivial test harness | |
private void runTest(RootNode n) { | |
RootCallTarget intTgt = Truffle.getRuntime().createCallTarget(n); | |
for (int i = 0; i < 10; i++) { | |
intTgt.call(); | |
} | |
} | |
public static void main(String[] args) { | |
ExceptionOnOnlyPath test = new ExceptionOnOnlyPath(); | |
System.out.println("throwsControlFlowException = false"); | |
test.runTest(createRootNode1()); | |
System.out.println("throwsControlFlowException = true"); | |
test.runTest(createRootNode2()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment