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