--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java Sun Dec 11 19:07:04 2016 -0800
@@ -0,0 +1,767 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.tools.jaotc;
+
+import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
+import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode;
+import static org.graalvm.compiler.hotspot.meta.HotSpotAOTProfilingPlugin.Options.TieredAOT;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryUsage;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import jdk.tools.jaotc.binformat.BinaryContainer;
+import jdk.tools.jaotc.binformat.ByteContainer;
+import jdk.tools.jaotc.collect.ClassCollector;
+import jdk.tools.jaotc.utils.Timer;
+
+import org.graalvm.compiler.api.runtime.GraalJVMCICompiler;
+import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
+import org.graalvm.compiler.hotspot.HotSpotHostBackend;
+import org.graalvm.compiler.runtime.RuntimeProvider;
+
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.runtime.JVMCI;
+
+public class Main implements LogPrinter {
+ static {
+ GeneratePIC.setValue(true);
+ ImmutableCode.setValue(true);
+ }
+
+ static class BadArgs extends Exception {
+ private static final long serialVersionUID = 1L;
+ final String key;
+ final Object[] args;
+ boolean showUsage;
+
+ BadArgs(String key, Object... args) {
+ super(MessageFormat.format(key, args));
+ this.key = key;
+ this.args = args;
+ }
+
+ BadArgs showUsage(boolean b) {
+ showUsage = b;
+ return this;
+ }
+ }
+
+ abstract static class Option {
+ final String help;
+ final boolean hasArg;
+ final String[] aliases;
+
+ Option(String help, boolean hasArg, String... aliases) {
+ this.help = help;
+ this.hasArg = hasArg;
+ this.aliases = aliases;
+ }
+
+ boolean isHidden() {
+ return false;
+ }
+
+ boolean matches(String opt) {
+ for (String a : aliases) {
+ if (a.equals(opt)) {
+ return true;
+ } else if (opt.startsWith("--") && hasArg && opt.startsWith(a + "=")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ boolean ignoreRest() {
+ return false;
+ }
+
+ abstract void process(Main task, String opt, String arg) throws BadArgs;
+ }
+
+ static Option[] recognizedOptions = {new Option(" --module <name> Module to compile", true, "--module") {
+ @Override
+ void process(Main task, String opt, String arg) {
+ task.options.module = arg;
+ }
+ }, new Option(" --module-path <path> Specify where to find module to compile", true, "--module-path") {
+ @Override
+ void process(Main task, String opt, String arg) {
+ task.options.modulepath = arg;
+ }
+ }, new Option(" --output <file> Output file name", true, "--output") {
+ @Override
+ void process(Main task, String opt, String arg) {
+ String name = arg;
+ if (name.endsWith(".so")) {
+ name = name.substring(0, name.length() - ".so".length());
+ }
+ task.options.outputName = name;
+ }
+ }, new Option(" --compile-commands <file> Name of file with compile commands", true, "--compile-commands") {
+ @Override
+ void process(Main task, String opt, String arg) {
+ task.options.methodList = arg;
+ }
+ }, new Option(" --compile-for-tiered Generated profiling code for tiered compilation", false, "--compile-for-tiered") {
+ @Override
+ void process(Main task, String opt, String arg) {
+ TieredAOT.setValue(true);
+ }
+ }, new Option(" --classpath <path> Specify where to find user class files", true, "--classpath", "--class-path") {
+ @Override
+ void process(Main task, String opt, String arg) {
+ task.options.classpath = arg;
+ }
+ }, new Option(" --threads <number> Number of compilation threads to be used", true, "--threads") {
+ @Override
+ void process(Main task, String opt, String arg) {
+ int threads = Integer.parseInt(arg);
+ final int available = Runtime.getRuntime().availableProcessors();
+ if (threads <= 0) {
+ task.warning("invalid number of threads specified: {0}, using: {1}", threads, available);
+ threads = available;
+ }
+ if (threads > available) {
+ task.warning("too many threads specified: {0}, limiting to: {1}", threads, available);
+ }
+ task.options.threads = Integer.min(threads, available);
+ }
+ }, new Option(" --ignore-errors Ignores all exceptions thrown during class loading", false, "--ignore-errors") {
+ @Override
+ void process(Main task, String opt, String arg) {
+ task.options.ignoreClassLoadingErrors = true;
+ }
+ }, new Option(" --exit-on-error Exit on compilation errors", false, "--exit-on-error") {
+ @Override
+ void process(Main task, String opt, String arg) {
+ task.options.exitOnError = true;
+ }
+ }, new Option(" --info Print information during compilation", false, "--info") {
+ @Override
+ void process(Main task, String opt, String arg) throws BadArgs {
+ task.options.info = true;
+ }
+ }, new Option(" --verbose Print verbose information", false, "--verbose") {
+ @Override
+ void process(Main task, String opt, String arg) throws BadArgs {
+ task.options.info = true;
+ task.options.verbose = true;
+ }
+ }, new Option(" --debug Print debug information", false, "--debug") {
+ @Override
+ void process(Main task, String opt, String arg) throws BadArgs {
+ task.options.info = true;
+ task.options.verbose = true;
+ task.options.debug = true;
+ }
+ }, new Option(" --help Print this usage message", false, "--help") {
+ @Override
+ void process(Main task, String opt, String arg) {
+ task.options.help = true;
+ }
+ }, new Option(" --version Version information", false, "--version") {
+ @Override
+ void process(Main task, String opt, String arg) {
+ task.options.version = true;
+ }
+ }, new Option(" -J<flag> Pass <flag> directly to the runtime system", false, "-J") {
+ @Override
+ void process(Main task, String opt, String arg) {
+ }
+ }};
+
+ public static class Options {
+ public List<String> files = new LinkedList<>();
+ public String module = null;
+ public String modulepath = "modules";
+ public String outputName = "unnamed";
+ public String methodList;
+ public String classpath = ".";
+
+ /**
+ * We don't see scaling beyond 16 threads.
+ */
+ private static final int COMPILER_THREADS = 16;
+
+ int threads = Integer.min(COMPILER_THREADS, Runtime.getRuntime().availableProcessors());
+
+ public boolean ignoreClassLoadingErrors;
+ public boolean exitOnError;
+ boolean info;
+ boolean verbose;
+ boolean debug;
+ boolean help;
+ boolean version;
+ }
+
+ /* package */final Options options = new Options();
+
+ /**
+ * Logfile.
+ */
+ private static FileWriter logFile = null;
+
+ private static final int EXIT_OK = 0; // No errors.
+ private static final int EXIT_CMDERR = 2; // Bad command-line arguments and/or switches.
+ private static final int EXIT_ABNORMAL = 4; // Terminated abnormally.
+
+ private static final String PROGNAME = "jaotc";
+
+ private static final String JVM_VERSION = System.getProperty("java.runtime.version");
+
+ public static void main(String[] args) throws Exception {
+ Main t = new Main();
+ final int exitCode = t.run(args);
+ System.exit(exitCode);
+ }
+
+ private int run(String[] args) {
+ if (log == null) {
+ log = new PrintWriter(System.out);
+ }
+
+ try {
+ handleOptions(args);
+ if (options.help) {
+ showHelp();
+ return EXIT_OK;
+ }
+ if (options.version) {
+ showVersion();
+ return EXIT_OK;
+ }
+
+ printlnInfo("Compiling " + options.outputName + "...");
+ final long start = System.currentTimeMillis();
+ run();
+ final long end = System.currentTimeMillis();
+ printlnInfo("Total time: " + (end - start) + " ms");
+
+ return EXIT_OK;
+ } catch (BadArgs e) {
+ reportError(e.key, e.args);
+ if (e.showUsage) {
+ showUsage();
+ }
+ return EXIT_CMDERR;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return EXIT_ABNORMAL;
+ } finally {
+ log.flush();
+ }
+ }
+
+ private static String humanReadableByteCount(long bytes) {
+ int unit = 1024;
+
+ if (bytes < unit) {
+ return bytes + " B";
+ }
+
+ int exp = (int) (Math.log(bytes) / Math.log(unit));
+ char pre = "KMGTPE".charAt(exp - 1);
+ return String.format("%.1f %cB", bytes / Math.pow(unit, exp), pre);
+ }
+
+ void printMemoryUsage() {
+ if (options.verbose) {
+ MemoryUsage memusage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
+ float freeratio = 1f - (float) memusage.getUsed() / memusage.getCommitted();
+ log.format(" [used: %-7s, comm: %-7s, freeRatio ~= %.1f%%]",
+ humanReadableByteCount(memusage.getUsed()),
+ humanReadableByteCount(memusage.getCommitted()),
+ freeratio * 100);
+ }
+ }
+
+ @SuppressWarnings("try")
+ private void run() throws Exception {
+ openLog();
+
+ try {
+ CompilationSpec compilationRestrictions = collectSpecifiedMethods();
+
+ Set<Class<?>> classesToCompile;
+
+ try (Timer t = new Timer(this, "")) {
+ ClassCollector collector = new ClassCollector(this.options, this);
+ classesToCompile = collector.collectClassesToCompile();
+ printInfo(classesToCompile.size() + " classes found");
+ }
+
+ GraalJVMCICompiler graalCompiler = (GraalJVMCICompiler) JVMCI.getRuntime().getCompiler();
+ HotSpotGraalRuntimeProvider runtime = (HotSpotGraalRuntimeProvider) graalCompiler.getGraalRuntime();
+ HotSpotHostBackend backend = (HotSpotHostBackend) runtime.getCapability(RuntimeProvider.class).getHostBackend();
+ MetaAccessProvider metaAccess = backend.getProviders().getMetaAccess();
+ GraalFilters filters = new GraalFilters(metaAccess);
+
+ List<AOTCompiledClass> classes;
+
+ try (Timer t = new Timer(this, "")) {
+ classes = collectMethodsToCompile(classesToCompile, compilationRestrictions, filters, metaAccess);
+ }
+
+ // Free memory!
+ try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
+ printMemoryUsage();
+ compilationRestrictions = null;
+ classesToCompile = null;
+ System.gc();
+ }
+
+ AOTBackend aotBackend = new AOTBackend(this, backend, filters);
+ AOTCompiler compiler = new AOTCompiler(this, aotBackend, options.threads);
+ classes = compiler.compileClasses(classes);
+
+ // Free memory!
+ try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
+ printMemoryUsage();
+ aotBackend = null;
+ compiler = null;
+ System.gc();
+ }
+
+ BinaryContainer binaryContainer = new BinaryContainer(runtime.getVMConfig(), JVM_VERSION);
+ DataBuilder dataBuilder = new DataBuilder(this, backend, classes, binaryContainer);
+ dataBuilder.prepareData();
+
+ // Print information about section sizes
+ printContainerInfo(binaryContainer.getHeaderContainer().getContainer());
+ printContainerInfo(binaryContainer.getConfigContainer());
+ printContainerInfo(binaryContainer.getKlassesOffsetsContainer());
+ printContainerInfo(binaryContainer.getMethodsOffsetsContainer());
+ printContainerInfo(binaryContainer.getKlassesDependenciesContainer());
+ printContainerInfo(binaryContainer.getStubsOffsetsContainer());
+ printContainerInfo(binaryContainer.getMethodMetadataContainer());
+ printContainerInfo(binaryContainer.getCodeContainer());
+ printContainerInfo(binaryContainer.getCodeSegmentsContainer());
+ printContainerInfo(binaryContainer.getConstantDataContainer());
+ printContainerInfo(binaryContainer.getMetaspaceGotContainer());
+ printContainerInfo(binaryContainer.getMetadataGotContainer());
+ printContainerInfo(binaryContainer.getMethodStateContainer());
+ printContainerInfo(binaryContainer.getOopGotContainer());
+ printContainerInfo(binaryContainer.getMetaspaceNamesContainer());
+
+ // Free memory!
+ try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
+ printMemoryUsage();
+ backend = null;
+ for (AOTCompiledClass aotCompClass : classes) {
+ aotCompClass.clear();
+ }
+ classes.clear();
+ classes = null;
+ dataBuilder = null;
+ binaryContainer.freeMemory();
+ System.gc();
+ }
+
+ String objectFileName = options.outputName + ".o";
+ String libraryFileName = options.outputName + ".so";
+
+ try (Timer t = new Timer(this, "Creating binary: " + objectFileName)) {
+ binaryContainer.createBinary(objectFileName, JVM_VERSION);
+ }
+
+ // Free memory!
+ try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
+ printMemoryUsage();
+ binaryContainer = null;
+ System.gc();
+ }
+
+ try (Timer t = new Timer(this, "Creating shared library: " + libraryFileName)) {
+ Process p = Runtime.getRuntime().exec("ld -shared -z noexecstack -o " + libraryFileName + " " + objectFileName);
+ final int exitCode = p.waitFor();
+ if (exitCode != 0) {
+ InputStream stderr = p.getErrorStream();
+ BufferedReader br = new BufferedReader(new InputStreamReader(stderr));
+ Stream<String> lines = br.lines();
+ StringBuilder sb = new StringBuilder();
+ lines.iterator().forEachRemaining(e -> sb.append(e));
+ throw new InternalError(sb.toString());
+ }
+ File objFile = new File(objectFileName);
+ if (objFile.exists()) {
+ if (!objFile.delete()) {
+ throw new InternalError("Failed to delete " + objectFileName + " file");
+ }
+ }
+ // Make non-executable for all.
+ File libFile = new File(libraryFileName);
+ if (libFile.exists()) {
+ if (!libFile.setExecutable(false, false)) {
+ throw new InternalError("Failed to change attribute for " + libraryFileName + " file");
+ }
+ }
+ }
+
+ printVerbose("Final memory ");
+ printMemoryUsage();
+ printlnVerbose("");
+
+ } finally {
+ closeLog();
+ }
+ }
+
+ private void addMethods(AOTCompiledClass aotClass, ResolvedJavaMethod[] methods, CompilationSpec compilationRestrictions, GraalFilters filters) {
+ for (ResolvedJavaMethod m : methods) {
+ addMethod(aotClass, m, compilationRestrictions, filters);
+ }
+ }
+
+ private void addMethod(AOTCompiledClass aotClass, ResolvedJavaMethod method, CompilationSpec compilationRestrictions, GraalFilters filters) {
+ // Don't compile native or abstract methods.
+ if (!method.hasBytecodes()) {
+ return;
+ }
+ if (!compilationRestrictions.shouldCompileMethod(method)) {
+ return;
+ }
+ if (!filters.shouldCompileMethod(method)) {
+ return;
+ }
+
+ aotClass.addMethod(method);
+ printlnVerbose(" added " + method.getName() + method.getSignature().toMethodDescriptor());
+ }
+
+ private void printContainerInfo(ByteContainer container) {
+ printlnVerbose(container.getContainerName() + ": " + container.getByteStreamSize() + " bytes");
+ }
+
+ PrintWriter log;
+
+ private void handleOptions(String[] args) throws BadArgs {
+ if (args.length == 0) {
+ options.help = true;
+ return;
+ }
+
+ // Make checkstyle happy.
+ int i = 0;
+ for (; i < args.length; i++) {
+ String arg = args[i];
+
+ if (arg.charAt(0) == '-') {
+ Option option = getOption(arg);
+ String param = null;
+
+ if (option.hasArg) {
+ if (arg.startsWith("--") && arg.indexOf('=') > 0) {
+ param = arg.substring(arg.indexOf('=') + 1, arg.length());
+ } else if (i + 1 < args.length) {
+ param = args[++i];
+ }
+
+ if (param == null || param.isEmpty() || param.charAt(0) == '-') {
+ throw new BadArgs("missing argument for option: {0}", arg).showUsage(true);
+ }
+ }
+
+ option.process(this, arg, param);
+
+ if (option.ignoreRest()) {
+ break;
+ }
+ } else {
+ options.files.add(arg);
+ }
+ }
+ }
+
+ private static Option getOption(String name) throws BadArgs {
+ for (Option o : recognizedOptions) {
+ if (o.matches(name)) {
+ return o;
+ }
+ }
+ throw new BadArgs("unknown option: {0}", name).showUsage(true);
+ }
+
+ public void printInfo(String message) {
+ if (options.info) {
+ log.print(message);
+ log.flush();
+ }
+ }
+
+ public void printlnInfo(String message) {
+ if (options.info) {
+ log.println(message);
+ log.flush();
+ }
+ }
+
+ public void printVerbose(String message) {
+ if (options.verbose) {
+ log.print(message);
+ log.flush();
+ }
+ }
+
+ public void printlnVerbose(String message) {
+ if (options.verbose) {
+ log.println(message);
+ log.flush();
+ }
+ }
+
+ public void printDebug(String message) {
+ if (options.debug) {
+ log.print(message);
+ log.flush();
+ }
+ }
+
+ public void printlnDebug(String message) {
+ if (options.debug) {
+ log.println(message);
+ log.flush();
+ }
+ }
+
+ public void printError(String message) {
+ log.println("Error: " + message);
+ log.flush();
+ }
+
+ private void reportError(String key, Object... args) {
+ printError(MessageFormat.format(key, args));
+ }
+
+ private void warning(String key, Object... args) {
+ log.println("Warning: " + MessageFormat.format(key, args));
+ log.flush();
+ }
+
+ private void showUsage() {
+ log.println("Usage: " + PROGNAME + " <options> list...");
+ log.println("use --help for a list of possible options");
+ }
+
+ private void showHelp() {
+ log.println("Usage: " + PROGNAME + " <options> <--module name> | <list...>");
+ log.println();
+ log.println(" list A list of class files, jar files or directories which");
+ log.println(" contains class files.");
+ log.println();
+ log.println("where possible options include:");
+ for (Option o : recognizedOptions) {
+ String name = o.aliases[0].substring(1); // there must always be at least one name
+ name = name.charAt(0) == '-' ? name.substring(1) : name;
+ if (o.isHidden() || name.equals("h")) {
+ continue;
+ }
+ log.println(o.help);
+ }
+ }
+
+ private void showVersion() {
+ log.println(PROGNAME + " " + JVM_VERSION);
+ }
+
+ /**
+ * Collect all method we should compile.
+ *
+ * @return array list of AOT classes which have compiled methods.
+ */
+ private List<AOTCompiledClass> collectMethodsToCompile(Set<Class<?>> classesToCompile, CompilationSpec compilationRestrictions, GraalFilters filters, MetaAccessProvider metaAccess) {
+ int total = 0;
+ int count = 0;
+ List<AOTCompiledClass> classes = new ArrayList<>();
+
+ for (Class<?> c : classesToCompile) {
+ ResolvedJavaType resolvedJavaType = metaAccess.lookupJavaType(c);
+ if (filters.shouldCompileAnyMethodInClass(resolvedJavaType)) {
+ AOTCompiledClass aotClass = new AOTCompiledClass(resolvedJavaType);
+ printlnVerbose(" Scanning " + c.getName());
+
+ // Constructors
+ try {
+ ResolvedJavaMethod[] ctors = resolvedJavaType.getDeclaredConstructors();
+ addMethods(aotClass, ctors, compilationRestrictions, filters);
+ total += ctors.length;
+ } catch (Throwable e) {
+ // If we are running in JCK mode we ignore all exceptions.
+ if (options.ignoreClassLoadingErrors) {
+ printError(c.getName() + ": " + e);
+ } else {
+ throw new InternalError(e);
+ }
+ }
+
+ // Methods
+ try {
+ ResolvedJavaMethod[] methods = resolvedJavaType.getDeclaredMethods();
+ addMethods(aotClass, methods, compilationRestrictions, filters);
+ total += methods.length;
+ } catch (Throwable e) {
+ // If we are running in JCK mode we ignore all exceptions.
+ if (options.ignoreClassLoadingErrors) {
+ printError(c.getName() + ": " + e);
+ } else {
+ throw new InternalError(e);
+ }
+ }
+
+ // Class initializer
+ try {
+ ResolvedJavaMethod clinit = resolvedJavaType.getClassInitializer();
+ if (clinit != null) {
+ addMethod(aotClass, clinit, compilationRestrictions, filters);
+ total++;
+ }
+ } catch (Throwable e) {
+ // If we are running in JCK mode we ignore all exceptions.
+ if (options.ignoreClassLoadingErrors) {
+ printError(c.getName() + ": " + e);
+ } else {
+ throw new InternalError(e);
+ }
+ }
+
+ // Found any methods to compile? Add the class.
+ if (aotClass.hasMethods()) {
+ classes.add(aotClass);
+ count += aotClass.getMethodCount();
+ }
+ }
+ }
+ printInfo(total + " methods total, " + count + " methods to compile");
+ return classes;
+ }
+
+ /**
+ * If a file with compilation limitations is specified using the java property
+ * jdk.tools.jaotc.compile.method.list, read the file's contents and collect the restrictions.
+ */
+ private CompilationSpec collectSpecifiedMethods() {
+ CompilationSpec compilationRestrictions = new CompilationSpec();
+ String methodListFileName = options.methodList;
+
+ if (methodListFileName != null && !methodListFileName.equals("")) {
+ try {
+ FileReader methListFile = new FileReader(methodListFileName);
+ BufferedReader readBuf = new BufferedReader(methListFile);
+ String line = null;
+ while ((line = readBuf.readLine()) != null) {
+ String trimmedLine = line.trim();
+ if (!trimmedLine.startsWith("#")) {
+ String[] components = trimmedLine.split(" ");
+ if (components.length == 2) {
+ String directive = components[0];
+ String pattern = components[1];
+ switch (directive) {
+ case "compileOnly":
+ compilationRestrictions.addCompileOnlyPattern(pattern);
+ break;
+ case "exclude":
+ compilationRestrictions.addExcludePattern(pattern);
+ break;
+ default:
+ System.out.println("Unrecognized command " + directive + ". Ignoring\n\t" + line + "\n encountered in " + methodListFileName);
+ }
+ } else {
+ if (!trimmedLine.equals("")) {
+ System.out.println("Ignoring malformed line:\n\t " + line + "\n");
+ }
+ }
+ }
+ }
+ readBuf.close();
+ } catch (FileNotFoundException e) {
+ throw new InternalError("Unable to open method list file: " + methodListFileName, e);
+ } catch (IOException e) {
+ throw new InternalError("Unable to read method list file: " + methodListFileName, e);
+ }
+ }
+
+ return compilationRestrictions;
+ }
+
+ private static void openLog() {
+ int v = Integer.getInteger("jdk.tools.jaotc.logCompilation", 0);
+ if (v == 0) {
+ logFile = null;
+ return;
+ }
+ // Create log file in current directory
+ String fileName = "aot_compilation" + new Date().getTime() + ".log";
+ Path logFilePath = Paths.get("./", fileName);
+ String logFileName = logFilePath.toString();
+ try {
+ // Create file to which we do not append
+ logFile = new FileWriter(logFileName, false);
+ } catch (IOException e) {
+ System.out.println("Unable to open logfile :" + logFileName + "\nNo logs will be created");
+ logFile = null;
+ }
+ }
+
+ public static void writeLog(String str) {
+ if (logFile != null) {
+ try {
+ logFile.write(str + "\n");
+ logFile.flush();
+ } catch (IOException e) {
+ // Print to console
+ System.out.println(str + "\n");
+ }
+ }
+ }
+
+ public static void closeLog() {
+ if (logFile != null) {
+ try {
+ logFile.close();
+ } catch (IOException e) {
+ // Do nothing
+ }
+ }
+ }
+}