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