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 /*
  25  * @test
  26  * @bug 8138651
  27  * @library /testlibrary /../../test/lib
  28  * @build IntrinsicDisabledTest
  29  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  30  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
  31  * @run main/othervm -Xbootclasspath/a:.
  32  *                   -XX:+UnlockDiagnosticVMOptions
  33  *                   -XX:+WhiteBoxAPI
  34  *                   -XX:DisableIntrinsic=_putCharVolatile,_putInt
  35  *                   -XX:DisableIntrinsic=_putIntVolatile
  36  *                   -XX:CompileCommand=option,sun.misc.Unsafe::putChar,ccstrlist,DisableIntrinsic,_getCharVolatile,_getInt
  37  *                   -XX:CompileCommand=option,sun.misc.Unsafe::putCharVolatile,ccstrlist,DisableIntrinsic,_getIntVolatile
  38  *                   IntrinsicDisabledTest
  39  */
  40 
  41 import java.lang.reflect.Executable;
  42 import java.util.Objects;
  43 
  44 import sun.hotspot.WhiteBox;
  45 
  46 import jdk.test.lib.Platform;
  47 
  48 public class IntrinsicDisabledTest {
  49 
  50     private static final WhiteBox wb = WhiteBox.getWhiteBox();
  51 
  52     /* Compilation level corresponding to C1. */
  53     private static final int COMP_LEVEL_SIMPLE = 1;
  54 
  55     /* Compilation level corresponding to C2. */
  56     private static final int COMP_LEVEL_FULL_OPTIMIZATION = 4;
  57 
  58     /* Determine if tiered compilation is enabled. */
  59     private static boolean isTieredCompilationEnabled() {
  60         return Boolean.valueOf(Objects.toString(wb.getVMFlag("TieredCompilation")));
  61     }
  62 
  63     /* This test uses several methods from sun.misc.Unsafe. The method
  64      * getMethod() returns a different Executable for each different
  65      * combination of its input parameters. There are eight possible
  66      * combinations, getMethod can return an Executable representing
  67      * the following methods: putChar, putCharVolatile, getChar,
  68      * getCharVolatile, putInt, putIntVolatile, getInt,
  69      * getIntVolatile. These methods were selected because they can
  70      * be intrinsified by both the C1 and the C2 compiler.
  71      */
  72     static Executable getMethod(boolean isChar, boolean isPut, boolean isVolatile) throws RuntimeException {
  73         Executable aMethod;
  74         String methodTypeName = isChar ? "Char" : "Int";
  75 
  76         try {
  77             Class aClass = Class.forName("sun.misc.Unsafe");
  78             if (isPut) {
  79                 aMethod = aClass.getDeclaredMethod("put" + methodTypeName + (isVolatile ? "Volatile" : ""),
  80                                                    Object.class,
  81                                                    long.class,
  82                                                    isChar ? char.class : int.class);
  83             } else {
  84                 aMethod = aClass.getDeclaredMethod("get" + methodTypeName + (isVolatile ? "Volatile" : ""),
  85                                                    Object.class,
  86                                                    long.class);
  87             }
  88         } catch (NoSuchMethodException e) {
  89             throw new RuntimeException("Test bug, method is unavailable. " + e);
  90         } catch (ClassNotFoundException e) {
  91             throw new RuntimeException("Test bug, class is unavailable. " + e);
  92         }
  93 
  94         return aMethod;
  95     }
  96 
  97     public static void test(int compLevel) {
  98 
  99         Executable putChar = getMethod(true, /*isPut =*/ true, /*isVolatile = */ false);
 100         Executable getChar = getMethod(true, /*isPut =*/ false, /*isVolatile = */ false);
 101         Executable putCharVolatile = getMethod(true, /*isPut =*/ true, /*isVolatile = */ true);
 102         Executable getCharVolatile = getMethod(true, /*isPut =*/ false, /*isVolatile = */ true);
 103         Executable putInt = getMethod(false, /*isPut =*/ true, /*isVolatile = */ false);
 104         Executable getInt = getMethod(false, /*isPut =*/ false, /*isVolatile = */ false);
 105         Executable putIntVolatile = getMethod(false, /*isPut =*/ true, /*isVolatile = */ true);
 106         Executable getIntVolatile = getMethod(false, /*isPut =*/ false, /*isVolatile = */ true);
 107 
 108         /* Test if globally disabling intrinsics works. */
 109         if (!wb.isIntrinsicAvailable(putChar, compLevel)) {
 110             throw new RuntimeException("Intrinsic for [" + putChar.toGenericString() +
 111                                        "] is not available globally although it should be.");
 112         }
 113 
 114         if (wb.isIntrinsicAvailable(putCharVolatile, compLevel)) {
 115             throw new RuntimeException("Intrinsic for [" + putCharVolatile.toGenericString() +
 116                                        "] is available globally although it should not be.");
 117         }
 118 
 119         if (wb.isIntrinsicAvailable(putInt, compLevel)) {
 120             throw new RuntimeException("Intrinsic for [" + putInt.toGenericString() +
 121                                        "] is available globally although it should not be.");
 122         }
 123 
 124         if (wb.isIntrinsicAvailable(putIntVolatile, compLevel)) {
 125             throw new RuntimeException("Intrinsic for [" + putIntVolatile.toGenericString() +
 126                                        "] is available globally although it should not be.");
 127         }
 128 
 129         /* Test if disabling intrinsics on a per-method level
 130          * works. The method for which intrinsics are
 131          * disabled (the compilation context) is putChar. */
 132         if (!wb.isIntrinsicAvailable(getChar, putChar, compLevel)) {
 133             throw new RuntimeException("Intrinsic for [" + getChar.toGenericString() +
 134                                        "] is not available for intrinsification in [" +
 135                                        putChar.toGenericString() + "] although it should be.");
 136         }
 137 
 138         if (wb.isIntrinsicAvailable(getCharVolatile, putChar, compLevel)) {
 139             throw new RuntimeException("Intrinsic for [" + getCharVolatile.toGenericString() +
 140                                        "] is available for intrinsification in [" +
 141                                        putChar.toGenericString() + "] although it should not be.");
 142         }
 143 
 144         if (wb.isIntrinsicAvailable(getInt, putChar, compLevel)) {
 145             throw new RuntimeException("Intrinsic for [" + getInt.toGenericString() +
 146                                        "] is available for intrinsification in [" +
 147                                        putChar.toGenericString() + "] although it should not be.");
 148         }
 149 
 150         if (wb.isIntrinsicAvailable(getIntVolatile, putCharVolatile, compLevel)) {
 151             throw new RuntimeException("Intrinsic for [" + getIntVolatile.toGenericString() +
 152                                        "] is available for intrinsification in [" +
 153                                        putCharVolatile.toGenericString() + "] although it should not be.");
 154         }
 155 
 156         /* Test if disabling intrinsics on a per-method level
 157          * leaves those intrinsics enabled globally. */
 158         if (!wb.isIntrinsicAvailable(getCharVolatile, compLevel)) {
 159             throw new RuntimeException("Intrinsic for [" + getCharVolatile.toGenericString() +
 160                                        "] is not available globally although it should be.");
 161         }
 162 
 163         if (!wb.isIntrinsicAvailable(getInt, compLevel)) {
 164             throw new RuntimeException("Intrinsic for [" + getInt.toGenericString() +
 165                                        "] is not available globally although it should be.");
 166         }
 167 
 168 
 169         if (!wb.isIntrinsicAvailable(getIntVolatile, compLevel)) {
 170             throw new RuntimeException("Intrinsic for [" + getIntVolatile.toGenericString() +
 171                                        "] is not available globally although it should be.");
 172         }
 173 
 174         /* Test if disabling an intrinsic globally disables it on a
 175          * per-method level as well. */
 176         if (!wb.isIntrinsicAvailable(putChar, getChar, compLevel)) {
 177             throw new RuntimeException("Intrinsic for [" + putChar.toGenericString() +
 178                                        "] is not available for intrinsification in [" +
 179                                        getChar.toGenericString() + "] although it should be.");
 180         }
 181 
 182         if (wb.isIntrinsicAvailable(putCharVolatile, getChar, compLevel)) {
 183             throw new RuntimeException("Intrinsic for [" + putCharVolatile.toGenericString() +
 184                                        "] is available for intrinsification in [" +
 185                                        getChar.toGenericString() + "] although it should not be.");
 186         }
 187 
 188         if (wb.isIntrinsicAvailable(putInt, getChar, compLevel)) {
 189             throw new RuntimeException("Intrinsic for [" + putInt.toGenericString() +
 190                                        "] is available for intrinsification in [" +
 191                                        getChar.toGenericString() + "] although it should not be.");
 192         }
 193 
 194         if (wb.isIntrinsicAvailable(putIntVolatile, getChar, compLevel)) {
 195             throw new RuntimeException("Intrinsic for [" + putIntVolatile.toGenericString() +
 196                                        "] is available for intrinsification in [" +
 197                                        getChar.toGenericString() + "] although it should not be.");
 198         }
 199     }
 200 
 201     public static void main(String args[]) {
 202         if (Platform.isServer()) {
 203             if (isTieredCompilationEnabled()) {
 204                 test(COMP_LEVEL_SIMPLE);
 205             }
 206             test(COMP_LEVEL_FULL_OPTIMIZATION);
 207         } else {
 208             test(COMP_LEVEL_SIMPLE);
 209         }
 210     }
 211 }