changeset 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 cd22c6bb4a35
children 5a7508f1a7ff
files graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java src/share/vm/graal/graalCompiler.cpp
diffstat 8 files changed, 181 insertions(+), 47 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java	Mon Dec 16 12:10:10 2013 -0800
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java	Mon Dec 16 23:33:40 2013 +0100
@@ -39,7 +39,7 @@
         boolean originalSetting = ExitVMOnException.getValue();
         // Compile a couple classes in rt.jar
         String file = System.getProperty("java.home") + "/lib/rt.jar";
-        new CompileTheWorld(file, 1, 5, false).compile();
+        new CompileTheWorld(file, null, 1, 5, false).compile();
         ExitVMOnException.setValue(originalSetting);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Mon Dec 16 12:10:10 2013 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Mon Dec 16 23:33:40 2013 +0100
@@ -47,7 +47,7 @@
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.tiers.*;
 
-public final class CompilationTask implements Runnable {
+public class CompilationTask implements Runnable {
 
     public static final ThreadLocal<Boolean> withinEnqueue = new ThreadLocal<Boolean>() {
 
@@ -77,7 +77,7 @@
         return new CompilationTask(backend, plan, optimisticOpts, profilingInfo, method, entryBCI, id);
     }
 
-    private CompilationTask(HotSpotBackend backend, PhasePlan plan, OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, HotSpotResolvedJavaMethod method, int entryBCI, int id) {
+    protected CompilationTask(HotSpotBackend backend, PhasePlan plan, OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, HotSpotResolvedJavaMethod method, int entryBCI, int id) {
         assert id >= 0;
         this.backend = backend;
         this.plan = plan;
@@ -120,6 +120,10 @@
 
     public static final DebugTimer CodeInstallationTime = Debug.timer("CodeInstallation");
 
+    protected Suites getSuites(HotSpotProviders providers) {
+        return providers.getSuites().getDefaultSuites();
+    }
+
     public void runCompilation() {
         /*
          * no code must be outside this try/finally because it could happen otherwise that
@@ -164,7 +168,7 @@
                 }
                 InlinedBytecodes.add(method.getCodeSize());
                 CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false);
-                Suites suites = providers.getSuites().getDefaultSuites();
+                Suites suites = getSuites(providers);
                 result = compileGraph(graph, cc, method, providers, backend, backend.getTarget(), graphCache, plan, optimisticOpts, profilingInfo, method.getSpeculationLog(), suites, true,
                                 new CompilationResult(), CompilationResultBuilderFactory.Default);
 
--- 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
      */
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Mon Dec 16 12:10:10 2013 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Mon Dec 16 23:33:40 2013 +0100
@@ -23,7 +23,9 @@
 package com.oracle.graal.hotspot;
 
 import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.hotspot.CompileTheWorld.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.Options.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -232,23 +234,23 @@
         initMirror(typeVoid);
 
         // Set some global options:
-        if (config.compileTheWorld) {
-            GraalOptions.CompileTheWorld.setValue(CompileTheWorld.SUN_BOOT_CLASS_PATH);
+        if (config.compileTheWorld && CompileTheWorld.Options.CompileTheWorldClasspath.getValue() == null) {
+            CompileTheWorld.Options.CompileTheWorldClasspath.setValue(SUN_BOOT_CLASS_PATH);
         }
         if (config.compileTheWorldStartAt != 1) {
-            GraalOptions.CompileTheWorldStartAt.setValue(config.compileTheWorldStartAt);
+            CompileTheWorld.Options.CompileTheWorldStartAt.setValue(config.compileTheWorldStartAt);
         }
         if (config.compileTheWorldStopAt != Integer.MAX_VALUE) {
-            GraalOptions.CompileTheWorldStopAt.setValue(config.compileTheWorldStopAt);
+            CompileTheWorld.Options.CompileTheWorldStopAt.setValue(config.compileTheWorldStopAt);
         }
 
         // Only set HotSpotPrintCompilation and HotSpotPrintInlining if they still have their
         // default value (false).
-        if (GraalOptions.HotSpotPrintCompilation.getValue() == false) {
-            GraalOptions.HotSpotPrintCompilation.setValue(config.printCompilation);
+        if (HotSpotPrintCompilation.getValue() == false) {
+            HotSpotPrintCompilation.setValue(config.printCompilation);
         }
-        if (GraalOptions.HotSpotPrintInlining.getValue() == false) {
-            GraalOptions.HotSpotPrintInlining.setValue(config.printInlining);
+        if (HotSpotPrintInlining.getValue() == false) {
+            HotSpotPrintInlining.setValue(config.printInlining);
         }
 
         if (Boolean.valueOf(System.getProperty("graal.printconfig"))) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Mon Dec 16 12:10:10 2013 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Mon Dec 16 23:33:40 2013 +0100
@@ -103,6 +103,22 @@
 
     // Called from VM code
     public static boolean setOption(String option) {
+        return parseOption(option, null);
+    }
+
+    interface OptionConsumer {
+        void set(OptionDescriptor desc, Object value);
+    }
+
+    /**
+     * Parses a given option value specification.
+     * 
+     * @param option the specification of an option and its value
+     * @param setter the object to notify of the parsed option and value. If null, the
+     *            {@link OptionValue#setValue(Object)} method of the specified option is called
+     *            instead.
+     */
+    public static boolean parseOption(String option, OptionConsumer setter) {
         if (option.length() == 0) {
             return false;
         }
@@ -175,9 +191,13 @@
         }
 
         if (value != null) {
-            OptionValue<?> optionValue = desc.getOptionValue();
-            optionValue.setValue(value);
-            // Logger.info("Set option " + desc.getName() + " to " + value);
+            if (setter != null) {
+                setter.set(desc, value);
+            } else {
+                OptionValue<?> optionValue = desc.getOptionValue();
+                optionValue.setValue(value);
+                // Logger.info("Set option " + desc.getName() + " to " + value);
+            }
         } else {
             Logger.info("Wrong value \"" + valueString + "\" for option " + optionName);
             return false;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Mon Dec 16 12:10:10 2013 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Mon Dec 16 23:33:40 2013 +0100
@@ -97,6 +97,10 @@
         this.runtime = runtime;
     }
 
+    public int allocateCompileTaskId() {
+        return compileTaskIds.incrementAndGet();
+    }
+
     public void startCompiler(boolean bootstrapEnabled) throws Throwable {
 
         FastNodeClassRegistry.initialize();
@@ -556,7 +560,7 @@
 
                 final ProfilingInfo profilingInfo = method.getCompilationProfilingInfo(osrCompilation);
                 final OptimisticOptimizations optimisticOpts = new OptimisticOptimizations(profilingInfo);
-                int id = compileTaskIds.incrementAndGet();
+                int id = allocateCompileTaskId();
                 HotSpotBackend backend = runtime.getHostBackend();
                 CompilationTask task = CompilationTask.create(backend, createPhasePlan(backend.getProviders(), optimisticOpts, osrCompilation), optimisticOpts, profilingInfo, method, entryBCI, id);
 
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Mon Dec 16 12:10:10 2013 -0800
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Mon Dec 16 23:33:40 2013 +0100
@@ -87,14 +87,6 @@
     @Option(help = "")
     public static final OptionValue<Integer> DeoptsToDisableOptimisticOptimization = new OptionValue<>(40);
 
-    // compilation queue
-    @Option(help = "Compile all methods in all classes on given class path")
-    public static final OptionValue<String> CompileTheWorld = new OptionValue<>(null);
-    @Option(help = "First class to consider when using CompileTheWorld")
-    public static final OptionValue<Integer> CompileTheWorldStartAt = new OptionValue<>(1);
-    @Option(help = "Last class to consider when using CompileTheWorld")
-    public static final OptionValue<Integer> CompileTheWorldStopAt = new OptionValue<>(Integer.MAX_VALUE);
-
     // graph caching
     @Option(help = "")
     public static final OptionValue<Boolean> CacheGraphs = new OptionValue<>(true);
--- a/src/share/vm/graal/graalCompiler.cpp	Mon Dec 16 12:10:10 2013 -0800
+++ b/src/share/vm/graal/graalCompiler.cpp	Mon Dec 16 23:33:40 2013 +0100
@@ -115,6 +115,11 @@
         // Avoid -Xcomp and -Xbatch problems by turning on interpreter and background compilation for bootstrapping.
         FlagSetting a(UseInterpreter, true);
         FlagSetting b(BackgroundCompilation, true);
+#ifndef PRODUCT
+        // Turn off CompileTheWorld during bootstrap
+        // so that a complete bootstrap occurs
+        FlagSetting c(CompileTheWorld, false);
+#endif
         VMToCompiler::bootstrap();
       }