Skip to content

Instantly share code, notes, and snippets.

@arthurp
Last active August 3, 2017 14:53
Show Gist options
  • Save arthurp/20d0643d5eb8aadc912640d372e87113 to your computer and use it in GitHub Desktop.
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

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.

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