1 /*
   2  * Copyright (c) 2013, 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 sun.hotspot.tools.ctw;
  25 
  26 import com.sun.management.HotSpotDiagnosticMXBean;
  27 import sun.management.ManagementFactoryHelper;
  28 
  29 import java.io.File;
  30 import java.util.regex.Pattern;
  31 
  32 /**
  33  * Auxiliary methods.
  34  *
  35  * @author igor.ignatyev@oracle.com
  36  */
  37 public class Utils {
  38     /**
  39      * Value of {@code -XX:CompileThreshold}
  40      */
  41     public static final boolean TIERED_COMPILATION
  42             = Boolean.parseBoolean(getVMOption("TieredCompilation", "false"));
  43     /**
  44      * Value of {@code -XX:BackgroundCompilation}
  45      */
  46     public static final boolean BACKGROUND_COMPILATION
  47             = Boolean.parseBoolean(getVMOption("BackgroundCompilation",
  48             "false"));
  49     /**
  50      * Value of {@code -XX:TieredStopAtLevel}
  51      */
  52     public static final int TIERED_STOP_AT_LEVEL;
  53     /**
  54      * Value of {@code -XX:CICompilerCount}
  55      */
  56     public static final Integer CI_COMPILER_COUNT
  57             = Integer.valueOf(getVMOption("CICompilerCount", "1"));
  58     /**
  59      * Initial compilation level.
  60      */
  61     public static final int INITIAL_COMP_LEVEL;
  62     /**
  63      * Compiled path-separator regexp.
  64      */
  65     public static final Pattern PATH_SEPARATOR = Pattern.compile(
  66             File.pathSeparator, Pattern.LITERAL);
  67     /**
  68      * Value of {@code -DDeoptimizeAllClassesRate}. Frequency of
  69      * {@code WB.deoptimizeAll()} invocation If it less that {@code 0},
  70      * {@code WB.deoptimizeAll()} will not be invoked.
  71      */
  72     public static final int DEOPTIMIZE_ALL_CLASSES_RATE
  73             = Integer.getInteger("DeoptimizeAllClassesRate", -1);
  74     /**
  75      * Value of {@code -DCompileTheWorldStopAt}. Last class to consider.
  76      */
  77     public static final long COMPILE_THE_WORLD_STOP_AT
  78             = Long.getLong("CompileTheWorldStopAt", Long.MAX_VALUE);
  79     /**
  80      * Value of {@code -DCompileTheWorldStartAt}. First class to consider.
  81      */
  82     public static final long COMPILE_THE_WORLD_START_AT
  83             = Long.getLong("CompileTheWorldStartAt", 1);
  84     /**
  85      * Value of {@code -DCompileTheWorldPreloadClasses}. Preload all classes
  86      * used by a class before start loading.
  87      */
  88     public static final boolean COMPILE_THE_WORLD_PRELOAD_CLASSES;
  89     /**
  90      * Value of {@code -Dsun.hotspot.tools.ctw.verbose}. Verbose output,
  91      * adds additional information about compilation.
  92      */
  93     public static final boolean IS_VERBOSE
  94             = Boolean.getBoolean("sun.hotspot.tools.ctw.verbose");
  95     /**
  96      * Value of {@code -Dsun.hotspot.tools.ctw.logfile}.Path to logfile, if
  97      * it's null, cout will be used.
  98      */
  99     public static final String LOG_FILE
 100             = System.getProperty("sun.hotspot.tools.ctw.logfile");
 101     static {
 102         if (Utils.TIERED_COMPILATION) {
 103             INITIAL_COMP_LEVEL = 1;
 104         } else {
 105             String vmName = System.getProperty("java.vm.name");
 106             if (Utils.endsWithIgnoreCase(vmName, " Server VM")) {
 107                 INITIAL_COMP_LEVEL = 4;
 108             } else if (Utils.endsWithIgnoreCase(vmName, " Client VM")
 109                     || Utils.endsWithIgnoreCase(vmName, " Minimal VM")) {
 110                 INITIAL_COMP_LEVEL = 1;
 111             } else {
 112                 throw new RuntimeException("Unknown VM: " + vmName);
 113             }
 114         }
 115 
 116         TIERED_STOP_AT_LEVEL = Integer.parseInt(getVMOption("TieredStopAtLevel",
 117                 String.valueOf(INITIAL_COMP_LEVEL)));
 118     }
 119 
 120     static {
 121         String tmp = System.getProperty("CompileTheWorldPreloadClasses");
 122         if (tmp == null) {
 123             COMPILE_THE_WORLD_PRELOAD_CLASSES = true;
 124         } else {
 125             COMPILE_THE_WORLD_PRELOAD_CLASSES = Boolean.parseBoolean(tmp);
 126         }
 127     }
 128 
 129     public static final String CLASSFILE_EXT = ".class";
 130 
 131     private Utils() {
 132     }
 133 
 134     /**
 135      * Tests if the string ends with the suffix, ignoring case
 136      * considerations
 137      *
 138      * @param string the tested string
 139      * @param suffix the suffix
 140      * @return {@code true} if {@code string} ends with the {@code suffix}
 141      * @see String#endsWith(String)
 142      */
 143     public static boolean endsWithIgnoreCase(String string, String suffix) {
 144         if (string == null || suffix == null) {
 145             return false;
 146         }
 147         int length = suffix.length();
 148         int toffset = string.length() - length;
 149         if (toffset < 0) {
 150             return false;
 151         }
 152         return string.regionMatches(true, toffset, suffix, 0, length);
 153     }
 154 
 155     /**
 156      * Returns value of VM option.
 157      *
 158      * @param name option's name
 159      * @return value of option or {@code null}, if option doesn't exist
 160      * @throws NullPointerException if name is null
 161      */
 162     public static String getVMOption(String name) {
 163         String result;
 164         HotSpotDiagnosticMXBean diagnostic
 165                 = ManagementFactoryHelper.getDiagnosticMXBean();
 166         result = diagnostic.getVMOption(name).getValue();
 167         return result;
 168     }
 169 
 170     /**
 171      * Returns value of VM option or default value.
 172      *
 173      * @param name         option's name
 174      * @param defaultValue default value
 175      * @return value of option or {@code defaultValue}, if option doesn't exist
 176      * @throws NullPointerException if name is null
 177      * @see #getVMOption(String)
 178      */
 179     public static String getVMOption(String name, String defaultValue) {
 180         String result;
 181         try {
 182             result = getVMOption(name);
 183         } catch (NoClassDefFoundError e) {
 184             // compact1, compact2 support
 185             result = defaultValue;
 186         }
 187         return result == null ? defaultValue : result;
 188     }
 189 
 190     /**
 191      * Tests if the filename is valid filename for class file.
 192      *
 193      * @param filename tested filename
 194      */
 195     public static boolean isClassFile(String filename) {
 196         // If the filename has a period after removing '.class', it's not valid class file
 197         return endsWithIgnoreCase(filename, CLASSFILE_EXT)
 198                 && (filename.indexOf('.')
 199                 == (filename.length() - CLASSFILE_EXT.length()));
 200     }
 201 
 202     /**
 203      * Converts the filename to classname.
 204      *
 205      * @param filename filename to convert
 206      * @return corresponding classname.
 207      * @throws AssertionError if filename isn't valid filename for class file -
 208      *                        {@link #isClassFile(String)}
 209      */
 210     public static String fileNameToClassName(String filename) {
 211         assert isClassFile(filename);
 212         return filename.substring(0, filename.length() - CLASSFILE_EXT.length())
 213                        .replace(File.separatorChar, '.');
 214     }
 215 }