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