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 }