changeset 18180:507093f8df35

add unittest for Truffle Assumptions cutting off branches. GRAAL-882
author Christian Wirth <christian.wirth@oracle.com>
date Tue, 28 Oct 2014 17:37:13 +0100
parents 37be28df9dd7
children d28acaa63680
files graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/AssumptionPartialEvaluationTest.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AssumptionCutsBranchTestNode.java
diffstat 3 files changed, 109 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- 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());
+    }
 }
--- 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);
--- /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;
+    }
+}