1 /* 2 * Copyright (c) 2016, 2017, 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 jdk.tools.jaotc; 25 26 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; 27 import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; 28 import static org.graalvm.compiler.hotspot.meta.HotSpotAOTProfilingPlugin.Options.TieredAOT; 29 30 import java.io.PrintWriter; 31 import java.text.MessageFormat; 32 import java.util.List; 33 import java.util.ListIterator; 34 import java.util.Set; 35 36 import jdk.tools.jaotc.binformat.BinaryContainer; 37 import jdk.tools.jaotc.Options.Option; 38 39 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; 40 import org.graalvm.compiler.api.runtime.GraalJVMCICompiler; 41 import org.graalvm.compiler.debug.DebugContext; 42 import org.graalvm.compiler.debug.DebugContext.Activation; 43 import org.graalvm.compiler.hotspot.CompilerConfigurationFactory; 44 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; 45 import org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory; 46 import org.graalvm.compiler.hotspot.HotSpotGraalOptionValues; 47 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; 48 import org.graalvm.compiler.hotspot.HotSpotHostBackend; 49 import org.graalvm.compiler.java.GraphBuilderPhase; 50 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; 51 import org.graalvm.compiler.options.OptionValues; 52 import org.graalvm.compiler.phases.BasePhase; 53 import org.graalvm.compiler.phases.PhaseSuite; 54 import org.graalvm.compiler.phases.tiers.HighTierContext; 55 import org.graalvm.compiler.printer.GraalDebugHandlersFactory; 56 import org.graalvm.compiler.runtime.RuntimeProvider; 57 58 import jdk.vm.ci.meta.MetaAccessProvider; 59 import jdk.vm.ci.meta.ResolvedJavaMethod; 60 import jdk.vm.ci.runtime.JVMCI; 61 62 public final class Main { 63 64 final Options options = new Options(); 65 private PrintWriter log; 66 LogPrinter printer; 67 GraalFilters filters; 68 69 private static final int EXIT_OK = 0; // No errors. 70 private static final int EXIT_CMDERR = 2; // Bad command-line arguments and/or switches. 71 private static final int EXIT_ABNORMAL = 4; // Terminated abnormally. 72 73 private static final String PROGNAME = "jaotc"; 74 75 private static final String JVM_VERSION = System.getProperty("java.runtime.version"); 76 77 public static void main(String[] args) throws Exception { 78 Main t = new Main(); 79 final int exitCode = t.run(args); 80 System.exit(exitCode); 81 } 82 83 private int run(String[] args) { 84 log = new PrintWriter(System.out); 85 printer = new LogPrinter(this, log); 86 87 try { 88 Options.handleOptions(this, args); 89 if (options.help) { 90 showHelp(); 91 return EXIT_OK; 92 } 93 if (options.version) { 94 showVersion(); 95 return EXIT_OK; 96 } 97 98 printer.printlnInfo("Compiling " + options.outputName + "..."); 99 final long start = System.currentTimeMillis(); 100 if (!run()) { 101 return EXIT_ABNORMAL; 102 } 103 final long end = System.currentTimeMillis(); 104 printer.printlnInfo("Total time: " + (end - start) + " ms"); 105 106 return EXIT_OK; 107 } catch (Options.BadArgs e) { 108 printer.reportError(e.key, e.args); 109 if (e.showUsage) { 110 showUsage(); 111 } 112 return EXIT_CMDERR; 113 } catch (Exception e) { 114 e.printStackTrace(); 115 return EXIT_ABNORMAL; 116 } finally { 117 log.flush(); 118 } 119 } 120 121 @SuppressWarnings("try") 122 private boolean run() throws Exception { 123 LogPrinter.openLog(); 124 125 try { 126 127 final Linker linker = new Linker(this); 128 final String objectFileName = linker.objFile(); 129 final Collector collector = new Collector(this); 130 Set<Class<?>> classesToCompile; 131 132 try (Timer t = new Timer(this, "")) { 133 classesToCompile = collector.collectClassesToCompile(); 134 printer.printInfo(classesToCompile.size() + " classes found"); 135 } 136 137 OptionValues graalOptions = HotSpotGraalOptionValues.HOTSPOT_OPTIONS; 138 // Setting -Dgraal.TieredAOT overrides --compile-for-tiered 139 if (!TieredAOT.hasBeenSet(graalOptions)) { 140 graalOptions = new OptionValues(graalOptions, TieredAOT, options.tiered); 141 } 142 graalOptions = new OptionValues(graalOptions, GeneratePIC, true, ImmutableCode, true); 143 GraalJVMCICompiler graalCompiler = HotSpotGraalCompilerFactory.createCompiler(JVMCI.getRuntime(), graalOptions, CompilerConfigurationFactory.selectFactory(null, graalOptions)); 144 HotSpotGraalRuntimeProvider runtime = (HotSpotGraalRuntimeProvider) graalCompiler.getGraalRuntime(); 145 HotSpotHostBackend backend = (HotSpotHostBackend) runtime.getCapability(RuntimeProvider.class).getHostBackend(); 146 MetaAccessProvider metaAccess = backend.getProviders().getMetaAccess(); 147 filters = new GraalFilters(metaAccess); 148 149 List<AOTCompiledClass> classes; 150 151 try (Timer t = new Timer(this, "")) { 152 classes = collector.collectMethodsToCompile(classesToCompile, metaAccess); 153 } 154 155 // Free memory! 156 try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) { 157 printer.printMemoryUsage(); 158 classesToCompile = null; 159 System.gc(); 160 } 161 162 AOTBackend aotBackend = new AOTBackend(this, graalOptions, backend); 163 SnippetReflectionProvider snippetReflection = aotBackend.getProviders().getSnippetReflection(); 164 AOTCompiler compiler = new AOTCompiler(this, graalOptions, aotBackend, options.threads); 165 classes = compiler.compileClasses(classes); 166 167 GraalHotSpotVMConfig graalHotSpotVMConfig = runtime.getVMConfig(); 168 PhaseSuite<HighTierContext> graphBuilderSuite = aotBackend.getGraphBuilderSuite(); 169 ListIterator<BasePhase<? super HighTierContext>> iterator = graphBuilderSuite.findPhase(GraphBuilderPhase.class); 170 GraphBuilderConfiguration graphBuilderConfig = ((GraphBuilderPhase) iterator.previous()).getGraphBuilderConfig(); 171 172 // Free memory! 173 try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) { 174 printer.printMemoryUsage(); 175 aotBackend = null; 176 compiler = null; 177 System.gc(); 178 } 179 180 BinaryContainer binaryContainer = new BinaryContainer(graalOptions, graalHotSpotVMConfig, graphBuilderConfig, JVM_VERSION); 181 DataBuilder dataBuilder = new DataBuilder(this, backend, classes, binaryContainer); 182 183 try (DebugContext debug = DebugContext.create(graalOptions, new GraalDebugHandlersFactory(snippetReflection)); Activation a = debug.activate()) { 184 dataBuilder.prepareData(debug); 185 } 186 187 // Print information about section sizes 188 printer.containersInfo(binaryContainer); 189 190 // Free memory! 191 try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) { 192 printer.printMemoryUsage(); 193 backend = null; 194 for (AOTCompiledClass aotCompClass : classes) { 195 aotCompClass.clear(); 196 } 197 classes.clear(); 198 classes = null; 199 dataBuilder = null; 200 binaryContainer.freeMemory(); 201 System.gc(); 202 } 203 204 try (Timer t = new Timer(this, "Creating binary: " + objectFileName)) { 205 binaryContainer.createBinary(objectFileName); 206 } 207 208 // Free memory! 209 try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) { 210 printer.printMemoryUsage(); 211 binaryContainer = null; 212 System.gc(); 213 } 214 215 try (Timer t = new Timer(this, "Creating shared library: " + linker.libFile())) { 216 linker.link(); 217 } 218 219 printer.printVerbose("Final memory "); 220 printer.printMemoryUsage(); 221 printer.printlnVerbose(""); 222 223 } finally { 224 LogPrinter.closeLog(); 225 } 226 return true; 227 } 228 229 void handleError(ResolvedJavaMethod resolvedMethod, Throwable e, String message) { 230 String methodName = JavaMethodInfo.uniqueMethodName(resolvedMethod); 231 232 if (options.debug) { 233 printer.printError("Failed compilation: " + methodName + ": " + e); 234 } 235 236 // Ignore some exceptions when meta-compiling Graal. 237 if (GraalFilters.shouldIgnoreException(e)) { 238 return; 239 } 240 241 LogPrinter.writeLog("Failed compilation of method " + methodName + message); 242 243 if (!options.debug) { 244 printer.printError("Failed compilation: " + methodName + ": " + e); 245 } 246 247 if (options.verbose) { 248 e.printStackTrace(log); 249 } 250 251 if (options.exitOnError) { 252 System.exit(1); 253 } 254 } 255 256 void warning(String key, Object... args) { 257 log.println("Warning: " + MessageFormat.format(key, args)); 258 log.flush(); 259 } 260 261 private void showUsage() { 262 log.println("Usage: " + PROGNAME + " <options> list"); 263 log.println("use --help for a list of possible options"); 264 log.flush(); 265 } 266 267 private void showHelp() { 268 log.println("Usage: " + PROGNAME + " <options> list"); 269 log.println(); 270 log.println(" list A : separated list of class names, modules, jar files"); 271 log.println(" or directories which contain class files."); 272 log.println(); 273 log.println("where options include:"); 274 for (Option o : Options.recognizedOptions) { 275 String name = o.aliases[0].substring(1); // there must always be at least one name 276 name = name.charAt(0) == '-' ? name.substring(1) : name; 277 if (o.isHidden() || name.equals("h")) { 278 continue; 279 } 280 log.println(o.help); 281 } 282 log.flush(); 283 } 284 285 private void showVersion() { 286 log.println(PROGNAME + " " + JVM_VERSION); 287 } 288 }