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.calls.common;
  25 
  26 import compiler.testlibrary.CompilerUtils;
  27 import jdk.test.lib.Asserts;
  28 import sun.hotspot.WhiteBox;
  29 
  30 import java.lang.reflect.Method;
  31 import java.util.Arrays;
  32 
  33 /**
  34  * A common class for Invoke* classes
  35  */
  36 public abstract class CallsBase {
  37     public static final String CALL_ERR_MSG = "Call insuccessfull";
  38     protected final Method calleeMethod;
  39     protected final Method callerMethod;
  40     protected final WhiteBox wb = WhiteBox.getWhiteBox();
  41     protected int compileCallee = -1;
  42     protected int compileCaller = -1;
  43     protected boolean nativeCallee = false;
  44     protected boolean nativeCaller = false;
  45     protected boolean calleeVisited = false;
  46     protected boolean checkCallerCompilationLevel;
  47     protected boolean checkCalleeCompilationLevel;
  48     protected int expectedCallerCompilationLevel;
  49     protected int expectedCalleeCompilationLevel;
  50 
  51     protected CallsBase() {
  52         try {
  53             callerMethod = getClass().getDeclaredMethod("caller");
  54             calleeMethod = getClass().getDeclaredMethod("callee",
  55                     getCalleeParametersTypes());
  56             wb.testSetDontInlineMethod(callerMethod, /* dontinline= */ true);
  57             wb.testSetDontInlineMethod(calleeMethod, /* dontinline= */ true);
  58         } catch (NoSuchMethodException e) {
  59             throw new Error("TEST BUG: can't find test method", e);
  60         }
  61     }
  62 
  63     /**
  64      * Provides callee parameters types to search method
  65      * @return array of types
  66      */
  67     protected Class[] getCalleeParametersTypes() {
  68         return new Class[] {int.class, long.class, float.class,
  69             double.class, String.class};
  70     }
  71 
  72     /**
  73      * Loads native library(libCallsNative.so)
  74      */
  75     protected static void loadNativeLibrary() {
  76         System.loadLibrary("CallsNative");
  77     }
  78 
  79     /**
  80      * Checks if requested compilation levels are inside of current vm capabilities
  81      * @return true if vm is capable of requested compilation levels
  82      */
  83     protected final boolean compilationLevelsSupported() {
  84         int[] compLevels = CompilerUtils.getAvailableCompilationLevels();
  85         boolean callerCompLevelSupported = compileCaller > 0
  86                 && Arrays.stream(compLevels)
  87                         .filter(elem -> elem == compileCaller)
  88                         .findAny()
  89                         .isPresent();
  90         boolean calleeCompLevelSupported = compileCallee > 0
  91                 && Arrays.stream(compLevels)
  92                         .filter(elem -> elem == compileCallee)
  93                         .findAny()
  94                         .isPresent();
  95         return callerCompLevelSupported && calleeCompLevelSupported;
  96     }
  97 
  98     /**
  99      * Parse test arguments
 100      * @param args test arguments
 101      */
 102     protected final void parseArgs(String args[]) {
 103         for (int i = 0; i < args.length; i++) {
 104             switch (args[i]) {
 105                 case "-nativeCallee":
 106                     nativeCallee = true;
 107                     break;
 108                 case "-nativeCaller":
 109                     nativeCaller = true;
 110                     break;
 111                 case "-compileCallee":
 112                     compileCallee = Integer.parseInt(args[++i]);
 113                     break;
 114                 case "-compileCaller":
 115                     compileCaller = Integer.parseInt(args[++i]);
 116                     break;
 117                 case "-checkCallerCompileLevel":
 118                     checkCallerCompilationLevel = true;
 119                     expectedCallerCompilationLevel = Integer.parseInt(args[++i]);
 120                     break;
 121                 case "-checkCalleeCompileLevel":
 122                     checkCalleeCompilationLevel = true;
 123                     expectedCalleeCompilationLevel = Integer.parseInt(args[++i]);
 124                     break;
 125                 default:
 126                     throw new Error("Can't parse test parameter:" + args[i]);
 127             }
 128         }
 129     }
 130 
 131     /**
 132      * Run basic logic of a test by doing compile
 133      * action(if needed). An arguments can be -compileCallee
 134      * $calleeCompilationLevel and/or -compileCaller $callerCompilationLevel
 135      * and/or -nativeCaller and/or -nativeCallee to indicate that native methods
 136      * for caller/callee should be used
 137      * @param args test args
 138      */
 139     protected final void runTest(String args[]) {
 140         parseArgs(args);
 141         if (compilationLevelsSupported()) {
 142             if (nativeCaller || nativeCallee) {
 143                 CallsBase.loadNativeLibrary();
 144             }
 145             Object lock = getLockObject();
 146             Asserts.assertNotNull(lock, "Lock object is null");
 147             /* a following lock is needed in case several instances of this
 148                test are launched in same vm */
 149             synchronized (lock) {
 150                 if (compileCaller > 0 || compileCallee > 0) {
 151                     caller(); // call once to have everything loaded
 152                     calleeVisited = false; // reset state
 153                 }
 154                 // compile with requested level if needed
 155                 if (compileCallee > 0) {
 156                     compileMethod(calleeMethod, compileCallee);
 157                 }
 158                 if (checkCalleeCompilationLevel) {
 159                     Asserts.assertEQ(expectedCalleeCompilationLevel,
 160                             wb.getMethodCompilationLevel(calleeMethod),
 161                             "Unexpected callee compilation level");
 162                 }
 163                 if (compileCaller > 0) {
 164                     compileMethod(callerMethod, compileCaller);
 165                 }
 166                 if (checkCallerCompilationLevel) {
 167                     Asserts.assertEQ(expectedCallerCompilationLevel,
 168                             wb.getMethodCompilationLevel(callerMethod),
 169                             "Unexpected caller compilation level");
 170                 }
 171                 // do calling work
 172                 if (nativeCaller) {
 173                     callerNative();
 174                 } else {
 175                     caller();
 176                 }
 177             }
 178         } else {
 179             System.out.println("WARNING: Requested compilation levels are "
 180                     + "out of current vm capabilities. Skipping.");
 181         }
 182     }
 183 
 184     /**
 185      * A method to compile another method, searching it by name in current class
 186      * @param method a method to compile
 187      * @param compLevel a compilation level
 188      */
 189     protected final void compileMethod(Method method, int compLevel) {
 190         wb.deoptimizeMethod(method);
 191         Asserts.assertTrue(wb.isMethodCompilable(method, compLevel));
 192         wb.enqueueMethodForCompilation(method, compLevel);
 193     }
 194 
 195     /*
 196      * @return Object to lock on during execution
 197      */
 198 
 199     protected abstract Object getLockObject();
 200 
 201     protected abstract void caller();
 202 
 203     protected abstract void callerNative();
 204 
 205     /**
 206      * A method checking values. Should be used to verify if all parameters are
 207      * passed as expected. Parameter N should have a value indicating number "N"
 208      * in respective type representation.
 209      */
 210     public static void checkValues(int param1, long param2, float param3,
 211             double param4, String param5) {
 212         Asserts.assertEQ(param1, 1);
 213         Asserts.assertEQ(param2, 2L);
 214         Asserts.assertEQ(param3, 3.0f);
 215         Asserts.assertEQ(param4, 4.0d);
 216         Asserts.assertEQ(param5, "5");
 217     }
 218 }