1/*
2 * Copyright (c) 2013, 2016, 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
24package sun.hotspot.tools.ctw;
25
26import com.sun.management.HotSpotDiagnosticMXBean;
27import java.lang.management.ManagementFactory;
28
29import java.io.File;
30import java.util.regex.Pattern;
31
32/**
33 * Auxiliary methods.
34 */
35public 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            String vmInfo = System.getProperty("java.vm.info");
105            boolean isEmulatedClient = (vmInfo != null) && vmInfo.contains("emulated-client");
106            if (Utils.endsWithIgnoreCase(vmName, " Server VM") && !isEmulatedClient) {
107                INITIAL_COMP_LEVEL = 4;
108            } else if (Utils.endsWithIgnoreCase(vmName, " Client VM")
109                    || Utils.endsWithIgnoreCase(vmName, " Minimal VM") || isEmulatedClient) {
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                = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
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        final char nameSeparator = '/';
213        return filename.substring(0, filename.length() - CLASSFILE_EXT.length())
214                       .replace(nameSeparator, '.');
215    }
216
217    public static String classNameToFileName(String classname) {
218        return classname.replace('.', '/')
219                        .concat(CLASSFILE_EXT);
220    }
221}
222