1 /*
   2  * Copyright (c) 2013, 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 import jdk.test.lib.Platform;
  25 
  26 import java.io.FileOutputStream;
  27 import java.lang.reflect.Executable;
  28 import java.util.Properties;
  29 
  30 import compiler.whitebox.CompilerWhiteBoxTest;
  31 import compiler.testlibrary.intrinsics.Verifier;
  32 
  33 public abstract class IntrinsicBase extends CompilerWhiteBoxTest {
  34     protected String javaVmName;
  35     protected String useMathExactIntrinsics;
  36 
  37     protected IntrinsicBase(TestCase testCase) {
  38         super(testCase);
  39         javaVmName = System.getProperty("java.vm.name");
  40         useMathExactIntrinsics = getVMOption("UseMathExactIntrinsics");
  41     }
  42 
  43     @Override
  44     protected void test() throws Exception {
  45         //java.lang.Math should be loaded to allow a compilation of the methods that use Math's method
  46         System.out.println("class java.lang.Math should be loaded. Proof: " + Math.class);
  47         printEnvironmentInfo();
  48 
  49         int expectedIntrinsicCount = 0;
  50 
  51         switch (MODE) {
  52             case "compiled mode":
  53             case "mixed mode":
  54                 if (isServerVM()) {
  55                     if (TIERED_COMPILATION) {
  56                         int max_level = TIERED_STOP_AT_LEVEL;
  57                         expectedIntrinsicCount = (max_level == COMP_LEVEL_MAX) ? 1 : 0;
  58                         for (int i = CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE; i <= max_level; ++i) {
  59                             deoptimize();
  60                             compileAtLevel(i);
  61                         }
  62                     } else {
  63                         expectedIntrinsicCount = 1;
  64                         deoptimize();
  65                         compileAtLevel(CompilerWhiteBoxTest.COMP_LEVEL_MAX);
  66                     }
  67                 } else {
  68                     deoptimize();
  69                     compileAtLevel(CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE);
  70                 }
  71 
  72                 if (!isIntrinsicAvailable()) {
  73                     expectedIntrinsicCount = 0;
  74                 }
  75                 break;
  76             case "interpreted mode": //test is not applicable in this mode;
  77                 System.err.println("Warning: This test is not applicable in mode: " + MODE);
  78                 break;
  79             default:
  80                 throw new RuntimeException("Test bug, unknown VM mode: " + MODE);
  81         }
  82 
  83         System.out.println("Expected intrinsic count is " + expectedIntrinsicCount + " name " + getIntrinsicId());
  84 
  85         final FileOutputStream out = new FileOutputStream(getVMOption("LogFile") + Verifier.PROPERTY_FILE_SUFFIX);
  86         Properties expectedProps = new Properties();
  87         expectedProps.setProperty(Verifier.INTRINSIC_NAME_PROPERTY, getIntrinsicId());
  88         expectedProps.setProperty(Verifier.INTRINSIC_EXPECTED_COUNT_PROPERTY, String.valueOf(expectedIntrinsicCount));
  89         expectedProps.store(out, null);
  90 
  91         out.close();
  92     }
  93 
  94     protected void printEnvironmentInfo() {
  95         System.out.println("java.vm.name=" + javaVmName);
  96         System.out.println("os.arch=" + Platform.getOsArch());
  97         System.out.println("java.vm.info=" + MODE);
  98         System.out.println("useMathExactIntrinsics=" + useMathExactIntrinsics);
  99     }
 100 
 101     protected void compileAtLevel(int level) {
 102         WHITE_BOX.enqueueMethodForCompilation(method, level);
 103         waitBackgroundCompilation();
 104         checkCompilation(method, level);
 105     }
 106 
 107     protected void checkCompilation(Executable executable, int level) {
 108         if (!WHITE_BOX.isMethodCompiled(executable)) {
 109             throw new RuntimeException("Test bug, expected compilation (level): " + level + ", but not compiled");
 110         }
 111         final int compilationLevel = WHITE_BOX.getMethodCompilationLevel(executable);
 112         if (compilationLevel != level) {
 113             if (!(TIERED_COMPILATION && level == COMP_LEVEL_FULL_PROFILE && compilationLevel == COMP_LEVEL_LIMITED_PROFILE)) { //possible case
 114                 throw new RuntimeException("Test bug, expected compilation (level): " + level + ", but level: " + compilationLevel);
 115             }
 116         }
 117     }
 118 
 119     // An intrinsic is available if:
 120     // - the intrinsic is enabled (by using the appropriate command-line flag) and
 121     // - the intrinsic is supported by the VM (i.e., the platform on which the VM is
 122     //   running provides the instructions necessary for the VM to generate the intrinsic).
 123     protected abstract boolean isIntrinsicAvailable();
 124 
 125     protected abstract String getIntrinsicId();
 126 
 127     protected boolean isServerVM() {
 128         return javaVmName.toLowerCase().contains("server");
 129     }
 130 
 131     static class IntTest extends IntrinsicBase {
 132 
 133         protected boolean isIntrinsicAvailable; // The tested intrinsic is available on the current platform.
 134 
 135         protected IntTest(MathIntrinsic.IntIntrinsic testCase) {
 136             super(testCase);
 137             // Only the C2 compiler intrinsifies exact math methods
 138             // so check if the intrinsics are available with C2.
 139             isIntrinsicAvailable = WHITE_BOX.isIntrinsicAvailable(testCase.getTestMethod(),
 140                                                                   COMP_LEVEL_FULL_OPTIMIZATION);
 141         }
 142 
 143         @Override
 144         protected boolean isIntrinsicAvailable() {
 145             return isIntrinsicAvailable;
 146         }
 147 
 148         @Override
 149         protected String getIntrinsicId() {
 150             return "_" + testCase.name().toLowerCase() + "ExactI";
 151         }
 152     }
 153 
 154     static class LongTest extends IntrinsicBase {
 155 
 156         protected boolean isIntrinsicAvailable; // The tested intrinsic is available on the current platform.
 157 
 158         protected LongTest(MathIntrinsic.LongIntrinsic testCase) {
 159             super(testCase);
 160             // Only the C2 compiler intrinsifies exact math methods
 161             // so check if the intrinsics are available with C2.
 162             isIntrinsicAvailable = WHITE_BOX.isIntrinsicAvailable(testCase.getTestMethod(),
 163                                                                   COMP_LEVEL_FULL_OPTIMIZATION);
 164         }
 165 
 166         @Override
 167         protected boolean isIntrinsicAvailable() {
 168             return isIntrinsicAvailable;
 169         }
 170 
 171         @Override
 172         protected String getIntrinsicId() {
 173             return "_" + testCase.name().toLowerCase() + "ExactL";
 174         }
 175     }
 176 }