1 /* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 // TODO add bugid and summary 25 26 /* 27 * @test 28 * @library /testlibrary /test/lib /compiler/whitebox / 29 * @build compiler.valhalla.valuetypes.ValueTypeTestBench 30 * @run main ClassFileInstaller sun.hotspot.WhiteBox 31 * @run main ClassFileInstaller jdk.test.lib.Platform 32 * @run main/othervm -noverify -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI 33 * compiler.valhalla.valuetypes.ValueTypeTestBench 34 */ 35 36 package compiler.valhalla.valuetypes; 37 38 import compiler.whitebox.CompilerWhiteBoxTest; 39 import jdk.internal.misc.Unsafe; 40 import jdk.test.lib.Asserts; 41 import jdk.test.lib.Platform; 42 import jdk.test.lib.ProcessTools; 43 import jdk.test.lib.OutputAnalyzer; 44 import sun.hotspot.WhiteBox; 45 46 import java.lang.annotation.Retention; 47 import java.lang.annotation.RetentionPolicy; 48 import java.lang.reflect.Method; 49 import java.util.ArrayList; 50 import java.util.Hashtable; 51 52 @Retention(RetentionPolicy.RUNTIME) 53 @interface Test { 54 String[] nodeBlacklist() default {}; 55 } 56 57 @Retention(RetentionPolicy.RUNTIME) 58 @interface ForceInline { } 59 60 @Retention(RetentionPolicy.RUNTIME) 61 @interface DontInline { } 62 63 @Retention(RetentionPolicy.RUNTIME) 64 @interface Exclude { } 65 66 public class ValueTypeTestBench { 67 private static final boolean PRINT_GRAPH = true; 68 private static final String ALLOC = "_new_instance_Java"; 69 private static final String LOADI = "LoadI"; 70 private static final String LOADL = "LoadL"; 71 private static final String LOADD = "LoadD"; 72 73 // ========== Test definitions ========== 74 75 @Test(nodeBlacklist = {ALLOC}) 76 public long test1() { 77 MyValue v = MyValue.createDontInline(1, 2, 3); 78 return v.x + v.y + (long) v.z; 79 } 80 81 @Exclude 82 public void test1_verifier() { 83 long result = test1(); 84 Asserts.assertEQ(result, 6L); 85 } 86 87 @Test(nodeBlacklist = {ALLOC, LOADI, LOADL, LOADD}) 88 public long test2() { 89 MyValue v = MyValue.createInline(1, 2, 3); 90 return v.x + v.y + (long) v.z; 91 } 92 93 @Exclude 94 public void test2_verifier() { 95 long result = test2(); 96 Asserts.assertEQ(result, 6L); 97 } 98 99 @Test(nodeBlacklist = {ALLOC}) 100 public long test3(MyValue v) { 101 return v.x + v.y + (long) v.z; 102 } 103 104 @Exclude 105 public void test3_verifier() { 106 MyValue v = MyValue.createDontInline(1, 2, 3); 107 long result = test3(v); 108 Asserts.assertEQ(result, 6L); 109 } 110 111 @Test(nodeBlacklist = {ALLOC, LOADI, LOADL, LOADD}) 112 public MyValue test4(MyValue v) { 113 return v; 114 } 115 116 @Exclude 117 public void test4_verifier() { 118 MyValue v1 = MyValue.createDontInline(1, 2, 3); 119 MyValue v2 = test4(v1); 120 Asserts.assertEQ(v1.x, v2.x); 121 Asserts.assertEQ(v1.y, v2.y); 122 Asserts.assertEQ(v1.z, v2.z); 123 } 124 125 @Test(nodeBlacklist = {ALLOC, LOADI, LOADL, LOADD}) 126 public long test5() { 127 MyValue v = MyValue.createInline(1, 2, 3); 128 return test5Inline(v); 129 } 130 131 @ForceInline 132 public long test5Inline(MyValue v) { 133 return v.x + v.y + (long) v.z; 134 } 135 136 @Exclude 137 public void test5_verifier() { 138 long result = test5(); 139 Asserts.assertEQ(result, 6L); 140 } 141 142 @Test(nodeBlacklist = {LOADI, LOADL, LOADD}) 143 public MyValue test6(int x, long y, double z) { 144 return MyValue.createInline(x, y, z); 145 } 146 147 @Exclude 148 public void test6_verifier() { 149 MyValue v = test6(1, 2, 3); 150 long result = v.x + v.y + (long) v.z; 151 Asserts.assertEQ(result, 6L); 152 } 153 154 155 // ========== Test infrastructure ========== 156 157 private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); 158 private static final int COMP_LEVEL_ANY = -1; 159 private static final int COMP_LEVEL_FULL_OPTIMIZATION = 4; 160 private static final Hashtable<String, Method> tests = new Hashtable<String, Method>(); 161 private static final int WARMUP = 10; 162 163 static { 164 for (Method m : ValueTypeTestBench.class.getDeclaredMethods()) { 165 if (m.isAnnotationPresent(Test.class)) { 166 tests.put(m.getName(), m); 167 } 168 } 169 } 170 171 public static void main(String[] args) throws Throwable { 172 if (args.length == 0) { 173 OutputAnalyzer oa = ProcessTools.executeTestJvm("-noverify", 174 "-XX:+UnlockDiagnosticVMOptions", "-Xbootclasspath/a:.", "-XX:+WhiteBoxAPI", 175 "-XX:-TieredCompilation", "-XX:-BackgroundCompilation", "-XX:-UseOnStackReplacement", 176 "-XX:CompileCommand=quiet", "-XX:+PrintCompilation", "-XX:+PrintIdeal", 177 "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.ValueTypeTestBench::*", 178 "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.MyValue::*", 179 ValueTypeTestBench.class.getName(), "run"); 180 String output = oa.getOutput(); 181 oa.shouldHaveExitValue(0); 182 parseOutput(output); 183 } else { 184 ValueTypeTestBench bench = new ValueTypeTestBench(); 185 bench.run(); 186 } 187 } 188 189 public static void parseOutput(String output) throws Exception { 190 String split = ValueTypeTestBench.class.getCanonicalName() + "::"; 191 for (String graph : output.split(split)) { 192 String[] lines = graph.split("\\n"); 193 String testName = lines[0].split(" ")[0]; 194 Method test = tests.get(testName); 195 if (test == null) { 196 // Skip helper methods 197 continue; 198 } 199 Test anno = test.getAnnotation(Test.class); 200 String[] blacklist = anno.nodeBlacklist(); 201 for (String black : blacklist) { 202 if (graph.contains(black)) { 203 System.out.println("\nGraph for " + graph); 204 throw new RuntimeException("Graph for test '" + testName + "' contains blacklisted node '" + black + "' "); 205 } 206 } 207 if (PRINT_GRAPH) { 208 System.out.println("\nGraph for " + graph); 209 } 210 tests.remove(testName); 211 System.out.println(testName + " passed"); 212 } 213 // Check if all tests were compiled 214 if (tests.size() != 0) { 215 for (String name : tests.keySet()) { 216 System.out.println("Test '" + name + "' not compiled!"); 217 } 218 throw new RuntimeException("Not all tests were compiled"); 219 } 220 } 221 222 public void setup(Method[] methods) { 223 for (Method m : methods) { 224 if (m.isAnnotationPresent(Test.class)) { 225 // Don't inline tests 226 WHITE_BOX.testSetDontInlineMethod(m, true); 227 } 228 if (m.isAnnotationPresent(Exclude.class)) { 229 WHITE_BOX.makeMethodNotCompilable(m, COMP_LEVEL_ANY, true); 230 WHITE_BOX.makeMethodNotCompilable(m, COMP_LEVEL_ANY, false); 231 } 232 if (m.isAnnotationPresent(ForceInline.class)) { 233 WHITE_BOX.testSetForceInlineMethod(m, true); 234 } else if (m.isAnnotationPresent(DontInline.class)) { 235 WHITE_BOX.testSetDontInlineMethod(m, true); 236 } 237 } 238 } 239 240 public void run() throws Exception { 241 setup(this.getClass().getDeclaredMethods()); 242 setup(MyValue.class.getDeclaredMethods()); 243 244 // Execute tests 245 for (Method test : tests.values()) { 246 Method verifier = getClass().getDeclaredMethod(test.getName() + "_verifier"); 247 // Warmup using verifier method 248 for (int i = 0; i < WARMUP; ++i) { 249 verifier.invoke(this); 250 } 251 // Trigger compilation 252 WHITE_BOX.enqueueMethodForCompilation(test, COMP_LEVEL_FULL_OPTIMIZATION); 253 // Check result 254 verifier.invoke(this); 255 } 256 } 257 } 258 259 __ByValue final class MyValue { 260 final int x; 261 final long y; 262 final double z; 263 264 private MyValue(int x, long y, double z) { 265 this.x = x; 266 this.y = y; 267 this.z = z; 268 } 269 270 @DontInline 271 public static MyValue createDontInline(int x, long y, double z) { 272 return __Make MyValue(x, y, z); 273 } 274 275 @ForceInline 276 public static MyValue createInline(int x, long y, double z) { 277 return __Make MyValue(x, y, z); 278 } 279 }