001/* 002 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.truffle.test; 024 025import jdk.internal.jvmci.code.*; 026 027import org.junit.*; 028 029import com.oracle.graal.replacements.*; 030import com.oracle.graal.truffle.*; 031import com.oracle.graal.truffle.test.nodes.*; 032import com.oracle.truffle.api.frame.*; 033import com.oracle.truffle.api.nodes.*; 034 035public class SimplePartialEvaluationTest extends PartialEvaluationTest { 036 037 public static Object constant42() { 038 return 42; 039 } 040 041 @Test 042 public void constantValue() { 043 FrameDescriptor fd = new FrameDescriptor(); 044 AbstractTestNode result = new ConstantTestNode(42); 045 assertPartialEvalEquals("constant42", new RootTestNode(fd, "constantValue", result)); 046 } 047 048 @Test 049 public void addConstants() { 050 FrameDescriptor fd = new FrameDescriptor(); 051 AbstractTestNode result = new AddTestNode(new ConstantTestNode(40), new ConstantTestNode(2)); 052 assertPartialEvalEquals("constant42", new RootTestNode(fd, "addConstants", result)); 053 } 054 055 @Test 056 public void neverPartOfCompilationTest() { 057 FrameDescriptor fd = new FrameDescriptor(); 058 AbstractTestNode firstTree = new NeverPartOfCompilationTestNode(new ConstantTestNode(1), 2); 059 assertPartialEvalEquals("constant42", new RootTestNode(fd, "neverPartOfCompilationTest", firstTree)); 060 061 AbstractTestNode secondTree = new NeverPartOfCompilationTestNode(new ConstantTestNode(1), 1); 062 try { 063 assertPartialEvalEquals("constant42", new RootTestNode(fd, "neverPartOfCompilationTest", secondTree)); 064 Assert.fail("Expected verification error!"); 065 } catch (SourceStackTrace t) { 066 // Expected verification error occurred. 067 StackTraceElement[] trace = t.getStackTrace(); 068 Assert.assertTrue(trace[0].toString().startsWith("com.oracle.graal.truffle.test.nodes.NeverPartOfCompilationTestNode.execute(NeverPartOfCompilationTestNode.java:")); 069 Assert.assertTrue(trace[1].toString().startsWith("com.oracle.graal.truffle.test.nodes.RootTestNode.execute(RootTestNode.java:")); 070 } 071 } 072 073 @Test 074 public void nestedLoopExplosion() { 075 FrameDescriptor fd = new FrameDescriptor(); 076 AbstractTestNode result = new AddTestNode(new NestedExplodedLoopTestNode(5), new ConstantTestNode(17)); 077 assertPartialEvalEquals("constant42", new RootTestNode(fd, "nestedLoopExplosion", result)); 078 } 079 080 @Test 081 public void twoMergesLoopExplosion() { 082 FrameDescriptor fd = new FrameDescriptor(); 083 AbstractTestNode result = new AddTestNode(new TwoMergesExplodedLoopTestNode(5), new ConstantTestNode(37)); 084 assertPartialEvalEquals("constant42", new RootTestNode(fd, "nestedLoopExplosion", result)); 085 } 086 087 @Test 088 public void sequenceConstants() { 089 FrameDescriptor fd = new FrameDescriptor(); 090 AbstractTestNode result = new BlockTestNode(new AbstractTestNode[]{new ConstantTestNode(40), new ConstantTestNode(42)}); 091 assertPartialEvalEquals("constant42", new RootTestNode(fd, "sequenceConstants", result)); 092 } 093 094 @Test 095 public void localVariable() { 096 FrameDescriptor fd = new FrameDescriptor(); 097 AbstractTestNode result = new BlockTestNode(new AbstractTestNode[]{new StoreLocalTestNode("x", fd, new ConstantTestNode(42)), new LoadLocalTestNode("x", fd)}); 098 assertPartialEvalEquals("constant42", new RootTestNode(fd, "localVariable", result)); 099 } 100 101 @Test 102 public void longSequenceConstants() { 103 FrameDescriptor fd = new FrameDescriptor(); 104 int length = 40; 105 AbstractTestNode[] children = new AbstractTestNode[length]; 106 for (int i = 0; i < children.length; ++i) { 107 children[i] = new ConstantTestNode(42); 108 } 109 110 AbstractTestNode result = new BlockTestNode(children); 111 assertPartialEvalEquals("constant42", new RootTestNode(fd, "longSequenceConstants", result)); 112 } 113 114 @Test 115 public void longAddConstants() { 116 FrameDescriptor fd = new FrameDescriptor(); 117 AbstractTestNode result = new ConstantTestNode(2); 118 for (int i = 0; i < 20; ++i) { 119 result = new AddTestNode(result, new ConstantTestNode(2)); 120 } 121 assertPartialEvalEquals("constant42", new RootTestNode(fd, "longAddConstants", result)); 122 } 123 124 @Test 125 public void mixLocalAndAdd() { 126 FrameDescriptor fd = new FrameDescriptor(); 127 AbstractTestNode result = new BlockTestNode(new AbstractTestNode[]{new StoreLocalTestNode("x", fd, new ConstantTestNode(40)), 128 new StoreLocalTestNode("x", fd, new AddTestNode(new LoadLocalTestNode("x", fd), new ConstantTestNode(2))), new LoadLocalTestNode("x", fd)}); 129 assertPartialEvalEquals("constant42", new RootTestNode(fd, "mixLocalAndAdd", result)); 130 } 131 132 @Test 133 public void loop() { 134 FrameDescriptor fd = new FrameDescriptor(); 135 AbstractTestNode result = new BlockTestNode(new AbstractTestNode[]{new StoreLocalTestNode("x", fd, new ConstantTestNode(0)), 136 new LoopTestNode(7, new StoreLocalTestNode("x", fd, new AddTestNode(new LoadLocalTestNode("x", fd), new ConstantTestNode(6))))}); 137 assertPartialEvalEquals("constant42", new RootTestNode(fd, "loop", result)); 138 } 139 140 @Test 141 public void longLoop() { 142 FrameDescriptor fd = new FrameDescriptor(); 143 AbstractTestNode result = new BlockTestNode(new AbstractTestNode[]{new StoreLocalTestNode("x", fd, new ConstantTestNode(0)), 144 new LoopTestNode(42, new StoreLocalTestNode("x", fd, new AddTestNode(new LoadLocalTestNode("x", fd), new ConstantTestNode(1))))}); 145 RootTestNode rootNode = new RootTestNode(fd, "loop", result); 146 assertPartialEvalNoInvokes(rootNode); 147 assertPartialEvalEquals("constant42", rootNode); 148 } 149 150 @Test 151 public void lambda() { 152 FrameDescriptor fd = new FrameDescriptor(); 153 AbstractTestNode result = new LambdaTestNode(); 154 assertPartialEvalEquals("constant42", new RootTestNode(fd, "constantValue", result)); 155 } 156 157 @Test 158 public void allowedRecursion() { 159 /* Recursion depth just below the threshold that reports it as too deep recursion. */ 160 FrameDescriptor fd = new FrameDescriptor(); 161 AbstractTestNode result = new RecursionTestNode(PEGraphDecoder.Options.InliningDepthError.getValue() - 5); 162 assertPartialEvalEquals("constant42", new RootTestNode(fd, "allowedRecursion", result)); 163 } 164 165 @Test(expected = BailoutException.class) 166 public void tooDeepRecursion() { 167 /* Recursion depth just above the threshold that reports it as too deep recursion. */ 168 FrameDescriptor fd = new FrameDescriptor(); 169 AbstractTestNode result = new RecursionTestNode(PEGraphDecoder.Options.InliningDepthError.getValue()); 170 assertPartialEvalEquals("constant42", new RootTestNode(fd, "tooDeepRecursion", result)); 171 } 172 173 @Test 174 public void intrinsicStatic() { 175 /* 176 * The intrinsic for String.equals() is inlined early during bytecode parsing, because we 177 * call equals() on a value that has the static type String. 178 */ 179 FrameDescriptor fd = new FrameDescriptor(); 180 AbstractTestNode result = new StringEqualsNode("abc", "abf"); 181 RootNode rootNode = new RootTestNode(fd, "intrinsicStatic", result); 182 OptimizedCallTarget compilable = compileHelper("intrinsicStatic", rootNode, new Object[0]); 183 184 Assert.assertEquals(42, compilable.call(new Object[0])); 185 } 186 187 @Test 188 public void intrinsicVirtual() { 189 /* 190 * The intrinsic for String.equals() is inlined late during Truffle partial evaluation, 191 * because we call equals() on a value that has the static type Object, but during partial 192 * evaluation the more precise type String is known. 193 */ 194 FrameDescriptor fd = new FrameDescriptor(); 195 AbstractTestNode result = new ObjectEqualsNode("abc", "abf"); 196 RootNode rootNode = new RootTestNode(fd, "intrinsicVirtual", result); 197 OptimizedCallTarget compilable = compileHelper("intrinsicVirtual", rootNode, new Object[0]); 198 199 Assert.assertEquals(42, compilable.call(new Object[0])); 200 } 201}