1/* 2 * Copyright (c) 2015, 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 24package compiler.whitebox; 25 26import sun.hotspot.WhiteBox; 27 28import java.lang.reflect.Constructor; 29import java.lang.reflect.Executable; 30import java.lang.reflect.Method; 31import java.util.concurrent.Callable; 32 33public enum SimpleTestCase implements CompilerWhiteBoxTest.TestCase { 34 /** constructor test case */ 35 CONSTRUCTOR_TEST(SimpleTestCaseHelper.CONSTRUCTOR, SimpleTestCaseHelper.CONSTRUCTOR_CALLABLE, false), 36 /** method test case */ 37 METHOD_TEST(SimpleTestCaseHelper.METHOD, SimpleTestCaseHelper.METHOD_CALLABLE, false), 38 /** static method test case */ 39 STATIC_TEST(SimpleTestCaseHelper.STATIC, SimpleTestCaseHelper.STATIC_CALLABLE, false), 40 /** OSR constructor test case */ 41 OSR_CONSTRUCTOR_TEST(SimpleTestCaseHelper.OSR_CONSTRUCTOR, SimpleTestCaseHelper.OSR_CONSTRUCTOR_CALLABLE, true), 42 /** OSR method test case */ 43 OSR_METHOD_TEST(SimpleTestCaseHelper.OSR_METHOD, SimpleTestCaseHelper.OSR_METHOD_CALLABLE, true), 44 /** OSR static method test case */ 45 OSR_STATIC_TEST(SimpleTestCaseHelper.OSR_STATIC, SimpleTestCaseHelper.OSR_STATIC_CALLABLE, true); 46 47 private final Executable executable; 48 private final Callable<Integer> callable; 49 private final boolean isOsr; 50 51 private SimpleTestCase(Executable executable, Callable<Integer> callable, 52 boolean isOsr) { 53 this.executable = executable; 54 this.callable = callable; 55 this.isOsr = isOsr; 56 } 57 58 @Override 59 public Executable getExecutable() { 60 return executable; 61 } 62 63 @Override 64 public Callable<Integer> getCallable() { 65 return callable; 66 } 67 68 @Override 69 public boolean isOsr() { 70 return isOsr; 71 } 72} 73 74 class SimpleTestCaseHelper { 75 76 public static final Callable<Integer> CONSTRUCTOR_CALLABLE 77 = new Callable<Integer>() { 78 @Override 79 public Integer call() throws Exception { 80 return new SimpleTestCaseHelper(1337).hashCode(); 81 } 82 }; 83 84 public static final Callable<Integer> METHOD_CALLABLE 85 = new Callable<Integer>() { 86 private final SimpleTestCaseHelper helper = new SimpleTestCaseHelper(); 87 88 @Override 89 public Integer call() throws Exception { 90 return helper.method(); 91 } 92 }; 93 94 public static final Callable<Integer> STATIC_CALLABLE 95 = new Callable<Integer>() { 96 @Override 97 public Integer call() throws Exception { 98 return staticMethod(); 99 } 100 }; 101 102 public static final Callable<Integer> OSR_CONSTRUCTOR_CALLABLE 103 = new Callable<Integer>() { 104 @Override 105 public Integer call() throws Exception { 106 return new SimpleTestCaseHelper(null, CompilerWhiteBoxTest.BACKEDGE_THRESHOLD).hashCode(); 107 } 108 }; 109 110 public static final Callable<Integer> OSR_METHOD_CALLABLE 111 = new Callable<Integer>() { 112 private final SimpleTestCaseHelper helper = new SimpleTestCaseHelper(); 113 114 @Override 115 public Integer call() throws Exception { 116 return helper.osrMethod(CompilerWhiteBoxTest.BACKEDGE_THRESHOLD); 117 } 118 }; 119 120 public static final Callable<Integer> OSR_STATIC_CALLABLE 121 = new Callable<Integer>() { 122 @Override 123 public Integer call() throws Exception { 124 return osrStaticMethod(CompilerWhiteBoxTest.BACKEDGE_THRESHOLD); 125 } 126 }; 127 128 public static final Constructor CONSTRUCTOR; 129 public static final Constructor OSR_CONSTRUCTOR; 130 public static final Method METHOD; 131 public static final Method STATIC; 132 public static final Method OSR_METHOD; 133 public static final Method OSR_STATIC; 134 135 static { 136 try { 137 CONSTRUCTOR = SimpleTestCaseHelper.class.getDeclaredConstructor(int.class); 138 } catch (NoSuchMethodException | SecurityException e) { 139 throw new RuntimeException( 140 "exception on getting method Helper.<init>(int)", e); 141 } 142 try { 143 OSR_CONSTRUCTOR = SimpleTestCaseHelper.class.getDeclaredConstructor( 144 Object.class, long.class); 145 } catch (NoSuchMethodException | SecurityException e) { 146 throw new RuntimeException( 147 "exception on getting method Helper.<init>(Object, long)", e); 148 } 149 METHOD = getMethod("method"); 150 STATIC = getMethod("staticMethod"); 151 OSR_METHOD = getMethod("osrMethod", long.class); 152 OSR_STATIC = getMethod("osrStaticMethod", long.class); 153 } 154 155 private static Method getMethod(String name, Class<?>... parameterTypes) { 156 try { 157 return SimpleTestCaseHelper.class.getDeclaredMethod(name, parameterTypes); 158 } catch (NoSuchMethodException | SecurityException e) { 159 throw new RuntimeException( 160 "exception on getting method Helper." + name, e); 161 } 162 } 163 164 private static int staticMethod() { 165 return 1138; 166 } 167 168 private int method() { 169 return 42; 170 } 171 172 /** 173 * Deoptimizes all non-osr versions of the given executable after 174 * compilation finished. 175 * 176 * @param e Executable 177 * @throws Exception 178 */ 179 private static void waitAndDeoptimize(Executable e) { 180 CompilerWhiteBoxTest.waitBackgroundCompilation(e); 181 if (WhiteBox.getWhiteBox().isMethodQueuedForCompilation(e)) { 182 throw new RuntimeException(e + " must not be in queue"); 183 } 184 // Deoptimize non-osr versions of executable 185 WhiteBox.getWhiteBox().deoptimizeMethod(e, false); 186 } 187 188 /** 189 * Executes the method multiple times to make sure we have 190 * enough profiling information before triggering an OSR 191 * compilation. Otherwise the C2 compiler may add uncommon traps. 192 * 193 * @param m Method to be executed 194 * @return Number of times the method was executed 195 * @throws Exception 196 */ 197 private static int warmup(Method m) throws Exception { 198 waitAndDeoptimize(m); 199 SimpleTestCaseHelper helper = new SimpleTestCaseHelper(); 200 int result = 0; 201 for (long i = 0; i < CompilerWhiteBoxTest.THRESHOLD; ++i) { 202 result += (int)m.invoke(helper, 1); 203 } 204 // Wait to make sure OSR compilation is not blocked by 205 // non-OSR compilation in the compile queue 206 CompilerWhiteBoxTest.waitBackgroundCompilation(m); 207 return result; 208 } 209 210 /** 211 * Executes the constructor multiple times to make sure we 212 * have enough profiling information before triggering an OSR 213 * compilation. Otherwise the C2 compiler may add uncommon traps. 214 * 215 * @param c Constructor to be executed 216 * @return Number of times the constructor was executed 217 * @throws Exception 218 */ 219 private static int warmup(Constructor c) throws Exception { 220 waitAndDeoptimize(c); 221 int result = 0; 222 for (long i = 0; i < CompilerWhiteBoxTest.THRESHOLD; ++i) { 223 result += c.newInstance(null, 1).hashCode(); 224 } 225 // Wait to make sure OSR compilation is not blocked by 226 // non-OSR compilation in the compile queue 227 CompilerWhiteBoxTest.waitBackgroundCompilation(c); 228 return result; 229 } 230 231 private static int osrStaticMethod(long limit) throws Exception { 232 int result = 0; 233 if (limit != 1) { 234 result = warmup(OSR_STATIC); 235 } 236 // Trigger osr compilation 237 for (long i = 0; i < limit; ++i) { 238 result += staticMethod(); 239 } 240 return result; 241 } 242 243 private int osrMethod(long limit) throws Exception { 244 int result = 0; 245 if (limit != 1) { 246 result = warmup(OSR_METHOD); 247 } 248 // Trigger osr compilation 249 for (long i = 0; i < limit; ++i) { 250 result += method(); 251 } 252 return result; 253 } 254 255 private final int x; 256 257 // for method and OSR method test case 258 public SimpleTestCaseHelper() { 259 x = 0; 260 } 261 262 // for OSR constructor test case 263 private SimpleTestCaseHelper(Object o, long limit) throws Exception { 264 int result = 0; 265 if (limit != 1) { 266 result = warmup(OSR_CONSTRUCTOR); 267 } 268 // Trigger osr compilation 269 for (long i = 0; i < limit; ++i) { 270 result += method(); 271 } 272 x = result; 273 } 274 275 // for constructor test case 276 private SimpleTestCaseHelper(int x) { 277 this.x = x; 278 } 279 280 @Override 281 public int hashCode() { 282 return x; 283 } 284 } 285 286