# HG changeset patch # User Christian Wirth # Date 1414514233 -3600 # Node ID 507093f8df35edb53341de0114a0acc485314aa2 # Parent 37be28df9dd7fdbbc3aecc470a99c955b80e470f add unittest for Truffle Assumptions cutting off branches. GRAAL-882 diff -r 37be28df9dd7 -r 507093f8df35 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/AssumptionPartialEvaluationTest.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/AssumptionPartialEvaluationTest.java Tue Oct 28 13:39:10 2014 +0100 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/AssumptionPartialEvaluationTest.java Tue Oct 28 17:37:13 2014 +0100 @@ -58,4 +58,21 @@ Assert.assertFalse(callTarget.isValid()); assertDeepEquals(43, callTarget.call()); } + + /** + * This tests whether a valid Assumption does successfully cut of the branch that is not + * executed. + */ + @Test + public void assumptionBranchCutoff() { + Assumption assumption = Truffle.getRuntime().createAssumption(); + AssumptionCutsBranchTestNode result = new AssumptionCutsBranchTestNode(assumption); + RootTestNode rootNode = new RootTestNode(new FrameDescriptor(), "cutoffBranch", result); + OptimizedCallTarget compilable = compileHelper("cutoffBranch", rootNode, new Object[0]); + + for (int i = 0; i < 100000; i++) { + Assert.assertEquals(0, compilable.call(new Object[0])); + } + Assert.assertNull(result.getChildNode()); + } } diff -r 37be28df9dd7 -r 507093f8df35 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Tue Oct 28 13:39:10 2014 +0100 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Tue Oct 28 17:37:13 2014 +0100 @@ -52,6 +52,14 @@ return assertPartialEvalEquals(methodName, root, new Object[0]); } + protected OptimizedCallTarget compileHelper(String methodName, RootNode root, Object[] arguments) { + Assumptions assumptions = new Assumptions(true); + final OptimizedCallTarget compilable = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(root); + StructuredGraph actual = partialEval(compilable, arguments, assumptions); + truffleCompiler.compileMethodHelper(actual, assumptions, methodName, getSpeculationLog(), compilable); + return compilable; + } + protected OptimizedCallTarget assertPartialEvalEquals(String methodName, RootNode root, Object[] arguments) { Assumptions assumptions = new Assumptions(true); final OptimizedCallTarget compilable = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(root); diff -r 37be28df9dd7 -r 507093f8df35 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AssumptionCutsBranchTestNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AssumptionCutsBranchTestNode.java Tue Oct 28 17:37:13 2014 +0100 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.truffle.test.nodes; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +@NodeInfo +public class AssumptionCutsBranchTestNode extends AbstractTestNode { + + private final Assumption assumption; + private int counter; + @Child private Node childNode; + + public AssumptionCutsBranchTestNode(Assumption assumption) { + this.assumption = assumption; + this.counter = 0; + } + + @Override + public int execute(VirtualFrame frame) { + int returnVal = 0; + if (!assumption.isValid()) { + // this branch should be cut off, thus the Assertion should not trigger + CompilerAsserts.neverPartOfCompilation("this branch should be cut off"); + + // execute some complicated but otherwise meaningless code + double sum = 0; + + if (Math.random() < 0.5) { + int iSum = 0; + for (int i = 0; i < 100; i++) { + if (Math.random() > 0.5) { + sum += Math.cos(Math.random()); + } else { + sum += Math.sin(Math.random()); + } + iSum += i * 2; + } + AssumptionCutsBranchTestNode node2 = new AssumptionCutsBranchTestNode(assumption); + node2.adoptChildren(); + childNode = node2.copy(); + + if (iSum % 2 != 0) { + // this is never executed, but introduces a potential invalidation + assumption.invalidate(); + } + } else { + sum = Math.random(); + } + + return Math.round(sum) % 100 == 0 && childNode.toString().contains("a") ? 666 : 777; + } else if (counter % 2 == 0) { + returnVal++; + } + counter++; + return returnVal % 2 == 0 ? returnVal : 0; // will always return 0 + } + + public Node getChildNode() { + return childNode; + } +}