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                 INITIAL_COMP_LEVEL = 1;
 110             } else {
 111                 throw new RuntimeException("Unknown VM: " + vmName);
 112             }
 113         }
 114 
 115         TIERED_STOP_AT_LEVEL = Integer.parseInt(getVMOption("TieredStopAtLevel",
 116                 String.valueOf(INITIAL_COMP_LEVEL)));
 117     }
 118 
 119     static {
 120         String tmp = System.getProperty("CompileTheWorldPreloadClasses");
 121         if (tmp == null) {
 122             COMPILE_THE_WORLD_PRELOAD_CLASSES = true;
 123         } else {
 124             COMPILE_THE_WORLD_PRELOAD_CLASSES = Boolean.parseBoolean(tmp);
 125         }
 126     }
 127 
 128     public static final String CLASSFILE_EXT = ".class";
 129 
 130     private Utils() {
 131     }
 132 
 133     /**
 134      * Tests if the string ends with the suffix, ignoring case
 135      * considerations
 136      *
 137      * @param string the tested string
 138      * @param suffix the suffix
 139      * @return {@code true} if {@code string} ends with the {@code suffix}
 140      * @see String#endsWith(String)
 141      */
 142     public static boolean endsWithIgnoreCase(String string, String suffix) {
 143         if (string == null || suffix == null) {
 144             return false;
 145         }
 146         int length = suffix.length();
 147         int toffset = string.length() - length;
 148         if (toffset < 0) {
 149             return false;
 150         }
 151         return string.regionMatches(true, toffset, suffix, 0, length);
 152     }
 153 
 154     /**
 155      * Returns value of VM option.
 156      *
 157      * @param name option's name
 158      * @return value of option or {@code null}, if option doesn't exist
 159      * @throws NullPointerException if name is null
 160      */
 161     public static String getVMOption(String name) {
 162         String result;
 163         HotSpotDiagnosticMXBean diagnostic
 164                 = ManagementFactoryHelper.getDiagnosticMXBean();
 165         result = diagnostic.getVMOption(name).getValue();
 166         return result;
 167     }
 168 
 169     /**
 170      * Returns value of VM option or default value.
 171      *
 172      * @param name         option's name
 173      * @param defaultValue default value
 174      * @return value of option or {@code defaultValue}, if option doesn't exist
 175      * @throws NullPointerException if name is null
 176      * @see #getVMOption(String)
 177      */
 178     public static String getVMOption(String name, String defaultValue) {
 179         String result = getVMOption(name);
 180         return result == null ? defaultValue : result;
 181     }
 182 
 183     /**
 184      * Tests if the filename is valid filename for class file.
 185      *
 186      * @param filename tested filename
 187      */
 188     public static boolean isClassFile(String filename) {
 189         // If the filename has a period after removing '.class', it's not valid class file
 190         return endsWithIgnoreCase(filename, CLASSFILE_EXT)
 191                 && (filename.indexOf('.')
 192                 == (filename.length() - CLASSFILE_EXT.length()));
 193     }
 194 
 195     /**
 196      * Converts the filename to classname.
 197      *
 198      * @param filename filename to convert
 199      * @return corresponding classname.
 200      * @throws AssertionError if filename isn't valid filename for class file -
 201      *                        {@link #isClassFile(String)}
 202      */
 203     public static String fileNameToClassName(String filename) {
 204         assert isClassFile(filename);
 205         return filename.substring(0, filename.length() - CLASSFILE_EXT.length())
 206                        .replace(File.separatorChar, '.');
 207     }
 208 }