Mercurial > hg > truffle
diff graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java @ 13353:0e5c4f9fa9a5
enabled non-hosted CompileTheWorld execution with complete bootstrapping and the ability to override compilation options separately for CTW compilations
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Mon, 16 Dec 2013 23:33:40 +0100 |
parents | ebdc13d9845d |
children | 5a6c617a66ac |
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java Mon Dec 16 12:10:10 2013 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java Mon Dec 16 23:33:40 2013 +0100 @@ -22,7 +22,9 @@ */ package com.oracle.graal.hotspot; +import static com.oracle.graal.hotspot.CompileTheWorld.Options.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; +import static com.oracle.graal.nodes.StructuredGraph.*; import static com.oracle.graal.phases.GraalOptions.*; import java.io.*; @@ -34,10 +36,14 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.bytecode.*; import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.HotSpotOptions.OptionConsumer; import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.nodes.*; +import com.oracle.graal.options.*; +import com.oracle.graal.options.OptionValue.OverrideScope; import com.oracle.graal.phases.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.replacements.*; /** @@ -45,6 +51,83 @@ */ public final class CompileTheWorld { + static class Options { + // @formatter:off + @Option(help = "Compile all methods in all classes on given class path") + public static final OptionValue<String> CompileTheWorldClasspath = new OptionValue<>(null); + @Option(help = "First class to consider when using -XX:+CompileTheWorld") + public static final OptionValue<Integer> CompileTheWorldStartAt = new OptionValue<>(1); + @Option(help = "Last class to consider when using -XX:+CompileTheWorld") + public static final OptionValue<Integer> CompileTheWorldStopAt = new OptionValue<>(Integer.MAX_VALUE); + @Option(help = "Option value overrides to use during compile the world. For example, " + + "to disable inlining and partial escape analysis specify '-PartialEscapeAnalysis -Inline'. " + + "The format for each option is the same as on the command line just without the '-G:' prefix.") + public static final OptionValue<String> CompileTheWorldConfig = new OptionValue<>(null); + // @formatter:on + } + + /** + * A mechanism for overriding Graal options that effect compilation. A {@link Config} object + * should be used in a try-with-resources statement to ensure overriding of options is scoped + * properly. For example: + * + * <pre> + * Config config = ...; + * try (AutoCloseable s = config == null ? null : config.apply()) { + * // perform a Graal compilation + * } + * </pre> + */ + @SuppressWarnings("serial") + static class Config extends HashMap<OptionValue<?>, Object> implements AutoCloseable, OptionConsumer { + OverrideScope scope; + + /** + * Creates a {@link Config} object by parsing a set of space separated override options. + * + * @param options a space separated set of option value settings with each option setting in + * a format compatible with + * {@link HotSpotOptions#parseOption(String, OptionConsumer)} + */ + Config(String options) { + for (String option : options.split("\\s+")) { + if (!HotSpotOptions.parseOption(option, this)) { + throw new GraalInternalError("Invalid option specified: %s", option); + } + } + } + + /** + * Applies the overrides represented by this object. The overrides are in effect until + * {@link #close()} is called on this object. + */ + Config apply() { + assert scope == null; + scope = OptionValue.override(this); + return this; + } + + public void close() { + assert scope != null; + scope.close(); + + scope = null; + + } + + public void set(OptionDescriptor desc, Object value) { + put(desc.getOptionValue(), value); + } + } + + static Config parseConfig(String input) { + if (input == null) { + return null; + } else { + return new Config(input); + } + } + /** * This is our magic token to trigger reading files from the boot class path. */ @@ -54,13 +137,13 @@ private final HotSpotGraalRuntime runtime = runtime(); private final VMToCompilerImpl vmToCompiler = (VMToCompilerImpl) runtime.getVMToCompiler(); - /** List of Zip/Jar files to compile (see {@link GraalOptions#CompileTheWorld}. */ + /** List of Zip/Jar files to compile (see {@link #CompileTheWorldClasspath}. */ private final String files; - /** Class index to start compilation at (see {@link GraalOptions#CompileTheWorldStartAt}. */ + /** Class index to start compilation at (see {@link #CompileTheWorldStartAt}. */ private final int startAt; - /** Class index to stop compilation at (see {@link GraalOptions#CompileTheWorldStopAt}. */ + /** Class index to stop compilation at (see {@link #CompileTheWorldStopAt}. */ private final int stopAt; // Counters @@ -69,28 +152,30 @@ private long compileTime = 0; private boolean verbose; + private final Config config; /** - * Create a compile-the-world instance with default values from - * {@link GraalOptions#CompileTheWorld}, {@link GraalOptions#CompileTheWorldStartAt} and - * {@link GraalOptions#CompileTheWorldStopAt}. + * Creates a compile-the-world instance with default values from + * {@link Options#CompileTheWorldClasspath}, {@link Options#CompileTheWorldStartAt} and + * {@link Options#CompileTheWorldStopAt}. */ public CompileTheWorld() { - this(CompileTheWorld.getValue(), CompileTheWorldStartAt.getValue(), CompileTheWorldStopAt.getValue(), true); + this(CompileTheWorldClasspath.getValue(), parseConfig(CompileTheWorldConfig.getValue()), CompileTheWorldStartAt.getValue(), CompileTheWorldStopAt.getValue(), true); } /** - * Create a compile-the-world instance. + * Creates a compile-the-world instance. * * @param files {@link File#pathSeparator} separated list of Zip/Jar files to compile * @param startAt index of the class file to start compilation at * @param stopAt index of the class file to stop compilation at */ - public CompileTheWorld(String files, int startAt, int stopAt, boolean verbose) { + public CompileTheWorld(String files, Config config, int startAt, int stopAt, boolean verbose) { this.files = files; this.startAt = startAt; this.stopAt = stopAt; this.verbose = verbose; + this.config = config; // We don't want the VM to exit when a method fails to compile... ExitVMOnException.setValue(false); @@ -101,12 +186,10 @@ } /** - * Compile all methods in all classes in the Zip/Jar files in - * {@link GraalOptions#CompileTheWorld}. If the GraalOptions.CompileTheWorld contains the magic - * token {@link CompileTheWorld#SUN_BOOT_CLASS_PATH} passed up from HotSpot we take the files - * from the boot class path. - * - * @throws Throwable + * Compiles all methods in all classes in the Zip/Jar archive files in + * {@link #CompileTheWorldClasspath}. If {@link #CompileTheWorldClasspath} contains the magic + * token {@link #SUN_BOOT_CLASS_PATH} passed up from HotSpot we take the files from the boot + * class path. */ public void compile() throws Throwable { if (SUN_BOOT_CLASS_PATH.equals(files)) { @@ -145,7 +228,7 @@ } /** - * Compile all methods in all classes in the Zip/Jar files passed. + * Compiles all methods in all classes in the Zip/Jar files passed. * * @param fileList {@link File#pathSeparator} separated list of Zip/Jar files to compile * @throws Throwable @@ -186,7 +269,7 @@ String className = je.getName().substring(0, je.getName().length() - ".class".length()); classFileCounter++; - try { + try (AutoCloseable s = config == null ? null : config.apply()) { // Load and initialize class Class<?> javaClass = Class.forName(className.replace('/', '.'), true, loader); @@ -233,25 +316,49 @@ } /** - * Helper method to schedule a method for compilation and gather some statistics. + * A compilation task that creates a fresh compilation suite for its compilation. This is + * required so that a CTW compilation can be {@linkplain Config configured} differently from a + * VM triggered compilation. + */ + static class CTWCompilationTask extends CompilationTask { + + CTWCompilationTask(HotSpotBackend backend, PhasePlan plan, OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, HotSpotResolvedJavaMethod method, int entryBCI, int id) { + super(backend, plan, optimisticOpts, profilingInfo, method, entryBCI, id); + } + + @Override + protected Suites getSuites(HotSpotProviders providers) { + return providers.getSuites().createSuites(); + } + } + + /** + * Compiles a method and gathers some statistics. */ private void compileMethod(HotSpotResolvedJavaMethod method) { try { long start = System.currentTimeMillis(); - vmToCompiler.compileMethod(method, StructuredGraph.INVOCATION_ENTRY_BCI, true); + + final ProfilingInfo profilingInfo = method.getCompilationProfilingInfo(false); + final OptimisticOptimizations optimisticOpts = new OptimisticOptimizations(profilingInfo); + int id = vmToCompiler.allocateCompileTaskId(); + HotSpotBackend backend = runtime.getHostBackend(); + PhasePlan phasePlan = vmToCompiler.createPhasePlan(backend.getProviders(), optimisticOpts, false); + CompilationTask task = new CTWCompilationTask(backend, phasePlan, optimisticOpts, profilingInfo, method, INVOCATION_ENTRY_BCI, id); + task.runCompilation(); + compileTime += (System.currentTimeMillis() - start); compiledMethodsCounter++; method.reprofile(); // makes the method also not-entrant } catch (Throwable t) { // Catch everything and print a message - println("CompileTheWorld (%d) : Error compiling method: %s", classFileCounter, MetaUtil.format("%H.%n(%p):%r", method)); + println("CompileTheWorldClasspath (%d) : Error compiling method: %s", classFileCounter, MetaUtil.format("%H.%n(%p):%r", method)); t.printStackTrace(TTY.cachedOut); } } /** - * Helper method for CompileTheWorld to determine if a method should be compiled (Cf. - * CompilationPolicy::can_be_compiled). + * Determines if a method should be compiled (Cf. CompilationPolicy::can_be_compiled). * * @return true if it can be compiled, false otherwise */