# HG changeset patch # User Andreas Woess # Date 1437354726 -7200 # Node ID 92e1be81876957b4e03639fd6099629ac502a500 # Parent 6670754e4bf3f9a8c243f14e2d61a0f0406cd7ce Truffle: add PE regression tests to prevent deoptimization on ControlFlowException diff -r 6670754e4bf3 -r 92e1be818769 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ControlFlowExceptionPartialEvaluationTest.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ControlFlowExceptionPartialEvaluationTest.java Mon Jul 20 02:48:57 2015 +0200 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ControlFlowExceptionPartialEvaluationTest.java Mon Jul 20 03:12:06 2015 +0200 @@ -24,7 +24,9 @@ import org.junit.*; +import com.oracle.graal.truffle.*; import com.oracle.graal.truffle.test.nodes.*; +import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; @@ -47,6 +49,21 @@ assertPartialEvalEquals("constant42", new RootTestNode(fd, "catchSlowPathAndControlFlowException", result)); } + @Test + public void catchControlFlowExceptionWithLoopExplosion() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new CatchControlFlowExceptionTestNode(new BlockTestNode(new ThrowControlFlowExceptionTestNode())); + assertPartialEvalEquals("constant42", new RootTestNode(fd, "catchControlFlowExceptionWithLoopExplosion", result)); + } + + @Test + public void catchControlFlowExceptionFromCall() { + Assume.assumeTrue(TruffleCompilerOptions.TruffleFunctionInlining.getValue()); + CallTarget callTarget = Truffle.getRuntime().createCallTarget(new RootTestNode(new FrameDescriptor(), "throwControlFlowException", new ThrowControlFlowExceptionTestNode())); + AbstractTestNode result = new CatchControlFlowExceptionTestNode(new CallTestNode(callTarget)); + assertPartialEvalEquals("constant42", new RootTestNode(new FrameDescriptor(), "catchControlFlowExceptionFromCall", result)); + } + public static class ThrowControlFlowExceptionTestNode extends AbstractTestNode { @Override public int execute(VirtualFrame frame) { @@ -94,4 +111,42 @@ return child.execute(frame); } } + + public static class BlockTestNode extends AbstractTestNode { + @Children private final AbstractTestNode[] statements; + + public BlockTestNode(AbstractTestNode... statements) { + this.statements = statements; + } + + @Override + public int execute(VirtualFrame frame) { + return executeSpecial(frame); + } + + /* + * A statically resolvable method, so that ExplodeLoop annotation is visible during parsing. + */ + @ExplodeLoop + private int executeSpecial(VirtualFrame frame) { + int result = 0; + for (AbstractTestNode statement : statements) { + result = statement.execute(frame); + } + return result; + } + } + + public static class CallTestNode extends AbstractTestNode { + @Child private DirectCallNode callNode; + + public CallTestNode(CallTarget callTarget) { + this.callNode = Truffle.getRuntime().createDirectCallNode(callTarget); + } + + @Override + public int execute(VirtualFrame frame) { + return (int) callNode.call(frame, new Object[0]); + } + } }